dovecot-2.1: imapc: Don't crash if a newly seen uncommitted mess...

dovecot at dovecot.org dovecot at dovecot.org
Wed Sep 7 10:01:47 EEST 2011


details:   http://hg.dovecot.org/dovecot-2.1/rev/3ae5d7e0a4b4
changeset: 13414:3ae5d7e0a4b4
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Sep 07 10:01:36 2011 +0300
description:
imapc: Don't crash if a newly seen uncommitted message is expunged.

diffstat:

 src/lib-storage/index/imapc/imapc-mailbox.c |  42 ++++++++++++++++++++++++++--
 src/lib-storage/index/imapc/imapc-storage.c |   1 +
 src/lib-storage/index/imapc/imapc-storage.h |   1 +
 src/lib-storage/index/imapc/imapc-sync.c    |   7 ++++
 4 files changed, 48 insertions(+), 3 deletions(-)

diffs (113 lines):

diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-mailbox.c
--- a/src/lib-storage/index/imapc/imapc-mailbox.c	Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-mailbox.c	Wed Sep 07 10:01:36 2011 +0300
@@ -46,6 +46,27 @@
 		mail_index_transaction_open_updated_view(mbox->delayed_sync_trans);
 }
 
+static int imapc_mailbox_commit_delayed_expunges(struct imapc_mailbox *mbox)
+{
+	struct mail_index_view *view = imapc_mailbox_get_sync_view(mbox);
+	struct mail_index_transaction *trans;
+	const uint32_t *uidp;
+	uint32_t lseq;
+	int ret;
+
+	trans = mail_index_transaction_begin(view,
+			MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
+	array_foreach(&mbox->delayed_expunged_uids, uidp) {
+		if (mail_index_lookup_seq(view, *uidp, &lseq))
+			mail_index_expunge(trans, lseq);
+	}
+	array_clear(&mbox->delayed_expunged_uids);
+	ret = mail_index_transaction_commit(&trans);
+	if (ret < 0)
+		mail_storage_set_index_error(&mbox->box);
+	return ret;
+}
+
 int imapc_mailbox_commit_delayed_trans(struct imapc_mailbox *mbox,
 				       bool *changes_r)
 {
@@ -64,6 +85,13 @@
 	}
 	if (mbox->sync_view != NULL)
 		mail_index_view_close(&mbox->sync_view);
+
+	if (array_count(&mbox->delayed_expunged_uids) > 0) {
+		/* delayed expunges - commit them now in a separate
+		   transaction */
+		if (imapc_mailbox_commit_delayed_expunges(mbox) < 0)
+			ret = -1;
+	}
 	return ret;
 }
 
@@ -289,10 +317,18 @@
 	imapc_msgmap_expunge(msgmap, rseq);
 
 	imapc_mailbox_init_delayed_trans(mbox);
-	if (!mail_index_lookup_seq(mbox->delayed_sync_view, uid, &lseq)) {
+	if (mail_index_lookup_seq(mbox->sync_view, uid, &lseq))
+		mail_index_expunge(mbox->delayed_sync_trans, lseq);
+	else if (mail_index_lookup_seq(mbox->delayed_sync_view, uid, &lseq)) {
+		/* this message exists only in this transaction. lib-index
+		   can't currently handle expunging anything except the last
+		   appended message in a transaction, and fixing it would be
+		   quite a lot of trouble. so instead we'll just delay doing
+		   this expunge until after the current transaction has been
+		   committed. */
+		array_append(&mbox->delayed_expunged_uids, &uid, 1);
+	} else {
 		/* already expunged by another session */
-	} else {
-		mail_index_expunge(mbox->delayed_sync_trans, lseq);
 	}
 	imapc_mailbox_idle_notify(mbox);
 }
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c	Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Wed Sep 07 10:01:36 2011 +0300
@@ -305,6 +305,7 @@
 	p_array_init(&mbox->resp_text_callbacks, pool, 16);
 	p_array_init(&mbox->fetch_mails, pool, 16);
 	p_array_init(&mbox->permanent_keywords, pool, 32);
+	p_array_init(&mbox->delayed_expunged_uids, pool, 16);
 	imapc_mailbox_register_callbacks(mbox);
 	return &mbox->box;
 }
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h	Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h	Wed Sep 07 10:01:36 2011 +0300
@@ -57,6 +57,7 @@
 	enum mail_flags permanent_flags;
 	ARRAY_TYPE(keywords) permanent_keywords;
 
+	ARRAY_TYPE(uint32_t) delayed_expunged_uids;
 	uint32_t sync_uid_validity;
 	uint32_t sync_uid_next;
 	uint32_t sync_fetch_first_uid;
diff -r 3828fa3b8fd4 -r 3ae5d7e0a4b4 src/lib-storage/index/imapc/imapc-sync.c
--- a/src/lib-storage/index/imapc/imapc-sync.c	Wed Sep 07 09:40:16 2011 +0300
+++ b/src/lib-storage/index/imapc/imapc-sync.c	Wed Sep 07 10:01:36 2011 +0300
@@ -331,6 +331,7 @@
 static int imapc_sync_finish(struct imapc_sync_context **_ctx)
 {
 	struct imapc_sync_context *ctx = *_ctx;
+	bool changes;
 	int ret = ctx->failed ? -1 : 0;
 
 	*_ctx = NULL;
@@ -343,6 +344,12 @@
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
 	}
 	ctx->mbox->syncing = FALSE;
+
+	/* this is done simply to commit delayed expunges if there are any
+	   (has to be done after sync is committed) */
+	if (imapc_mailbox_commit_delayed_trans(ctx->mbox, &changes) < 0)
+		ctx->failed = TRUE;
+
 	i_free(ctx);
 	return ret;
 }


More information about the dovecot-cvs mailing list