From 5b2ed7f0a1df12a40047fcca1f3f3b488c52e335 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 10:56:50 -0600 Subject: [PATCH 01/12] Ignore shared libraries and test logs. --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index c02d70e..bce3275 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.o +*.so *.beam c_src/system +test/logs From c5e50712e11e254e3740549f73c68b1aabed7eba Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 10:59:40 -0600 Subject: [PATCH 02/12] Add the ability to pass flags to the open_database function. --- c_src/bdberl_drv.c | 19 +++++++++++-------- src/bdberl_port.erl | 37 +++++++++++++++++++++++++++++++++---- test/port_SUITE.erl | 12 +++--------- 3 files changed, 47 insertions(+), 21 deletions(-) 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). - - - - - - From d2f15bef806c7851171b27589d92ca5a261a22c3 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 12:30:52 -0600 Subject: [PATCH 03/12] Clean up and expand the binary decoding macros. --- c_src/bdberl_drv.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index 0639561..f1bf979 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -79,7 +79,9 @@ 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 DECODE_BYTE(_buf, _off) (_buf[_off]) +#define DECODE_INT(_buf, _off) (*((int*)_buf+_off)) +#define DECODE_STRING(_buf, _off) (char*)(_buf+_off) #define RETURN_BH(bh, outbuf) *outbuf = (char*)bh.bin; return bh.bin->orig_size; @@ -209,9 +211,9 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, { // Extract the type code and filename from the inbuf // Inbuf is: <> - unsigned int flags = DECODE_UINT(inbuf); - DBTYPE type = (DBTYPE)inbuf[4]; - char* name = (char*)(inbuf+5); + unsigned flags = (unsigned) DECODE_INT(inbuf, 0); + DBTYPE type = (DBTYPE) DECODE_BYTE(inbuf, 4); + char* name = DECODE_STRING(inbuf, 5); int dbref; int status; int rc = open_database(name, type, flags, d, &dbref); @@ -238,9 +240,9 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, // TODO: If data is inflight, fail. Abort any open txns. // Take the provided dbref and attempt to close it - int dbref = *((int*)inbuf); + int dbref = DECODE_INT(inbuf, 0); int rc = close_database(dbref, d); - + // Outbuf is: <> RETURN_INT(rc, outbuf); } @@ -301,7 +303,7 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, } // Inbuf is: << DbRef:32, Rest/binary>> - int dbref = *((int*)inbuf); + int dbref = DECODE_INT(inbuf, 0); // Make sure this port currently has dbref open -- if it doesn't, error out. Of note, // if it's in our list, we don't need to grab the RWLOCK, as we don't have to worry about From cf6ef4d2963d047c93984a21b1b65e71044797f1 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 12:58:54 -0600 Subject: [PATCH 04/12] Added flags to the close_database function. --- c_src/bdberl_drv.c | 17 ++++++++++------- src/bdberl_port.erl | 9 ++++++++- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index f1bf979..7eb75d7 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -17,8 +17,8 @@ /** * Function prototypes */ -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 int open_database(const char* name, DBTYPE type, unsigned flags, PortData* data, int* errno); +static int close_database(int dbref, unsigned flags, PortData* data); static void do_async_put(void* arg); static void do_async_put_free(void* arg); @@ -182,7 +182,7 @@ static void bdberl_drv_stop(ErlDrvData handle) // Close all the databases we previously opened while (d->dbrefs) { - close_database(d->dbrefs->dbref, d); + close_database(d->dbrefs->dbref, 0, d); } // Release the port instance data @@ -210,7 +210,7 @@ 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: <> + // Inbuf is: <> unsigned flags = (unsigned) DECODE_INT(inbuf, 0); DBTYPE type = (DBTYPE) DECODE_BYTE(inbuf, 4); char* name = DECODE_STRING(inbuf, 5); @@ -240,8 +240,11 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, // TODO: If data is inflight, fail. Abort any open txns. // Take the provided dbref and attempt to close it + // Inbuf is: <> int dbref = DECODE_INT(inbuf, 0); - int rc = close_database(dbref, d); + unsigned flags = (unsigned) DECODE_INT(inbuf, 4); + + int rc = close_database(dbref, flags, d); // Outbuf is: <> RETURN_INT(rc, outbuf); @@ -538,7 +541,7 @@ static int open_database(const char* name, DBTYPE type, unsigned int flags, Port } } -static int close_database(int dbref, PortData* data) +static int close_database(int dbref, unsigned flags, PortData* data) { printf("Closing %d for port %p\n", dbref, data->port); @@ -562,7 +565,7 @@ static int close_database(int dbref, PortData* data) { printf("Closing actual database for dbref %d\n", dbref); // Close out the BDB handle - database->db->close(database->db, 0); + database->db->close(database->db, flags); // Remove the entry from the names map hive_hash_remove(G_DATABASES_NAMES, database->name); diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index f58f107..3a0c57c 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -36,6 +36,8 @@ -define(DB_THREAD, 16#00000004). -define(DB_TRUNCATE, 16#00008000). +-define(DB_NOSYNC, 21). + -define(STATUS_OK, 0). -define(STATUS_ERROR, 1). @@ -73,7 +75,11 @@ open_database(Port, Name, Type, Opts) -> end. close_database(Port, DbRef) -> - Cmd = <>, + close_database(Port, DbRef, []). + +close_database(Port, DbRef, Opts) -> + Flags = process_flags(Opts), + Cmd = <>, case erlang:port_control(Port, ?CMD_CLOSE_DB, Cmd) of <<0:32/native-integer>> -> {error, invalid_dbref}; @@ -165,6 +171,7 @@ flag_value(Flag) -> exclusive -> ?DB_EXCL; multiversion -> ?DB_MULTIVERSION; no_mmap -> ?DB_NOMMAP; + no_sync -> ?DB_NOSYNC; readonly -> ?DB_RDONLY; threaded -> ?DB_THREAD; truncate -> ?DB_TRUNCATE From eab107df7a262ed419c1ec9cb8da05cd12e43db1 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 15:41:41 -0600 Subject: [PATCH 05/12] Fixed a typo: foudn -> found --- c_src/bdberl_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index 7eb75d7..3ccd0e5 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -403,7 +403,7 @@ static void bdberl_drv_ready_async(ErlDrvData handle, ErlDrvThreadData thread_da } else if (adata->rc == DB_NOTFOUND) { - printf("not foudn\n"); + printf("not found\n"); ErlDrvTermData response[] = { ERL_DRV_ATOM, driver_mk_atom("not_found") }; driver_output_term(d->port, response, sizeof(response) / sizeof(response[0])); } From 7ec347c73eae86e40792179e088824bdc01e8fb2 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 16:04:34 -0600 Subject: [PATCH 06/12] Added flags to the put function. --- c_src/bdberl_drv.c | 21 ++++++++++++--------- src/bdberl_port.erl | 24 +++++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index 3ccd0e5..a10f89b 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -80,8 +80,9 @@ static hive_hash* G_DATABASES_NAMES; #define WRITE_UNLOCK(L) erl_drv_rwlock_rwunlock(L) #define DECODE_BYTE(_buf, _off) (_buf[_off]) -#define DECODE_INT(_buf, _off) (*((int*)_buf+_off)) -#define DECODE_STRING(_buf, _off) (char*)(_buf+_off) +#define DECODE_INT(_buf, _off) *((int*)(_buf+(_off))) +#define DECODE_STRING(_buf, _off) (char*)(_buf+(_off)) +#define DECODE_BLOB(_buf, _off) (void*)(_buf+(_off)) #define RETURN_BH(bh, outbuf) *outbuf = (char*)bh.bin; return bh.bin->orig_size; @@ -585,8 +586,11 @@ static int close_database(int dbref, unsigned flags, PortData* data) static void do_async_put(void* arg) { printf("do_async_put\n"); + + // Payload is: <> AsyncData* adata = (AsyncData*)arg; - + unsigned flags = DECODE_INT(adata->payload, 4); + // Setup DBTs DBT key; DBT value; @@ -594,16 +598,15 @@ static void do_async_put(void* arg) memset(&value, '\0', sizeof(DBT)); // Parse payload into DBTs - // Payload is: << DbRef:32, KeyLen:32, Key:KeyLen, ValLen:32, Val:ValLen>> - key.size = *((int*)(adata->payload + 4)); - key.data = (void*)(adata->payload + 8); - value.size = *((int*)(adata->payload + 8 + key.size)); - value.data = (void*)(adata->payload + 8 + key.size + 4); + key.size = DECODE_INT(adata->payload, 8); + key.data = DECODE_BLOB(adata->payload, 12); + value.size = DECODE_INT(adata->payload, 12 + key.size); + value.data = DECODE_BLOB(adata->payload, 12 + key.size + 4); // Execute the actual put -- we'll process the result back in the driver_async_ready function // All databases are opened with AUTO_COMMIT, so if msg->port->txn is NULL, the put will still // be atomic - adata->rc = adata->db->put(adata->db, adata->port->txn, &key, &value, 0); + adata->rc = adata->db->put(adata->db, adata->port->txn, &key, &value, flags); } static void do_async_put_free(void* arg) diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index 3a0c57c..24db0e8 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -10,7 +10,7 @@ open_database/3, open_database/4, close_database/2, txn_begin/1, txn_commit/1, txn_abort/1, - put/4, + put/4, put/5, get/3]). -define(CMD_NONE, 0). @@ -36,7 +36,10 @@ -define(DB_THREAD, 16#00000004). -define(DB_TRUNCATE, 16#00008000). --define(DB_NOSYNC, 21). +-define(DB_APPEND, 2). +-define(DB_NODUPDATA, 19). +-define(DB_NOOVERWRITE, 20). +-define(DB_NOSYNC, 21). -define(STATUS_OK, 0). -define(STATUS_ERROR, 1). @@ -119,11 +122,14 @@ txn_abort(Port) -> ?ERROR_NO_TXN -> {error, no_txn} end. - put(Port, DbRef, Key, Value) -> + put(Port, DbRef, Key, Value, []). + +put(Port, DbRef, Key, Value, Opts) -> {KeyLen, KeyBin} = to_binary(Key), {ValLen, ValBin} = to_binary(Value), - Cmd = <>, + Flags = process_flags(Opts), + Cmd = <>, <> = erlang:port_control(Port, ?CMD_PUT, Cmd), case Result of ?ERROR_NONE -> @@ -150,27 +156,27 @@ get(Port, DbRef, Key) -> ?ERROR_ASYNC_PENDING -> {error, async_pending}; ?ERROR_INVALID_DBREF -> {error, invalid_dbref} end. - - - to_binary(Term) -> Bin = term_to_binary(Term), {size(Bin), Bin}. -process_flags([Flag]) -> - flag_value(Flag); +process_flags([]) -> + 0; process_flags([Flag|Flags]) -> flag_value(Flag) bor process_flags(Flags). flag_value(Flag) -> case Flag of + append -> ?DB_APPEND; auto_commit -> ?DB_AUTO_COMMIT; create -> ?DB_CREATE; exclusive -> ?DB_EXCL; multiversion -> ?DB_MULTIVERSION; + no_duplicate -> ?DB_NODUPDATA; no_mmap -> ?DB_NOMMAP; + no_overwrite -> ?DB_NOOVERWRITE; no_sync -> ?DB_NOSYNC; readonly -> ?DB_RDONLY; threaded -> ?DB_THREAD; From abb8ca794633791af240f7b0615e4bca3532cf6f Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 16:05:41 -0600 Subject: [PATCH 07/12] Renamed DECODE_ macros to UNPACK_ --- c_src/bdberl_drv.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index a10f89b..81dcaa9 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -79,10 +79,10 @@ 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_BYTE(_buf, _off) (_buf[_off]) -#define DECODE_INT(_buf, _off) *((int*)(_buf+(_off))) -#define DECODE_STRING(_buf, _off) (char*)(_buf+(_off)) -#define DECODE_BLOB(_buf, _off) (void*)(_buf+(_off)) +#define UNPACK_BYTE(_buf, _off) (_buf[_off]) +#define UNPACK_INT(_buf, _off) *((int*)(_buf+(_off))) +#define UNPACK_STRING(_buf, _off) (char*)(_buf+(_off)) +#define UNPACK_BLOB(_buf, _off) (void*)(_buf+(_off)) #define RETURN_BH(bh, outbuf) *outbuf = (char*)bh.bin; return bh.bin->orig_size; @@ -212,9 +212,9 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, { // Extract the type code and filename from the inbuf // Inbuf is: <> - unsigned flags = (unsigned) DECODE_INT(inbuf, 0); - DBTYPE type = (DBTYPE) DECODE_BYTE(inbuf, 4); - char* name = DECODE_STRING(inbuf, 5); + unsigned flags = (unsigned) UNPACK_INT(inbuf, 0); + DBTYPE type = (DBTYPE) UNPACK_BYTE(inbuf, 4); + char* name = UNPACK_STRING(inbuf, 5); int dbref; int status; int rc = open_database(name, type, flags, d, &dbref); @@ -242,8 +242,8 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, // Take the provided dbref and attempt to close it // Inbuf is: <> - int dbref = DECODE_INT(inbuf, 0); - unsigned flags = (unsigned) DECODE_INT(inbuf, 4); + int dbref = UNPACK_INT(inbuf, 0); + unsigned flags = (unsigned) UNPACK_INT(inbuf, 4); int rc = close_database(dbref, flags, d); @@ -307,7 +307,7 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, } // Inbuf is: << DbRef:32, Rest/binary>> - int dbref = DECODE_INT(inbuf, 0); + int dbref = UNPACK_INT(inbuf, 0); // Make sure this port currently has dbref open -- if it doesn't, error out. Of note, // if it's in our list, we don't need to grab the RWLOCK, as we don't have to worry about @@ -589,7 +589,7 @@ static void do_async_put(void* arg) // Payload is: <> AsyncData* adata = (AsyncData*)arg; - unsigned flags = DECODE_INT(adata->payload, 4); + unsigned flags = UNPACK_INT(adata->payload, 4); // Setup DBTs DBT key; @@ -598,10 +598,10 @@ static void do_async_put(void* arg) memset(&value, '\0', sizeof(DBT)); // Parse payload into DBTs - key.size = DECODE_INT(adata->payload, 8); - key.data = DECODE_BLOB(adata->payload, 12); - value.size = DECODE_INT(adata->payload, 12 + key.size); - value.data = DECODE_BLOB(adata->payload, 12 + key.size + 4); + key.size = UNPACK_INT(adata->payload, 8); + key.data = UNPACK_BLOB(adata->payload, 12); + value.size = UNPACK_INT(adata->payload, 12 + key.size); + value.data = UNPACK_BLOB(adata->payload, 12 + key.size + 4); // Execute the actual put -- we'll process the result back in the driver_async_ready function // All databases are opened with AUTO_COMMIT, so if msg->port->txn is NULL, the put will still From dfc1a98b01fb67f7b29b82147278aee5367ed6da Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 16:48:25 -0600 Subject: [PATCH 08/12] Ignore TextMate project files. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index bce3275..175fca5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ *.o *.so *.beam +*.tmproj c_src/system test/logs From 13d1174bb56138b4fc7bbf7c47162fecdd66c1d3 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 16:49:17 -0600 Subject: [PATCH 09/12] Added all of the operation codes and flag values from db.h. --- src/bdberl_port.erl | 222 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 209 insertions(+), 13 deletions(-) diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index 24db0e8..a11ec28 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -26,20 +26,216 @@ -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). +%% DB API flags +-define(DB_AGGRESSIVE, 16#00000001). +-define(DB_ARCH_ABS, 16#00000001). +-define(DB_ARCH_DATA, 16#00000002). +-define(DB_ARCH_LOG, 16#00000004). +-define(DB_ARCH_REMOVE, 16#00000008). +-define(DB_AUTO_COMMIT, 16#00000100). +-define(DB_CDB_ALLDB, 16#00000004). +-define(DB_CHKSUM, 16#00000004). +-define(DB_CKP_INTERNAL, 16#00000002). +-define(DB_CREATE, 16#00000001). +-define(DB_CXX_NO_EXCEPTIONS, 16#00000002). +-define(DB_DIRECT, 16#00000002). +-define(DB_DIRECT_DB, 16#00000040). +-define(DB_DSYNC_DB, 16#00000080). +-define(DB_DUP, 16#00000008). +-define(DB_DUPSORT, 16#00000002). +-define(DB_DURABLE_UNKNOWN, 16#00000020). +-define(DB_ENCRYPT, 16#00000001). +-define(DB_ENCRYPT_AES, 16#00000001). +-define(DB_EXCL, 16#00000400). +-define(DB_EXTENT, 16#00000004). +-define(DB_FAST_STAT, 16#00000001). +-define(DB_FCNTL_LOCKING, 16#00001000). +-define(DB_FLUSH, 16#00000001). +-define(DB_FORCE, 16#00000001). +-define(DB_FOREIGN_ABORT, 16#00000001). +-define(DB_FOREIGN_CASCADE, 16#00000002). +-define(DB_FOREIGN_NULLIFY, 16#00000004). +-define(DB_FREELIST_ONLY, 16#00000001). +-define(DB_FREE_SPACE, 16#00000002). +-define(DB_IGNORE_LEASE, 16#00001000). +-define(DB_IMMUTABLE_KEY, 16#00000002). +-define(DB_INIT_CDB, 16#00000020). +-define(DB_INIT_LOCK, 16#00000040). +-define(DB_INIT_LOG, 16#00000080). +-define(DB_INIT_MPOOL, 16#00000100). +-define(DB_INIT_REP, 16#00000200). +-define(DB_INIT_TXN, 16#00000400). +-define(DB_INORDER, 16#00000010). +-define(DB_JOIN_NOSORT, 16#00000001). +-define(DB_LOCKDOWN, 16#00000800). +-define(DB_LOCK_NOWAIT, 16#00000001). +-define(DB_LOCK_RECORD, 16#00000002). +-define(DB_LOCK_SET_TIMEOUT, 16#00000004). +-define(DB_LOCK_SWITCH, 16#00000008). +-define(DB_LOCK_UPGRADE, 16#00000010). +-define(DB_LOG_AUTO_REMOVE, 16#00000004). +-define(DB_LOG_CHKPNT, 16#00000002). +-define(DB_LOG_COMMIT, 16#00000004). +-define(DB_LOG_DIRECT, 16#00000001). +-define(DB_LOG_DSYNC, 16#00000002). +-define(DB_LOG_IN_MEMORY, 16#00000008). +-define(DB_LOG_NOCOPY, 16#00000008). +-define(DB_LOG_NOT_DURABLE, 16#00000010). +-define(DB_LOG_WRNOSYNC, 16#00000020). +-define(DB_LOG_ZERO, 16#00000010). +-define(DB_MPOOL_CREATE, 16#00000001). +-define(DB_MPOOL_DIRTY, 16#00000002). +-define(DB_MPOOL_DISCARD, 16#00000001). +-define(DB_MPOOL_EDIT, 16#00000004). +-define(DB_MPOOL_FREE, 16#00000008). +-define(DB_MPOOL_LAST, 16#00000010). +-define(DB_MPOOL_NEW, 16#00000020). +-define(DB_MPOOL_NOFILE, 16#00000001). +-define(DB_MPOOL_NOLOCK, 16#00000002). +-define(DB_MPOOL_UNLINK, 16#00000002). +-define(DB_MULTIPLE, 16#00002000). +-define(DB_MULTIPLE_KEY, 16#00000100). +-define(DB_MULTIVERSION, 16#00000008). +-define(DB_MUTEX_ALLOCATED, 16#00000001). +-define(DB_MUTEX_LOCKED, 16#00000002). +-define(DB_MUTEX_LOGICAL_LOCK, 16#00000004). +-define(DB_MUTEX_PROCESS_ONLY, 16#00000008). +-define(DB_MUTEX_SELF_BLOCK, 16#00000010). +-define(DB_NOLOCKING, 16#00000200). +-define(DB_NOMMAP, 16#00000010). +-define(DB_NOORDERCHK, 16#00000002). +-define(DB_NOPANIC, 16#00000400). +-define(DB_NO_AUTO_COMMIT, 16#00002000). +-define(DB_ODDFILESIZE, 16#00000040). +-define(DB_ORDERCHKONLY, 16#00000004). +-define(DB_OVERWRITE, 16#00001000). +-define(DB_PANIC_ENVIRONMENT, 16#00002000). +-define(DB_PRINTABLE, 16#00000008). +-define(DB_PRIVATE, 16#00001000). +-define(DB_PR_PAGE, 16#00000010). +-define(DB_PR_RECOVERYTEST, 16#00000020). +-define(DB_RDONLY, 16#00000080). +-define(DB_RDWRMASTER, 16#00004000). +-define(DB_READ_COMMITTED, 16#00000400). +-define(DB_READ_UNCOMMITTED, 16#00000200). +-define(DB_RECNUM, 16#00000020). +-define(DB_RECOVER, 16#00000010). +-define(DB_RECOVER_FATAL, 16#00002000). +-define(DB_REGION_INIT, 16#00004000). +-define(DB_REGISTER, 16#00004000). +-define(DB_RENUMBER, 16#00000040). +-define(DB_REPMGR_CONF_2SITE_STRICT, 16#00000001). +-define(DB_REPMGR_PEER, 16#00000001). +-define(DB_REP_ANYWHERE, 16#00000001). +-define(DB_REP_CLIENT, 16#00000001). +-define(DB_REP_CONF_BULK, 16#00000002). +-define(DB_REP_CONF_DELAYCLIENT, 16#00000004). +-define(DB_REP_CONF_LEASE, 16#00000008). +-define(DB_REP_CONF_NOAUTOINIT, 16#00000010). +-define(DB_REP_CONF_NOWAIT, 16#00000020). +-define(DB_REP_ELECTION, 16#00000004). +-define(DB_REP_MASTER, 16#00000002). +-define(DB_REP_NOBUFFER, 16#00000002). +-define(DB_REP_PERMANENT, 16#00000004). +-define(DB_REP_REREQUEST, 16#00000008). +-define(DB_REVSPLITOFF, 16#00000080). +-define(DB_RMW, 16#00000800). +-define(DB_RPCCLIENT, 16#00000001). +-define(DB_SALVAGE, 16#00000040). +-define(DB_SA_SKIPFIRSTKEY, 16#00010000). +-define(DB_SEQ_DEC, 16#00000001). +-define(DB_SEQ_INC, 16#00000002). +-define(DB_SEQ_RANGE_SET, 16#00000004). +-define(DB_SEQ_WRAP, 16#00000008). +-define(DB_SEQ_WRAPPED, 16#00000010). +-define(DB_SET_LOCK_TIMEOUT, 16#00000002). +-define(DB_SET_TXN_NOW, 16#00000004). +-define(DB_SET_TXN_TIMEOUT, 16#00000001). +-define(DB_SNAPSHOT, 16#00000100). +-define(DB_STAT_ALL, 16#00000002). +-define(DB_STAT_CLEAR, 16#00000001). +-define(DB_STAT_LOCK_CONF, 16#00000004). +-define(DB_STAT_LOCK_LOCKERS, 16#00000008). +-define(DB_STAT_LOCK_OBJECTS, 16#00000010). +-define(DB_STAT_LOCK_PARAMS, 16#00000020). +-define(DB_STAT_MEMP_HASH, 16#00000004). +-define(DB_STAT_MEMP_NOERROR, 16#00000008). +-define(DB_STAT_SUBSYSTEM, 16#00000004). +-define(DB_ST_DUPOK, 16#00000100). +-define(DB_ST_DUPSET, 16#00000200). +-define(DB_ST_DUPSORT, 16#00000400). +-define(DB_ST_IS_RECNO, 16#00000800). +-define(DB_ST_OVFL_LEAF, 16#00001000). +-define(DB_ST_RECNUM, 16#00002000). +-define(DB_ST_RELEN, 16#00004000). +-define(DB_ST_TOPLEVEL, 16#00008000). +-define(DB_SYSTEM_MEM, 16#00008000). +-define(DB_THREAD, 16#00000004). +-define(DB_TIME_NOTGRANTED, 16#00008000). +-define(DB_TRUNCATE, 16#00008000). +-define(DB_TXN_NOSYNC, 16#00000001). +-define(DB_TXN_NOT_DURABLE, 16#00000200). +-define(DB_TXN_NOWAIT, 16#00000002). +-define(DB_TXN_SNAPSHOT, 16#00000800). +-define(DB_TXN_SYNC, 16#00000004). +-define(DB_TXN_WAIT, 16#00000008). +-define(DB_TXN_WRITE_NOSYNC, 16#00000020). +-define(DB_UNREF, 16#00000080). +-define(DB_UPGRADE, 16#00000001). +-define(DB_USE_ENVIRON, 16#00000002). +-define(DB_USE_ENVIRON_ROOT, 16#00000008). +-define(DB_VERB_DEADLOCK, 16#00000001). +-define(DB_VERB_FILEOPS, 16#00000002). +-define(DB_VERB_FILEOPS_ALL, 16#00000004). +-define(DB_VERB_RECOVERY, 16#00000008). +-define(DB_VERB_REGISTER, 16#00000010). +-define(DB_VERB_REPLICATION, 16#00000020). +-define(DB_VERB_REPMGR_CONNFAIL, 16#00000040). +-define(DB_VERB_REPMGR_MISC, 16#00000080). +-define(DB_VERB_REP_ELECT, 16#00000100). +-define(DB_VERB_REP_LEASE, 16#00000200). +-define(DB_VERB_REP_MISC, 16#00000400). +-define(DB_VERB_REP_MSGS, 16#00000800). +-define(DB_VERB_REP_SYNC, 16#00001000). +-define(DB_VERB_WAITSFOR, 16#00002000). +-define(DB_VERIFY, 16#00000002). +-define(DB_WRITEOPEN, 16#00010000). +-define(DB_XA_CREATE, 16#00000800). +-define(DB_YIELDCPU, 16#00010000). --define(DB_APPEND, 2). --define(DB_NODUPDATA, 19). --define(DB_NOOVERWRITE, 20). --define(DB_NOSYNC, 21). +%% DB access method and cursor operation values. Each value is an operation +%% code to which additional bit flags are added. +-define(DB_AFTER, 1). +-define(DB_APPEND, 2). +-define(DB_BEFORE, 3). +-define(DB_CONSUME, 4). +-define(DB_CONSUME_WAIT, 5). +-define(DB_CURRENT, 6). +-define(DB_FIRST, 7). +-define(DB_GET_BOTH, 8). +-define(DB_GET_BOTHC, 9). +-define(DB_GET_BOTH_RANGE, 10). +-define(DB_GET_RECNO, 11). +-define(DB_JOIN_ITEM, 12). +-define(DB_KEYFIRST, 13). +-define(DB_KEYLAST, 14). +-define(DB_LAST, 15). +-define(DB_NEXT, 16). +-define(DB_NEXT_DUP, 17). +-define(DB_NEXT_NODUP, 18). +-define(DB_NODUPDATA, 19). +-define(DB_NOOVERWRITE, 20). +-define(DB_NOSYNC, 21). +-define(DB_POSITION, 22). +-define(DB_PREV, 23). +-define(DB_PREV_DUP, 24). +-define(DB_PREV_NODUP, 25). +-define(DB_SET, 26). +-define(DB_SET_RANGE, 27). +-define(DB_SET_RECNO, 28). +-define(DB_UPDATE_SECONDARY, 29). +-define(DB_WRITECURSOR, 30). +-define(DB_WRITELOCK, 31). -define(STATUS_OK, 0). -define(STATUS_ERROR, 1). From 332e18e7be2f9357ecf71b47a031c63d65b123f4 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 16:57:35 -0600 Subject: [PATCH 10/12] Added flags to get function. --- c_src/bdberl_drv.c | 12 +++++++----- src/bdberl_port.erl | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index 81dcaa9..ee95c8b 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -618,7 +618,10 @@ static void do_async_put_free(void* arg) static void do_async_get(void* arg) { printf("do_async_get\n"); + + // Payload is: << DbRef:32, Flags:32, KeyLen:32, Key:KeyLen >> AsyncData* adata = (AsyncData*)arg; + unsigned flags = UNPACK_INT(adata->payload, 4); // Setup DBTs DBT key; @@ -627,9 +630,8 @@ static void do_async_get(void* arg) memset(&value, '\0', sizeof(DBT)); // Parse payload into DBT - // Payload is: << DbRef:32, KeyLen:32, Key:KeyLen >> - key.size = *((int*)(adata->payload + 4)); - key.data = (void*)(adata->payload + 8); + key.size = UNPACK_INT(adata->payload, 8); + key.data = UNPACK_BLOB(adata->payload, 12); // Allocate memory to hold the value -- hard code initial size to 4k // TODO: Make this smarter! @@ -637,13 +639,13 @@ static void do_async_get(void* arg) value.ulen = 4096; value.flags = DB_DBT_USERMEM; - int rc = adata->db->get(adata->db, adata->port->txn, &key, &value, 0); + int rc = adata->db->get(adata->db, adata->port->txn, &key, &value, flags); while (rc == DB_BUFFER_SMALL) { // Grow our value buffer and try again value.data = driver_realloc(value.data, value.size); value.ulen = value.size; - rc = adata->db->get(adata->db, adata->port->txn, &key, &value, 0); + rc = adata->db->get(adata->db, adata->port->txn, &key, &value, flags); } adata->payload = value.data; diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index a11ec28..2e02eda 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -337,10 +337,13 @@ put(Port, DbRef, Key, Value, Opts) -> ?ERROR_INVALID_DBREF -> {error, invalid_dbref} end. - get(Port, DbRef, Key) -> + get(Port, DbRef, Key, []). + +get(Port, DbRef, Key, Opts) -> {KeyLen, KeyBin} = to_binary(Key), - Cmd = <>, + Flags = process_flags(Opts), + Cmd = <>, <> = erlang:port_control(Port, ?CMD_GET, Cmd), case Result of ?ERROR_NONE -> @@ -365,16 +368,25 @@ process_flags([Flag|Flags]) -> flag_value(Flag) -> case Flag of - append -> ?DB_APPEND; - auto_commit -> ?DB_AUTO_COMMIT; - create -> ?DB_CREATE; - exclusive -> ?DB_EXCL; - multiversion -> ?DB_MULTIVERSION; - no_duplicate -> ?DB_NODUPDATA; - no_mmap -> ?DB_NOMMAP; - no_overwrite -> ?DB_NOOVERWRITE; - no_sync -> ?DB_NOSYNC; - readonly -> ?DB_RDONLY; - threaded -> ?DB_THREAD; - truncate -> ?DB_TRUNCATE + append -> ?DB_APPEND; + auto_commit -> ?DB_AUTO_COMMIT; + consume -> ?DB_CONSUME; + consume_wait -> ?DB_CONSUME_WAIT; + create -> ?DB_CREATE; + exclusive -> ?DB_EXCL; + get_both -> ?DB_GET_BOTH; + ignore_lease -> ?DB_IGNORE_LEASE; + multiple -> ?DB_MULTIPLE; + multiversion -> ?DB_MULTIVERSION; + no_duplicate -> ?DB_NODUPDATA; + no_mmap -> ?DB_NOMMAP; + no_overwrite -> ?DB_NOOVERWRITE; + no_sync -> ?DB_NOSYNC; + read_committed -> ?DB_READ_COMMITTED; + read_uncommitted -> ?DB_READ_UNCOMMITTED; + readonly -> ?DB_RDONLY; + rmw -> ?DB_RMW; + set_recno -> ?DB_SET_RECNO; + threaded -> ?DB_THREAD; + truncate -> ?DB_TRUNCATE end. From f743d855d8470cced43eeea49c0963a86b2f5131 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 17:05:08 -0600 Subject: [PATCH 11/12] Added flags for txn_begin function. --- c_src/bdberl_drv.c | 7 +++++-- src/bdberl_port.erl | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index ee95c8b..1e40888 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -212,7 +212,7 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, { // Extract the type code and filename from the inbuf // Inbuf is: <> - unsigned flags = (unsigned) UNPACK_INT(inbuf, 0); + unsigned flags = UNPACK_INT(inbuf, 0); DBTYPE type = (DBTYPE) UNPACK_BYTE(inbuf, 4); char* name = UNPACK_STRING(inbuf, 5); int dbref; @@ -264,8 +264,11 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, RETURN_INT(ERROR_TXN_OPEN, outbuf); } + // Inbuf is <> + unsigned flags = UNPACK_INT(inbuf, 0); + // Outbuf is <> - int rc = G_DB_ENV->txn_begin(G_DB_ENV, 0, &(d->txn), 0); + int rc = G_DB_ENV->txn_begin(G_DB_ENV, 0, &(d->txn), flags); RETURN_INT(rc, outbuf); } case CMD_TXN_COMMIT: diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index 2e02eda..8ff421a 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -287,7 +287,12 @@ close_database(Port, DbRef, Opts) -> end. txn_begin(Port) -> - <> = erlang:port_control(Port, ?CMD_TXN_BEGIN, <<>>), + txn_begin(Port, []). + +txn_begin(Port, Opts) -> + Flags = process_flags(Opts), + Cmd = <>, + <> = erlang:port_control(Port, ?CMD_TXN_BEGIN, Cmd), case Result of ?ERROR_NONE -> ok; ?ERROR_ASYNC_PENDING -> {error, async_pending}; @@ -388,5 +393,11 @@ flag_value(Flag) -> rmw -> ?DB_RMW; set_recno -> ?DB_SET_RECNO; threaded -> ?DB_THREAD; - truncate -> ?DB_TRUNCATE + truncate -> ?DB_TRUNCATE; + txn_no_sync -> ?DB_TXN_NOSYNC; + txn_no_wait -> ?DB_TXN_NOWAIT; + txn_snapshot -> ?DB_TXN_SNAPSHOT; + txn_sync -> ?DB_TXN_SYNC; + txn_wait -> ?DB_TXN_WAIT; + txn_write_nosync -> ?DB_TXN_WRITE_NOSYNC end. From 71f64d96666d2ceaca2f19613434b5f3c3d54a15 Mon Sep 17 00:00:00 2001 From: Phillip Toland Date: Wed, 10 Dec 2008 17:12:16 -0600 Subject: [PATCH 12/12] Added flags for the txn_commit function. --- c_src/bdberl_drv.c | 8 +++++++- src/bdberl_port.erl | 7 ++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/c_src/bdberl_drv.c b/c_src/bdberl_drv.c index 1e40888..b4d99e9 100644 --- a/c_src/bdberl_drv.c +++ b/c_src/bdberl_drv.c @@ -290,6 +290,11 @@ static int bdberl_drv_control(ErlDrvData handle, unsigned int cmd, AsyncData* adata = zalloc(sizeof(AsyncData)); adata->port = d; + if (cmd == CMD_TXN_COMMIT) + { + adata->payload = (void*) UNPACK_INT(inbuf, 0); + } + // Update port data to indicate we have an operation in progress d->async_op = cmd; @@ -670,7 +675,8 @@ static void do_async_txnop(void* arg) AsyncData* adata = (AsyncData*)arg; if (adata->port->async_op == CMD_TXN_COMMIT) { - adata->rc = adata->port->txn->commit(adata->port->txn, 0); + unsigned flags = (unsigned) adata->payload; + adata->rc = adata->port->txn->commit(adata->port->txn, flags); } else { diff --git a/src/bdberl_port.erl b/src/bdberl_port.erl index 8ff421a..5ecc924 100644 --- a/src/bdberl_port.erl +++ b/src/bdberl_port.erl @@ -300,7 +300,12 @@ txn_begin(Port, Opts) -> end. txn_commit(Port) -> - <> = erlang:port_control(Port, ?CMD_TXN_COMMIT, <<>>), + txn_commit(Port, []). + +txn_commit(Port, Opts) -> + Flags = process_flags(Opts), + Cmd = <>, + <> = erlang:port_control(Port, ?CMD_TXN_COMMIT, Cmd), case Result of ?ERROR_NONE -> receive