dovecot-1.2: virtual: If another session adds a new mailbox to i...

dovecot at dovecot.org dovecot at dovecot.org
Mon Jul 27 02:51:42 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/88d4e83fcea5
changeset: 9252:88d4e83fcea5
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jul 26 19:51:37 2009 -0400
description:
virtual: If another session adds a new mailbox to index, handle it without crashing.
For now we'll just disconnect the session.

diffstat:

3 files changed, 60 insertions(+), 16 deletions(-)
src/plugins/virtual/virtual-storage.c |   12 +++++-
src/plugins/virtual/virtual-storage.h |    1 
src/plugins/virtual/virtual-sync.c    |   63 +++++++++++++++++++++++++--------

diffs (208 lines):

diff -r b24bdff70c63 -r 88d4e83fcea5 src/plugins/virtual/virtual-storage.c
--- a/src/plugins/virtual/virtual-storage.c	Sun Jul 26 19:37:05 2009 -0400
+++ b/src/plugins/virtual/virtual-storage.c	Sun Jul 26 19:51:37 2009 -0400
@@ -628,6 +628,16 @@ virtual_get_virtual_box_patterns(struct 
 
 	array_append_array(includes, &mbox->list_include_patterns);
 	array_append_array(excludes, &mbox->list_exclude_patterns);
+}
+
+static bool virtual_is_inconsistent(struct mailbox *box)
+{
+	struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
+
+	if (mbox->inconsistent)
+		return TRUE;
+
+	return index_storage_is_inconsistent(box);
 }
 
 static void virtual_class_init(void)
@@ -700,6 +710,6 @@ struct mailbox virtual_mailbox = {
 		virtual_save_finish,
 		virtual_save_cancel,
 		mail_storage_copy,
-		index_storage_is_inconsistent
+		virtual_is_inconsistent
 	}
 };
diff -r b24bdff70c63 -r 88d4e83fcea5 src/plugins/virtual/virtual-storage.h
--- a/src/plugins/virtual/virtual-storage.h	Sun Jul 26 19:37:05 2009 -0400
+++ b/src/plugins/virtual/virtual-storage.h	Sun Jul 26 19:51:37 2009 -0400
@@ -124,6 +124,7 @@ struct virtual_mailbox {
 
 	unsigned int uids_mapped:1;
 	unsigned int sync_initialized:1;
+	unsigned int inconsistent:1;
 };
 
 extern MODULE_CONTEXT_DEFINE(virtual_storage_module,
diff -r b24bdff70c63 -r 88d4e83fcea5 src/plugins/virtual/virtual-sync.c
--- a/src/plugins/virtual/virtual-sync.c	Sun Jul 26 19:37:05 2009 -0400
+++ b/src/plugins/virtual/virtual-sync.c	Sun Jul 26 19:51:37 2009 -0400
@@ -130,7 +130,24 @@ static int bbox_mailbox_id_cmp(const voi
 	return 0;
 }
 
-static bool virtual_sync_ext_header_read(struct virtual_sync_context *ctx)
+static int
+virtual_sync_get_backend_box(struct virtual_sync_context *ctx, const char *name,
+			     struct virtual_backend_box **bbox_r)
+{
+	*bbox_r = virtual_backend_box_lookup_name(ctx->mbox, name);
+	if (*bbox_r != NULL || !ctx->mbox->sync_initialized)
+		return 0;
+
+	/* another process just added a new mailbox.
+	   we can't handle this currently. */
+	ctx->mbox->inconsistent = TRUE;
+	mail_storage_set_error(ctx->mbox->ibox.box.storage, MAIL_ERROR_TEMP,
+		"Backend mailbox added by another session. "
+		"Reopen the virtual mailbox.");
+	return -1;
+}
+
+static int virtual_sync_ext_header_read(struct virtual_sync_context *ctx)
 {
 	const struct virtual_mail_index_header *ext_hdr;
 	const struct mail_index_header *hdr;
@@ -140,7 +157,7 @@ static bool virtual_sync_ext_header_read
 	size_t ext_size;
 	unsigned int i, count, ext_name_offset, ext_mailbox_count;
 	uint32_t prev_mailbox_id;
-	bool ret = TRUE;
+	int ret = 1;
 
 	hdr = mail_index_get_header(ctx->sync_view);
 	mail_index_get_header_ext(ctx->sync_view, ctx->mbox->virtual_ext_id,
@@ -154,7 +171,6 @@ static bool virtual_sync_ext_header_read
 		return TRUE;
 	}
 
-	ctx->mbox->sync_initialized = TRUE;
 	ctx->mbox->prev_uid_validity = hdr->uid_validity;
 	if (ext_hdr == NULL ||
 	    ctx->mbox->search_args_crc32 != ext_hdr->search_args_crc32) {
@@ -172,7 +188,7 @@ static bool virtual_sync_ext_header_read
 				ctx->mbox->path);
 			ctx->index_broken = TRUE;
 			ext_mailbox_count = 0;
-			ret = FALSE;
+			ret = 0;
 		} else {
 			ext_mailbox_count = ext_hdr->mailbox_count;
 		}
@@ -204,11 +220,15 @@ static bool virtual_sync_ext_header_read
 
 			nameptr = CONST_PTR_OFFSET(ext_data, ext_name_offset);
 			name = t_strndup(nameptr, mailboxes[i].name_len);
-			bbox = virtual_backend_box_lookup_name(ctx->mbox, name);
+			if (virtual_sync_get_backend_box(ctx, name, &bbox) < 0)
+				ret = -1;
 		} T_END;
+
 		if (bbox == NULL) {
-			/* mailbox no longer exists */
-			ret = FALSE;
+			if (ret < 0)
+				return -1;
+			/* mailbox no longer exists. */
+			ret = 0;
 		} else {
 			bbox->mailbox_id = mailboxes[i].id;
 			bbox->sync_uid_validity = mailboxes[i].uid_validity;
@@ -221,17 +241,18 @@ static bool virtual_sync_ext_header_read
 	}
 	if (i < ext_mailbox_count) {
 		ctx->index_broken = TRUE;
-		ret = FALSE;
+		ret = 0;
 	}
 	ctx->mbox->highest_mailbox_id = ext_hdr == NULL ? 0 :
 		ext_hdr->highest_mailbox_id;
+	ctx->mbox->sync_initialized = TRUE;
 
 	/* assign new mailbox IDs if any are missing */
 	bboxes = array_get_modifiable(&ctx->mbox->backend_boxes, &count);
 	for (i = 0; i < count; i++) {
 		if (bboxes[i]->mailbox_id == 0) {
 			bboxes[i]->mailbox_id = ++ctx->mbox->highest_mailbox_id;
-			ret = FALSE;
+			ret = 0;
 		}
 	}
 	/* sort the backend mailboxes by mailbox_id. */
@@ -1256,7 +1277,7 @@ static void virtual_sync_backend_add_new
 	ctx->mbox->sync_virtual_next_uid = first_uid + i;
 }
 
-static void
+static int
 virtual_sync_apply_existing_appends(struct virtual_sync_context *ctx)
 {
 	uint32_t virtual_ext_id = ctx->mbox->virtual_ext_id;
@@ -1269,18 +1290,18 @@ virtual_sync_apply_existing_appends(stru
 	uint32_t seq, seq2;
 
 	if (!ctx->mbox->uids_mapped)
-		return;
+		return 0;
 
 	hdr = mail_index_get_header(ctx->sync_view);
 	if (ctx->mbox->sync_virtual_next_uid >= hdr->next_uid)
-		return;
+		return 0;
 
 	/* another process added messages to virtual index. get backend boxes'
 	   uid lists up-to-date by adding the new messages there. */
 	if (!mail_index_lookup_seq_range(ctx->sync_view,
 					 ctx->mbox->sync_virtual_next_uid,
 					 (uint32_t)-1, &seq, &seq2))
-		return;
+		return 0;
 
 	memset(&uidmap, 0, sizeof(uidmap));
 	for (; seq <= seq2; seq++) {
@@ -1293,12 +1314,20 @@ virtual_sync_apply_existing_appends(stru
 		if (bbox == NULL || bbox->mailbox_id != vrec->mailbox_id) {
 			bbox = virtual_backend_box_lookup(ctx->mbox,
 							  vrec->mailbox_id);
+			if (bbox == NULL) {
+				mail_storage_set_critical(
+					ctx->mbox->ibox.box.storage,
+					"Mailbox ID %u unexpectedly lost",
+					vrec->mailbox_id);
+				return -1;
+			}
 		}
 		array_append(&bbox->uids, &uidmap, 1);
 		bbox->uids_nonsorted = TRUE;
 	}
 
 	virtual_sync_backend_boxes_sort_uids(ctx->mbox);
+	return 0;
 }
 
 static void
@@ -1341,7 +1370,8 @@ static int virtual_sync_backend_boxes(st
 	unsigned int i, count;
 	int ret;
 
-	virtual_sync_apply_existing_appends(ctx);
+	if (virtual_sync_apply_existing_appends(ctx) < 0)
+		return -1;
 
 	i_array_init(&ctx->all_adds, 128);
 	bboxes = array_get(&ctx->mbox->backend_boxes, &count);
@@ -1437,7 +1467,10 @@ static int virtual_sync(struct virtual_m
 		return ret;
 	}
 
-	if (!virtual_sync_ext_header_read(ctx))
+	ret = virtual_sync_ext_header_read(ctx);
+	if (ret < 0)
+		return virtual_sync_finish(ctx, FALSE);
+	if (ret == 0)
 		ctx->ext_header_rewrite = TRUE;
 	/* apply changes from virtual index to backend mailboxes */
 	virtual_sync_index_changes(ctx);


More information about the dovecot-cvs mailing list