diff --git a/c/bdb.c b/c/bdb.c index 8115b37..53ae3c1 100644 --- a/c/bdb.c +++ b/c/bdb.c @@ -1,5 +1,8 @@ #include "bdb.h" +static s48_value scheme_DB_VERSION = S48_FALSE; +static s48_value scheme_DB_VERSION_VERBOSE = S48_FALSE; + /* initialise flag constants */ static s48_value scheme_DB_RPCCLIENT = S48_FALSE; static s48_value scheme_DB_INIT_LOCK = S48_FALSE; @@ -51,7 +54,6 @@ static s48_value scheme_DB_MULTIPLE_KEY = S48_FALSE; static s48_value scheme_DB_TXN_NOSYNC = S48_FALSE; static s48_value scheme_DB_TXN_NOWAIT = S48_FALSE; static s48_value scheme_DB_TXN_SYNC = S48_FALSE; - static s48_value scheme_DB_DONOTINDEX = S48_FALSE; static s48_value scheme_DB_FILEOPEN = S48_FALSE; static s48_value scheme_DB_KEYEMPTY = S48_FALSE; @@ -76,6 +78,35 @@ static s48_value scheme_DB_REP_UNAVAIL = S48_FALSE; static s48_value scheme_DB_RUNRECOVERY = S48_FALSE; static s48_value scheme_DB_SECONDARY_BAD = S48_FALSE; static s48_value scheme_DB_VERIFY_BAD = S48_FALSE; +static s48_value scheme_DB_LOCK_NOWAIT = S48_FALSE; +static s48_value scheme_DB_ENCRYPT_AES = S48_FALSE; +static s48_value scheme_DB_CDB_ALLDB = S48_FALSE; +static s48_value scheme_DB_DIRECT_DB = S48_FALSE; +static s48_value scheme_DB_DIRECT_LOG = S48_FALSE; +static s48_value scheme_DB_LOG_AUTOREMOVE = S48_FALSE; +static s48_value scheme_DB_NOLOCKING = S48_FALSE; +static s48_value scheme_DB_NOPANIC = S48_FALSE; +static s48_value scheme_DB_OVERWRITE = S48_FALSE; +static s48_value scheme_DB_PANIC_ENVIRONMENT = S48_FALSE; +static s48_value scheme_DB_REGION_INIT = S48_FALSE; +static s48_value scheme_DB_TIME_NOTGRANTED = S48_FALSE; +static s48_value scheme_DB_TXN_NOT_DURABLE = S48_FALSE; +static s48_value scheme_DB_TXN_WRITE_NOSYNC = S48_FALSE; +static s48_value scheme_DB_FORCE = S48_FALSE; +static s48_value scheme_DB_CHKSUM = S48_FALSE; +static s48_value scheme_DB_ENCRYPT = S48_FALSE; +static s48_value scheme_DB_DUP = S48_FALSE; +static s48_value scheme_DB_DUPSORT = S48_FALSE; +static s48_value scheme_DB_RECNUM = S48_FALSE; +static s48_value scheme_DB_REVSPLITOFF = S48_FALSE; +static s48_value scheme_DB_RENUMBER = S48_FALSE; +static s48_value scheme_DB_SNAPSHOT = S48_FALSE; +static s48_value scheme_DB_PREV_NODUP = S48_FALSE; +static s48_value scheme_DB_AFTER = S48_FALSE; +static s48_value scheme_DB_BEFORE = S48_FALSE; +static s48_value scheme_DB_KEYFIRST = S48_FALSE; +static s48_value scheme_DB_KEYLAST = S48_FALSE; + /* initialise DB_TYPES */ static s48_value scheme_DB_BTREE = S48_FALSE; @@ -277,6 +308,8 @@ s48_value scsh_bdb_env_lock_get(s48_value senv_handle, s48_value slocker_id, res = dbenv->lock_get(dbenv, locker_id, flags, &object, lock_mode, lock); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer((long) lock) : S48_FALSE); } @@ -438,8 +471,8 @@ s48_value scsh_bdb_env_get_encrypt_flags(s48_value senv_handle) res = dbenv->get_encrypt_flags(dbenv, &flags); if (res > 0) s48_raise_os_error(res); - else - return s48_list_2(s48_enter_integer(res), s48_enter_integer(flags)); + return s48_list_2(s48_enter_integer(res), + s48_enter_integer(flags)); } /* set timeout for locks and transactions */ @@ -477,6 +510,8 @@ s48_value scsh_bdb_env_get_timeout(s48_value senv_handle, s48_value lockp) flags = (lockp == S48_FALSE) ? DB_SET_TXN_TIMEOUT : DB_SET_LOCK_TIMEOUT; S48_GC_UNPROTECT(); res = dbenv->get_timeout(dbenv, &timeout, flags); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer((long) timeout) : S48_FALSE); } @@ -508,6 +543,8 @@ s48_value scsh_bdb_env_get_tx_max(s48_value senv_handle) dbenv = scsh_extract_dbenv(senv_handle); res = dbenv->get_tx_max(dbenv, &max); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer(max) : S48_FALSE); } @@ -538,6 +575,8 @@ s48_value scsh_bdb_env_get_tx_timestamp(s48_value senv_handle) dbenv = scsh_extract_dbenv(senv_handle); res = dbenv->get_tx_timestamp(dbenv, ×tamp); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer(timestamp) : S48_FALSE); } @@ -569,6 +608,8 @@ s48_value scsh_bdb_env_get_tmp_dir(s48_value senv_handle) dbenv = scsh_extract_dbenv(senv_handle); res = dbenv->get_tmp_dir(dbenv, (const char **) &tmpdir); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), ((res == 0) && (tmpdir != NULL)) ? s48_enter_string(tmpdir) : S48_FALSE); @@ -601,6 +642,8 @@ s48_value scsh_bdb_env_get_flags(s48_value senv_handle) dbenv = scsh_extract_dbenv(senv_handle); res = dbenv->get_flags(dbenv, &flags); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer(flags) : S48_FALSE); } @@ -804,6 +847,8 @@ s48_value scsh_bdb_get_encrypt_flags(s48_value sdatabase) db = scsh_extract_db(sdatabase); res = db->get_encrypt_flags(db, &flags); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer(flags) : S48_FALSE); } @@ -833,6 +878,8 @@ s48_value scsh_bdb_get_flags(s48_value sdatabase) db = scsh_extract_db(sdatabase); res = db->get_flags(db, &flags); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer(flags) : S48_FALSE); } @@ -858,6 +905,8 @@ s48_value scsh_bdb_get_lorder(s48_value sdatabase) db = scsh_extract_db(sdatabase); res = db->get_lorder(db, &lorder); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? ((lorder == 4321) ? S48_TRUE : S48_FALSE) : S48_UNSPECIFIC); @@ -888,6 +937,8 @@ s48_value scsh_bdb_get_pagesize(s48_value sdatabase) db = scsh_extract_db(sdatabase); res = db->get_pagesize(db, &pagesize); + if (res > 0) + s48_raise_os_error(res); return s48_list_2(s48_enter_integer(res), (res == 0) ? s48_enter_integer(pagesize) : S48_FALSE); } @@ -944,6 +995,9 @@ s48_value scsh_bdb_get(s48_value handle, s48_value skey, S48_GC_UNPROTECT(); res = dbp->get(dbp, txnid, &key, &data, flags); + if (res > 0) + s48_raise_os_error(res); + switch (res) { case DB_NOTFOUND: case DB_KEYEMPTY: @@ -989,10 +1043,9 @@ s48_value scsh_bdb_create_cursor(s48_value handle, s48_value stxnid, DB_TXN *txnid; u_int32_t flags; s48_value ret = S48_FALSE; - S48_DECLARE_GC_PROTECT(4); + S48_GC_PROTECT_4(handle, stxnid, sflags, ret); - dbp = scsh_extract_db(handle); flags = s48_extract_integer(sflags); txnid = EXTRACT_OPTIONAL_TXNID(stxnid); @@ -1015,7 +1068,7 @@ s48_value scsh_bdb_close_cursor(s48_value scursor) res = cursor->c_close(cursor); CHECK_BDB_RESULT_CODE(res); - return s48_enter_integer(res); + return S48_FALSE; } /* retrieve values from cursor */ @@ -1039,6 +1092,57 @@ s48_value scsh_bdb_cursor_cget(s48_value dbc, s48_value sflags) return scsh_enter_DBT_as_bytevector(data); } +/* return a count of duplicates */ +s48_value scsh_bdb_cursor_count(s48_value scursor) +{ + DBC *dbc; + int res; + db_recno_t countp; + + dbc = scsh_extract_cursor(scursor); + res = dbc->c_count(dbc, &countp, 0); + if (res > 0) + s48_raise_os_error(res); + return s48_list_2(s48_enter_integer(res), + (res == 0) ? s48_enter_integer((long) countp) : S48_FALSE); +} + +/* delete by cursor */ +s48_value scsh_bdb_cursor_del(s48_value scursor) +{ + DBC *dbc; + int res; + + dbc = scsh_extract_cursor(scursor); + res = dbc->c_del(dbc, 0); + CHECK_BDB_RESULT_CODE(res); + return S48_FALSE; +} + +/* store by cursor */ +s48_value scsh_bdb_cursor_put(s48_value scursor, s48_value skey, + s48_value sdata, s48_value sflags) +{ + DBT key, data; + DBC *dbc; + u_int32_t flags; + int res; + S48_DECLARE_GC_PROTECT(4); + + S48_GC_PROTECT_4(scursor, skey, sdata, sflags); + dbc = scsh_extract_cursor(scursor); + flags = s48_extract_integer(sflags); + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + scsh_extract_bytevector_as_DBT(skey, &key); + scsh_extract_bytevector_as_DBT(sdata, &data); + S48_GC_UNPROTECT(); + + res = dbc->c_put(dbc, &key, &data, flags); + CHECK_BDB_RESULT_CODE(res); + return S48_FALSE; +} + s48_value scsh_bdb_txn_begin (s48_value handle, s48_value sparent, s48_value sflags) { @@ -1099,6 +1203,17 @@ s48_value scsh_bdb_txn_commit(s48_value stxnid, s48_value sflags) /* initialize bindings */ void scsh_init_bdb_bindings(void) { + S48_GC_PROTECT_GLOBAL(scheme_DB_VERSION); + scheme_DB_VERSION = s48_list_3(s48_enter_integer(DB_VERSION_MAJOR), + s48_enter_integer(DB_VERSION_MINOR), + s48_enter_integer(DB_VERSION_PATCH)); + s48_define_exported_binding("scheme_DB_VERSION", scheme_DB_VERSION); + + S48_GC_PROTECT_GLOBAL(scheme_DB_VERSION_VERBOSE); + scheme_DB_VERSION_VERBOSE = s48_enter_string(DB_VERSION_STRING); + s48_define_exported_binding("scheme_DB_VERSION_VERBOSE", + scheme_DB_VERSION_VERBOSE); + /* records */ S48_GC_PROTECT_GLOBAL(bdb_db_record_type); bdb_db_record_type = s48_get_imported_binding("bdb-db"); @@ -1174,6 +1289,34 @@ void scsh_init_bdb_bindings(void) ENTER_INTEGER_CONSTANT(scheme_DB_QUEUE, DB_QUEUE); ENTER_INTEGER_CONSTANT(scheme_DB_RECNO, DB_RECNO); ENTER_INTEGER_CONSTANT(scheme_DB_UNKNOWN, DB_UNKNOWN); + ENTER_INTEGER_CONSTANT(scheme_DB_LOCK_NOWAIT, DB_LOCK_NOWAIT); + ENTER_INTEGER_CONSTANT(scheme_DB_ENCRYPT_AES, DB_ENCRYPT_AES); + ENTER_INTEGER_CONSTANT(scheme_DB_CDB_ALLDB, DB_CDB_ALLDB); + ENTER_INTEGER_CONSTANT(scheme_DB_DIRECT_DB, DB_DIRECT_DB); + ENTER_INTEGER_CONSTANT(scheme_DB_DIRECT_LOG, DB_DIRECT_LOG); + ENTER_INTEGER_CONSTANT(scheme_DB_LOG_AUTOREMOVE, DB_LOG_AUTOREMOVE); + ENTER_INTEGER_CONSTANT(scheme_DB_NOLOCKING, DB_NOLOCKING); + ENTER_INTEGER_CONSTANT(scheme_DB_NOPANIC, DB_NOPANIC); + ENTER_INTEGER_CONSTANT(scheme_DB_OVERWRITE, DB_OVERWRITE); + ENTER_INTEGER_CONSTANT(scheme_DB_PANIC_ENVIRONMENT, DB_PANIC_ENVIRONMENT); + ENTER_INTEGER_CONSTANT(scheme_DB_REGION_INIT, DB_REGION_INIT); + ENTER_INTEGER_CONSTANT(scheme_DB_TIME_NOTGRANTED, DB_TIME_NOTGRANTED); + ENTER_INTEGER_CONSTANT(scheme_DB_TXN_NOT_DURABLE, DB_TXN_NOT_DURABLE); + ENTER_INTEGER_CONSTANT(scheme_DB_TXN_WRITE_NOSYNC, DB_TXN_WRITE_NOSYNC); + ENTER_INTEGER_CONSTANT(scheme_DB_FORCE, DB_FORCE); + ENTER_INTEGER_CONSTANT(scheme_DB_CHKSUM, DB_CHKSUM); + ENTER_INTEGER_CONSTANT(scheme_DB_ENCRYPT, DB_ENCRYPT); + ENTER_INTEGER_CONSTANT(scheme_DB_DUP, DB_DUP); + ENTER_INTEGER_CONSTANT(scheme_DB_DUPSORT, DB_DUPSORT); + ENTER_INTEGER_CONSTANT(scheme_DB_RECNUM, DB_RECNUM); + ENTER_INTEGER_CONSTANT(scheme_DB_REVSPLITOFF, DB_REVSPLITOFF); + ENTER_INTEGER_CONSTANT(scheme_DB_RENUMBER, DB_RENUMBER); + ENTER_INTEGER_CONSTANT(scheme_DB_SNAPSHOT, DB_SNAPSHOT); + ENTER_INTEGER_CONSTANT(scheme_DB_PREV_NODUP, DB_PREV_NODUP); + ENTER_INTEGER_CONSTANT(scheme_DB_AFTER, DB_AFTER); + ENTER_INTEGER_CONSTANT(scheme_DB_BEFORE, DB_BEFORE); + ENTER_INTEGER_CONSTANT(scheme_DB_KEYFIRST, DB_KEYFIRST); + ENTER_INTEGER_CONSTANT(scheme_DB_KEYLAST, DB_KEYLAST); /* return codes */ ENTER_INTEGER_CONSTANT(scheme_DB_DONOTINDEX, DB_DONOTINDEX); @@ -1243,6 +1386,9 @@ void scsh_init_bdb_bindings(void) S48_EXPORT_FUNCTION(scsh_bdb_create_cursor); S48_EXPORT_FUNCTION(scsh_bdb_close_cursor); S48_EXPORT_FUNCTION(scsh_bdb_cursor_cget); + S48_EXPORT_FUNCTION(scsh_bdb_cursor_count); + S48_EXPORT_FUNCTION(scsh_bdb_cursor_del); + S48_EXPORT_FUNCTION(scsh_bdb_cursor_put); S48_EXPORT_FUNCTION(scsh_bdb_txn_begin); S48_EXPORT_FUNCTION(scsh_bdb_txn_abort); S48_EXPORT_FUNCTION(scsh_bdb_txn_commit);