From: Art Cancro Date: Fri, 28 Jul 2006 03:30:57 +0000 (+0000) Subject: CtdlDeleteMessages() now has a bulk API. Updated all of the X-Git-Tag: v7.86~3976 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=ea1849b79ff5c285db6c12eb7e410934c2ac2a05 CtdlDeleteMessages() now has a bulk API. Updated all of the callers to use it. Also updated the IMAP and POP3 expunge functions to actually make use of the bulk delete. This should significantly improve performance when used with large folders. --- diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 3934cd290..a95ecd450 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -2165,7 +2165,7 @@ void ReplicationChecks(struct CtdlMessage *msg) { 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); + CtdlDeleteMessages(CC->room.QRname, &old_msgnum, 1, "", 0); } } @@ -3295,7 +3295,8 @@ void cmd_ent0(char *entargs) * (returns the actual number of messages deleted) */ int CtdlDeleteMessages(char *room_name, /* which room */ - long dmsgnum, /* or "0" for any */ + long *dmsgnums, /* array of msg numbers to be deleted */ + int num_dmsgnums, /* number of msgs to be deleted, or 0 for "any" */ char *content_type, /* or "" for any */ int deferred /* let TDAP sweep it later */ ) @@ -3306,13 +3307,13 @@ int CtdlDeleteMessages(char *room_name, /* which room */ long *msglist = NULL; long *dellist = NULL; int num_msgs = 0; - int i; + int i, j; int num_deleted = 0; int delete_this; struct MetaData smi; - lprintf(CTDL_DEBUG, "CtdlDeleteMessages(%s, %ld, %s, %d)\n", - room_name, dmsgnum, content_type, deferred); + lprintf(CTDL_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s, %d)\n", + room_name, num_dmsgnums, content_type, deferred); /* get room record, obtaining a lock... */ if (lgetroom(&qrbuf, room_name) != 0) { @@ -3335,9 +3336,20 @@ int CtdlDeleteMessages(char *room_name, /* which room */ /* Set/clear a bit for each criterion */ - if ((dmsgnum == 0L) || (msglist[i] == dmsgnum)) { + /* 0 messages in the list or a null list means that we are + * interested in deleting any messages which meet the other criteria. + */ + if ((num_dmsgnums == 0) || (dmsgnums == NULL)) { delete_this |= 0x01; } + else { + for (j=0; jroom.QRname, delnum, "", 1); + num_deleted = CtdlDeleteMessages(CC->room.QRname, &delnum, 1, "", 1); if (num_deleted) { cprintf("%d %d message%s deleted.\n", CIT_OK, @@ -3532,7 +3544,7 @@ void cmd_move(char *args) * if this is a 'move' rather than a 'copy' operation. */ if (is_copy == 0) { - CtdlDeleteMessages(CC->room.QRname, num, "", 0); + CtdlDeleteMessages(CC->room.QRname, &num, 1, "", 0); } cprintf("%d Message %s.\n", CIT_OK, (is_copy ? "copied" : "moved") ); @@ -3742,7 +3754,7 @@ void CtdlWriteObject(char *req_room, /* Room to stuff it in */ */ if (is_unique) { lprintf(CTDL_DEBUG, "Deleted %d other msgs of this type\n", - CtdlDeleteMessages(roomname, 0L, content_type, 0) + CtdlDeleteMessages(roomname, NULL, 0, content_type, 0) ); } /* Now write the data */ diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 4282a75e4..49571ba7b 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -104,7 +104,7 @@ int CtdlForEachMessage(int mode, long ref, struct CtdlMessage *compare, void (*CallBack) (long, void *), void *userdata); -int CtdlDeleteMessages(char *, long, char *, int); +int CtdlDeleteMessages(char *, long *, int, char *, int); void CtdlWriteObject(char *, char *, char *, struct ctdluser *, int, int, unsigned int); struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body); diff --git a/citadel/room_ops.c b/citadel/room_ops.c index 9386c7d0d..17dd4ff9e 100644 --- a/citadel/room_ops.c +++ b/citadel/room_ops.c @@ -1607,7 +1607,7 @@ void delete_room(struct ctdlroom *qrbuf) /* Delete the messages in the room * (Careful: this opens an S_ROOMS critical section!) */ - CtdlDeleteMessages(qrbuf->QRname, 0L, "", 0); + CtdlDeleteMessages(qrbuf->QRname, NULL, 0, "", 0); /* Flag the room record as not in use */ lgetroom(qrbuf, qrbuf->QRname); diff --git a/citadel/serv_calendar.c b/citadel/serv_calendar.c index 56d8294b1..596271cc9 100644 --- a/citadel/serv_calendar.c +++ b/citadel/serv_calendar.c @@ -430,7 +430,7 @@ void ical_respond(long msgnum, char *partnum, char *action) { /* Now that we've processed this message, we don't need it * anymore. So delete it. */ - CtdlDeleteMessages(CC->room.QRname, msgnum, "", 1); + CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "", 1); /* Free the memory we allocated and return a response. */ icalcomponent_free(ird.cal); @@ -777,7 +777,7 @@ void ical_handle_rsvp(long msgnum, char *partnum, char *action) { /* Now that we've processed this message, we don't need it * anymore. So delete it. (Maybe make this optional?) */ - CtdlDeleteMessages(CC->room.QRname, msgnum, "", 1); + CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "", 1); /* Free the memory we allocated and return a response. */ icalcomponent_free(ird.cal); @@ -1473,7 +1473,7 @@ void ical_putics(void) * the entire calendar with an entire new (or updated) calendar. * (Careful: this opens an S_ROOMS critical section!) */ - CtdlDeleteMessages(CC->room.QRname, 0L, "", 0); + CtdlDeleteMessages(CC->room.QRname, NULL, 0, "", 0); /* If the top-level component is *not* a VCALENDAR, we can drop it right * in. This will almost never happen. diff --git a/citadel/serv_expire.c b/citadel/serv_expire.c index 5b6fda96a..28b0968de 100644 --- a/citadel/serv_expire.c +++ b/citadel/serv_expire.c @@ -212,7 +212,7 @@ void DoPurgeMessages(FILE *purgelist) { if (!strncasecmp(buf, "m=", 2)) { msgnum = atol(&buf[2]); if (msgnum > 0L) { - CtdlDeleteMessages(roomname, msgnum, "", 0); + CtdlDeleteMessages(roomname, &msgnum, 1, "", 0); } } } diff --git a/citadel/serv_imap.c b/citadel/serv_imap.c index f8edbb8e3..fd64162af 100644 --- a/citadel/serv_imap.c +++ b/citadel/serv_imap.c @@ -706,26 +706,30 @@ void imap_select(int num_parms, char *parms[]) /* * Does the real work for expunge. - * FIXME do this with the new bulk API */ int imap_do_expunge(void) { int i; int num_expunged = 0; + long *delmsgs = NULL; + int num_delmsgs = 0; lprintf(CTDL_DEBUG, "imap_do_expunge() called\n"); if (IMAP->selected == 0) { return (0); } - if (IMAP->num_msgs > 0) + if (IMAP->num_msgs > 0) { + delmsgs = malloc(IMAP->num_msgs * sizeof(long)); for (i = 0; i < IMAP->num_msgs; ++i) { if (IMAP->flags[i] & IMAP_DELETED) { - CtdlDeleteMessages(CC->room.QRname, - IMAP->msgids[i], "", 1); - ++num_expunged; + delmsgs[num_delmsgs++] = IMAP->msgids[i]; } } + CtdlDeleteMessages(CC->room.QRname, delmsgs, num_delmsgs, "", 1); + num_expunged += num_delmsgs; + free(delmsgs); + } if (num_expunged > 0) { imap_rescan_msgids(); diff --git a/citadel/serv_network.c b/citadel/serv_network.c index 01220281a..27704f103 100644 --- a/citadel/serv_network.c +++ b/citadel/serv_network.c @@ -865,7 +865,7 @@ void network_spool_msg(long msgnum, void *userdata) { /* Delete this message if delete-after-send is set */ if (delete_after_send) { - CtdlDeleteMessages(CC->room.QRname, msgnum, "", 0); + CtdlDeleteMessages(CC->room.QRname, &msgnum, 1, "", 0); } } diff --git a/citadel/serv_pop3.c b/citadel/serv_pop3.c index 684611277..a015e429d 100644 --- a/citadel/serv_pop3.c +++ b/citadel/serv_pop3.c @@ -466,12 +466,19 @@ void pop3_update(void) { int i; struct visit vbuf; + long *deletemsgs = NULL; + int num_deletemsgs = 0; + /* Remove messages marked for deletion */ - if (POP3->num_msgs > 0) for (i=0; inum_msgs; ++i) { - if (POP3->msgs[i].deleted) { - CtdlDeleteMessages(MAILROOM, - POP3->msgs[i].msgnum, "", 1); + if (POP3->num_msgs > 0) { + deletemsgs = malloc(POP3->num_msgs * sizeof(long)); + for (i=0; inum_msgs; ++i) { + if (POP3->msgs[i].deleted) { + deletemsgs[num_deletemsgs++] = POP3->msgs[i].msgnum; + } } + CtdlDeleteMessages(MAILROOM, deletemsgs, num_deletemsgs, "", 1); + free(deletemsgs); } /* Set last read pointer */ diff --git a/citadel/serv_smtp.c b/citadel/serv_smtp.c index dfa9c65bf..e1a933475 100644 --- a/citadel/serv_smtp.c +++ b/citadel/serv_smtp.c @@ -1641,17 +1641,18 @@ void smtp_do_procmsg(long msgnum, void *userdata) { * message and the message message. */ if (incomplete_deliveries_remaining <= 0) { - CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "", 0); - CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, text_msgid, "", 0); + long delmsgs[2]; + delmsgs[0] = msgnum; + delmsgs[1] = text_msgid; + CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, delmsgs, 2, "", 0); } - /* * Uncompleted delivery instructions remain, so delete the old * instructions and replace with the updated ones. */ if (incomplete_deliveries_remaining > 0) { - CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, msgnum, "", 0); + CtdlDeleteMessages(SMTP_SPOOLOUT_ROOM, &msgnum, 1, "", 0); msg = malloc(sizeof(struct CtdlMessage)); memset(msg, 0, sizeof(struct CtdlMessage)); msg->cm_magic = CTDLMESSAGE_MAGIC; diff --git a/citadel/serv_vcard.c b/citadel/serv_vcard.c index c49ca6b6c..51f7b29f5 100644 --- a/citadel/serv_vcard.c +++ b/citadel/serv_vcard.c @@ -323,7 +323,7 @@ int vcard_upload_beforesave(struct CtdlMessage *msg) { * vCard in the user's config room at all times. */ CtdlDeleteMessages(CC->room.QRname, - 0L, "text/x-vcard", 1); + NULL, 0, "text/x-vcard", 1); /* Make the author of the message the name of the user. */