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
|
*.tmproj
|
||||||
c_src/system
|
c_src/system
|
||||||
test/logs
|
test/logs
|
||||||
|
test/test.cover
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{application, bdberl,
|
{application, bdberl,
|
||||||
[{description, "Berkeley DB Erlang Driver"},
|
[{description, "Berkeley DB Erlang Driver"},
|
||||||
{vsn, "1"},
|
{vsn, "1"},
|
||||||
{modules, [ bdberl_port ]},
|
{modules, [ bdberl_port, bdberl_db ]},
|
||||||
{registered, []},
|
{registered, []},
|
||||||
{applications, [kernel,
|
{applications, [kernel,
|
||||||
stdlib]},
|
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,
|
-export([new/0,
|
||||||
open_database/3, open_database/4,
|
open_database/3, open_database/4,
|
||||||
close_database/2,
|
close_database/2, close_database/3,
|
||||||
txn_begin/1, txn_begin/2,
|
txn_begin/1, txn_begin/2,
|
||||||
txn_commit/1, txn_commit/2, txn_abort/1,
|
txn_commit/1, txn_commit/2, txn_abort/1,
|
||||||
get_cache_size/1, set_cache_size/4,
|
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