IMAP COPY messages in bulk. I think it works
authorArt Cancro <ajc@citadel.org>
Thu, 18 May 2006 03:08:26 +0000 (03:08 +0000)
committerArt Cancro <ajc@citadel.org>
Thu, 18 May 2006 03:08:26 +0000 (03:08 +0000)
but it needs lots more testing.

citadel/imap_misc.c
citadel/msgbase.c
citadel/msgbase.h

index ab292c58673bf2d1c26a0f85c0372d4076c4405d..a4b7daa003b56e5ad844b89f4302673212869332 100644 (file)
@@ -64,6 +64,7 @@ int imap_do_copy(char *destination_folder) {
        char roomname[ROOMNAMELEN];
        struct ctdlroom qrbuf;
        struct timeval tv1, tv2, tv3;
+       long *selected_msgs = NULL;
        int num_selected = 0;
 
        if (IMAP->num_msgs < 1) {
@@ -74,27 +75,24 @@ int imap_do_copy(char *destination_folder) {
        if (i != 0) return(i);
 
        /*
-        * Optimization note ... ajc 2005oct09
-        * 
-        * As we can see below, we're going to end up making lots of
-        * repeated calls to CtdlCopyMsgToRoom() if the user selects
-        * multiple messages and then does a copy or move operation.
-        *
-        * The plan (documented in this comment so I don't forget what I was
-        * going to do) is to refactor CtdlCopyMsgToRoom() so that it accepts
-        * a list of message ID's instead of a single one.  Then we can alter
-        * the code which appears below, to copy all the message pointers in
-        * one shot.
-        * 
+        * Copy all the message pointers in one shot.
         */
        gettimeofday(&tv1, NULL);
+
+       selected_msgs = malloc(sizeof(long) * IMAP->num_msgs);
+       if (selected_msgs == NULL) return(-1);
+
        for (i = 0; i < IMAP->num_msgs; ++i) {
                if (IMAP->flags[i] & IMAP_SELECTED) {
-                       ++num_selected;
-                       CtdlCopyMsgToRoom(IMAP->msgids[i], roomname);
+                       selected_msgs[num_selected++] = IMAP->msgids[i];
                }
        }
 
+       if (num_selected > 0) {
+               CtdlCopyMsgsToRoom(selected_msgs, num_selected, roomname);
+       }
+       free(selected_msgs);
+
        /* Don't bother wasting any more time if there were no messages. */
        if (num_selected == 0) {
                return(0);
index 77a56668d579cc13004935b5a28753bf391b3ace..7c47bb2a8b96121d8a9e35e291169ac7d7d7b05f 100644 (file)
@@ -3443,18 +3443,26 @@ void cmd_dele(char *delstr)
 
 
 /*
- * Back end API function for moves and deletes
+ * Back end API function for moves and deletes (multiple messages)
  */
-int CtdlCopyMsgToRoom(long msgnum, char *dest) {
+int CtdlCopyMsgsToRoom(long *msgnums, int num_msgs, char *dest) {
        int err;
 
-       err = CtdlSaveMsgPointerInRoom(dest, msgnum, 1, NULL);
+       err = CtdlSaveMsgPointersInRoom(dest, msgnums, num_msgs, 1, NULL);
        if (err != 0) return(err);
 
        return(0);
 }
 
 
+/*
+ * Back end API function for moves and deletes (single message)
+ */
+int CtdlCopyMsgToRoom(long msgnum, char *dest) {
+       return CtdlCopyMsgsToRoom(&msgnum, 1, dest);
+}
+
+
 
 /*
  * move or copy a message to another room
index 1f1500a035feab6e8e78699b8de2103a9c97b5ee..4282a75e40baf0af33858a130a8ad60ceca49a99 100644 (file)
@@ -112,6 +112,8 @@ void CtdlFreeMessage(struct CtdlMessage *msg);
 void serialize_message(struct ser_ret *, struct CtdlMessage *);
 int is_valid_message(struct CtdlMessage *);
 void ReplicationChecks(struct CtdlMessage *);
+int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newmsgs,
+                               int do_repl_check, struct CtdlMessage *supplied_msg);
 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);
@@ -129,6 +131,7 @@ int CtdlOutputPreLoadedMsg(struct CtdlMessage *,
                int do_proto,           /* do Citadel protocol responses? */
                int crlf                /* 0=LF, 1=CRLF */
 );
+int CtdlCopyMsgsToRoom(long *msgnum, int num_msgs, char *dest);
 int CtdlCopyMsgToRoom(long msgnum, char *dest);
 int CtdlDoIHavePermissionToDeleteMessagesFromThisRoom(void);
 int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, size_t n);