dovecot-2.2: lib-storage: Fixed mailbox_update() when using mail...

dovecot at dovecot.org dovecot at dovecot.org
Tue Feb 19 13:18:49 EET 2013


details:   http://hg.dovecot.org/dovecot-2.2/rev/2529f4e12665
changeset: 15848:2529f4e12665
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Feb 19 13:17:42 2013 +0200
description:
lib-storage: Fixed mailbox_update() when using mailbox_list_index=yes

diffstat:

 src/lib-storage/list/mailbox-list-index-backend.c |   67 ++++++++++-
 src/lib-storage/list/mailbox-list-index-status.c  |  121 +++++++++++++++------
 src/lib-storage/list/mailbox-list-index.c         |   16 ++-
 src/lib-storage/list/mailbox-list-index.h         |    2 +
 4 files changed, 162 insertions(+), 44 deletions(-)

diffs (truncated from 348 to 300 lines):

diff -r 19e24db0bbd4 -r 2529f4e12665 src/lib-storage/list/mailbox-list-index-backend.c
--- a/src/lib-storage/list/mailbox-list-index-backend.c	Tue Feb 19 13:17:05 2013 +0200
+++ b/src/lib-storage/list/mailbox-list-index-backend.c	Tue Feb 19 13:17:42 2013 +0200
@@ -9,6 +9,8 @@
 #include "mailbox-list-index-storage.h"
 #include "mailbox-list-index-sync.h"
 
+#include <stdio.h>
+
 #define GLOBAL_TEMP_PREFIX ".temp."
 
 struct index_mailbox_list {
@@ -79,6 +81,20 @@
 	return 1;
 }
 
+static const char *
+index_get_guid_path(struct mailbox_list *_list, const char *root_dir,
+		    const guid_128_t mailbox_guid)
+{
+	if (_list->set.mailbox_dir_name == '\0') {
+		return t_strconcat(root_dir, "/",
+				   guid_128_to_string(mailbox_guid), NULL);
+	} else {
+		return t_strdup_printf("%s/%s%s", root_dir,
+				       _list->set.mailbox_dir_name,
+				       guid_128_to_string(mailbox_guid));
+	}
+}
+
 static int
 index_list_get_path(struct mailbox_list *_list, const char *name,
 		    enum mailbox_list_path_type type, const char **path_r)
@@ -128,14 +144,8 @@
 		mailbox_list_set_error(_list, MAIL_ERROR_NOTFOUND,
 				       T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
 		ret = -1;
-	} else if (_list->set.mailbox_dir_name == '\0') {
-		*path_r = t_strconcat(root_dir, "/",
-				      guid_128_to_string(mailbox_guid), NULL);
-		ret = 1;
 	} else {
-		*path_r = t_strdup_printf("%s/%s%s", root_dir,
-					  _list->set.mailbox_dir_name,
-					  guid_128_to_string(mailbox_guid));
+		*path_r = index_get_guid_path(_list, root_dir, mailbox_guid);
 		ret = 1;
 	}
 	mail_index_view_close(&view);
@@ -310,6 +320,48 @@
 		ibox->module_ctx.super.create_box(box, update, directory);
 }
 
+static int
+index_list_mailbox_update(struct mailbox *box,
+			  const struct mailbox_update *update)
+{
+	struct index_list_mailbox *ibox = INDEX_LIST_STORAGE_CONTEXT(box);
+	const char *root_dir, *old_path, *new_path;
+
+	if (mailbox_list_get_path(box->list, box->name,
+				  MAILBOX_LIST_PATH_TYPE_MAILBOX,
+				  &old_path) <= 0)
+		old_path = NULL;
+
+	if (ibox->module_ctx.super.update_box(box, update) < 0)
+		return -1;
+
+	/* rename the directory */
+	if (!guid_128_is_empty(update->mailbox_guid) &&
+	    mailbox_list_set_get_root_path(&box->list->set,
+					   MAILBOX_LIST_PATH_TYPE_MAILBOX,
+					   &root_dir)) {
+		new_path = index_get_guid_path(box->list, root_dir,
+					       update->mailbox_guid);
+		if (strcmp(old_path, new_path) == 0)
+			;
+		else if (rename(old_path, new_path) == 0)
+			;
+		else if (errno == ENOENT) {
+			mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+			return -1;
+		} else {
+			mail_storage_set_critical(box->storage,
+						  "rename(%s, %s) failed: %m",
+						  old_path, new_path);
+			return -1;
+		}
+	}
+
+	mailbox_list_index_update_mailbox_index(box, update);
+	return 0;
+}
+
 static void
 index_list_try_delete(struct index_mailbox_list *list, const char *name,
 		      enum mailbox_list_path_type type)
@@ -609,4 +661,5 @@
 	if (strcmp(box->list->name, MAILBOX_LIST_NAME_INDEX) != 0)
 		return;
 	box->v.create_box = index_list_mailbox_create;
+	box->v.update_box = index_list_mailbox_update;
 }
diff -r 19e24db0bbd4 -r 2529f4e12665 src/lib-storage/list/mailbox-list-index-status.c
--- a/src/lib-storage/list/mailbox-list-index-status.c	Tue Feb 19 13:17:05 2013 +0200
+++ b/src/lib-storage/list/mailbox-list-index-status.c	Tue Feb 19 13:17:42 2013 +0200
@@ -129,8 +129,7 @@
 		return 0;
 	}
 
-	ret = index_list_open_view(box, &view, &seq);
-	if (ret <= 0)
+	if ((ret = index_list_open_view(box, &view, &seq)) <= 0)
 		return ret;
 
 	ret = mailbox_list_index_status(box->list, view, seq, items,
@@ -167,8 +166,7 @@
 		return 0;
 	}
 
-	ret = index_list_open_view(box, &view, &seq);
-	if (ret <= 0)
+	if ((ret = index_list_open_view(box, &view, &seq)) <= 0)
 		return ret;
 
 	ret = mailbox_list_index_status(box->list, view, seq, 0,
@@ -195,37 +193,34 @@
 }
 
 static int
-index_list_update(struct mailbox *box, struct mail_index_view *view,
-		  uint32_t seq, const struct mailbox_status *status)
+index_list_update_full(struct mailbox *box, struct mail_index_view *view,
+		       uint32_t seq, const guid_128_t new_guid,
+		       const struct mailbox_status *new_status,
+		       bool update_backend)
 {
 	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(box->list);
 	struct mail_index_transaction *trans;
 	struct mail_index_transaction_commit_result result;
-	struct mailbox_metadata metadata;
 	struct mailbox_status old_status;
-	guid_128_t mailbox_guid;
+	guid_128_t old_guid;
 	bool rec_changed, msgs_changed, hmodseq_changed;
 
-	i_assert(box->opened);
+	memset(&old_status, 0, sizeof(old_status));
+	memset(old_guid, 0, sizeof(old_guid));
+	(void)mailbox_list_index_status(box->list, view, seq, CACHED_STATUS_ITEMS,
+					&old_status, old_guid);
 
-	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
-		memset(&metadata, 0, sizeof(metadata));
-
-	memset(&old_status, 0, sizeof(old_status));
-	memset(mailbox_guid, 0, sizeof(mailbox_guid));
-	(void)mailbox_list_index_status(box->list, view, seq, CACHED_STATUS_ITEMS,
-					&old_status, mailbox_guid);
-
-	rec_changed = old_status.uidvalidity != status->uidvalidity;
-	if (memcmp(metadata.guid, mailbox_guid, sizeof(metadata.guid)) != 0 &&
-	    guid_128_is_empty(metadata.guid))
+	rec_changed = old_status.uidvalidity != new_status->uidvalidity &&
+		new_status->uidvalidity != 0;
+	if (!guid_128_equals(new_guid, old_guid) &&
+	    !guid_128_is_empty(new_guid))
 		rec_changed = TRUE;
-	msgs_changed = old_status.messages != status->messages ||
-		old_status.unseen != status->unseen ||
-		old_status.recent != status->recent ||
-		old_status.uidnext != status->uidnext;
+	msgs_changed = old_status.messages != new_status->messages ||
+		old_status.unseen != new_status->unseen ||
+		old_status.recent != new_status->recent ||
+		old_status.uidnext != new_status->uidnext;
 	/* update highest-modseq only if they're ever been used */
-	if (old_status.highest_modseq == status->highest_modseq) {
+	if (old_status.highest_modseq == new_status->highest_modseq) {
 		hmodseq_changed = FALSE;
 	} else if ((box->enabled_features & MAILBOX_FEATURE_CONDSTORE) != 0 ||
 		   old_status.highest_modseq != 0) {
@@ -240,7 +235,7 @@
 	}
 
 	if (hmodseq_changed &&
-	    old_status.highest_modseq != status->highest_modseq)
+	    old_status.highest_modseq != new_status->highest_modseq)
 		hmodseq_changed = TRUE;
 
 	if (!rec_changed && !msgs_changed && !hmodseq_changed)
@@ -259,9 +254,10 @@
 		i_assert(old_data != NULL);
 		memcpy(&rec, old_data, sizeof(rec));
 
-		rec.uid_validity = status->uidvalidity;
-		if (!guid_128_is_empty(metadata.guid))
-			memcpy(rec.guid, metadata.guid, sizeof(rec.guid));
+		if (new_status->uidvalidity != 0)
+			rec.uid_validity = new_status->uidvalidity;
+		if (!guid_128_is_empty(new_guid))
+			memcpy(rec.guid, new_guid, sizeof(rec.guid));
 		mail_index_update_ext(trans, seq, ilist->ext_id, &rec, NULL);
 	}
 
@@ -269,21 +265,23 @@
 		struct mailbox_list_index_msgs_record msgs;
 
 		memset(&msgs, 0, sizeof(msgs));
-		msgs.messages = status->messages;
-		msgs.unseen = status->unseen;
-		msgs.recent = status->recent;
-		msgs.uidnext = status->uidnext;
+		msgs.messages = new_status->messages;
+		msgs.unseen = new_status->unseen;
+		msgs.recent = new_status->recent;
+		msgs.uidnext = new_status->uidnext;
 
 		mail_index_update_ext(trans, seq, ilist->msgs_ext_id,
 				      &msgs, NULL);
 	}
 	if (hmodseq_changed) {
 		mail_index_update_ext(trans, seq, ilist->hmodseq_ext_id,
-				      &status->highest_modseq, NULL);
+				      &new_status->highest_modseq, NULL);
 	}
 
-	if (box->v.list_index_update_sync != NULL)
-		box->v.list_index_update_sync(box, trans, seq);
+	if (update_backend) {
+		if (box->v.list_index_update_sync != NULL)
+			box->v.list_index_update_sync(box, trans, seq);
+	}
 
 	if (mail_index_transaction_commit_full(&trans, &result) < 0) {
 		mailbox_list_index_set_index_error(box->list);
@@ -292,6 +290,20 @@
 	return 0;
 }
 
+static int
+index_list_update(struct mailbox *box, struct mail_index_view *view,
+		  uint32_t seq, const struct mailbox_status *status)
+{
+	struct mailbox_metadata metadata;
+
+	i_assert(box->opened);
+
+	if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
+		memset(&metadata, 0, sizeof(metadata));
+	return index_list_update_full(box, view, seq, metadata.guid,
+				      status, TRUE);
+}
+
 static void
 index_list_update_mailbox(struct mailbox *box, struct mail_index_view *view)
 {
@@ -349,6 +361,43 @@
 	mail_index_view_close(&list_view);
 }
 
+void mailbox_list_index_update_mailbox_index(struct mailbox *box,
+					     const struct mailbox_update *update)
+{
+	struct mailbox_status status;
+	struct mail_index_view *view;
+	guid_128_t mailbox_guid;
+	uint32_t seq;
+	int ret;
+
+	if ((ret = index_list_open_view(box, &view, &seq)) <= 0)
+		return;
+
+	(void)mailbox_list_index_status(box->list, view, seq,
+					CACHED_STATUS_ITEMS, &status,
+					mailbox_guid);
+	if (update->uid_validity != 0)
+		status.uidvalidity = update->uid_validity;
+	if ((!guid_128_equals(update->mailbox_guid, mailbox_guid) &&
+	     !guid_128_is_empty(update->mailbox_guid) &&
+	     !guid_128_is_empty(mailbox_guid)) ||
+	    update->uid_validity != 0 ||
+	    update->min_next_uid != 0 ||
+	    update->min_first_recent_uid != 0 ||
+	    update->min_highest_modseq != 0) {
+		/* reset status counters. let the syncing later figure out
+		   their correct values. */
+		status.messages = 0;
+		status.unseen = 0;
+		status.recent = 0;
+		status.uidnext = 0;
+		status.highest_modseq = 0;
+	}
+	index_list_update_full(box, view, seq, update->mailbox_guid,
+			       &status, FALSE);
+	mail_index_view_close(&view);
+}
+
 static int index_list_sync_deinit(struct mailbox_sync_context *ctx,


More information about the dovecot-cvs mailing list