]> code.citadel.org Git - citadel.git/commitdiff
ctdl3264: open and close databases
authorArt Cancro <ajc@citadel.org>
Wed, 22 Feb 2023 05:14:07 +0000 (00:14 -0500)
committerArt Cancro <ajc@citadel.org>
Wed, 22 Feb 2023 05:14:07 +0000 (00:14 -0500)
citadel/Makefile
citadel/utils/ctdl3264.c

index 1b9bd8b28ade1f6f9d436539e9db0140d5cd251d..cf3fe1a82c404fe887734b5d388f5a0f96c2716e 100644 (file)
@@ -39,7 +39,7 @@ chkpwd: utils/chkpwd.c utils/auth.c utils/*.h server/*.h
        cc ${CFLAGS} ${LDFLAGS} utils/chkpwd.c utils/auth.c -lcrypt -o chkpwd
 
 ctdl3264: utils/ctdl3264.c utils/*.h server/*.h utils/ctdl3264_structs.h
-       cc ${CFLAGS} ${LDFLAGS} utils/ctdl3264.c -o ctdl3264
+       cc ${CFLAGS} ${LDFLAGS} utils/ctdl3264.c -lcitadel -lz -ldb -o ctdl3264
 
 utils/ctdl3264_structs.h: server/server.h utils/ctdl3264_prep.sh
        utils/ctdl3264_prep.sh
index 7e59e75035a97ab9909426c5ad50f2cf366a1c2d..39c1f55fa7610cefb4f1e1d5b8d695ec7a138562 100644 (file)
 #include <stdarg.h>
 #include <limits.h>
 #include <libcitadel.h>
+#include <zlib.h>
+#include <db.h>
 #include "../server/sysdep.h"
 #include "../server/citadel_defs.h"
 #include "../server/server.h"
 #include "../server/citadel_dirs.h"
 #include "ctdl3264_structs.h"
 
+static DB *dbp[MAXCDB];                // One DB handle for each Citadel database
+static DB_ENV *dbenv;          // The DB environment (global)
+
+// Open the various databases we'll be using.  Any database which
+// 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 open_databases(void) {
+       int ret;
+       int i;
+       char dbfilename[32];
+       u_int32_t flags = 0;
+       int dbversion_major, dbversion_minor, dbversion_patch;
+
+       printf( "db: open_databases() starting\n"
+               "db:    Linked zlib: %s\n"
+               "db: Compiled libdb: %s\n"
+               "db:   Linked libdb: %s\n",
+               zlibVersion(),
+               DB_VERSION_STRING,
+               db_version(&dbversion_major, &dbversion_minor, &dbversion_patch)
+       );
+
+       // Create synthetic integer version numbers and compare them.
+       // Never allow citserver to run with a libdb older then the one with which it was compiled.
+       int compiled_db_version = ( (DB_VERSION_MAJOR * 1000000) + (DB_VERSION_MINOR * 1000) + (DB_VERSION_PATCH) );
+       int linked_db_version = ( (dbversion_major * 1000000) + (dbversion_minor * 1000) + (dbversion_patch) );
+       if (compiled_db_version > linked_db_version) {
+               printf( "db: citserver is running with a version of libdb older than the one with which it was compiled.\n"
+                       "db: This is an invalid configuration.  citserver will now exit to prevent data loss.");
+               exit(CTDLEXIT_DB);
+       }
+
+       printf("db: Setting up DB environment\n");
+       ret = db_env_create(&dbenv, 0);
+       if (ret) {
+               printf("db: db_env_create: %s\n", db_strerror(ret));
+               printf("db: exit code %d\n", ret);
+               exit(CTDLEXIT_DB);
+       }
+
+       // We want to specify the shared memory buffer pool cachesize, but everything else is the default.
+       ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0);
+       if (ret) {
+               printf("db: set_cachesize: %s\n", db_strerror(ret));
+               dbenv->close(dbenv, 0);
+               printf("db: exit code %d\n", ret);
+               exit(CTDLEXIT_DB);
+       }
+
+       if ((ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT))) {
+               printf("db: set_lk_detect: %s\n", db_strerror(ret));
+               dbenv->close(dbenv, 0);
+               printf("db: exit code %d\n", ret);
+               exit(CTDLEXIT_DB);
+       }
+
+       flags = DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_INIT_TXN | DB_INIT_LOCK | DB_THREAD | DB_INIT_LOG;
+       printf("db: dbenv->open(dbenv, %s, %d, 0)\n", ctdl_db_dir, flags);
+       ret = dbenv->open(dbenv, ctdl_db_dir, flags, 0);                                // try opening the database cleanly
+       if (ret == DB_RUNRECOVERY) {
+               printf("db: dbenv->open: %s\n", db_strerror(ret));
+               printf("db: attempting recovery...\n");
+               flags |= DB_RECOVER;
+               ret = dbenv->open(dbenv, ctdl_db_dir, flags, 0);                        // try recovery
+       }
+       if (ret == DB_RUNRECOVERY) {
+               printf("db: dbenv->open: %s\n", db_strerror(ret));
+               printf("db: attempting catastrophic recovery...\n");
+               flags &= ~DB_RECOVER;
+               flags |= DB_RECOVER_FATAL;
+               ret = dbenv->open(dbenv, ctdl_db_dir, flags, 0);                        // try catastrophic recovery
+       }
+       if (ret) {
+               printf("db: dbenv->open: %s\n", db_strerror(ret));
+               dbenv->close(dbenv, 0);
+               printf("db: exit code %d\n", ret);
+               exit(CTDLEXIT_DB);
+       }
+
+       for (i = 0; i < MAXCDB; ++i) {
+               printf("db: mounting database %d\n", i);
+               ret = db_create(&dbp[i], dbenv, 0);                                     // Create a database handle
+               if (ret) {
+                       printf("db: db_create: %s\n", db_strerror(ret));
+                       printf("db: exit code %d\n", ret);
+                       exit(CTDLEXIT_DB);
+               }
+
+               snprintf(dbfilename, sizeof dbfilename, "cdb.%02x", i);                 // table names by number
+               ret = dbp[i]->open(dbp[i], NULL, dbfilename, NULL, DB_BTREE, DB_AUTO_COMMIT, 0600);
+               if (ret) {
+                       printf("db: db_open[%02x]: %s\n", i, db_strerror(ret));
+                       if (ret == ENOMEM) {
+                               printf("db: You may need to tune your database; please check http://www.citadel.org for more information.\n");
+                       }
+                       printf("db: exit code %d\n", ret);
+                       exit(CTDLEXIT_DB);
+               }
+       }
+}
+
+
+// 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 close_databases(void) {
+       int i;
+       int ret;
+
+       //syslog(LOG_INFO, "db: performing final checkpoint");
+       //if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0))) {
+               //syslog(LOG_ERR, "db: txn_checkpoint: %s", db_strerror(ret));
+       //}
+
+       printf("db: flushing the database logs\n");
+       if ((ret = dbenv->log_flush(dbenv, NULL))) {
+               printf("db: log_flush: %s\n", db_strerror(ret));
+       }
+
+       // close the tables
+       printf("db: closing databases\n");
+       for (i = 0; i < MAXCDB; ++i) {
+               printf("db: closing database %02x\n", i);
+               ret = dbp[i]->close(dbp[i], 0);
+               if (ret) {
+                       printf("db: db_close: %s\n", db_strerror(ret));
+               }
+
+       }
+
+       // Close the handle.
+       ret = dbenv->close(dbenv, 0);
+       if (ret) {
+               printf("db: DBENV->close: %s\n", db_strerror(ret));
+       }
+}
 
 int main(int argc, char **argv) {
        char ctdldir[PATH_MAX]=CTDLDIR;
@@ -51,5 +188,8 @@ int main(int argc, char **argv) {
                }
        }
 
+       open_databases();
+       close_databases();
+
        exit(0);
 }