dovecot: Handle UIDVALIDITY changes by resetting index.

dovecot at dovecot.org dovecot at dovecot.org
Sun Jul 1 01:05:51 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/f8caf3c6a5a7
changeset: 5850:f8caf3c6a5a7
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jul 01 01:05:40 2007 +0300
description:
Handle UIDVALIDITY changes by resetting index.

diffstat:

3 files changed, 54 insertions(+), 22 deletions(-)
src/lib-storage/index/maildir/maildir-sync.c   |   17 ++++---
src/lib-storage/index/mbox/mbox-sync-private.h |    3 +
src/lib-storage/index/mbox/mbox-sync.c         |   56 +++++++++++++++++-------

diffs (183 lines):

diff -r a9df50952600 -r f8caf3c6a5a7 src/lib-storage/index/maildir/maildir-sync.c
--- a/src/lib-storage/index/maildir/maildir-sync.c	Sun Jul 01 01:05:26 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync.c	Sun Jul 01 01:05:40 2007 +0300
@@ -1067,6 +1067,7 @@ int maildir_sync_index(struct maildir_in
 	struct maildir_uidlist_iter_ctx *iter;
 	struct mail_index_transaction *trans = sync_ctx->trans;
 	const struct mail_index_header *hdr;
+	struct mail_index_header empty_hdr;
 	const struct mail_index_record *rec;
 	uint32_t seq, uid, prev_uid;
         enum maildir_uidlist_rec_flag uflags;
@@ -1087,12 +1088,13 @@ int maildir_sync_index(struct maildir_in
 	    uid_validity != 0 && hdr->uid_validity != 0) {
 		/* uidvalidity changed and mailbox isn't being initialized,
 		   reset mailbox so we can add all messages as new */
-		mail_storage_set_critical(&mbox->storage->storage,
-			"Maildir %s sync: UIDVALIDITY changed (%u -> %u)",
-			mbox->path, hdr->uid_validity, uid_validity);
-
-		mail_index_mark_corrupted(mbox->ibox.index);
-		return -1;
+		i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
+			  mbox->path, hdr->uid_validity, uid_validity);
+		mail_index_reset(trans);
+
+		memset(&empty_hdr, 0, sizeof(empty_hdr));
+		empty_hdr.next_uid = 1;
+		hdr = &empty_hdr;
 	}
 
 	seq = prev_uid = 0;
@@ -1293,6 +1295,7 @@ int maildir_sync_index(struct maildir_in
 		   have to do it here before syncing index records, since after
 		   that the uidlist's next_uid value may have changed. */
 		next_uid = maildir_uidlist_get_next_uid(mbox->uidlist);
+		i_assert(next_uid > prev_uid);
 		if (hdr->next_uid < next_uid) {
 			mail_index_update_header(trans,
 				offsetof(struct mail_index_header, next_uid),
@@ -1300,7 +1303,7 @@ int maildir_sync_index(struct maildir_in
 		}
 	}
 
-	if (!mbox->syncing_commit) {
+	if (!mbox->syncing_commit && hdr != &empty_hdr) {
 		/* now, sync the index. NOTE: may recurse back to here with
 		   partial syncs */
 		mbox->syncing_commit = TRUE;
diff -r a9df50952600 -r f8caf3c6a5a7 src/lib-storage/index/mbox/mbox-sync-private.h
--- a/src/lib-storage/index/mbox/mbox-sync-private.h	Sun Jul 01 01:05:26 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-private.h	Sun Jul 01 01:05:40 2007 +0300
@@ -112,6 +112,8 @@ struct mbox_sync_context {
 	struct mail_index_sync_ctx *index_sync_ctx;
 	struct mail_index_view *sync_view;
 	struct mail_index_transaction *t;
+
+	struct mail_index_header reset_hdr;
 	const struct mail_index_header *hdr;
 
 	string_t *header, *from_line;
@@ -142,6 +144,7 @@ struct mbox_sync_context {
 	unsigned int renumber_uids:1;
 	unsigned int moved_offsets:1;
 	unsigned int ext_modified:1;
+	unsigned int index_reset:1;
 };
 
 int mbox_sync(struct mbox_mailbox *mbox, enum mbox_sync_flags flags);
diff -r a9df50952600 -r f8caf3c6a5a7 src/lib-storage/index/mbox/mbox-sync.c
--- a/src/lib-storage/index/mbox/mbox-sync.c	Sun Jul 01 01:05:26 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Sun Jul 01 01:05:40 2007 +0300
@@ -207,7 +207,7 @@ static int mbox_sync_read_index_syncs(st
 	if (sync_ctx->index_sync_ctx == NULL)
 		return 0;
 
-	if (uid == 0) {
+	if (uid == 0 || sync_ctx->index_reset) {
 		/* nothing for this or the future ones */
 		uid = (uint32_t)-1;
 	}
@@ -324,6 +324,11 @@ mbox_sync_read_index_rec(struct mbox_syn
         const struct mail_index_record *rec = NULL;
 	uint32_t messages_count;
 	int ret = 0;
+
+	if (sync_ctx->index_reset) {
+		*rec_r = NULL;
+		return 1;
+	}
 
 	messages_count =
 		mail_index_view_get_messages_count(sync_ctx->sync_view);
@@ -376,6 +381,11 @@ static int mbox_sync_find_index_md5(stru
 	uint32_t messages_count;
 	const void *data;
 	int ret;
+
+	if (sync_ctx->index_reset) {
+		*rec_r = NULL;
+		return 0;
+	}
 
 	messages_count =
 		mail_index_view_get_messages_count(sync_ctx->sync_view);
@@ -1001,6 +1011,8 @@ mbox_sync_seek_to_uid(struct mbox_sync_c
 	uint32_t seq1, seq2;
 	const struct stat *st;
 
+	i_assert(!sync_ctx->index_reset);
+
 	if (mail_index_lookup_uid_range(sync_view, uid, (uint32_t)-1,
 					&seq1, &seq2) < 0) {
 		mail_storage_set_index_error(&sync_ctx->mbox->ibox);
@@ -1037,6 +1049,8 @@ static int mbox_sync_partial_seek_next(s
 {
 	uint32_t messages_count;
 	int ret;
+
+	i_assert(!sync_ctx->index_reset);
 
 	/* delete sync records up to next message. so if there's still
 	   something left in array, it means the next message needs modifying */
@@ -1077,6 +1091,21 @@ static int mbox_sync_partial_seek_next(s
 	return ret;
 }
 
+static bool mbox_sync_uidvalidity_changed(struct mbox_sync_context *sync_ctx)
+{
+	if (sync_ctx->base_uid_validity != 0 &&
+	    sync_ctx->hdr->uid_validity != 0 &&
+	    sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity) {
+		i_warning("UIDVALIDITY changed (%u -> %u) in mbox file %s",
+			  sync_ctx->hdr->uid_validity,
+			  sync_ctx->base_uid_validity,
+			  sync_ctx->mbox->path);
+		sync_ctx->index_reset = TRUE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
 static int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
                           struct mbox_sync_mail_context *mail_ctx,
 			  bool partial)
@@ -1108,20 +1137,11 @@ static int mbox_sync_loop(struct mbox_sy
 	while ((ret = mbox_sync_read_next_mail(sync_ctx, mail_ctx)) > 0) {
 		uid = mail_ctx->mail.uid;
 
-		if (mail_ctx->seq == 1 && sync_ctx->base_uid_validity != 0 &&
-		    sync_ctx->hdr->uid_validity != 0 &&
-		    sync_ctx->base_uid_validity !=
-		    sync_ctx->hdr->uid_validity) {
-			mail_storage_set_critical(
-				&sync_ctx->mbox->storage->storage,
-				"UIDVALIDITY changed (%u -> %u) "
-				"in mbox file %s",
-				sync_ctx->hdr->uid_validity,
-				sync_ctx->base_uid_validity,
-				sync_ctx->mbox->path);
-
-			mail_index_mark_corrupted(sync_ctx->mbox->ibox.index);
-			return -1;
+		if (mail_ctx->seq == 1) {
+			if (mbox_sync_uidvalidity_changed(sync_ctx)) {
+				sync_ctx->mbox->mbox_sync_dirty = TRUE;
+				return 0;
+			}
 		}
 
 		if (mail_ctx->mail.uid_broken && partial) {
@@ -1546,6 +1566,12 @@ static void mbox_sync_restart(struct mbo
         mail_index_sync_reset(sync_ctx->index_sync_ctx);
 	mail_index_transaction_reset(sync_ctx->t);
 
+	if (sync_ctx->index_reset) {
+		mail_index_reset(sync_ctx->t);
+		sync_ctx->reset_hdr.next_uid = 1;
+		sync_ctx->hdr = &sync_ctx->reset_hdr;
+	}
+
 	sync_ctx->prev_msg_uid = 0;
 	sync_ctx->next_uid = sync_ctx->hdr->next_uid;
 	sync_ctx->idx_next_uid = sync_ctx->hdr->next_uid;


More information about the dovecot-cvs mailing list