From 7ca1bdc8e6aea3ace1fbec8736e9fd4a8c4d26d5 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Tue, 8 Aug 2023 17:55:10 -0400 Subject: [PATCH] Mostly finished the abstractions, now just need to silence some compiler warnings that came up --- citadel/server/database.h | 27 +++--- citadel/server/database_bdb.c | 162 ++++++++++++++++++++-------------- 2 files changed, 107 insertions(+), 82 deletions(-) diff --git a/citadel/server/database.h b/citadel/server/database.h index f1da45f76..ae7df3963 100644 --- a/citadel/server/database.h +++ b/citadel/server/database.h @@ -10,20 +10,19 @@ void cdb_init_backends(void); -void cdb_open_databases(void); -void cdb_close_databases(void); -int cdb_store(int, const void *, int, void *, int); -int cdb_delete(int, void *, int); -void cdb_free(struct cdbdata *); -struct cdbdata * cdb_next_item(int); -void cdb_close_cursor(int); -void cdb_begin_transaction(void); -void cdb_end_transaction(void); -void cdb_check_handles(void); -void cdb_trunc(int); -void cdb_chmod_data(void); -void check_handles(void *); - +extern void (*cdb_open_databases)(void); +extern void (*cdb_close_databases)(void); +extern int (*cdb_store)(int, const void *, int, void *, int); +extern int (*cdb_delete)(int, void *, int); +extern void (*cdb_free)(struct cdbdata *); +extern struct cdbdata * (*cdb_next_item)(int); +extern void (*cdb_close_cursor)(int); +extern void (*cdb_begin_transaction)(void); +extern void (*cdb_end_transaction)(void); +extern void (*cdb_check_handles)(void); +extern void (*cdb_trunc)(int); +extern void (*cdb_chmod_data)(void); +extern void (*check_handles)(void *); extern struct cdbdata * (*cdb_fetch)(int, const void *, int); extern void (*cdb_checkpoint)(void); extern void (*cdb_compact)(void); diff --git a/citadel/server/database_bdb.c b/citadel/server/database_bdb.c index 6f55c476f..95b90d7e8 100644 --- a/citadel/server/database_bdb.c +++ b/citadel/server/database_bdb.c @@ -30,16 +30,29 @@ #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() ); @@ -49,7 +62,7 @@ void cdb_abort(void) { // 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); } @@ -57,7 +70,7 @@ void cdb_verbose_log(const DB_ENV *dbenv, const char *msg, const char *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); } @@ -70,7 +83,7 @@ static void txabort(DB_TXN *tid) { if (ret) { syslog(LOG_ERR, "bdb: txn_abort: %s", db_strerror(ret)); - cdb_abort(); + bdb_abort(); } } @@ -83,7 +96,7 @@ static void txcommit(DB_TXN *tid) { if (ret) { syslog(LOG_ERR, "bdb: txn_commit: %s", db_strerror(ret)); - cdb_abort(); + bdb_abort(); } } @@ -96,7 +109,7 @@ static void txbegin(DB_TXN **tid) { if (ret) { syslog(LOG_ERR, "bdb: txn_begin: %s", db_strerror(ret)); - cdb_abort(); + bdb_abort(); } } @@ -104,7 +117,7 @@ static void txbegin(DB_TXN **tid) { // panic callback static void dbpanic(DB_ENV *env, int errval) { syslog(LOG_ERR, "bdb: PANIC: %s", db_strerror(errval)); - cdb_abort(); + bdb_abort(); } @@ -113,7 +126,7 @@ static void cclose(DBC *cursor) { if ((ret = cursor->c_close(cursor))) { syslog(LOG_ERR, "bdb: c_close: %s", db_strerror(ret)); - cdb_abort(); + bdb_abort(); } } @@ -124,17 +137,17 @@ static void bailIfCursor(DBC **cursors, const char *msg) { 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(); } } @@ -147,8 +160,8 @@ void bdb_checkpoint(void) { 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 @@ -165,14 +178,14 @@ void bdb_checkpoint(void) { // 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)); @@ -209,8 +222,8 @@ void cdb_open_databases(void) { } 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); @@ -277,7 +290,7 @@ void cdb_open_databases(void) { // 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]; @@ -297,7 +310,7 @@ void cdb_chmod_data(void) { // 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; @@ -336,7 +349,7 @@ void cdb_close_databases(void) { // 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)))) { @@ -368,7 +381,7 @@ void cdb_decompress_if_necessary(struct cdbdata *cdb) { 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); @@ -379,7 +392,7 @@ void cdb_decompress_if_necessary(struct cdbdata *cdb) { // 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; @@ -408,7 +421,7 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) 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)); @@ -424,8 +437,8 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) 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); @@ -448,8 +461,8 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) 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 { @@ -465,7 +478,7 @@ int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen) // 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; @@ -477,9 +490,9 @@ int cdb_delete(int cdb, void *key, int keylen) { 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(); } } } @@ -495,8 +508,8 @@ int cdb_delete(int cdb, void *key, int keylen) { 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 { @@ -520,7 +533,7 @@ static DBC *localcursor(int cdb) { if (ret) { syslog(LOG_ERR, "bdb: localcursor: %s", db_strerror(ret)); - cdb_abort(); + bdb_abort(); } return curs; @@ -529,7 +542,7 @@ static DBC *localcursor(int cdb) { // 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 @@ -562,8 +575,8 @@ struct cdbdata *bdb_fetch(int cdb, const void *key, int keylen) { } 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) { @@ -572,13 +585,13 @@ struct cdbdata *bdb_fetch(int cdb, const void *key, int keylen) { 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); } } @@ -588,9 +601,9 @@ struct cdbdata *bdb_fetch(int cdb, const void *key, int keylen) { // // 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); } @@ -598,7 +611,7 @@ void cdb_free(struct cdbdata *cdb) { } -void cdb_close_cursor(int cdb) { +void bdb_close_cursor(int cdb) { if (TSD->cursors[cdb] != NULL) { cclose(TSD->cursors[cdb]); } @@ -614,23 +627,23 @@ void bdb_rewind(int 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; @@ -644,49 +657,49 @@ struct cdbdata *cdb_next_item(int cdb) { 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); @@ -697,13 +710,13 @@ void cdb_end_transaction(void) { // 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"); @@ -718,7 +731,7 @@ void cdb_trunc(int cdb) { 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."); } @@ -734,7 +747,7 @@ void bdb_compact(void) { 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); @@ -742,7 +755,7 @@ void bdb_compact(void) { syslog(LOG_ERR, "bdb: compact: %s", db_strerror(ret)); } } - syslog(LOG_DEBUG, "bdb: cdb_compact() finished"); + syslog(LOG_DEBUG, "bdb: bdb_compact() finished"); } @@ -751,5 +764,18 @@ void cdb_init_backends(void) { 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"); } -- 2.39.2