#include "citserver.h"
#include "config.h"
-void (*cdb_compact)(void) = NULL;
-void (*cdb_checkpoint)(void) = NULL;
-void (*cdb_rewind)(int) = NULL;
-struct cdbdata * (*cdb_fetch)(int, const void *, int) = NULL;
+void (*cdb_open_databases)(void) = NULL;
+void (*cdb_close_databases)(void) = NULL;
+int (*cdb_store)(int, const void *, int, void *, int) = NULL;
+int (*cdb_delete)(int, void *, int) = NULL;
+void (*cdb_free)(struct cdbdata *) = NULL;
+struct cdbdata * (*cdb_next_item)(int) = NULL;
+void (*cdb_close_cursor)(int) = NULL;
+void (*cdb_begin_transaction)(void) = NULL;
+void (*cdb_end_transaction)(void) = NULL;
+void (*cdb_check_handles)(void) = NULL;
+void (*cdb_trunc)(int) = NULL;
+void (*cdb_chmod_data)(void) = NULL;
+void (*check_handles)(void *) = NULL;
+void (*cdb_compact)(void) = NULL;
+void (*cdb_checkpoint)(void) = NULL;
+void (*cdb_rewind)(int) = NULL;
+struct cdbdata * (*cdb_fetch)(int, const void *, int) = NULL;
static DB *dbp[MAXCDB]; // One DB handle for each Citadel database
static DB_ENV *dbenv; // The DB environment (global)
-void cdb_abort(void) {
+void bdb_abort(void) {
syslog(LOG_DEBUG, "bdb: citserver is stopping in order to prevent data loss. uid=%d gid=%d euid=%d egid=%d",
getuid(), getgid(), geteuid(), getegid()
);
// Verbose logging callback
-void cdb_verbose_log(const DB_ENV *dbenv, const char *msg, const char *foo) {
+void bdb_verbose_log(const DB_ENV *dbenv, const char *msg, const char *foo) {
if (!IsEmptyStr(msg)) {
syslog(LOG_DEBUG, "bdb: %s %s", msg, foo);
}
// Verbose logging callback
-void cdb_verbose_err(const DB_ENV *dbenv, const char *errpfx, const char *msg) {
+void bdb_verbose_err(const DB_ENV *dbenv, const char *errpfx, const char *msg) {
syslog(LOG_ERR, "bdb: %s", msg);
}
if (ret) {
syslog(LOG_ERR, "bdb: txn_abort: %s", db_strerror(ret));
- cdb_abort();
+ bdb_abort();
}
}
if (ret) {
syslog(LOG_ERR, "bdb: txn_commit: %s", db_strerror(ret));
- cdb_abort();
+ bdb_abort();
}
}
if (ret) {
syslog(LOG_ERR, "bdb: txn_begin: %s", db_strerror(ret));
- cdb_abort();
+ bdb_abort();
}
}
// panic callback
static void dbpanic(DB_ENV *env, int errval) {
syslog(LOG_ERR, "bdb: PANIC: %s", db_strerror(errval));
- cdb_abort();
+ bdb_abort();
}
if ((ret = cursor->c_close(cursor))) {
syslog(LOG_ERR, "bdb: c_close: %s", db_strerror(ret));
- cdb_abort();
+ bdb_abort();
}
}
for (i = 0; i < MAXCDB; i++)
if (cursors[i] != NULL) {
syslog(LOG_ERR, "bdb: cursor still in progress on cdb %02x: %s", i, msg);
- cdb_abort();
+ bdb_abort();
}
}
-void cdb_check_handles(void) {
+void bdb_check_handles(void) {
bailIfCursor(TSD->cursors, "in check_handles");
if (TSD->tid != NULL) {
syslog(LOG_ERR, "bdb: transaction still in progress!");
- cdb_abort();
+ bdb_abort();
}
}
ret = dbenv->txn_checkpoint(dbenv, MAX_CHECKPOINT_KBYTES, MAX_CHECKPOINT_MINUTES, 0);
if (ret != 0) {
- syslog(LOG_ERR, "bdb: cdb_checkpoint() txn_checkpoint: %s", db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_checkpoint() txn_checkpoint: %s", db_strerror(ret));
+ bdb_abort();
}
// After a successful checkpoint, we can cull the unused logs
// does not exist should be created. Note that we don't need a
// critical section here, because there aren't any active threads
// manipulating the database yet.
-void cdb_open_databases(void) {
+void bdb_open_databases(void) {
int ret;
int i;
char dbfilename[32];
u_int32_t flags = 0;
int dbversion_major, dbversion_minor, dbversion_patch;
- syslog(LOG_DEBUG, "bdb: cdb_open_databases() starting");
+ syslog(LOG_DEBUG, "bdb: bdb_open_databases() starting");
syslog(LOG_DEBUG, "bdb: Linked zlib: %s", zlibVersion());
syslog(LOG_DEBUG, "bdb: Compiled libdb: %s", DB_VERSION_STRING);
syslog(LOG_DEBUG, "bdb: Linked libdb: %s", db_version(&dbversion_major, &dbversion_minor, &dbversion_patch));
}
dbenv->set_errpfx(dbenv, "citserver");
dbenv->set_paniccall(dbenv, dbpanic);
- dbenv->set_errcall(dbenv, cdb_verbose_err);
- dbenv->set_msgcall(dbenv, cdb_verbose_log);
+ dbenv->set_errcall(dbenv, bdb_verbose_err);
+ dbenv->set_msgcall(dbenv, bdb_verbose_log);
dbenv->set_verbose(dbenv, DB_VERB_DEADLOCK, 1);
dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
// Make sure we own all the files, because in a few milliseconds we're going to drop root privs.
-void cdb_chmod_data(void) {
+void bdb_chmod_data(void) {
DIR *dp;
struct dirent *d;
char filename[PATH_MAX];
// Close all of the db database files we've opened. This can be done in a loop, since it's just a bunch of closes.
-void cdb_close_databases(void) {
+void bdb_close_databases(void) {
int i;
int ret;
// Decompress a database item if it was compressed on disk
-void cdb_decompress_if_necessary(struct cdbdata *cdb) {
+void bdb_decompress_if_necessary(struct cdbdata *cdb) {
static int magic = COMPRESS_MAGIC;
if ((cdb == NULL) || (cdb->ptr == NULL) || (cdb->len < sizeof(magic)) || (memcmp(cdb->ptr, &magic, sizeof(magic)))) {
if (uncompress((Bytef *) uncompressed_data,
(uLongf *) &destLen, (const Bytef *) compressed_data, (uLong) sourceLen) != Z_OK) {
syslog(LOG_ERR, "bdb: uncompress() error");
- cdb_abort();
+ bdb_abort();
}
free(cdb->ptr);
// Store a piece of data. Returns 0 if the operation was successful. If a
// key already exists it should be overwritten.
-int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) {
+int bdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) {
DBT dkey, ddata;
DB_TXN *tid = NULL;
compressed_data = malloc(buffer_len);
if (compress2((Bytef *) (compressed_data + sizeof(struct CtdlCompressHeader)), &destLen, (Bytef *) cdata, (uLongf) cdatalen, 1) != Z_OK) {
syslog(LOG_ERR, "bdb: compress2() error");
- cdb_abort();
+ bdb_abort();
}
zheader.compressed_len = (size_t) destLen;
memcpy(compressed_data, &zheader, sizeof(struct CtdlCompressHeader));
0 // flags
);
if (ret) {
- syslog(LOG_ERR, "bdb: cdb_store(%d): %s", cdb, db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_store(%d): %s", cdb, db_strerror(ret));
+ bdb_abort();
}
if (compressing) {
free(compressed_data);
goto retry;
}
else {
- syslog(LOG_ERR, "bdb: cdb_store(%d): %s", cdb, db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_store(%d): %s", cdb, db_strerror(ret));
+ bdb_abort();
}
}
else {
// Delete a piece of data. Returns 0 if the operation was successful.
-int cdb_delete(int cdb, void *key, int keylen) {
+int bdb_delete(int cdb, void *key, int keylen) {
DBT dkey;
DB_TXN *tid;
int ret;
if (TSD->tid != NULL) {
ret = dbp[cdb]->del(dbp[cdb], TSD->tid, &dkey, 0);
if (ret) {
- syslog(LOG_ERR, "bdb: cdb_delete(%d): %s", cdb, db_strerror(ret));
+ syslog(LOG_ERR, "bdb: bdb_delete(%d): %s", cdb, db_strerror(ret));
if (ret != DB_NOTFOUND) {
- cdb_abort();
+ bdb_abort();
}
}
}
goto retry;
}
else {
- syslog(LOG_ERR, "bdb: cdb_delete(%d): %s", cdb, db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_delete(%d): %s", cdb, db_strerror(ret));
+ bdb_abort();
}
}
else {
if (ret) {
syslog(LOG_ERR, "bdb: localcursor: %s", db_strerror(ret));
- cdb_abort();
+ bdb_abort();
}
return curs;
// Fetch a piece of data. If not found, returns NULL. Otherwise, it returns
// a struct cdbdata which it is the caller's responsibility to free later on
-// using the cdb_free() routine.
+// using the bdb_free() routine.
struct cdbdata *bdb_fetch(int cdb, const void *key, int keylen) {
if (keylen == 0) { // key length zero is impossible
}
if ((ret != 0) && (ret != DB_NOTFOUND)) {
- syslog(LOG_ERR, "bdb: cdb_fetch(%d): %s", cdb, db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_fetch(%d): %s", cdb, db_strerror(ret));
+ bdb_abort();
}
if (ret != 0) {
tempcdb = (struct cdbdata *) malloc(sizeof(struct cdbdata));
if (tempcdb == NULL) {
- syslog(LOG_ERR, "bdb: cdb_fetch() cannot allocate memory for tempcdb: %m");
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_fetch() cannot allocate memory for tempcdb: %m");
+ bdb_abort();
}
else {
tempcdb->len = dret.size;
tempcdb->ptr = dret.data;
- cdb_decompress_if_necessary(tempcdb);
+ bdb_decompress_if_necessary(tempcdb);
return (tempcdb);
}
}
//
// Note that we only free the 'ptr' portion if it is not NULL. This allows
// other code to assume ownership of that memory simply by storing the
-// pointer elsewhere and then setting 'ptr' to NULL. cdb_free() will then
+// pointer elsewhere and then setting 'ptr' to NULL. bdb_free() will then
// avoid freeing it.
-void cdb_free(struct cdbdata *cdb) {
+void bdb_free(struct cdbdata *cdb) {
if (cdb->ptr) {
free(cdb->ptr);
}
}
-void cdb_close_cursor(int cdb) {
+void bdb_close_cursor(int cdb) {
if (TSD->cursors[cdb] != NULL) {
cclose(TSD->cursors[cdb]);
}
int ret = 0;
if (TSD->cursors[cdb] != NULL) {
- syslog(LOG_ERR, "bdb: cdb_rewind: must close cursor on database %d before reopening", cdb);
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_rewind: must close cursor on database %d before reopening", cdb);
+ bdb_abort();
// cclose(TSD->cursors[cdb]);
}
// Now initialize the cursor
ret = dbp[cdb]->cursor(dbp[cdb], TSD->tid, &TSD->cursors[cdb], 0);
if (ret) {
- syslog(LOG_ERR, "bdb: cdb_rewind: db_cursor: %s", db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_rewind: db_cursor: %s", db_strerror(ret));
+ bdb_abort();
}
}
// Fetch the next item in a sequential search. Returns a pointer to a
// cdbdata structure, or NULL if we've hit the end.
-struct cdbdata *cdb_next_item(int cdb) {
+struct cdbdata *bdb_next_item(int cdb) {
DBT key, data;
struct cdbdata *cdbret;
int ret = 0;
if (ret) {
if (ret != DB_NOTFOUND) {
- syslog(LOG_ERR, "bdb: cdb_next_item(%d): %s", cdb, db_strerror(ret));
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_next_item(%d): %s", cdb, db_strerror(ret));
+ bdb_abort();
}
- cdb_close_cursor(cdb);
+ bdb_close_cursor(cdb);
return NULL; // presumably, end of file
}
cdbret = (struct cdbdata *) malloc(sizeof(struct cdbdata));
cdbret->len = data.size;
cdbret->ptr = data.data;
- cdb_decompress_if_necessary(cdbret);
+ bdb_decompress_if_necessary(cdbret);
return (cdbret);
}
// Transaction-based stuff. I'm writing this as I bake cookies...
-void cdb_begin_transaction(void) {
+void bdb_begin_transaction(void) {
bailIfCursor(TSD->cursors, "can't begin transaction during r/o cursor");
if (TSD->tid != NULL) {
- syslog(LOG_ERR, "bdb: cdb_begin_transaction: ERROR: nested transaction");
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_begin_transaction: ERROR: nested transaction");
+ bdb_abort();
}
txbegin(&TSD->tid);
}
-void cdb_end_transaction(void) {
+void bdb_end_transaction(void) {
int i;
for (i = 0; i < MAXCDB; i++) {
if (TSD->cursors[i] != NULL) {
- syslog(LOG_WARNING, "bdb: cdb_end_transaction: WARNING: cursor %d still open at transaction end", i);
+ syslog(LOG_WARNING, "bdb: bdb_end_transaction: WARNING: cursor %d still open at transaction end", i);
cclose(TSD->cursors[i]);
TSD->cursors[i] = NULL;
}
}
if (TSD->tid == NULL) {
- syslog(LOG_ERR, "bdb: cdb_end_transaction: ERROR: txcommit(NULL) !!");
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_end_transaction: ERROR: txcommit(NULL) !!");
+ bdb_abort();
}
else {
txcommit(TSD->tid);
// Truncate (delete every record)
-void cdb_trunc(int cdb) {
+void bdb_trunc(int cdb) {
int ret;
u_int32_t count;
if (TSD->tid != NULL) {
- syslog(LOG_ERR, "bdb: cdb_trunc must not be called in a transaction.");
- cdb_abort();
+ syslog(LOG_ERR, "bdb: bdb_trunc must not be called in a transaction.");
+ bdb_abort();
}
else {
bailIfCursor(TSD->cursors, "attempt to write during r/o cursor");
goto retry;
}
else {
- syslog(LOG_ERR, "bdb: cdb_truncate(%d): %s", cdb, db_strerror(ret));
+ syslog(LOG_ERR, "bdb: bdb_truncate(%d): %s", cdb, db_strerror(ret));
if (ret == ENOMEM) {
syslog(LOG_ERR, "bdb: You may need to tune your database; please read http://www.citadel.org for more information.");
}
int ret;
int i;
- syslog(LOG_DEBUG, "bdb: cdb_compact() started");
+ syslog(LOG_DEBUG, "bdb: bdb_compact() started");
for (i = 0; i < MAXCDB; i++) {
syslog(LOG_DEBUG, "bdb: compacting database %d", i);
ret = dbp[i]->compact(dbp[i], NULL, NULL, NULL, NULL, DB_FREE_SPACE, NULL);
syslog(LOG_ERR, "bdb: compact: %s", db_strerror(ret));
}
}
- syslog(LOG_DEBUG, "bdb: cdb_compact() finished");
+ syslog(LOG_DEBUG, "bdb: bdb_compact() finished");
}
cdb_checkpoint = bdb_checkpoint;
cdb_rewind = bdb_rewind;
cdb_fetch = bdb_fetch;
+ cdb_open_databases = bdb_open_databases;
+ cdb_close_databases = bdb_close_databases;
+ cdb_store = bdb_store;
+ cdb_delete = bdb_delete;
+ cdb_free = bdb_free;
+ cdb_next_item = bdb_next_item;
+ cdb_close_cursor = bdb_close_cursor;
+ cdb_begin_transaction = bdb_begin_transaction;
+ cdb_end_transaction = bdb_end_transaction;
+ cdb_check_handles = bdb_check_handles;
+ cdb_trunc = bdb_trunc;
+ cdb_chmod_data = bdb_chmod_data;
+
syslog(LOG_INFO, "db: initialized Berkeley DB backend");
}