dovecot: If we see expunged messages coming back, log a warning ...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 9 05:44:44 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/ac05ec8c7171
changeset: 5924:ac05ec8c7171
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Jul 09 00:14:34 2007 +0300
description:
If we see expunged messages coming back, log a warning and give them a new
UID instead of marking the index corrupted.

diffstat:

1 file changed, 55 insertions(+), 62 deletions(-)
src/lib-storage/index/maildir/maildir-sync-index.c |  117 +++++++++-----------

diffs (160 lines):

diff -r 239078f515a8 -r ac05ec8c7171 src/lib-storage/index/maildir/maildir-sync-index.c
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Mon Jul 09 00:13:51 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Mon Jul 09 00:14:34 2007 +0300
@@ -22,6 +22,7 @@ struct maildir_index_sync_context {
         struct maildir_keywords_sync_ctx *keywords_sync_ctx;
 	struct mail_index_transaction *trans;
 
+	struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
 	struct index_sync_changes_context *sync_changes;
 	enum mail_flags flags;
 	ARRAY_TYPE(keyword_indexes) keywords;
@@ -101,6 +102,49 @@ static int maildir_sync_flags(struct mai
 			"rename(%s, %s) failed: %m", path, newpath);
 	}
 	return -1;
+}
+
+static void maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
+					 enum maildir_uidlist_rec_flag uflags,
+					 const char *filename, uint32_t uid)
+{
+	int ret;
+
+	if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
+		/* partial syncing */
+		return;
+	}
+
+	/* most likely a race condition: we read the maildir, then someone else
+	   expunged messages and committed changes to index. so, this message
+	   shouldn't actually exist. */
+	if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
+		/* mark it racy and check in next sync */
+		ctx->mbox->dirty_cur_time = ioloop_time;
+		maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
+					  MAILDIR_UIDLIST_REC_FLAG_RACING);
+		return;
+	}
+
+	if (ctx->uidlist_sync_ctx == NULL) {
+		ret = maildir_uidlist_sync_init(ctx->mbox->uidlist,
+						MAILDIR_UIDLIST_SYNC_PARTIAL,
+						&ctx->uidlist_sync_ctx);
+		i_assert(ret > 0);
+	}
+
+	uflags &= (MAILDIR_UIDLIST_REC_FLAG_NEW_DIR |
+		   MAILDIR_UIDLIST_REC_FLAG_RECENT);
+	maildir_uidlist_sync_remove(ctx->uidlist_sync_ctx, filename);
+	ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
+					filename, uflags);
+	i_assert(ret > 0);
+
+	/* give the new UID to it immediately */
+	maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
+
+	i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
+		  "(old uid=%u, file=%s)", ctx->mbox->path, uid, filename);
 }
 
 int maildir_sync_index_begin(struct maildir_mailbox *mbox,
@@ -237,39 +281,8 @@ int maildir_sync_index(struct maildir_in
 
 		if (seq > hdr->messages_count) {
 			if (uid < hdr->next_uid) {
-				/* most likely a race condition: we read the
-				   maildir, then someone else expunged messages
-				   and committed changes to index. so, this
-				   message shouldn't actually exist. mark it
-				   racy and check in next sync.
-
-				   the difference between this and the later
-				   check is that this one happens when messages
-				   are expunged from the end */
-				if ((uflags &
-				    MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
-					/* partial syncing */
-					continue;
-				}
-				if ((uflags &
-				     MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
-					mail_storage_set_critical(
-						&mbox->storage->storage,
-						"Maildir %s sync: "
-						"UID < next_uid "
-						"(%u < %u, file = %s)",
-						mbox->path, uid, hdr->next_uid,
-						filename);
-					mail_index_mark_corrupted(
-						mbox->ibox.index);
-					ret = -1;
-					break;
-				}
-				mbox->dirty_cur_time = ioloop_time;
-				maildir_uidlist_add_flags(mbox->uidlist,
-					filename,
-					MAILDIR_UIDLIST_REC_FLAG_RACING);
-
+				maildir_handle_uid_insertion(ctx, uflags,
+							     filename, uid);
 				seq--;
 				continue;
 			}
@@ -296,40 +309,15 @@ int maildir_sync_index(struct maildir_in
 			break;
 		}
 
-		if (rec->uid < uid) {
+		if (uid > rec->uid) {
 			/* expunged */
 			mail_index_expunge(trans, seq);
 			goto __again;
 		}
 
-		if (rec->uid > uid) {
-			/* most likely a race condition: we read the
-			   maildir, then someone else expunged messages and
-			   committed changes to index. so, this message
-			   shouldn't actually exist. mark it racy and check
-			   in next sync. */
-			if ((uflags &
-			    MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
-				/* partial syncing */
-				seq--;
-				continue;
-			}
-			if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) != 0) {
-				mail_storage_set_critical(
-					&mbox->storage->storage,
-					"Maildir %s sync: "
-					"UID inserted in the middle of mailbox "
-					"(%u > %u, file = %s)",
-					mbox->path, rec->uid, uid, filename);
-				mail_index_mark_corrupted(mbox->ibox.index);
-				ret = -1;
-				break;
-			}
-
-			mbox->dirty_cur_time = ioloop_time;
-			maildir_uidlist_add_flags(mbox->uidlist, filename,
-				MAILDIR_UIDLIST_REC_FLAG_RACING);
-
+		if (uid < rec->uid) {
+			maildir_handle_uid_insertion(ctx, uflags,
+						     filename, uid);
 			seq--;
 			continue;
 		}
@@ -424,6 +412,11 @@ int maildir_sync_index(struct maildir_in
 	maildir_uidlist_iter_deinit(iter);
 	mbox->syncing_commit = FALSE;
 
+	if (ctx->uidlist_sync_ctx != NULL) {
+		if (maildir_uidlist_sync_deinit(&ctx->uidlist_sync_ctx) < 0)
+			ret = -1;
+	}
+
 	if (mbox->ibox.box.v.sync_notify != NULL)
 		mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0);
 


More information about the dovecot-cvs mailing list