]> code.citadel.org Git - citadel.git/blobdiff - citadel/server/modules/expire/serv_expire.c
Remediated an unrecoverable problem in CDB_USETABLE.
[citadel.git] / citadel / server / modules / expire / serv_expire.c
index ff1f9455276c42b9996aee4e6be081fbdd0b2bc5..abcf62b121f8e57d6984da64ad377211f2d26020 100644 (file)
@@ -2,17 +2,10 @@
 //
 // You might also see this module affectionately referred to as TDAP (The Dreaded Auto-Purger).
 //
-// Copyright (c) 1988-2022 by citadel.org (Art Cancro, Wilifried Goesgens, and others)
+// Copyright (c) 1988-2023 by citadel.org (Art Cancro, Wilifried Goesgens, and others)
 //
-// This program is open source software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as published
-// by the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU General Public License for more details.
+// This program is open source software.  Use, duplication, or disclosure
+// is subject to the terms of the GNU General Public License, version 3.
 
 
 #include "../../sysdep.h"
@@ -29,7 +22,7 @@
 #include <string.h>
 #include <limits.h>
 #include <libcitadel.h>
-#include "../../citadel.h"
+#include "../../citadel_defs.h"
 #include "../../server.h"
 #include "../../citserver.h"
 #include "../../support.h"
@@ -73,11 +66,6 @@ struct ctdlroomref {
        long msgnum;
 };
 
-struct UPurgeList {
-       struct UPurgeList *next;
-       char up_key[256];
-};
-
 struct EPurgeList {
        struct EPurgeList *next;
        int ep_keylen;
@@ -320,14 +308,13 @@ int PurgeRooms(void) {
        while (RoomPurgeList != NULL) {
                if (CtdlGetRoom(&qrbuf, RoomPurgeList->name) == 0) {
                        transcript=realloc(transcript, strlen(transcript)+SIZ);
-                       snprintf(&transcript[strlen(transcript)], SIZ, " %s\n",
-                               qrbuf.QRname);
+                       snprintf(&transcript[strlen(transcript)], SIZ, " %s\n", qrbuf.QRname);
                        CtdlDeleteRoom(&qrbuf);
+                       ++num_rooms_purged;
                }
                pptr = RoomPurgeList->next;
                free(RoomPurgeList);
                RoomPurgeList = pptr;
-               ++num_rooms_purged;
        }
 
        if (num_rooms_purged > 0) CtdlAideMessage(transcript, "Room Autopurger Message");
@@ -464,8 +451,7 @@ int PurgeUsers(void) {
                strcpy(transcript, "The following users have been auto-purged:\n");
                while (UserPurgeList != NULL) {
                        transcript=realloc(transcript, strlen(transcript)+SIZ);
-                       snprintf(&transcript[strlen(transcript)], SIZ, " %s\n",
-                               UserPurgeList->name);
+                       snprintf(&transcript[strlen(transcript)], SIZ, " %s\n", UserPurgeList->name);
                        purge_user(UserPurgeList->name);
                        pptr = UserPurgeList->next;
                        free(UserPurgeList);
@@ -503,11 +489,11 @@ int PurgeUsers(void) {
 // traverse the visit file, checking each record against those two lists and
 // purging the ones that do not have a match on _both_ lists.  (Remember, if
 // either the room or user being referred to is no longer on the system, the
-// record is completely useless.)
+// record is useless and should be removed.)
 //
 int PurgeVisits(void) {
        struct cdbdata *cdbvisit;
-       visit vbuf;
+       struct visit vbuf;
        struct VPurgeList *VisitPurgeList = NULL;
        struct VPurgeList *vptr;
        int purged = 0;
@@ -526,10 +512,10 @@ int PurgeVisits(void) {
        // Now traverse through the visits, purging irrelevant records...
        cdb_rewind(CDB_VISIT);
        while(cdbvisit = cdb_next_item(CDB_VISIT), cdbvisit != NULL) {
-               memset(&vbuf, 0, sizeof(visit));
+               memset(&vbuf, 0, sizeof(struct visit));
                memcpy(&vbuf, cdbvisit->ptr,
-                       ( (cdbvisit->len > sizeof(visit)) ?
-                         sizeof(visit) : cdbvisit->len) );
+                       ( (cdbvisit->len > sizeof(struct visit)) ?
+                         sizeof(struct visit) : cdbvisit->len) );
                cdb_free(cdbvisit);
 
                RoomIsValid = 0;
@@ -593,18 +579,20 @@ int PurgeVisits(void) {
 
 
 // Purge the use table of old entries.
+// Holy crap, this is WAY better.  We need to replace most linked lists with arrays.
 int PurgeUseTable(StrBuf *ErrMsg) {
        int purged = 0;
+       int total = 0;
        struct cdbdata *cdbut;
        struct UseTable ut;
-       struct UPurgeList *ul = NULL;
-       struct UPurgeList *uptr; 
+       Array *purge_list = array_new(sizeof(int));
 
        // Phase 1: traverse through the table, discovering old records...
 
        syslog(LOG_DEBUG, "Purge use table: phase 1");
        cdb_rewind(CDB_USETABLE);
        while(cdbut = cdb_next_item(CDB_USETABLE), cdbut != NULL) {
+               ++total;
                if (cdbut->len > sizeof(struct UseTable))
                        memcpy(&ut, cdbut->ptr, sizeof(struct UseTable));
                else {
@@ -613,28 +601,22 @@ int PurgeUseTable(StrBuf *ErrMsg) {
                }
                cdb_free(cdbut);
 
-               if ( (time(NULL) - ut.ut_timestamp) > USETABLE_RETAIN ) {
-                       uptr = (struct UPurgeList *) malloc(sizeof(struct UPurgeList));
-                       if (uptr != NULL) {
-                               uptr->next = ul;
-                               safestrncpy(uptr->up_key, ut.ut_msgid, sizeof uptr->up_key);
-                               ul = uptr;
-                       }
+               if ( (time(NULL) - ut.timestamp) > USETABLE_RETAIN ) {
+                       array_append(purge_list, &ut.hash);
                        ++purged;
                }
-
        }
 
        // Phase 2: delete the records
        syslog(LOG_DEBUG, "Purge use table: phase 2");
-       while (ul != NULL) {
-               cdb_delete(CDB_USETABLE, ul->up_key, strlen(ul->up_key));
-               uptr = ul->next;
-               free(ul);
-               ul = uptr;
+       int i;
+       for (i=0; i<purged; ++i) {
+               struct UseTable *u = (struct UseTable *)array_get_element_at(purge_list, i);
+               cdb_delete(CDB_USETABLE, &u->hash, sizeof(int));
        }
+       array_free(purge_list);
 
-       syslog(LOG_DEBUG, "Purge use table: finished (purged %d records)", purged);
+       syslog(LOG_DEBUG, "Purge use table: finished (purged %d of %d records)", purged, total);
        return(purged);
 }
 
@@ -690,49 +672,6 @@ int PurgeEuidIndexTable(void) {
 }
 
 
-// Purge external auth assocations for missing users (theoretically this will never delete anything)
-int PurgeStaleExtAuthAssociations(void) {
-       struct cdbdata *cdboi;
-       struct ctdluser usbuf;
-       HashList *keys = NULL;
-       HashPos *HashPos;
-       char *deleteme = NULL;
-       long len;
-       void *Value;
-       const char *Key;
-       int num_deleted = 0;
-       long usernum = 0L;
-
-       keys = NewHash(1, NULL);
-       if (!keys) return(0);
-
-       cdb_rewind(CDB_EXTAUTH);
-       while (cdboi = cdb_next_item(CDB_EXTAUTH), cdboi != NULL) {
-               if (cdboi->len > sizeof(long)) {
-                       memcpy(&usernum, cdboi->ptr, sizeof(long));
-                       if (CtdlGetUserByNumber(&usbuf, usernum) != 0) {
-                               deleteme = strdup(cdboi->ptr + sizeof(long)),
-                               Put(keys, deleteme, strlen(deleteme), deleteme, NULL);
-                       }
-               }
-               cdb_free(cdboi);
-       }
-
-       // Go through the hash list, deleting keys we stored in it
-
-       HashPos = GetNewHashPos(keys, 0);
-       while (GetNextHashPos(keys, HashPos, &len, &Key, &Value)!=0) {
-               syslog(LOG_DEBUG, "Deleting associated external authenticator <%s>",  (char*)Value);
-               cdb_delete(CDB_EXTAUTH, Value, strlen(Value));
-               // note: don't free(Value) -- deleting the hash list will handle this for us
-               ++num_deleted;
-       }
-       DeleteHashPos(&HashPos);
-       DeleteHash(&keys);
-       return num_deleted;
-}
-
-
 void purge_databases(void) {
        int retval;
        static time_t last_purge = 0;
@@ -783,11 +722,6 @@ void purge_databases(void) {
                        syslog(LOG_NOTICE, "Purged %d entries from the EUID index.", retval);
        }
 
-       if (!server_shutting_down) {
-               retval = PurgeStaleExtAuthAssociations();
-               syslog(LOG_NOTICE, "Purged %d stale external auth associations.", retval);
-       }
-
        //if (!server_shutting_down) {
        //      FIXME this is where we could do a non-interactive delete of zero-refcount messages
        //}