#include "db_helper.h" #include #include #include #define UNWRAP_DBENV() \ DB_ENV* dbenv; \ if (*dbenvp == NULL) return -20881; /* Haskell binding-specific error code */ \ dbenv = *dbenvp; #define UNWRAP_DB_TXN_() \ if (dbtxnp == NULL) \ dbtxn = NULL; \ else { \ if (*dbtxnp == NULL) return -20883; /* Haskell binding-specific error code */ \ dbtxn = *dbtxnp; \ } #define UNWRAP_DB_TXN2_() \ if (dbtxnp == NULL) \ dbtxn = NULL; \ else { \ if (dbtxnp[1] == NULL) return -20883; /* Haskell binding-specific error code */ \ dbtxn = dbtxnp[1]; \ } #define UNWRAP_DB() \ DB* db = *dbp; \ if (db == NULL) return -20882; /* Haskell binding-specific error code */ #define UNWRAP_DBCURSOR() \ DBC* dbc = *dbcp; \ if (dbc == NULL) return -20884; /* Haskell binding-specific error code */ #define UNWRAP_DB_TXN() \ DB_TXN* dbtxn; \ UNWRAP_DB_TXN_() #define UNWRAP_DB_TXN2() \ DB_TXN* dbtxn; \ UNWRAP_DB_TXN2_() int _dbenv_create(MY_DBENV** dbenvpp, u_int32_t flags) { int ret; *dbenvpp = (MY_DBENV*)malloc(sizeof(MY_DBENV*)); ret = db_env_create(*dbenvpp, flags); if (ret != 0) free(*dbenvpp); return ret; } int _dbenv_toNative(MY_DBENV* dbenvp, DB_ENV** pDbEnv) { int ret; UNWRAP_DBENV(); *pDbEnv = dbenv; return 0; } int _dbenv_set_data_dir(MY_DBENV* dbenvp, char* dir) { UNWRAP_DBENV(); return dbenv->set_data_dir(dbenv, dir); } int _dbenv_set_lg_dir(MY_DBENV* dbenvp, char* dir) { UNWRAP_DBENV(); return dbenv->set_lg_dir(dbenv, dir); } int _dbenv_get_lk_max_lockers(MY_DBENV* dbenvp, u_int32_t *lk_maxp) { UNWRAP_DBENV(); return dbenv->get_lk_max_lockers(dbenv, lk_maxp); } int _dbenv_set_lk_max_lockers(MY_DBENV* dbenvp, u_int32_t max) { UNWRAP_DBENV(); return dbenv->set_lk_max_lockers(dbenv, max); } int _dbenv_get_lk_max_locks(MY_DBENV* dbenvp, u_int32_t *lk_maxp) { UNWRAP_DBENV(); return dbenv->get_lk_max_locks(dbenv, lk_maxp); } int _dbenv_set_lk_max_locks(MY_DBENV* dbenvp, u_int32_t max) { UNWRAP_DBENV(); return dbenv->set_lk_max_locks(dbenv, max); } int _dbenv_get_lk_max_objects(MY_DBENV* dbenvp, u_int32_t *lk_maxp) { UNWRAP_DBENV(); return dbenv->get_lk_max_objects(dbenv, lk_maxp); } int _dbenv_set_lk_max_objects(MY_DBENV* dbenvp, u_int32_t max) { UNWRAP_DBENV(); return dbenv->set_lk_max_objects(dbenv, max); } int _dbenv_get_tx_max(MY_DBENV* dbenvp, u_int32_t *lk_maxp) { UNWRAP_DBENV(); return dbenv->get_tx_max(dbenv, lk_maxp); } int _dbenv_set_tx_max(MY_DBENV* dbenvp, u_int32_t max) { UNWRAP_DBENV(); return dbenv->set_tx_max(dbenv, max); } int _dbenv_get_cachesize(MY_DBENV* dbenvp, u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep) { UNWRAP_DBENV(); return dbenv->get_cachesize(dbenv, gbytesp, bytesp, ncachep); } int _dbenv_set_cachesize(MY_DBENV* dbenvp, u_int32_t gbytes, u_int32_t bytes, int ncache) { UNWRAP_DBENV(); return dbenv->set_cachesize(dbenv, gbytes, bytes, ncache); } int _dbenv_get_lg_regionmax(MY_DBENV* dbenvp, u_int32_t *lk_maxp) { UNWRAP_DBENV(); return dbenv->get_lg_regionmax(dbenv, lk_maxp); } int _dbenv_set_lg_regionmax(MY_DBENV* dbenvp, u_int32_t max) { UNWRAP_DBENV(); return dbenv->set_lg_regionmax(dbenv, max); } int _dbenv_set_lk_detect(MY_DBENV* dbenvp, u_int32_t flag) { UNWRAP_DBENV(); return dbenv->set_lk_detect(dbenv, flag); } int _dbenv_set_flags(MY_DBENV* dbenvp, u_int32_t flags, int onoff) { UNWRAP_DBENV(); return dbenv->set_flags(dbenv, flags, onoff); } #if (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 7) || DB_VERSION_MAJOR > 4 int _dbenv_log_set_config(MY_DBENV* dbenvp, u_int32_t flags, int onoff) { UNWRAP_DBENV(); return dbenv->log_set_config(dbenv, flags, onoff); } #endif int _dbenv_open(MY_DBENV* dbenvp, char *db_home, u_int32_t flags, int mode) { UNWRAP_DBENV(); return dbenv->open(dbenv, db_home, flags, mode); } int _dbenv_close(MY_DBENV* dbenvp, u_int32_t flags) { int ret; if (*dbenvp != NULL) { ret = (*dbenvp)->close(*dbenvp,flags); *dbenvp = NULL; } else ret = 0; return ret; } int _db_create(DB*** dbpp, MY_DBENV* dbenvp, u_int32_t flags) { int ret; UNWRAP_DBENV(); *dbpp = (DB**)malloc(sizeof(DB**)); ret = db_create(*dbpp, dbenv, flags); if (ret != 0) free(*dbpp); return ret; } void _db_delete(DB** dbp) { if (*dbp != NULL) (*dbp)->close(*dbp, 0); free(dbp); } int _db_set_pagesize(DB** dbp, u_int32_t pagesize) { UNWRAP_DB(); return db->set_pagesize(db, pagesize); } int _db_open(DB** dbp, DB_TXN** txnp, const char* file, const char* database, int type, u_int32_t flags, int mode) { DB_TXN* txn; UNWRAP_DB(); if (txnp == NULL) txn = NULL; else { if (*txnp == NULL) return -20883; /* Haskell binding-specific error code */ txn = *txnp; } return db->open(db, txn, file, database, (DBTYPE) type, flags, mode); } int _dbenv_txn_begin(MY_DBENV* dbenvp, DB_TXN** parentp, DB_TXN*** txnpp, u_int32_t flags) { int ret; DB_TXN* parent; UNWRAP_DBENV(); if (parentp == NULL) parent = NULL; else { parent = *parentp; if (parent == NULL) return -20883; /* Haskell binding-specific error code */ } *txnpp = (DB_TXN**)malloc(sizeof(DB_TXN*)*2); ret = dbenv->txn_begin(dbenv, parent, *txnpp, flags); /* Store the DB_TXN twice - the first is NULLed when we pass it to be wrapped as a DBXML transaction. We keep the second for operations where we still want to access it after DBXML has taken it over, in particular _dbtxn_id(). */ (*txnpp)[1] = (*txnpp)[0]; return ret; } int _dbenv_txn_checkpoint(MY_DBENV* dbenvp, u_int32_t kbyte, u_int32_t min, u_int32_t flags) { UNWRAP_DBENV(); return dbenv->txn_checkpoint(dbenv, kbyte, min, flags); } int _dbtxn_abort(DB_TXN** dbtxnp) { UNWRAP_DB_TXN(); dbtxnp[0] = NULL; dbtxnp[1] = NULL; return dbtxn->abort(dbtxn); } int _dbtxn_commit(DB_TXN** dbtxnp, u_int32_t flags) { UNWRAP_DB_TXN(); dbtxnp[0] = NULL; dbtxnp[1] = NULL; return dbtxn->commit(dbtxn, flags); } void _dbtxn_delete(DB_TXN** dbtxnp) { if (*dbtxnp != NULL) (*dbtxnp)->abort(*dbtxnp); free(dbtxnp); } int _dbtxn_id(DB_TXN** dbtxnp, u_int32_t* locker) { UNWRAP_DB_TXN2(); *locker = dbtxn->id(dbtxn); return 0; } int _dbenv_lock_get(MY_DBENV* dbenvp, u_int32_t lockerID, u_int32_t flags, const char* object, u_int32_t object_len, u_int32_t lockmode, _DB_LOCK** dblock) { DBT dbt; UNWRAP_DBENV(); memset(&dbt, 0, sizeof(dbt)); dbt.flags = DB_DBT_USERMEM; dbt.data = (void*)object; dbt.size = object_len; *dblock = (_DB_LOCK*)malloc(sizeof(_DB_LOCK)); (*dblock)->dbenv = dbenvp; int ret = dbenv->lock_get(dbenv, lockerID, flags, &dbt, (db_lockmode_t)lockmode, &(*dblock)->lock); if (ret != 0) free(*dblock); return ret; } int _dbenv_lock_put(_DB_LOCK* dblock) { MY_DBENV* dbenvp = dblock->dbenv; UNWRAP_DBENV(); return dbenv->lock_put(dbenv, &dblock->lock); } void _dblock_delete(_DB_LOCK* dblock) { free(dblock); } void _freeString(char* str) { free(str); } int _db_get(DB** dbp, DB_TXN** dbtxnp, const char* key, u_int32_t key_len, char** value, u_int32_t* value_len, u_int32_t flags) { DBT keyDbt; DBT valueDbt; int ret; DB_TXN* dbtxn; UNWRAP_DB(); UNWRAP_DB_TXN2_(); memset(&keyDbt, 0, sizeof(keyDbt)); keyDbt.flags = DB_DBT_USERMEM; keyDbt.data = (void*)key; keyDbt.size = key_len; memset(&valueDbt, 0, sizeof(valueDbt)); valueDbt.flags = DB_DBT_MALLOC; *value = NULL; *value_len = 0; ret = db->get(db, dbtxn, &keyDbt, &valueDbt, flags); if (ret == 0) { *value = (char*)valueDbt.data; *value_len = valueDbt.size; } return ret; } int _db_put(DB** dbp, DB_TXN** dbtxnp, const char* key, u_int32_t key_len, const char* value, u_int32_t value_len, u_int32_t flags) { DBT keyDbt; DBT valueDbt; DB_TXN* dbtxn; UNWRAP_DB(); UNWRAP_DB_TXN2_(); memset(&keyDbt, 0, sizeof(keyDbt)); keyDbt.flags = DB_DBT_USERMEM; keyDbt.data = (void*)key; keyDbt.size = key_len; memset(&valueDbt, 0, sizeof(valueDbt)); valueDbt.flags = DB_DBT_USERMEM; valueDbt.data = (void*)value; valueDbt.size = value_len; return db->put(db, dbtxn, &keyDbt, &valueDbt, flags); } int _db_del(DB** dbp, DB_TXN** dbtxnp, const char* key, u_int32_t key_len, u_int32_t flags) { DBT keyDbt; DB_TXN* dbtxn; UNWRAP_DB(); UNWRAP_DB_TXN2_(); memset(&keyDbt, 0, sizeof(keyDbt)); keyDbt.flags = DB_DBT_USERMEM; keyDbt.data = (void*)key; keyDbt.size = key_len; return db->del(db, dbtxn, &keyDbt, flags); } int _db_close(DB** dbp, u_int32_t flags) { UNWRAP_DB(); *dbp = NULL; return db->close(db, flags); } int _db_set_flags(DB** dbp, u_int32_t flags) { UNWRAP_DB(); return db->set_flags(db, flags); } int _db_sync(DB** dbp, u_int32_t flags) { UNWRAP_DB(); return db->sync(db, flags); } int _db_cursor(DB** dbp, DB_TXN** dbtxnp, DBC*** dbcursorpp, u_int32_t flags) { DB_TXN* dbtxn; UNWRAP_DB(); UNWRAP_DB_TXN2_(); *dbcursorpp = (DBC**)malloc(sizeof(DBC**)); int ret = db->cursor(db, dbtxn, *dbcursorpp, flags); if (ret != 0) free(*dbcursorpp); return ret; } void _dbcursor_delete(DBC** dbc) { if (*dbc != NULL) (*dbc)->close(*dbc); free(dbc); } int _dbCursor_close(DBC** dbc) { if (*dbc != NULL) { int ret = (*dbc)->close(*dbc); *dbc = NULL; return ret; } else return 0; } int _dbCursor_count(DBC** dbcp, u_int32_t* countp, u_int32_t flags) { UNWRAP_DBCURSOR(); db_recno_t countp_; int ret = dbc->count(dbc, &countp_, flags); *countp = (u_int32_t) countp_; return ret; } int _dbCursor_del(DBC** dbcp, u_int32_t flags) { UNWRAP_DBCURSOR(); return dbc->del(dbc, flags); } int _dbCursor_dup(DBC** dbcp, DBC*** dbcursorpp, u_int32_t flags) { UNWRAP_DBCURSOR(); *dbcursorpp = (DBC**)malloc(sizeof(DBC**)); int ret = dbc->dup(dbc, *dbcursorpp, flags); if (ret != 0) free(*dbcursorpp); return ret; } int _dbCursor_get(DBC** dbcp, char** key, u_int32_t* key_len, char** value, u_int32_t* value_len, u_int32_t flags) { UNWRAP_DBCURSOR(); int ret; DBT keyDbt; memset(&keyDbt, 0, sizeof(keyDbt)); keyDbt.flags = DB_DBT_MALLOC; *key = NULL; *key_len = 0; DBT valueDbt; memset(&valueDbt, 0, sizeof(valueDbt)); valueDbt.flags = DB_DBT_MALLOC; *value = NULL; *value_len = 0; ret = dbc->get(dbc, &keyDbt, &valueDbt, flags); if (ret == 0) { *key = (char*)keyDbt.data; *key_len = keyDbt.size; *value = (char*)valueDbt.data; *value_len = valueDbt.size; } return ret; } int _dbCursor_set(DBC** dbcp, const char* key, u_int32_t key_len, char** okey, u_int32_t* okey_len, char** value, u_int32_t* value_len, u_int32_t flags) { UNWRAP_DBCURSOR(); int ret; DBT keyDbt; memset(&keyDbt, 0, sizeof(keyDbt)); keyDbt.flags = okey ? DB_DBT_MALLOC : DB_DBT_USERMEM; keyDbt.data = (void*)key; keyDbt.size = key_len; DBT valueDbt; memset(&valueDbt, 0, sizeof(valueDbt)); valueDbt.flags = DB_DBT_MALLOC; *value = NULL; *value_len = 0; ret = dbc->get(dbc, &keyDbt, &valueDbt, flags); if (ret == 0) { if (okey) { *okey = (char*)keyDbt.data; *okey_len = keyDbt.size; } *value = (char*)valueDbt.data; *value_len = valueDbt.size; } return ret; } int _dbCursor_put(DBC** dbcp, const char* key, u_int32_t key_len, const char* value, u_int32_t value_len, u_int32_t flags) { UNWRAP_DBCURSOR(); DBT keyDbt; memset(&keyDbt, 0, sizeof(keyDbt)); keyDbt.flags = DB_DBT_USERMEM; keyDbt.data = (void*)key; keyDbt.size = key_len; DBT valueDbt; memset(&valueDbt, 0, sizeof(valueDbt)); valueDbt.flags = DB_DBT_USERMEM; valueDbt.data = (void*)value; valueDbt.size = value_len; return dbc->put(dbc, &keyDbt, &valueDbt, flags); }