Changed the way we do the TSD area.
authorDave West <davew@uncensored.citadel.org>
Wed, 5 Dec 2007 20:17:22 +0000 (20:17 +0000)
committerDave West <davew@uncensored.citadel.org>
Wed, 5 Dec 2007 20:17:22 +0000 (20:17 +0000)
Now this code is in sysdep.c
Added an element to the TSD to store a pointer to this threads control
structure. This allows a speed up in CtdlThreadSleep(),
CtdlThreadCheckStop() and the odd one or two other places since this
thread no longer needs to search the list of threads to find its own
control ctructure.

citadel/citserver.c
citadel/database.h
citadel/database_sleepycat.c
citadel/include/ctdl_module.h
citadel/modules/checkpoint/serv_checkpoint.c
citadel/modules/expire/serv_expire.c
citadel/modules/fulltext/serv_fulltext.c
citadel/server_main.c
citadel/sysdep.c
citadel/sysdep_decls.h

index f2c957d78b08bd97f9ae54f2b93606b44536b292..d04ee38b231f2626536496f4daaa8c64f5708d86 100644 (file)
@@ -135,6 +135,10 @@ void master_startup(void) {
        lprintf(CTDL_INFO, "Opening databases\n");
        open_databases();
 
+       ctdl_thread_internal_init_tsd();
+       
+       CtdlThreadAllocTSD();
+       
        if (do_defrag) {
                defrag_databases();
        }
index c7fe3833eca7e18707a193ae8e663e6eb18f2456..c4aac796eaac8d600ff9569389261cf1e7fa5060 100644 (file)
@@ -1,4 +1,9 @@
 /* $Id$ */
+
+#ifndef DATABASE_H
+#define DATABASE_H
+
+
 void defrag_databases (void);
 void open_databases (void);
 void close_databases (void);
@@ -18,6 +23,7 @@ void cdb_trunc(int cdb);
 void *checkpoint_thread(void *arg);
 void cdb_chmod_data(void);
 void cdb_checkpoint(void);
+void check_handles(void *arg);
 
 /*
  * Database records beginning with this magic number are assumed to
@@ -36,4 +42,5 @@ struct CtdlCompressHeader {
        size_t compressed_len;
 };
 
+#endif /* DATABASE_H */
 
index ddd8edb12b407725f25c6304278c792369a84b7e..64191dcb940ef6bd937d8c3edbe8312dfffce914 100644 (file)
 static DB *dbp[MAXCDB];                /* One DB handle for each Citadel database */
 static DB_ENV *dbenv;          /* The DB environment (global) */
 
-struct cdbtsd {                        /* Thread-specific DB stuff */
-       DB_TXN *tid;            /* Transaction handle */
-       DBC *cursors[MAXCDB];   /* Cursors, for traversals... */
-};
 
 #ifdef HAVE_ZLIB
 #include <zlib.h>
 #endif
 
-static pthread_key_t tsdkey;
-
-#define MYCURSORS      (((struct cdbtsd*)pthread_getspecific(tsdkey))->cursors)
-#define MYTID          (((struct cdbtsd*)pthread_getspecific(tsdkey))->tid)
 
 /* Verbose logging callback */
 void cdb_verbose_log(const DB_ENV *dbenv, const char *msg)
@@ -157,10 +149,10 @@ static void bailIfCursor(DBC ** cursors, const char *msg)
                }
 }
 
-static void check_handles(void *arg)
+void check_handles(void *arg)
 {
        if (arg != NULL) {
-               struct cdbtsd *tsd = (struct cdbtsd *) arg;
+               ThreadTSD *tsd = (ThreadTSD *) arg;
 
                bailIfCursor(tsd->cursors, "in check_handles");
 
@@ -172,46 +164,9 @@ static void check_handles(void *arg)
        }
 }
 
-static void dest_tsd(void *arg)
-{
-       if (arg != NULL) {
-               check_handles(arg);
-               free(arg);
-       }
-}
-
-/*
- * Ensure that we have a key for thread-specific data.  We don't
- * put anything in here that Citadel cares about; this is just database
- * related stuff like cursors and transactions.
- *
- * This should be called immediately after startup by any thread which wants
- * to use database calls, except for whatever thread calls open_databases.
- */
-void cdb_allocate_tsd(void)
-{
-       struct cdbtsd *tsd;
-
-       if (pthread_getspecific(tsdkey) != NULL)
-               return;
-
-       tsd = malloc(sizeof(struct cdbtsd));
-
-       tsd->tid = NULL;
-
-       memset(tsd->cursors, 0, sizeof tsd->cursors);
-       pthread_setspecific(tsdkey, tsd);
-}
-
-void cdb_free_tsd(void)
-{
-       dest_tsd(pthread_getspecific(tsdkey));
-       pthread_setspecific(tsdkey, NULL);
-}
-
 void cdb_check_handles(void)
 {
-       check_handles(pthread_getspecific(tsdkey));
+       check_handles(pthread_getspecific(ThreadKey));
 }
 
 
@@ -434,14 +389,6 @@ void open_databases(void)
                }
        }
 
-       if ((ret = pthread_key_create(&tsdkey, dest_tsd))) {
-               lprintf(CTDL_EMERG, "pthread_key_create: %s\n",
-                       strerror(ret));
-               exit(CTDLEXIT_DB);
-       }
-
-       cdb_allocate_tsd();
-       
 }
 
 
@@ -485,8 +432,8 @@ void close_databases(void)
        int a;
        int ret;
 
-       cdb_free_tsd();
-
+       ctdl_thread_internal_free_tsd();
+       
        if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0))) {
                lprintf(CTDL_EMERG,
                        "txn_checkpoint: %s\n", db_strerror(ret));
index 93fbf02125b73a5e893f5a554aa37fe4781bf39a..b0508a96bf80482b7e79b444c2249fe9df630493 100644 (file)
@@ -115,9 +115,9 @@ void CtdlModuleStartCryptoMsgs(char *ok_response, char *nosup_response, char *er
 struct CtdlThreadNode *CtdlThreadCreate(char *name, long flags, void *(*thread_func) (void *arg), void *args);
 void CtdlThreadSleep(int secs);
 void CtdlThreadStop(struct CtdlThreadNode *thread);
-int CtdlThreadCheckStop(struct CtdlThreadNode *this_thread);
+int CtdlThreadCheckStop(void);
 void CtdlThreadCancel(struct CtdlThreadNode *thread);
-const char *CtdlThreadName(struct CtdlThreadNode *thread, const char *name);
+const char *CtdlThreadName(const char *name);
 struct CtdlThreadNode *CtdlThreadSelf(void);
 int CtdlThreadGetCount(void);
 int CtdlThreadGetWorkers(void);
@@ -126,11 +126,13 @@ double CtdlThreadGetLoadAvg(void);
 void CtdlThreadGC(void);
 void CtdlThreadStopAll(void);
 int CtdlThreadSelect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout, struct CtdlThreadNode *self);
+void CtdlThreadAllocTSD(void);
 
 /* Macros to speed up getting outr thread */
-#define CT _this_cit_thread
-#define CT_PUSH() \
-       struct CtdlThreadNode *_this_cit_thread;\
-       _this_cit_thread = CtdlThreadSelf()
+
+#define MYCURSORS      (((ThreadTSD*)pthread_getspecific(ThreadKey))->cursors)
+#define MYTID          (((ThreadTSD*)pthread_getspecific(ThreadKey))->tid)
+#define CT             (((ThreadTSD*)pthread_getspecific(ThreadKey))->self)
+
 
 #endif /* CTDL_MODULE_H */
index 98c685856e056fce248f8d0bcf3c6207189a2e3f..32bfad00bb438526597a59b7acfb9bab7bedaf69 100644 (file)
@@ -44,7 +44,7 @@
 void *checkpoint_thread(void *arg) {
        struct CitContext checkpointCC;
 
-       CT_PUSH();
+       CtdlThreadAllocTSD();
        
        CtdlLogPrintf(CTDL_DEBUG, "checkpoint_thread() initializing\n");
 
@@ -53,9 +53,7 @@ void *checkpoint_thread(void *arg) {
        checkpointCC.cs_pid = 0;
        pthread_setspecific(MyConKey, (void *)&checkpointCC );
 
-       cdb_allocate_tsd();
-
-       while (!CtdlThreadCheckStop(CT)) {
+       while (!CtdlThreadCheckStop()) {
                cdb_checkpoint();
                CtdlThreadSleep(60);
        }
index d856761c8657991d6d9081f26f0886bd55bb8963..e807f969bf34cad0c9d80b3da73a3b94b7c9da7b 100644 (file)
@@ -720,11 +720,9 @@ void *purge_databases(void *args)
         time_t now;
         struct tm tm;
 
-        CT_PUSH();     // Makes it easier to access this threads structure
+       CtdlThreadAllocTSD();
 
-        cdb_allocate_tsd();
-
-        while (!CtdlThreadCheckStop(CT)) {
+        while (!CtdlThreadCheckStop()) {
                 /* Do the auto-purge if the current hour equals the purge hour,
                  * but not if the operation has already been performed in the
                  * last twelve hours.  This is usually enough granularity.
@@ -739,49 +737,49 @@ void *purge_databases(void *args)
 
                 lprintf(CTDL_INFO, "Auto-purger: starting.\n");
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        retval = PurgeUsers();
                        lprintf(CTDL_NOTICE, "Purged %d users.\n", retval);
                }
                
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        PurgeMessages();
                        lprintf(CTDL_NOTICE, "Expired %d messages.\n", messages_purged);
                }
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        retval = PurgeRooms();
                        lprintf(CTDL_NOTICE, "Expired %d rooms.\n", retval);
                }
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        retval = PurgeVisits();
                        lprintf(CTDL_NOTICE, "Purged %d visits.\n", retval);
                }
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        retval = PurgeUseTable();
                        lprintf(CTDL_NOTICE, "Purged %d entries from the use table.\n", retval);
                }
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        retval = PurgeEuidIndexTable();
                        lprintf(CTDL_NOTICE, "Purged %d entries from the EUID index.\n", retval);
                }
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        retval = TDAP_ProcessAdjRefCountQueue();
                        lprintf(CTDL_NOTICE, "Processed %d message reference count adjustments.\n", retval);
                }
 
-               if (!CtdlThreadCheckStop(CT))
+               if (!CtdlThreadCheckStop())
                {
                        lprintf(CTDL_INFO, "Auto-purger: finished.\n");
                        last_purge = now;       /* So we don't do it again soon */
index 4737f66f07a7069a5f7e16b174c35cec0f23107f..7c76d9d640f7fba95570c91be1b0bbf5eea9ec7d 100644 (file)
@@ -222,8 +222,6 @@ void do_fulltext_indexing(void) {
        time_t run_time = 0L;
        time_t end_time = 0L;
        
-       CT_PUSH();
-       
        /*
         * Don't do this if the site doesn't have it enabled.
         */
@@ -299,7 +297,7 @@ void do_fulltext_indexing(void) {
                        ft_index_message(ft_newmsgs[i], 1);
 
                        /* Check to see if we need to quit early */
-                       if (CtdlThreadCheckStop(CT)) {
+                       if (CtdlThreadCheckStop()) {
                                lprintf(CTDL_DEBUG, "Indexer quitting early\n");
                                ft_newhighest = ft_newmsgs[i];
                                break;
@@ -341,7 +339,7 @@ void do_fulltext_indexing(void) {
 void *indexer_thread(void *arg) {
        struct CitContext indexerCC;
 
-       CT_PUSH();
+       CtdlThreadAllocTSD();
        
        lprintf(CTDL_DEBUG, "indexer_thread() initializing\n");
 
@@ -350,9 +348,7 @@ void *indexer_thread(void *arg) {
        indexerCC.cs_pid = 0;
        pthread_setspecific(MyConKey, (void *)&indexerCC );
 
-       cdb_allocate_tsd();
-
-       while (!CtdlThreadCheckStop(CT)) {
+       while (!CtdlThreadCheckStop()) {
                do_fulltext_indexing();
                CtdlThreadSleep(300);
        }
@@ -503,7 +499,7 @@ CTDL_MODULE_INIT(fulltext)
        }
        else
        {
-               CtdlThreadCreate("indexer", CTDLTHREAD_BIGSTACK, indexer_thread, NULL);
+               CtdlThreadCreate("Indexer", CTDLTHREAD_BIGSTACK, indexer_thread, NULL);
        }
        /* return our Subversion id for the Log */
        return "$Id$";
index 343d0ae13b2daffce1cf72aad7fffe9f32d7c4bd..20bc5dddf0629e0b2912e60a5a7fe2fa0b90302e 100644 (file)
@@ -347,15 +347,10 @@ void go_threading(void)
        int i;
        struct CtdlThreadNode *last_worker;
        
-       /* We can't use CT_PUSH() here so we do it the long way 
-        * So we can still use CT for current thread */
-       struct CtdlThreadNode *_this_cit_thread;
-       
        /*
         * Initialise the thread system
         */
        ctdl_thread_internal_init();
-       _this_cit_thread = CtdlThreadSelf();
        /*
         * Now create a bunch of worker threads.
         */
index 268196996dccec6d35755861205b1e007c20ba7e..e24af347b234342b2ac37d96898d82ccf40a01a7 100644 (file)
@@ -1020,6 +1020,8 @@ static pthread_t GC_thread;
 static char *CtdlThreadStates[CTDL_THREAD_LAST_STATE];
 double CtdlThreadLoadAvg = 0;
 double CtdlThreadWorkerAvg = 0;
+pthread_key_t ThreadKey;
+
 /*
  * Pinched the following bits regarding signals from Kannel.org
  */
@@ -1076,6 +1078,64 @@ static void ctdl_thread_internal_restore_signals(sigset_t *old_set)
 }
 
 
+
+/*
+ * A function to destroy the TSD
+ */
+static void ctdl_thread_internal_dest_tsd(void *arg)
+{
+       if (arg != NULL) {
+               check_handles(arg);
+               free(arg);
+       }
+}
+
+
+/*
+ * A function to initialise the thread TSD
+ */
+void ctdl_thread_internal_init_tsd(void)
+{
+       int ret;
+       
+       if ((ret = pthread_key_create(&ThreadKey, ctdl_thread_internal_dest_tsd))) {
+               lprintf(CTDL_EMERG, "pthread_key_create: %s\n",
+                       strerror(ret));
+               exit(CTDLEXIT_DB);
+       }
+}
+
+/*
+ * Ensure that we have a key for thread-specific data. 
+ *
+ * This should be called immediately after startup by any thread 
+ * 
+ */
+void CtdlThreadAllocTSD(void)
+{
+       ThreadTSD *tsd;
+
+       if (pthread_getspecific(ThreadKey) != NULL)
+               return;
+
+       tsd = malloc(sizeof(ThreadTSD));
+
+       tsd->tid = NULL;
+
+       memset(tsd->cursors, 0, sizeof tsd->cursors);
+       tsd->self = NULL;
+       
+       pthread_setspecific(ThreadKey, tsd);
+}
+
+
+void ctdl_thread_internal_free_tsd(void)
+{
+       ctdl_thread_internal_dest_tsd(pthread_getspecific(ThreadKey));
+       pthread_setspecific(ThreadKey, NULL);
+}
+
+
 void ctdl_thread_internal_cleanup(void)
 {
        int i;
@@ -1084,6 +1144,7 @@ void ctdl_thread_internal_cleanup(void)
        {
                free (CtdlThreadStates[i]);
        }
+       ctdl_thread_internal_free_tsd();
 }
 
 void ctdl_thread_internal_init(void)
@@ -1129,6 +1190,7 @@ void ctdl_thread_internal_init(void)
        this_thread->name = "Garbage Collection Thread";
        
        this_thread->tid = GC_thread;
+       CT = this_thread;
        
        num_threads++;  // Increase the count of threads in the system.
 
@@ -1283,34 +1345,6 @@ double CtdlThreadGetLoadAvg(void)
        return ret;
 }
 
-/*
- * A function to find the thread structure for this thread
- */
-struct CtdlThreadNode *CtdlThreadSelf(void)
-{
-       pthread_t self_tid;
-       struct CtdlThreadNode *this_thread;
-       
-       self_tid = pthread_self();
-       
-       begin_critical_section(S_THREAD_LIST);
-       this_thread = CtdlThreadList;
-       while(this_thread)
-       {
-               pthread_mutex_lock(&this_thread->ThreadMutex);
-               if (pthread_equal(self_tid, this_thread->tid))
-               {
-                       pthread_mutex_unlock(&this_thread->ThreadMutex);
-                       end_critical_section(S_THREAD_LIST);
-                       return this_thread;
-               }
-               pthread_mutex_unlock(&this_thread->ThreadMutex);
-               this_thread = this_thread->next;
-       }
-       end_critical_section(S_THREAD_LIST);
-       return NULL;
-}
-
 
 
 
@@ -1318,27 +1352,20 @@ struct CtdlThreadNode *CtdlThreadSelf(void)
  * A function to rename a thread
  * Returns a const char *
  */
-const char *CtdlThreadName(struct CtdlThreadNode *thread, const char *name)
+const char *CtdlThreadName(const char *name)
 {
-       struct CtdlThreadNode *this_thread;
        const char *old_name;
        
-       if (!thread)
-               this_thread = CtdlThreadSelf();
-       else
-               this_thread = thread;
-       if (!this_thread)
+       if (!CT)
        {
                CtdlLogPrintf(CTDL_WARNING, "Thread system WARNING. Attempt to CtdlThreadRename() a non thread. %s\n", name);
                return NULL;
        }
-//     begin_critical_section(S_THREAD_LIST);
-       pthread_mutex_lock(&this_thread->ThreadMutex);
-       old_name = this_thread->name;
+       pthread_mutex_lock(&CT->ThreadMutex);
+       old_name = CT->name;
        if (name)
-               this_thread->name = name;
-       pthread_mutex_unlock(&this_thread->ThreadMutex);
-//     end_critical_section (S_THREAD_LIST);
+               CT->name = name;
+       pthread_mutex_unlock(&CT->ThreadMutex);
        return (old_name);
 }      
 
@@ -1351,7 +1378,7 @@ void CtdlThreadCancel(struct CtdlThreadNode *thread)
        struct CtdlThreadNode *this_thread;
        
        if (!thread)
-               this_thread = CtdlThreadSelf();
+               this_thread = CT;
        else
                this_thread = thread;
        if (!this_thread)
@@ -1379,27 +1406,27 @@ void CtdlThreadCancel(struct CtdlThreadNode *thread)
 /*
  * A function for a thread to check if it has been asked to stop
  */
-int CtdlThreadCheckStop(struct CtdlThreadNode *this_thread)
+int CtdlThreadCheckStop(void)
 {
-       if (!this_thread)
+       if (!CT)
        {
                CtdlLogPrintf(CTDL_EMERG, "Thread system PANIC, CtdlThreadCheckStop() called by a non thread.\n");
                CtdlThreadStopAll();
                return -1;
        }
-       pthread_mutex_lock(&this_thread->ThreadMutex);
-       if(this_thread->state == CTDL_THREAD_STOP_REQ)
+       pthread_mutex_lock(&CT->ThreadMutex);
+       if(CT->state == CTDL_THREAD_STOP_REQ)
        {
-               this_thread->state = CTDL_THREAD_STOPPING;
-               pthread_mutex_unlock(&this_thread->ThreadMutex);
+               CT->state = CTDL_THREAD_STOPPING;
+               pthread_mutex_unlock(&CT->ThreadMutex);
                return -1;
        }
-       else if((this_thread->state < CTDL_THREAD_STOP_REQ) && (this_thread->state > CTDL_THREAD_CREATE))
+       else if((CT->state < CTDL_THREAD_STOP_REQ) && (CT->state > CTDL_THREAD_CREATE))
        {
-               pthread_mutex_unlock(&this_thread->ThreadMutex);
+               pthread_mutex_unlock(&CT->ThreadMutex);
                return -1;
        }
-       pthread_mutex_unlock(&this_thread->ThreadMutex);
+       pthread_mutex_unlock(&CT->ThreadMutex);
        return 0;
 }
 
@@ -1413,7 +1440,7 @@ void CtdlThreadStop(struct CtdlThreadNode *thread)
        struct CtdlThreadNode *this_thread;
        
        if (!thread)
-               this_thread = CtdlThreadSelf();
+               this_thread = CT;
        else
                this_thread = thread;
        if (!this_thread)
@@ -1437,11 +1464,9 @@ void CtdlThreadSleep(int secs)
 {
        struct timespec wake_time;
        struct timeval time_now;
-       struct CtdlThreadNode *self;
        
        
-       self = CtdlThreadSelf();
-       if (!self)
+       if (!CT)
        {
                CtdlLogPrintf(CTDL_WARNING, "CtdlThreadSleep() called by something that is not a thread. Should we die?\n");
                return;
@@ -1453,17 +1478,17 @@ void CtdlThreadSleep(int secs)
        wake_time.tv_nsec = time_now.tv_usec * 10;
 
 //     begin_critical_section(S_THREAD_LIST);
-       ctdl_thread_internal_change_state (self, CTDL_THREAD_SLEEPING);
+       ctdl_thread_internal_change_state (CT, CTDL_THREAD_SLEEPING);
 //     end_critical_section(S_THREAD_LIST);
        
 //     pthread_mutex_lock(&self->SleepMutex); /* Prevent something asking us to awaken before we've gone to sleep */
-       pthread_mutex_lock(&self->ThreadMutex); /* Prevent something asking us to awaken before we've gone to sleep */
-       pthread_cond_timedwait(&self->SleepCond, &self->ThreadMutex, &wake_time);
-       pthread_mutex_unlock(&self->ThreadMutex);
+       pthread_mutex_lock(&CT->ThreadMutex); /* Prevent something asking us to awaken before we've gone to sleep */
+       pthread_cond_timedwait(&CT->SleepCond, &CT->ThreadMutex, &wake_time);
+       pthread_mutex_unlock(&CT->ThreadMutex);
 //     pthread_mutex_unlock(&self->SleepMutex);
        
 //     begin_critical_section(S_THREAD_LIST);
-       ctdl_thread_internal_change_state (self, CTDL_THREAD_RUNNING);
+       ctdl_thread_internal_change_state (CT, CTDL_THREAD_RUNNING);
 //     end_critical_section(S_THREAD_LIST);
 }
 
@@ -1473,20 +1498,18 @@ void CtdlThreadSleep(int secs)
  */
 static void ctdl_internal_thread_cleanup(void *arg)
 {
-       struct CtdlThreadNode *this_thread;
-       this_thread = CtdlThreadSelf();
        /*
         * In here we were called by the current thread because it is exiting
         * NB. WE ARE THE CURRENT THREAD
         */
-       CtdlLogPrintf(CTDL_NOTICE, "Thread \"%s\" (%ld) exited.\n", this_thread->name, this_thread->tid);
+       CtdlLogPrintf(CTDL_NOTICE, "Thread \"%s\" (%ld) exited.\n", CT->name, CT->tid);
 //     begin_critical_section(S_THREAD_LIST);
        #ifdef HAVE_BACKTRACE
        eCrash_UnregisterThread();
        #endif
-       pthread_mutex_lock(&this_thread->ThreadMutex);
-       this_thread->state = CTDL_THREAD_EXITED;        // needs to be last thing else house keeping will unlink us too early
-       pthread_mutex_unlock(&this_thread->ThreadMutex);
+       pthread_mutex_lock(&CT->ThreadMutex);
+       CT->state = CTDL_THREAD_EXITED; // needs to be last thing else house keeping will unlink us too early
+       pthread_mutex_unlock(&CT->ThreadMutex);
 //     end_critical_section(S_THREAD_LIST);
 //     CtdlThreadGC();
 }
@@ -1669,6 +1692,8 @@ static void *ctdl_internal_thread_func (void *arg)
        // Register the cleanup function to take care of when we exit.
        pthread_cleanup_push(ctdl_internal_thread_cleanup, NULL);
        // Get our thread data structure
+       CtdlThreadAllocTSD();
+       CT = this_thread;
        this_thread->pid = getpid();
        memcpy(&this_thread->last_state_change, &this_thread->start_time, sizeof (struct timeval));     /* Changed state so mark it. */
        /* Only change to running state if we weren't asked to stop during the create cycle
@@ -1677,7 +1702,7 @@ static void *ctdl_internal_thread_func (void *arg)
         */
        pthread_mutex_unlock(&this_thread->ThreadMutex);
                
-       if (!CtdlThreadCheckStop(this_thread))
+       if (!CtdlThreadCheckStop())
        {
                pthread_mutex_lock(&this_thread->ThreadMutex);
                this_thread->state = CTDL_THREAD_RUNNING;
@@ -1698,7 +1723,7 @@ static void *ctdl_internal_thread_func (void *arg)
        /*
         * run the thread to do the work but only if we haven't been asked to stop
         */
-       if (!CtdlThreadCheckStop(this_thread))
+       if (!CtdlThreadCheckStop())
                ret = (this_thread->thread_func)(this_thread->user_args);
        
        /*
@@ -1990,11 +2015,8 @@ void *worker_thread(void *arg) {
        int force_purge = 0;
        int m;
        
-       CT_PUSH();
-       
-       cdb_allocate_tsd();
 
-       while (!CtdlThreadCheckStop(CT)) {
+       while (!CtdlThreadCheckStop()) {
 
                /* make doubly sure we're not holding any stale db handles
                 * which might cause a deadlock.
@@ -2040,13 +2062,13 @@ do_select:      force_purge = 0;
                        }
                }
 
-               if (!CtdlThreadCheckStop(CT)) {
+               if (!CtdlThreadCheckStop()) {
                        tv.tv_sec = 1;          /* wake up every second if no input */
                        tv.tv_usec = 0;
                        retval = CtdlThreadSelect(highest + 1, &readfds, NULL, NULL, &tv, CT);
                }
 
-               if (CtdlThreadCheckStop(CT)) return(NULL);
+               if (CtdlThreadCheckStop()) return(NULL);
 
                /* Now figure out who made this select() unblock.
                 * First, check for an error or exit condition.
@@ -2060,7 +2082,7 @@ do_select:        force_purge = 0;
                        if (errno != EINTR) {
                                CtdlLogPrintf(CTDL_EMERG, "Exiting (%s)\n", strerror(errno));
                                CtdlThreadStopAll();
-                       } else if (!CtdlThreadCheckStop(CT)) {
+                       } else if (!CtdlThreadCheckStop()) {
                                CtdlLogPrintf(CTDL_DEBUG, "Un handled select failure.\n");
                                goto do_select;
                        }
index d2ae1b87af3861d5fa93a6fe433fd82a06170959..f2480f47de3bb1ca0aae85fae46ced38b75d1310 100644 (file)
 #include <pthread.h>
 #include <stdarg.h>
 #include "sysdep.h"
+
+#ifdef HAVE_DB_H
+#include <db.h>
+#elif defined(HAVE_DB4_DB_H)
+#include <db4/db.h>
+#else
+#error Neither <db.h> nor <db4/db.h> was found by configure. Install db4-devel.
+#endif
+
+
+#if DB_VERSION_MAJOR < 4 || DB_VERSION_MINOR < 1
+#error Citadel requires Berkeley DB v4.1 or newer.  Please upgrade.
+#endif
+
 #include "server.h"
+#include "database.h"
 
 #if SIZEOF_SIZE_T == SIZEOF_INT 
 #define SIZE_T_FMT "%d"
@@ -96,11 +111,6 @@ extern volatile int restart_server;
 extern int verbosity;
 extern int rescan[];
 
-extern struct worker_node {
-        pthread_t tid;
-        struct worker_node *next;
-} *worker_list;
-
 
 
 /*
@@ -150,14 +160,22 @@ extern struct CtdlThreadNode {
        struct CtdlThreadNode *next;            /* Next thread in the thread table */
 } *CtdlThreadList;
 
+typedef struct {
+       DB_TXN *tid;            /* Transaction handle */
+       DBC *cursors[MAXCDB];   /* Cursors, for traversals... */
+       struct CtdlThreadNode *self;    /* Pointer to this threads control structure */
+}ThreadTSD ;
 
 extern double CtdlThreadLoadAvg;
 extern double CtdlThreadWorkerAvg;
+extern pthread_key_t ThreadKey;
 
+void ctdl_thread_internal_init_tsd(void);
 void ctdl_internal_thread_gc (void);
 void ctdl_thread_internal_init(void);
 void ctdl_thread_internal_cleanup(void);
 void ctdl_thread_internal_calc_loadavg(void);
+void ctdl_thread_internal_free_tsd(void);
 struct CtdlThreadNode *ctdl_internal_create_thread(char *name, long flags, void *(*thread_func) (void *arg), void *args);