Added rough cut of db api.
This commit is contained in:
parent
e90e790d9c
commit
e1bcd7aa52
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@
|
|||
*.tmproj
|
||||
c_src/system
|
||||
test/logs
|
||||
test/test.cover
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{application, bdberl,
|
||||
[{description, "Berkeley DB Erlang Driver"},
|
||||
{vsn, "1"},
|
||||
{modules, [ bdberl_port ]},
|
||||
{modules, [ bdberl_port, bdberl_db ]},
|
||||
{registered, []},
|
||||
{applications, [kernel,
|
||||
stdlib]},
|
||||
|
|
68
src/bdberl_db.erl
Normal file
68
src/bdberl_db.erl
Normal file
|
@ -0,0 +1,68 @@
|
|||
%% -------------------------------------------------------------------
|
||||
%%
|
||||
%% bdberl: API Interface
|
||||
%% Copyright (c) 2008 The Hive. All rights reserved.
|
||||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
-module(bdberl_db).
|
||||
|
||||
|
||||
-export([open/3, open/4,
|
||||
close/1, close/2,
|
||||
put/3, put/4,
|
||||
get/2, get/3,
|
||||
transaction/2,
|
||||
update/3]).
|
||||
|
||||
|
||||
open(Port, Name, Type) ->
|
||||
open(Port, Name, Type, [create]).
|
||||
|
||||
open(Port, Name, Type, Opts) ->
|
||||
case bdberl_port:open_database(Port, Name, Type, Opts) of
|
||||
{ok, DbRef} -> {ok, {db, Port, DbRef}};
|
||||
{error, Reason} -> {error, Reason}
|
||||
end.
|
||||
|
||||
close(Db) ->
|
||||
close(Db, []).
|
||||
|
||||
close({db, Port, DbRef}, Opts) ->
|
||||
bdberl_port:close_database(Port, DbRef, Opts).
|
||||
|
||||
put(Db, Key, Value) ->
|
||||
put(Db, Key, Value, []).
|
||||
|
||||
put({db, Port, DbRef}, Key, Value, Opts) ->
|
||||
bdberl_port:put(Port, DbRef, Key, Value, Opts).
|
||||
|
||||
get(Db, Key) ->
|
||||
get(Db, Key, []).
|
||||
|
||||
get({db, Port, DbRef}, Key, Opts) ->
|
||||
bdberl_port:get(Port, DbRef, Key, Opts).
|
||||
|
||||
|
||||
transaction({db, Port, _DbRef}, Fun) ->
|
||||
bdberl_port:txn_begin(Port),
|
||||
try Fun() of
|
||||
abort ->
|
||||
bdberl_port:txn_abort(Port),
|
||||
{error, transaction_aborted};
|
||||
Value ->
|
||||
bdberl_port:txn_commit(Port),
|
||||
{ok, Value}
|
||||
catch
|
||||
_ : Reason ->
|
||||
bdberl_port:txn_abort(Port),
|
||||
{error, {transaction_failed, Reason}}
|
||||
end.
|
||||
|
||||
update(Db, Key, Fun) ->
|
||||
F = fun() ->
|
||||
{ok, Value} = get(Db, Key, [rmw]),
|
||||
NewValue = Fun(Key, Value),
|
||||
ok = put(Db, Key, NewValue),
|
||||
NewValue
|
||||
end,
|
||||
transaction(Db, F).
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
-export([new/0,
|
||||
open_database/3, open_database/4,
|
||||
close_database/2,
|
||||
close_database/2, close_database/3,
|
||||
txn_begin/1, txn_begin/2,
|
||||
txn_commit/1, txn_commit/2, txn_abort/1,
|
||||
get_cache_size/1, set_cache_size/4,
|
||||
|
|
3
test/cover.spec
Normal file
3
test/cover.spec
Normal file
|
@ -0,0 +1,3 @@
|
|||
{export, ["test/test.cover"]}.
|
||||
{level, details}.
|
||||
{incl_dirs_r, ["ebin"]}.
|
85
test/db_api_SUITE.erl
Normal file
85
test/db_api_SUITE.erl
Normal file
|
@ -0,0 +1,85 @@
|
|||
%% -------------------------------------------------------------------
|
||||
%%
|
||||
%% bdberl: DB API Tests
|
||||
%% Copyright (c) 2008 The Hive. All rights reserved.
|
||||
%%
|
||||
%% -------------------------------------------------------------------
|
||||
-module(db_api_SUITE).
|
||||
|
||||
-compile(export_all).
|
||||
|
||||
-include_lib("ct.hrl").
|
||||
|
||||
all() ->
|
||||
[open_should_create_database_if_none_exists,
|
||||
get_should_fail_when_getting_a_nonexistant_record,
|
||||
get_should_return_a_value_when_getting_a_valid_record,
|
||||
transaction_should_commit_on_success,
|
||||
transaction_should_abort_on_exception,
|
||||
transaction_should_abort_on_user_abort,
|
||||
update_should_save_value_if_successful].
|
||||
|
||||
|
||||
init_per_testcase(_TestCase, Config) ->
|
||||
{ok, Port} = bdberl_port:new(),
|
||||
{ok, Db} = bdberl_db:open(Port, "api_test.db", btree, [create, exclusive]),
|
||||
[{port, Port},{db, Db}|Config].
|
||||
|
||||
end_per_testcase(_TestCase, Config) ->
|
||||
ok = bdberl_db:close(?config(db, Config)),
|
||||
true = port_close(?config(port, Config)),
|
||||
ok = file:delete("api_test.db").
|
||||
|
||||
|
||||
open_should_create_database_if_none_exists(_Config) ->
|
||||
true = filelib:is_file("api_test.db").
|
||||
|
||||
get_should_fail_when_getting_a_nonexistant_record(Config) ->
|
||||
not_found = bdberl_db:get(?config(db, Config), bad_key).
|
||||
|
||||
get_should_return_a_value_when_getting_a_valid_record(Config) ->
|
||||
Db = ?config(db, Config),
|
||||
ok = bdberl_db:put(Db, mykey, avalue),
|
||||
{ok, avalue} = bdberl_db:get(Db, mykey).
|
||||
|
||||
transaction_should_commit_on_success(Config) ->
|
||||
Db = ?config(db, Config),
|
||||
F = fun() -> bdberl_db:put(Db, mykey, avalue) end,
|
||||
{ok, ok} = bdberl_db:transaction(Db, F),
|
||||
{ok, avalue} = bdberl_db:get(Db, mykey).
|
||||
|
||||
transaction_should_abort_on_exception(Config) ->
|
||||
Db = ?config(db, Config),
|
||||
|
||||
F = fun() ->
|
||||
bdberl_db:put(Db, mykey, should_not_see_this),
|
||||
throw(testing)
|
||||
end,
|
||||
|
||||
{error, {transaction_failed, testing}} = bdberl_db:transaction(Db, F),
|
||||
not_found = bdberl_db:get(Db, mykey).
|
||||
|
||||
transaction_should_abort_on_user_abort(Config) ->
|
||||
Db = ?config(db, Config),
|
||||
|
||||
F = fun() ->
|
||||
bdberl_db:put(Db, mykey, should_not_see_this),
|
||||
abort
|
||||
end,
|
||||
|
||||
{error, transaction_aborted} = bdberl_db:transaction(Db, F),
|
||||
not_found = bdberl_db:get(Db, mykey).
|
||||
|
||||
update_should_save_value_if_successful(Config) ->
|
||||
Db = ?config(db, Config),
|
||||
ok = bdberl_db:put(Db, mykey, avalue),
|
||||
|
||||
F = fun(Key, Value) ->
|
||||
mykey = Key,
|
||||
avalue = Value,
|
||||
newvalue
|
||||
end,
|
||||
|
||||
{ok, newvalue} = bdberl_db:update(Db, mykey, F),
|
||||
{ok, newvalue} = bdberl_db:get(Db, mykey).
|
||||
|
Loading…
Reference in a new issue