dovecot-2.0: mdbox: Fixed a race condition when expunging messages.

dovecot at dovecot.org dovecot at dovecot.org
Sun Mar 14 15:02:30 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/3f43b5c47a0e
changeset: 10907:3f43b5c47a0e
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Mar 14 15:02:28 2010 +0200
description:
mdbox: Fixed a race condition when expunging messages.

diffstat:

 src/lib-storage/index/dbox-multi/mdbox-sync.c |  32 +++++++++++++++++++++++++++-----
 1 files changed, 27 insertions(+), 5 deletions(-)

diffs (67 lines):

diff -r 841af633f8d0 -r 3f43b5c47a0e src/lib-storage/index/dbox-multi/mdbox-sync.c
--- a/src/lib-storage/index/dbox-multi/mdbox-sync.c	Sun Mar 14 03:47:34 2010 +0200
+++ b/src/lib-storage/index/dbox-multi/mdbox-sync.c	Sun Mar 14 15:02:28 2010 +0200
@@ -84,24 +84,39 @@
 	return 0;
 }
 
-static void dbox_sync_mark_expunges(struct mdbox_sync_context *ctx)
+static int dbox_sync_mark_expunges(struct mdbox_sync_context *ctx)
 {
+	enum mail_index_transaction_flags flags =
+		MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL;
 	struct mailbox *box = &ctx->mbox->box;
+	struct mail_index_transaction *trans;
 	struct seq_range_iter iter;
 	unsigned int n;
 	const void *data;
 	uint32_t seq, uid;
 
+	/* use a separate transaction here so that we can commit the changes
+	   during map transaction */
+	trans = mail_index_transaction_begin(ctx->sync_view, flags);
 	seq_range_array_iter_init(&iter, &ctx->expunged_seqs); n = 0;
 	while (seq_range_array_iter_nth(&iter, n++, &seq)) {
 		mail_index_lookup_uid(ctx->sync_view, seq, &uid);
 		mail_index_lookup_ext(ctx->sync_view, seq,
 				      ctx->mbox->guid_ext_id, &data, NULL);
-		mail_index_expunge_guid(ctx->trans, seq, data);
+		mail_index_expunge_guid(trans, seq, data);
+	}
+	if (mail_index_transaction_commit(&trans) < 0)
+		return -1;
 
-		if (box->v.sync_notify != NULL)
+	if (box->v.sync_notify != NULL) {
+		/* do notifications after commit finished successfully */
+		seq_range_array_iter_init(&iter, &ctx->expunged_seqs); n = 0;
+		while (seq_range_array_iter_nth(&iter, n++, &seq)) {
+			mail_index_lookup_uid(ctx->sync_view, seq, &uid);
 			box->v.sync_notify(box, uid, MAILBOX_SYNC_TYPE_EXPUNGE);
+		}
 	}
+	return 0;
 }
 
 static int mdbox_sync_index_finish_expunges(struct mdbox_sync_context *ctx)
@@ -112,11 +127,18 @@
 	map_trans = dbox_map_transaction_begin(ctx->mbox->storage->map, FALSE);
 	ret = dbox_map_update_refcounts(map_trans, &ctx->expunged_map_uids, -1);
 	if (ret == 0) {
+		/* write refcount changes to map index */
 		ret = dbox_map_transaction_commit(map_trans);
-		if (ret == 0)
-			dbox_sync_mark_expunges(ctx);
+		if (ret == 0) {
+			/* write changes to mailbox index */
+			ret = dbox_sync_mark_expunges(ctx);
+		}
 	}
 
+	/* this finally finishes the map sync and makes it clear that the
+	   map transaction was successfully finished. */
+	if (ret < 0)
+		dbox_map_transaction_set_failed(map_trans);
 	dbox_map_transaction_free(&map_trans);
 	return ret;
 }


More information about the dovecot-cvs mailing list