* Finished (mostly) the Sleepycat DB backend ... added transaction logging
authorArt Cancro <ajc@citadel.org>
Sun, 3 Dec 2000 04:12:21 +0000 (04:12 +0000)
committerArt Cancro <ajc@citadel.org>
Sun, 3 Dec 2000 04:12:21 +0000 (04:12 +0000)
citadel/ChangeLog
citadel/database.c
citadel/database.h
citadel/database_sleepycat.c
citadel/sysdep.c

index d21f132836da333a8dd08abfa64f70f360231978..cb9114fa8523bce4066e486a7e3cd4fa4f8dfd23 100644 (file)
@@ -1,4 +1,7 @@
  $Log$
+ Revision 573.37  2000/12/03 04:12:21  ajc
+ * Finished (mostly) the Sleepycat DB backend ... added transaction logging
+
  Revision 573.36  2000/11/30 03:23:17  ajc
  * Got the Sleepycat DB back end working, by opening the databases in a non
    shared, non threaded mode, and using Citadel's locking to serialize access.
@@ -2173,3 +2176,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant <bryant@cs.usm.maine.edu>
 
 Fri Jul 10 1998 Art Cancro <ajc@uncensored.citadel.org>
        * Initial CVS import 
+
index 77360c6e0cf4703d6e8c8bb838d6e41d7b1c450b..0276e7b1fe82a9730563eb33c421336d722f1f87 100644 (file)
@@ -1,8 +1,7 @@
 /*
  * $Id$
  *
- * This file contains a set of abstractions that allow Citadel to plug into any
- * record manager or database system for its data store.
+ * GDBM database driver for Citadel/UX
  *
  */
 
@@ -340,3 +339,15 @@ struct cdbdata *cdb_next_item(int cdb)
 
        return (cdbret);
 }
+
+
+
+/*
+ * GDBM doesn't support transaction-based logging.  Stub out these functions.
+ */
+
+void cdb_begin_transaction(void) {
+}
+
+void cdb_end_transaction(void) {
+}
index fd029f5576c021c71ed49e0899a1c5d4377cc1aa..399f2013a308a84bf00a84535d09c4eac1c40f97 100644 (file)
@@ -8,3 +8,5 @@ struct cdbdata *cdb_fetch (int cdb, void *key, int keylen);
 void cdb_free (struct cdbdata *cdb);
 void cdb_rewind (int cdb);
 struct cdbdata *cdb_next_item (int cdb);
+void cdb_begin_transaction(void);
+void cdb_end_transaction(void);
index f8bb3dc0580357a5679dcfe876dbdfe2e3b2098e..9731c9a7aba035c378913d6f5ab3694c639b569b 100644 (file)
 #include "citserver.h"
 #include "database.h"
 #include "sysdep_decls.h"
+#include "dynloader.h"
 
 
+/* 
+ * FIXME this should be defined somewhere else.
+ */
+int transaction_based = 1;
+
+DB *dbp[MAXCDB];               /* One DB handle for each Citadel database */
+DB_ENV *dbenv;                 /* The DB environment (global) */
+
+struct cdbssd {                        /* Session-specific DB stuff */
+       DBC *cursor;            /* Cursor, for traversals... */
+       DB_TXN *tid;            /* Transaction ID */
+};
+
+struct cdbssd *ssd_arr = NULL;
+int num_ssd = 0;
+#define MYCURSOR       ssd_arr[CC->cs_pid].cursor
+#define MYTID          ssd_arr[CC->cs_pid].tid
+
 /*
- * This array holds one DB handle for each Citadel database.
+ * Ensure that we have enough space for session-specific data.  We don't
+ * put anything in here that Citadel cares about; this is just database
+ * related stuff like cursors and transactions.
  */
-DB *dbp[MAXCDB];
+void cdb_allocate_ssd(void) {
+       /*
+        * Make sure we have a cursor allocated for this session
+        */
 
-DB_ENV *dbenv;
+       lprintf(9, "num_ssd before realloc = %d\n", num_ssd);
+       if (num_ssd <= CC->cs_pid) {
+               num_ssd = CC->cs_pid + 1;
+               if (ssd_arr == NULL) {
+                       ssd_arr = (struct cdbssd *)
+                           mallok((sizeof(struct cdbssd) * num_ssd));
+               } else {
+                       ssd_arr = (struct cdbssd *)
+                           reallok(ssd_arr, (sizeof(struct cdbssd) * num_ssd));
+               }
+       }
+       lprintf(9, "num_ssd  after realloc = %d\n", num_ssd);
+}
 
-DBC **cursorz = NULL;
-int num_cursorz = 0;
-#define MYCURSOR cursorz[CC->cs_pid]
 
 /*
  * Reclaim unused space in the databases.  We need to do each one of
@@ -56,6 +89,7 @@ void open_databases(void)
        int ret;
        int i;
        char dbfilename[256];
+       u_int32_t flags = 0;
 
         /*
          * Silently try to create the database subdirectory.  If it's
@@ -89,10 +123,9 @@ void open_databases(void)
         * is serialized already, so don't bother the database manager with
         * it.  Besides, it locks up when we do it that way.
          */
-        /* (void)dbenv->set_data_dir(dbenv, "/database/files"); */
-        ret = dbenv->open(dbenv, "./data",
-               ( DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE ),
-               0);
+        flags = DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE;
+       if (transaction_based) flags = flags | DB_INIT_TXN;
+        ret = dbenv->open(dbenv, "./data", flags, 0);
        if (ret) {
                lprintf(1, "dbenv->open: %s\n", db_strerror(ret));
                 dbenv->close(dbenv, 0);
@@ -129,6 +162,10 @@ void open_databases(void)
 
        }
 
+       cdb_allocate_ssd();
+       CtdlRegisterSessionHook(cdb_allocate_ssd, EVT_START);
+
+
 }
 
 
@@ -186,7 +223,7 @@ int cdb_store(int cdb,
 
        begin_critical_section(S_DATABASE);
        ret = dbp[cdb]->put(dbp[cdb],           /* db */
-                               NULL,           /* transaction ID (hmm...) */
+                               MYTID,          /* transaction ID */
                                &dkey,          /* key */
                                &ddata,         /* data */
                                0);             /* flags */
@@ -212,7 +249,7 @@ int cdb_delete(int cdb, void *key, int keylen)
        dkey.data = key;
 
        begin_critical_section(S_DATABASE);
-       ret = dbp[cdb]->del(dbp[cdb], NULL, &dkey, 0);
+       ret = dbp[cdb]->del(dbp[cdb], MYTID, &dkey, 0);
        end_critical_section(S_DATABASE);
        return (ret);
 
@@ -240,7 +277,7 @@ struct cdbdata *cdb_fetch(int cdb, void *key, int keylen)
        dret.flags = DB_DBT_MALLOC;
 
        begin_critical_section(S_DATABASE);
-       ret = dbp[cdb]->get(dbp[cdb], NULL, &dkey, &dret, 0);
+       ret = dbp[cdb]->get(dbp[cdb], MYTID, &dkey, &dret, 0);
        end_critical_section(S_DATABASE);
        if ((ret != 0) && (ret != DB_NOTFOUND)) {
                lprintf(1, "cdb_fetch: %s\n", db_strerror(ret));
@@ -276,27 +313,13 @@ void cdb_rewind(int cdb)
 {
        int ret = 0;
 
-       /*
-        * Make sure we have a cursor allocated for this session
-        */
-
-       if (num_cursorz <= CC->cs_pid) {
-               num_cursorz = CC->cs_pid + 1;
-               if (cursorz == NULL) {
-                       cursorz = (DBC **)
-                           mallok((sizeof(DBC *) * num_cursorz));
-               } else {
-                       cursorz = (DBC **)
-                           reallok(cursorz, (sizeof(DBC *) * num_cursorz));
-               }
-       }
-
+       cdb_allocate_ssd();
 
        /*
         * Now initialize the cursor
         */
        begin_critical_section(S_DATABASE);
-       ret = dbp[cdb]->cursor(dbp[cdb], NULL, &MYCURSOR, 0);
+       ret = dbp[cdb]->cursor(dbp[cdb], MYTID, &MYCURSOR, 0);
        if (ret) {
                lprintf(1, "db_cursor: %s\n", db_strerror(ret));
        }
@@ -332,3 +355,21 @@ struct cdbdata *cdb_next_item(int cdb)
 
        return (cdbret);
 }
+
+
+/*
+ * Transaction-based stuff.  I'm writing this as I bake cookies...
+ */
+
+void cdb_begin_transaction(void) {
+       if (!transaction_based) {
+               MYTID = NULL;
+               return;
+       }
+
+       txn_begin(dbenv, NULL, &MYTID, 0);
+}
+
+void cdb_end_transaction(void) {
+       if (transaction_based) txn_commit(MYTID, 0);
+}
index 083e3550ea7763076a3853d418aefb8ded7cfb27..8a37d59339bd8021a41526565f5dd7083ecec0f4 100644 (file)
@@ -7,8 +7,8 @@
  * Here's where we (hopefully) have most parts of the Citadel server that
  * would need to be altered to run the server in a non-POSIX environment.
  * 
- * Eventually we'll try porting to a different platform and either have
- * multiple variants of this file or simply load it up with #ifdefs.
+ * If we ever port to a different platform and either have multiple
+ * variants of this file or simply load it up with #ifdefs.
  *
  */
 
@@ -186,7 +186,7 @@ void dump_tracked() {
 
 
 /*
- * we used to use master_cleanup() as a signal handler to shut down the server.
+ * We used to use master_cleanup() as a signal handler to shut down the server.
  * however, master_cleanup() and the functions it calls do some things that
  * aren't such a good idea to do from a signal handler: acquiring mutexes,
  * playing with signal masks on BSDI systems, etc. so instead we install the
@@ -215,7 +215,8 @@ void init_sysdep(void) {
        /*
         * Set up a place to put thread-specific data.
         * We only need a single pointer per thread - it points to the
-        * thread's CitContext structure in the ContextList linked list.
+        * CitContext structure (in the ContextList linked list) of the
+        * session to which the calling thread is currently bound.
         */
        if (pthread_key_create(&MyConKey, NULL) != 0) {
                lprintf(1, "Can't create TSD key!!  %s\n", strerror(errno));
@@ -370,7 +371,11 @@ struct CitContext *MyContext(void) {
 
 
 /*
- * Initialize a new context and place it in the list.
+ * Initialize a new context and place it in the list.  The session number
+ * used to be the PID (which is why it's called cs_pid), but that was when we
+ * had one process per session.  Now we just assign them sequentially, starting
+ * at 1 (don't change it to 0 because masterCC uses 0) and re-using them when
+ * sessions terminate.
  */
 struct CitContext *CreateNewContext(void) {
        struct CitContext *me, *ptr;
@@ -563,8 +568,15 @@ void sysdep_master_cleanup(void) {
         */
        for (serviceptr = ServiceHookTable; serviceptr != NULL;
            serviceptr = serviceptr->next ) {
-               lprintf(3, "Closing listener on port %d\n",
-                       serviceptr->tcp_port);
+
+               if (serviceptr->tcp_port > 0)
+                       lprintf(3, "Closing listener on port %d\n",
+                               serviceptr->tcp_port);
+
+               if (serviceptr->sockpath != NULL)
+                       lprintf(3, "Closing listener on '%s'\n",
+                               serviceptr->sockpath);
+
                close(serviceptr->msock);
 
                /* If it's a Unix domain socket, remove the file. */
@@ -792,6 +804,7 @@ void CtdlRedirectOutput(FILE *fp, int sock) {
 void InitializeMasterCC(void) {
        memset(&masterCC, 0, sizeof(struct CitContext));
        masterCC.internal_pgm = 1;
+       masterCC.cs_pid = 0;
 }
 
 
@@ -1167,7 +1180,9 @@ SETUP_FD: memcpy(&readfds, &masterfds, sizeof masterfds);
                        /* We're bound to a session, now do *one* command */
                        if (bind_me != NULL) {
                                become_session(bind_me);
+                               cdb_begin_transaction();
                                CC->h_command_function();
+                               cdb_end_transaction();
                                become_session(NULL);
                                bind_me->state = CON_IDLE;
                                if (bind_me->kill_me == 1) {