dovecot-2.0: single-dbox: Fixed broken mailbox handling.

dovecot at dovecot.org dovecot at dovecot.org
Tue Jun 29 22:21:55 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/9d9be6aa3a55
changeset: 11658:9d9be6aa3a55
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Jun 29 20:21:51 2010 +0100
description:
single-dbox: Fixed broken mailbox handling.

diffstat:

 src/lib-storage/index/dbox-single/sdbox-storage.c      |  37 ++++++++++++++----
 src/lib-storage/index/dbox-single/sdbox-storage.h      |   6 ++-
 src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c |  20 +++++++++-
 src/lib-storage/index/dbox-single/sdbox-sync.c         |  18 +++++----
 src/lib-storage/index/dbox-single/sdbox-sync.h         |   2 +-
 5 files changed, 63 insertions(+), 20 deletions(-)

diffs (233 lines):

diff -r 4e5032891954 -r 9d9be6aa3a55 src/lib-storage/index/dbox-single/sdbox-storage.c
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c	Tue Jun 29 19:34:16 2010 +0100
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.c	Tue Jun 29 20:21:51 2010 +0100
@@ -84,10 +84,13 @@
 int sdbox_read_header(struct sdbox_mailbox *mbox,
 		      struct sdbox_index_header *hdr, bool log_error)
 {
+	struct mail_index_view *view;
 	const void *data;
 	size_t data_size;
+	int ret;
 
-	mail_index_get_header_ext(mbox->box.view, mbox->hdr_ext_id,
+	view = mail_index_view_open(mbox->box.index);
+	mail_index_get_header_ext(view, mbox->hdr_ext_id,
 				  &data, &data_size);
 	if (data_size < SDBOX_INDEX_HEADER_MIN_SIZE &&
 	    (!mbox->creating || data_size != 0)) {
@@ -97,11 +100,14 @@
 				"dbox %s: Invalid dbox header size",
 				mbox->box.path);
 		}
-		return -1;
+		ret = -1;
+	} else {
+		memset(hdr, 0, sizeof(*hdr));
+		memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
+		ret = 0;
 	}
-	memset(hdr, 0, sizeof(*hdr));
-	memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
-	return 0;
+	mail_index_view_close(&view);
+	return ret;
 }
 
 void sdbox_update_header(struct sdbox_mailbox *mbox,
@@ -198,9 +204,15 @@
 	return ret;
 }
 
-static void sdbox_set_mailbox_corrupted(struct mailbox *box ATTR_UNUSED)
+static void sdbox_set_mailbox_corrupted(struct mailbox *box)
 {
-	/* FIXME */
+	struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
+	struct sdbox_index_header hdr;
+
+	if (sdbox_read_header(mbox, &hdr, TRUE) < 0 || hdr.rebuild_count == 0)
+		mbox->corrupted_rebuild_count = 1;
+	else
+		mbox->corrupted_rebuild_count = hdr.rebuild_count;
 }
 
 static void sdbox_set_file_corrupted(struct dbox_file *_file)
@@ -210,6 +222,15 @@
 	sdbox_set_mailbox_corrupted(&file->mbox->box);
 }
 
+static void sdbox_mailbox_close(struct mailbox *box)
+{
+	struct sdbox_mailbox *mbox = (struct sdbox_mailbox *)box;
+
+	if (mbox->corrupted_rebuild_count != 0)
+		(void)sdbox_sync(mbox, 0);
+	index_storage_mailbox_close(box);
+}
+
 static int
 sdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
 {
@@ -264,7 +285,7 @@
 		index_storage_allow_new_keywords,
 		index_storage_mailbox_enable,
 		dbox_mailbox_open,
-		index_storage_mailbox_close,
+		sdbox_mailbox_close,
 		index_storage_mailbox_free,
 		dbox_mailbox_create,
 		dbox_mailbox_update,
diff -r 4e5032891954 -r 9d9be6aa3a55 src/lib-storage/index/dbox-single/sdbox-storage.h
--- a/src/lib-storage/index/dbox-single/sdbox-storage.h	Tue Jun 29 19:34:16 2010 +0100
+++ b/src/lib-storage/index/dbox-single/sdbox-storage.h	Tue Jun 29 20:21:51 2010 +0100
@@ -10,7 +10,8 @@
 
 #define SDBOX_INDEX_HEADER_MIN_SIZE (sizeof(uint32_t))
 struct sdbox_index_header {
-	uint32_t oldv1_highest_maildir_uid;
+	/* increased every time a full mailbox rebuild is done */
+	uint32_t rebuild_count;
 	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
 };
 
@@ -23,6 +24,9 @@
 	struct sdbox_storage *storage;
 
 	uint32_t hdr_ext_id;
+	/* if non-zero, storage should be rebuilt (except if rebuild_count
+	   has changed from this value) */
+	uint32_t corrupted_rebuild_count;
 
 	unsigned int creating:1;
 };
diff -r 4e5032891954 -r 9d9be6aa3a55 src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c
--- a/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c	Tue Jun 29 19:34:16 2010 +0100
+++ b/src/lib-storage/index/dbox-single/sdbox-sync-rebuild.c	Tue Jun 29 20:21:51 2010 +0100
@@ -36,12 +36,16 @@
 			return 0;
 		ret = dbox_file_get_mail_stream(file, 0, NULL);
 	}
+	if (ret == 0) {
+		if ((ret = dbox_file_fix(file, 0)) == 0)
+			ret = dbox_file_get_mail_stream(file, 0, NULL);
+	}
 
 	if (ret <= 0) {
 		if (ret < 0)
 			return -1;
 
-		i_warning("dbox: Ignoring broken file: %s", file->cur_path);
+		i_warning("dbox: Skipping unfixable file: %s", file->cur_path);
 		return 0;
 	}
 
@@ -132,6 +136,8 @@
 		memset(&hdr, 0, sizeof(hdr));
 	if (!mail_guid_128_is_empty(hdr.mailbox_guid))
 		mail_generate_guid_128(hdr.mailbox_guid);
+	if (++hdr.rebuild_count == 0)
+		hdr.rebuild_count = 1;
 	mail_index_update_header_ext(ctx->trans, mbox->hdr_ext_id, 0,
 				     &hdr, sizeof(hdr));
 }
@@ -154,13 +160,22 @@
 	return ret;
 }
 
-int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox)
+int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox, bool force)
 {
 	struct dbox_sync_rebuild_context *ctx;
 	struct mail_index_view *view;
 	struct mail_index_transaction *trans;
+	struct sdbox_index_header hdr;
 	int ret;
 
+	if (!force && sdbox_read_header(mbox, &hdr, FALSE) == 0) {
+		if (hdr.rebuild_count != mbox->corrupted_rebuild_count &&
+		    hdr.rebuild_count != 0) {
+			/* already rebuilt by someone else */
+			return 0;
+		}
+	}
+
 	view = mail_index_view_open(mbox->box.index);
 	trans = mail_index_transaction_begin(view,
 					MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
@@ -174,5 +189,6 @@
 	else
 		ret = mail_index_transaction_commit(&trans);
 	mail_index_view_close(&view);
+	mbox->corrupted_rebuild_count = 0;
 	return ret;
 }
diff -r 4e5032891954 -r 9d9be6aa3a55 src/lib-storage/index/dbox-single/sdbox-sync.c
--- a/src/lib-storage/index/dbox-single/sdbox-sync.c	Tue Jun 29 19:34:16 2010 +0100
+++ b/src/lib-storage/index/dbox-single/sdbox-sync.c	Tue Jun 29 20:21:51 2010 +0100
@@ -104,7 +104,6 @@
 	const struct mail_index_header *hdr;
 	struct mail_index_sync_rec sync_rec;
 	uint32_t seq1, seq2;
-	int ret = 1;
 
 	hdr = mail_index_get_header(ctx->sync_view);
 	if (hdr->uid_validity == 0) {
@@ -122,7 +121,7 @@
 
 	if (box->v.sync_notify != NULL)
 		box->v.sync_notify(box, 0, 0);
-	return ret;
+	return 1;
 }
 
 static int
@@ -151,10 +150,12 @@
 	enum mail_index_sync_flags sync_flags;
 	unsigned int i;
 	int ret;
-	bool rebuild;
+	bool rebuild, force_rebuild;
 
-	rebuild = sdbox_refresh_header(mbox, TRUE, FALSE) < 0 ||
-		(flags & SDBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
+	force_rebuild = (flags & SDBOX_SYNC_FLAG_FORCE_REBUILD) != 0;
+	rebuild = force_rebuild ||
+		mbox->corrupted_rebuild_count != 0 ||
+		sdbox_refresh_header(mbox, TRUE, FALSE) < 0;
 
 	ctx = i_new(struct sdbox_sync_context, 1);
 	ctx->mbox = mbox;
@@ -181,8 +182,7 @@
 			return ret;
 		}
 
-		/* now that we're locked, check again if we want to rebuild. */
-		if (sdbox_refresh_header(mbox, FALSE, TRUE) < 0)
+		if (rebuild)
 			ret = 0;
 		else {
 			if ((ret = sdbox_sync_index(ctx)) > 0)
@@ -201,7 +201,9 @@
 				/* do a full resync and try again. */
 				i_warning("dbox %s: Rebuilding index",
 					  ctx->mbox->box.path);
-				ret = sdbox_sync_index_rebuild(mbox);
+				rebuild = FALSE;
+				ret = sdbox_sync_index_rebuild(mbox,
+							       force_rebuild);
 			}
 		}
 		mail_index_sync_rollback(&ctx->index_sync_ctx);
diff -r 4e5032891954 -r 9d9be6aa3a55 src/lib-storage/index/dbox-single/sdbox-sync.h
--- a/src/lib-storage/index/dbox-single/sdbox-sync.h	Tue Jun 29 19:34:16 2010 +0100
+++ b/src/lib-storage/index/dbox-single/sdbox-sync.h	Tue Jun 29 20:21:51 2010 +0100
@@ -29,7 +29,7 @@
 int sdbox_sync_finish(struct sdbox_sync_context **ctx, bool success);
 int sdbox_sync(struct sdbox_mailbox *mbox, enum sdbox_sync_flags flags);
 
-int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox);
+int sdbox_sync_index_rebuild(struct sdbox_mailbox *mbox, bool force);
 
 struct mailbox_sync_context *
 sdbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags);


More information about the dovecot-cvs mailing list