* The EUID index is now built, and replication checks are being performed
authorArt Cancro <ajc@citadel.org>
Sun, 2 Oct 2005 04:40:58 +0000 (04:40 +0000)
committerArt Cancro <ajc@citadel.org>
Sun, 2 Oct 2005 04:40:58 +0000 (04:40 +0000)
  using it.  It is much faster now because we don't have to scan the entire
  room anymore.  We still need to do two things:
  1. Write a server command to fetch messages by EUID instead of msgnum
  2. Find a way to purge stale EUID index records.

citadel/ChangeLog
citadel/citadel.h
citadel/database_cleanup.sh
citadel/euidindex.c
citadel/msgbase.c
citadel/msgbase.h
citadel/serv_chat.c
citadel/serv_upgrade.c
citadel/serv_vandelay.c
citadel/serv_vcard.c

index 68f8d76be4e6a48c7bab8cfbbdf50456c90b5ecc..fac7b52334b014bc6e1b0d5256e729296323c000 100644 (file)
@@ -1,4 +1,11 @@
 $Log$
+Revision 655.19  2005/10/02 04:40:58  ajc
+* The EUID index is now built, and replication checks are being performed
+  using it.  It is much faster now because we don't have to scan the entire
+  room anymore.  We still need to do two things:
+  1. Write a server command to fetch messages by EUID instead of msgnum
+  2. Find a way to purge stale EUID index records.
+
 Revision 655.18  2005/10/01 05:18:57  ajc
 * Began writing code to index messages by euid per room
 
@@ -7183,3 +7190,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 78eb2a4cf597b774ad6d2755dd76216b52a7905e..a8f97fe478f2594f79327cae7083a933c60cd96c 100644 (file)
@@ -33,7 +33,7 @@ extern "C" {
 /*
  * Text description of this software
  */
-#define CITADEL        "Citadel 6.55"
+#define CITADEL        "Citadel 6.57"
 
 /*
  * REV_LEVEL is the current version number (multiplied by 100 to avoid having
@@ -45,7 +45,7 @@ extern "C" {
  * usually more strict because you're not really supposed to dump/load and
  * upgrade at the same time.
  */
-#define REV_LEVEL      656             /* This version */
+#define REV_LEVEL      657             /* This version */
 #define REV_MIN                591             /* Oldest compatible database */
 #define EXPORT_REV_MIN 655             /* Oldest compatible export files */
 
index 850dc181d865b2be6c1eb95470490b25526c2c56..4a37bba767035d74882143d15494fa0e34479dab 100755 (executable)
@@ -37,6 +37,10 @@ WARNING #3:
   Please try "db_recover -c" from the data/ directory first.  Use this tool
   only if that one fails to fix your problem.
 
+WARNING #4:
+  You must have an amount of free space on your disk that is at least twice
+  the size of your database.
+
 !
 
 echo -n "Do you want to continue? "
@@ -52,7 +56,7 @@ case "$yesno" in
                exit
 esac
 
-for x in 00 01 02 03 04 05 06 07 08 09
+for x in 00 01 02 03 04 05 06 07 08 09 0a
 do
        filename=cdb.$x
        echo Dumping $filename
index 04c14b91a8982cfe542870e5b13490defcd0f690..62bc53c1206d2ab25ce2b5165cf5a7e0c0fcf829 100644 (file)
 
 
 long locate_message_by_euid(char *euid, struct ctdlroom *qrbuf) {
-       return(0);
+       char *key;
+       int key_len;
+       struct cdbdata *cdb_euid;
+       long msgnum = (-1L);
+
+       lprintf(CTDL_DEBUG, "Searching for EUID <%s> in <%s>\n", euid, qrbuf->QRname);
+
+       key_len = strlen(euid) + sizeof(long) + 1;
+       key = malloc(key_len);
+       memcpy(key, &qrbuf->QRnumber, sizeof(long));
+       strcpy(&key[sizeof(long)], euid);
+
+       cdb_euid = cdb_fetch(CDB_EUIDINDEX, key, key_len);
+       free(key);
+
+       if (cdb_euid == NULL) {
+               return(-1L);
+       }
+
+       if (cdb_euid->len == sizeof(long)) {
+               msgnum = *(long *)cdb_euid->ptr;
+       }
+
+       cdb_free(cdb_euid);
+       lprintf(CTDL_DEBUG, "returning msgnum==%ld\n", msgnum);
+       return(msgnum);
 }
 
 void index_message_by_euid(char *euid, struct ctdlroom *qrbuf, long msgnum) {
@@ -62,6 +87,7 @@ void index_message_by_euid(char *euid, struct ctdlroom *qrbuf, long msgnum) {
        strcpy(&key[sizeof(long)], euid);
 
        cdb_store(CDB_EUIDINDEX, key, key_len, &msgnum, sizeof(long));
+       free(key);
 }
 
 
index 3bca31e77ca845a049816849bf9cb23f22078a0a..71a769022a54381cc694fbc992a3b8765ac5a0a1 100644 (file)
@@ -1772,8 +1772,14 @@ void cmd_opna(char *cmdbuf)
  * Save a message pointer into a specified room
  * (Returns 0 for success, nonzero for failure)
  * roomname may be NULL to use the current room
+ *
+ * Note that the 'supplied_msg' field may be set to NULL, in which case
+ * the message will be fetched from disk, by number, if we need to perform
+ * replication checks.  This adds an additional database read, so if the
+ * caller already has the message in memory then it should be supplied.
  */
-int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) {
+int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check,
+                               struct CtdlMessage *supplied_msg) {
        int i;
        char hold_rm[ROOMNAMELEN];
        struct cdbdata *cdbfr;
@@ -1782,37 +1788,34 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) {
        long highest_msg = 0L;
        struct CtdlMessage *msg = NULL;
 
-       lprintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom(%s, %ld, %d)\n",
-               roomname, msgid, flags);
+       lprintf(CTDL_DEBUG, "CtdlSaveMsgPointerInRoom(roomname=%s, msgid=%ld, do_repl_check=%d)\n",
+               roomname, msgid, do_repl_check);
 
        strcpy(hold_rm, CC->room.QRname);
 
        /* We may need to check to see if this message is real */
-       if (  (flags & SM_VERIFY_GOODNESS)
-          || (flags & SM_DO_REPL_CHECK)
-          ) {
-               msg = CtdlFetchMessage(msgid, 1);
+       if (do_repl_check) {
+               if (supplied_msg != NULL) {
+                       msg = supplied_msg;
+               }
+               else {
+                       msg = CtdlFetchMessage(msgid, 0);
+               }
                if (msg == NULL) return(ERROR + ILLEGAL_VALUE);
        }
 
        /* Perform replication checks if necessary */
-       if ( (flags & SM_DO_REPL_CHECK) && (msg != NULL) ) {
+       if ( (do_repl_check) && (msg != NULL) ) {
 
                if (getroom(&CC->room,
                   ((roomname != NULL) ? roomname : CC->room.QRname) )
                   != 0) {
                        lprintf(CTDL_ERR, "No such room <%s>\n", roomname);
-                       if (msg != NULL) CtdlFreeMessage(msg);
+                       if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
                        return(ERROR + ROOM_NOT_FOUND);
                }
 
-               if (ReplicationChecks(msg) != 0) {
-                       getroom(&CC->room, hold_rm);
-                       if (msg != NULL) CtdlFreeMessage(msg);
-                       lprintf(CTDL_DEBUG,
-                               "Did replication, and newer exists\n");
-                       return(0);
-               }
+               ReplicationChecks(msg);
        }
 
        /* Now the regular stuff */
@@ -1820,7 +1823,7 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) {
           ((roomname != NULL) ? roomname : CC->room.QRname) )
           != 0) {
                lprintf(CTDL_ERR, "No such room <%s>\n", roomname);
-               if (msg != NULL) CtdlFreeMessage(msg);
+               if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
                return(ERROR + ROOM_NOT_FOUND);
        }
 
@@ -1846,7 +1849,7 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) {
                if (msglist[i] == msgid) {
                        lputroom(&CC->room);    /* unlock the room */
                        getroom(&CC->room, hold_rm);
-                       if (msg != NULL) CtdlFreeMessage(msg);
+                       if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
                        free(msglist);
                        return(ERROR + ALREADY_EXISTS);
                }
@@ -1880,12 +1883,17 @@ int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags) {
        getroom(&CC->room, hold_rm);
 
        /* Bump the reference count for this message. */
-       if ((flags & SM_DONT_BUMP_REF)==0) {
-               AdjRefCount(msgid, +1);
+       AdjRefCount(msgid, +1);
+
+       /* If the message has an Exclusive ID, index that... */
+       if (msg != NULL) {
+               if (msg->cm_fields['E'] != NULL) {
+                       index_message_by_euid(msg->cm_fields['E'], &CC->room, msgid);
+               }
        }
 
        /* Return success. */
-       if (msg != NULL) CtdlFreeMessage(msg);
+       if ( (msg != NULL) && (msg != supplied_msg) ) CtdlFreeMessage(msg);
        return (0);
 }
 
@@ -2013,37 +2021,23 @@ void serialize_message(struct ser_ret *ret,             /* return values */
 
 
 /*
- * Back end for the ReplicationChecks() function
+ * Check to see if any messages already exist in the current room which
+ * carry the same Exclusive ID as this one.  If any are found, delete them.
  */
-void check_repl(long msgnum, void *userdata) {
-       lprintf(CTDL_DEBUG, "check_repl() replacing message %ld\n", msgnum);
-       CtdlDeleteMessages(CC->room.QRname, msgnum, "", 0);
-}
-
-
-/*
- * Check to see if any messages already exist which carry the same Exclusive ID
- * as this one.  If any are found, delete them.
- *
- */
-int ReplicationChecks(struct CtdlMessage *msg) {
-       struct CtdlMessage *template;
-       int abort_this = 0;
+void ReplicationChecks(struct CtdlMessage *msg) {
+       long old_msgnum = (-1L);
 
        /* No exclusive id?  Don't do anything. */
-       if (msg->cm_fields['E'] == NULL) return 0;
-       if (strlen(msg->cm_fields['E']) == 0) return 0;
+       if (msg == NULL) return;
+       if (msg->cm_fields['E'] == NULL) return;
+       if (strlen(msg->cm_fields['E']) == 0) return;
        lprintf(CTDL_DEBUG, "Exclusive ID: <%s>\n", msg->cm_fields['E']);
 
-       template = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage));
-       memset(template, 0, sizeof(struct CtdlMessage));
-       template->cm_fields['E'] = strdup(msg->cm_fields['E']);
-
-       CtdlForEachMessage(MSGS_ALL, 0L, NULL, template, check_repl, NULL);
-
-       CtdlFreeMessage(template);
-       lprintf(CTDL_DEBUG, "ReplicationChecks() returning %d\n", abort_this);
-       return(abort_this);
+       old_msgnum = locate_message_by_euid(msg->cm_fields['E'], &CC->room);
+       if (old_msgnum > 0L) {
+               lprintf(CTDL_DEBUG, "ReplicationChecks() replacing message %ld\n", old_msgnum);
+               CtdlDeleteMessages(CC->room.QRname, old_msgnum, "", 0);
+       }
 }
 
 
@@ -2186,7 +2180,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
 
        /* If this message has an Exclusive ID, perform replication checks */
        lprintf(CTDL_DEBUG, "Performing replication checks\n");
-       if (ReplicationChecks(msg) > 0) return(-4);
+       ReplicationChecks(msg);
 
        /* Save it to disk */
        lprintf(CTDL_DEBUG, "Saving to disk\n");
@@ -2235,17 +2229,16 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,     /* message to save */
         * is no local sender; it would otherwise go to the Trashcan).
         */
        if ((!CC->internal_pgm) || (recps == NULL)) {
-               if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0) != 0) {
+               if (CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 1, msg) != 0) {
                        lprintf(CTDL_ERR, "ERROR saving message pointer!\n");
-                       CtdlSaveMsgPointerInRoom(config.c_aideroom,
-                                                       newmsgid, 0);
+                       CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg);
                }
        }
 
        /* For internet mail, drop a copy in the outbound queue room */
        if (recps != NULL)
         if (recps->num_internet > 0) {
-               CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, newmsgid, 0);
+               CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, newmsgid, 0, msg);
        }
 
        /* If other rooms are specified, drop them there too. */
@@ -2255,7 +2248,7 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,       /* message to save */
                extract_token(recipient, recps->recp_room, i,
                                        '|', sizeof recipient);
                lprintf(CTDL_DEBUG, "Delivering to room <%s>\n", recipient);
-               CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0);
+               CtdlSaveMsgPointerInRoom(recipient, newmsgid, 0, msg);
        }
 
        /* Bump this user's messages posted counter. */
@@ -2277,13 +2270,12 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,     /* message to save */
                if (getuser(&userbuf, recipient) == 0) {
                        MailboxName(actual_rm, sizeof actual_rm,
                                        &userbuf, MAILROOM);
-                       CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0);
+                       CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
                        BumpNewMailCounter(userbuf.usernum);
                }
                else {
                        lprintf(CTDL_DEBUG, "No user <%s>\n", recipient);
-                       CtdlSaveMsgPointerInRoom(config.c_aideroom,
-                                                       newmsgid, 0);
+                       CtdlSaveMsgPointerInRoom(config.c_aideroom, newmsgid, 0, msg);
                }
        }
 
@@ -3258,8 +3250,7 @@ void cmd_dele(char *delstr)
 int CtdlCopyMsgToRoom(long msgnum, char *dest) {
        int err;
 
-       err = CtdlSaveMsgPointerInRoom(dest, msgnum,
-               (SM_VERIFY_GOODNESS | SM_DO_REPL_CHECK) );
+       err = CtdlSaveMsgPointerInRoom(dest, msgnum, 1, NULL);
        if (err != 0) return(err);
 
        return(0);
index ad232cf0552db6ee4c1c1fa4627091632ebc191a..ead3bbf2daa89115a382ae0f42d9232ccd5e641a 100644 (file)
 #define MSGS_GT         5
 #define MSGS_EQ                6
 
-/*
- * Flags which may be passed to CtdlSaveMsgPointerInRoom()
- */
-#define SM_VERIFY_GOODNESS     1       /* Verify this is a real msg number */
-#define SM_DO_REPL_CHECK       2       /* Perform replication checks */
-#define SM_DONT_BUMP_REF       4       /* Don't bump reference count
-                                          (use with extreme care!!!!!!) */
-
-
 /*
  * Possible return codes from CtdlOutputMsg()
  */
@@ -117,8 +108,8 @@ struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body);
 void CtdlFreeMessage(struct CtdlMessage *msg);
 void serialize_message(struct ser_ret *, struct CtdlMessage *);
 int is_valid_message(struct CtdlMessage *);
-int ReplicationChecks(struct CtdlMessage *);
-int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int flags);
+void ReplicationChecks(struct CtdlMessage *);
+int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check, struct CtdlMessage *msg);
 char *CtdlReadMessageBody(char *terminator, size_t maxlen, char *exist, int crlf);
 char *CtdlGetSysConfig(char *sysconfname);
 void CtdlPutSysConfig(char *sysconfname, char *sysconfdata);
index b323dab7a5590a46f2a9efb93afc0fe6bcc11373..ce6f7324b08e7a1a8c2ec5d122368ee8cb4c6758 100644 (file)
@@ -639,7 +639,7 @@ int send_instant_message(char *lun, char *x_user, char *x_msg)
                /* Now save a copy in the global log room, if configured */
                if (strlen(config.c_logpages) > 0) {
                        create_room(config.c_logpages, 3, "", 0, 1, 1, VIEW_BBS);
-                       CtdlSaveMsgPointerInRoom(config.c_logpages, msgnum, 0);
+                       CtdlSaveMsgPointerInRoom(config.c_logpages, msgnum, 0, NULL);
                }
 
                /* Save a copy in each recipient's log room, creating those
@@ -649,7 +649,7 @@ int send_instant_message(char *lun, char *x_user, char *x_msg)
                 */
                while (sl != NULL) {
                        create_room(sl->roomname, 5, "", 0, 1, 1, VIEW_BBS);
-                       CtdlSaveMsgPointerInRoom(sl->roomname, msgnum, 0);
+                       CtdlSaveMsgPointerInRoom(sl->roomname, msgnum, 0, NULL);
                        sptr = sl->next;
                        free(sl);
                        sl = sptr;
index db92fbf2de04e9e9c1c29a46bc934c3d76208758..19aff117f89e8a97932c806584b8b3c3e92ff3fd 100644 (file)
@@ -217,6 +217,9 @@ void check_server_upgrades(void) {
        if ((CitControl.version > 000) && (CitControl.version < 608)) {
                convert_ctdluid_to_minusone();
        }
+       if ((CitControl.version > 000) && (CitControl.version < 657)) {
+               rebuild_euid_index();
+       }
 
        CitControl.version = REV_LEVEL;
        put_control();
@@ -226,6 +229,5 @@ void check_server_upgrades(void) {
 char *serv_upgrade_init(void)
 {
        check_server_upgrades();
-       rebuild_euid_index();   /* FIXME */
        return "$Id$";
 }
index 5f4de4aca0d0c01ae168569fa484cc38747f2919..49f5ed9de98e8e6853d38b38694b06449f827729 100644 (file)
@@ -43,6 +43,7 @@
 #include "user_ops.h"
 #include "room_ops.h"
 #include "control.h"
+#include "euidindex.h"
 
 #define END_OF_MESSAGE "---eom---dbd---"
 
@@ -460,7 +461,7 @@ void artv_import_room(void) {
         * one per line terminated by a 0.
         */
        while (client_getln(buf, sizeof buf), msgnum = atol(buf), msgnum > 0) {
-               CtdlSaveMsgPointerInRoom(qrbuf.QRname, msgnum, 0);
+               CtdlSaveMsgPointerInRoom(qrbuf.QRname, msgnum, 0, NULL);
                ++msgcount;
        }
        lprintf(CTDL_INFO, "(%d messages)\n", msgcount);
@@ -590,6 +591,7 @@ void artv_do_import(void) {
        }
        lprintf(CTDL_INFO, "Invalid keyword <%s>.  Flushing input.\n", buf);
        while (client_getln(buf, sizeof buf), strcmp(buf, "000"))  ;;
+       rebuild_euid_index();
 }
 
 
index 86e5afd3dc24d6e7d425afa37e50ad88722e214a..0c35d8c188996f55a01be54da04457790d44b85b 100644 (file)
@@ -455,8 +455,7 @@ int vcard_upload_aftersave(struct CtdlMessage *msg) {
                        vcard_free(v);
 
                        /* Put it in the Global Address Book room... */
-                       CtdlSaveMsgPointerInRoom(ADDRESS_BOOK_ROOM, I,
-                               (SM_VERIFY_GOODNESS | SM_DO_REPL_CHECK) );
+                       CtdlSaveMsgPointerInRoom(ADDRESS_BOOK_ROOM, I, 1, msg);
 
                        /* ...and also in the directory database. */
                        vcard_add_to_directory(I, NULL);