Added rough cut of db api.

This commit is contained in:
Phillip Toland 2008-12-12 11:14:03 -06:00
parent e90e790d9c
commit e1bcd7aa52
6 changed files with 159 additions and 2 deletions

1
.gitignore vendored
View file

@ -4,3 +4,4 @@
*.tmproj
c_src/system
test/logs
test/test.cover

View file

@ -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
View 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).

View file

@ -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
View file

@ -0,0 +1,3 @@
{export, ["test/test.cover"]}.
{level, details}.
{incl_dirs_r, ["ebin"]}.

85
test/db_api_SUITE.erl Normal file
View 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).