diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index cc18983..0639561 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -17,7 +17,7 @@ /** * Function prototypes */ -static int open_database(const char* name, DBTYPE type, PortData* data, int* errno); +static int open_database(const char* name, DBTYPE type, unsigned int flags, PortData* data, int* errno); static int close_database(int dbref, PortData* data); static void do_async_put(void* arg); @@ -79,6 +79,8 @@ static hive_hash* G_DATABASES_NAMES; #define WRITE_LOCK(L) erl_drv_rwlock_rwlock(L) #define WRITE_UNLOCK(L) erl_drv_rwlock_rwunlock(L) +#define DECODE_UINT(B) (unsigned int)(B[0] + (B[1] << 8) + (B[2] << 16) + (B[3] << 24)) + #define RETURN_BH(bh, outbuf) *outbuf = (char*)bh.bin; return bh.bin->orig_size; #define RETURN_INT(val, outbuf) { \ @@ -206,12 +208,13 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, case CMD_OPEN_DB: { // Extract the type code and filename from the inbuf - // Inbuf is: <> - DBTYPE type = (DBTYPE)((char)*inbuf); - char* name = (char*)(inbuf+1); + // Inbuf is: <> + unsigned int flags = DECODE_UINT(inbuf); + DBTYPE type = (DBTYPE)inbuf[4]; + char* name = (char*)(inbuf+5); int dbref; int status; - int rc = open_database(name, type, d, &dbref); + int rc = open_database(name, type, flags, d, &dbref); if (rc == 0) { status = STATUS_OK; @@ -420,7 +423,7 @@ static void bdberl_drv_process_exit(ErlDrvData handle, ErlDrvMonitor *monitor) { } -static int open_database(const char* name, DBTYPE type, PortData* data, int* dbref_res) +static int open_database(const char* name, DBTYPE type, unsigned int flags, PortData* data, int* dbref_res) { *dbref_res = -1; @@ -502,9 +505,9 @@ static int open_database(const char* name, DBTYPE type, PortData* data, int* dbr WRITE_UNLOCK(G_DATABASES_RWLOCK); return rc; } - + // Attempt to open our database - rc = db->open(db, 0, name, 0, type, DB_CREATE | DB_AUTO_COMMIT | DB_THREAD, 0); + rc = db->open(db, 0, name, 0, type, flags, 0); if (rc != 0) { // Failure while opening the database -- cleanup the handle, drop the lock diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index 5810059..f58f107 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -7,7 +7,7 @@ -module(bdberl_port). -export([new/0, - open_database/3, + open_database/3, open_database/4, close_database/2, txn_begin/1, txn_commit/1, txn_abort/1, put/4, @@ -26,6 +26,16 @@ -define(DB_TYPE_BTREE, 1). -define(DB_TYPE_HASH, 2). +-define(DB_AUTO_COMMIT, 16#00000100). +-define(DB_CREATE, 16#00000001). +-define(DB_EXCL, 16#00000400). +-define(DB_MULTIVERSION, 16#00000008). +-define(DB_NOMMAP, 16#00000010). +-define(DB_RDONLY, 16#00000080). +-define(DB_READ_UNCOMMITTED, 16#00000200). +-define(DB_THREAD, 16#00000004). +-define(DB_TRUNCATE, 16#00008000). + -define(STATUS_OK, 0). -define(STATUS_ERROR, 1). @@ -44,14 +54,17 @@ new() -> Port = open_port({spawn, bdberl_drv}, [binary]), {ok, Port}. - open_database(Port, Name, Type) -> + open_database(Port, Name, Type, [create, auto_commit, threaded]). + +open_database(Port, Name, Type, Opts) -> %% Map database type into an integer code case Type of btree -> TypeCode = ?DB_TYPE_BTREE; hash -> TypeCode = ?DB_TYPE_HASH - end, - Cmd = <>, + end, + Flags = process_flags(Opts), + Cmd = <>, case erlang:port_control(Port, ?CMD_OPEN_DB, Cmd) of <> -> {ok, DbRef}; @@ -140,3 +153,19 @@ to_binary(Term) -> Bin = term_to_binary(Term), {size(Bin), Bin}. +process_flags([Flag]) -> + flag_value(Flag); +process_flags([Flag|Flags]) -> + flag_value(Flag) bor process_flags(Flags). + +flag_value(Flag) -> + case Flag of + auto_commit -> ?DB_AUTO_COMMIT; + create -> ?DB_CREATE; + exclusive -> ?DB_EXCL; + multiversion -> ?DB_MULTIVERSION; + no_mmap -> ?DB_NOMMAP; + readonly -> ?DB_RDONLY; + threaded -> ?DB_THREAD; + truncate -> ?DB_TRUNCATE + end. diff --git a/test/port_SUITE.erl b/test/port_SUITE.erl index f674d83..ca524e4 100644 --- a/test/port_SUITE.erl +++ b/test/port_SUITE.erl @@ -12,12 +12,12 @@ all() -> % [test_db]. [test_put, test_txn]. -init_per_testcase(TestCase, Config) -> +init_per_testcase(_TestCase, Config) -> Config. -end_per_testcase(TestCase, _Config) -> +end_per_testcase(_TestCase, _Config) -> ok. - + test_db(_Config) -> {ok, P} = bdberl_port:new(), @@ -71,9 +71,3 @@ test_txn(_Config) -> ok = bdberl_port:txn_begin(P), not_found = bdberl_port:get(P, 0, akey), ok = bdberl_port:txn_commit(P). - - - - - -