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.
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);
}
}
* (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 */
)
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) {
/* 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; j<num_dmsgnums; ++j) {
+ if (msglist[i] == dmsgnums[j]) {
+ delete_this |= 0x01;
+ }
+ }
+ }
+
if (strlen(content_type) == 0) {
delete_this |= 0x02;
} else {
}
delnum = extract_long(delstr, 0);
- num_deleted = CtdlDeleteMessages(CC->room.QRname, delnum, "", 1);
+ num_deleted = CtdlDeleteMessages(CC->room.QRname, &delnum, 1, "", 1);
if (num_deleted) {
cprintf("%d %d message%s deleted.\n", CIT_OK,
* 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") );
*/
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 */
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);
/* 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);
/* 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);
/* 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);
* 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.
if (!strncasecmp(buf, "m=", 2)) {
msgnum = atol(&buf[2]);
if (msgnum > 0L) {
- CtdlDeleteMessages(roomname, msgnum, "", 0);
+ CtdlDeleteMessages(roomname, &msgnum, 1, "", 0);
}
}
}
/*
* 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();
/* 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);
}
}
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; i<POP3->num_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; i<POP3->num_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 */
* 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;
* 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.
*/