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