dovecot-1.2: virtual: Fixes.
dovecot at dovecot.org
dovecot at dovecot.org
Thu Mar 12 21:22:57 EET 2009
details: http://hg.dovecot.org/dovecot-1.2/rev/8785db70472f
changeset: 8815:8785db70472f
user: Timo Sirainen <tss at iki.fi>
date: Thu Mar 12 15:22:51 2009 -0400
description:
virtual: Fixes.
diffstat:
1 file changed, 123 insertions(+), 139 deletions(-)
src/plugins/virtual/virtual-sync.c | 262 ++++++++++++++++--------------------
diffs (truncated from 345 to 300 lines):
diff -r eb71ec588694 -r 8785db70472f src/plugins/virtual/virtual-sync.c
--- a/src/plugins/virtual/virtual-sync.c Wed Mar 11 17:22:15 2009 -0400
+++ b/src/plugins/virtual/virtual-sync.c Thu Mar 12 15:22:51 2009 -0400
@@ -41,7 +41,6 @@ struct virtual_sync_context {
unsigned int ext_header_changed:1;
unsigned int ext_header_rewrite:1;
unsigned int expunge_removed:1;
- unsigned int retry:1;
};
static void virtual_sync_set_uidvalidity(struct virtual_sync_context *ctx)
@@ -62,8 +61,10 @@ static void virtual_sync_external_flags(
const char *const *kw_names;
struct mail_keywords *keywords;
- if (!mail_set_uid(bbox->sync_mail, real_uid))
- i_panic("UID lost unexpectedly");
+ if (!mail_set_uid(bbox->sync_mail, real_uid)) {
+ i_panic("UID %u lost unexpectedly from %s",
+ real_uid, bbox->box->name);
+ }
/* copy flags */
flags = mail_get_flags(bbox->sync_mail);
@@ -472,113 +473,6 @@ static int virtual_sync_backend_box_init
return ret;
}
-static int virtual_backend_uidmap_cmp(const void *p1, const void *p2)
-{
- const struct virtual_backend_uidmap *u1 = p1, *u2 = p2;
-
- if (u1->real_uid < u2->real_uid)
- return -1;
- if (u1->real_uid > u2->real_uid)
- return 1;
- return 0;
-}
-
-static void
-virtual_sync_backend_add_existing_uids(struct virtual_sync_context *ctx,
- struct virtual_backend_box *bbox,
- struct mail_search_result *result)
-{
- struct virtual_backend_uidmap uidmap, *uids;
- const struct virtual_mail_index_record *vrec;
- const void *data;
- uint32_t vseq, vuid, messages;
- unsigned int uid_count;
- bool expunged;
-
- /* add the currently existing UIDs to uidmap. */
- memset(&uidmap, 0, sizeof(uidmap));
- array_clear(&bbox->uids);
-
- messages = mail_index_view_get_messages_count(ctx->sync_view);
- for (vseq = 1; vseq <= messages; vseq++) {
- mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
- mail_index_lookup_ext(ctx->sync_view, vseq,
- ctx->mbox->virtual_ext_id,
- &data, &expunged);
- vrec = data;
- if (vrec->mailbox_id == bbox->mailbox_id) {
- seq_range_array_add(&result->uids, 0, vrec->real_uid);
- uidmap.real_uid = vrec->real_uid;
- uidmap.virtual_uid = vuid;
- array_append(&bbox->uids, &uidmap, 1);
- }
- }
-
- /* the uidmap must be sorted by real_uids */
- uids = array_get_modifiable(&bbox->uids, &uid_count);
- qsort(uids, uid_count, sizeof(*uids), virtual_backend_uidmap_cmp);
-}
-
-static void
-virtual_sync_backend_remove_expunged_uids(struct mail_search_result *result)
-{
- struct index_mailbox *ibox = (struct index_mailbox *)result->box;
- const struct seq_range *range;
- unsigned int i, count;
- uint32_t seq, uid;
-
- range = array_get(&result->uids, &count);
- for (i = 0; i < count; i++) {
- for (uid = range[i].seq1; uid <= range[i].seq2; uid++) {
- if (!mail_index_lookup_seq(ibox->view, uid, &seq))
- mailbox_search_result_remove(result, uid);
- }
- }
-}
-
-static int virtual_sync_backend_box_continue(struct virtual_sync_context *ctx,
- struct virtual_backend_box *bbox)
-{
- const enum mailbox_search_result_flags result_flags =
- MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
- MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC;
- struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
- struct mail_search_result *result;
- ARRAY_TYPE(seq_range) flag_updates;
- uint64_t modseq;
- uint32_t seq, old_msg_count;
-
- /* build the initial search result from the existing UIDs */
- result = mailbox_search_result_alloc(bbox->box, bbox->search_args,
- result_flags);
- mailbox_search_result_initial_done(result);
- virtual_sync_backend_add_existing_uids(ctx, bbox, result);
-
- /* changes done from now on must update the sync queue */
- virtual_sync_backend_remove_expunged_uids(result);
-
- /* get list of changed messages */
- if (bbox->sync_next_uid <= 1 ||
- !mail_index_lookup_seq_range(ibox->view, 1, bbox->sync_next_uid-1,
- &seq, &old_msg_count))
- old_msg_count = 0;
- t_array_init(&flag_updates, I_MIN(128, old_msg_count));
- for (seq = 1; seq <= old_msg_count; seq++) {
- modseq = mail_index_modseq_lookup(ibox->view, seq);
- if (modseq > bbox->sync_highest_modseq)
- seq_range_array_add(&flag_updates, 0, seq);
- }
-
- if (index_search_result_update_flags(result, &flag_updates) < 0 ||
- index_search_result_update_appends(result, old_msg_count) < 0) {
- mailbox_search_result_free(&result);
- return -1;
- }
-
- bbox->search_result = result;
- return 0;
-}
-
static int virtual_backend_uidmap_bsearch_cmp(const void *key, const void *data)
{
const uint32_t *uidp = key;
@@ -629,8 +523,7 @@ virtual_sync_mailbox_box_remove(struct v
}
}
left = rec_count - src;
- memmove(uidmap + dest, uidmap + src, left);
- array_delete(&bbox->uids, dest + left, src - dest);
+ array_delete(&bbox->uids, dest, src - dest);
}
static void
@@ -687,6 +580,114 @@ virtual_sync_mailbox_box_add(struct virt
}
}
}
+}
+
+static int virtual_backend_uidmap_cmp(const void *p1, const void *p2)
+{
+ const struct virtual_backend_uidmap *u1 = p1, *u2 = p2;
+
+ if (u1->real_uid < u2->real_uid)
+ return -1;
+ if (u1->real_uid > u2->real_uid)
+ return 1;
+ return 0;
+}
+
+static void
+virtual_sync_backend_handle_old_vmsgs(struct virtual_sync_context *ctx,
+ struct virtual_backend_box *bbox,
+ struct mail_search_result *result)
+{
+ struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
+ struct virtual_backend_uidmap uidmap, *uids;
+ const struct virtual_mail_index_record *vrec;
+ const void *data;
+ uint32_t seq, vseq, vuid, messages;
+ unsigned int uid_count;
+ bool expunged;
+
+ /* add the currently existing UIDs to uidmap. remember the messages
+ that were already expunged */
+ memset(&uidmap, 0, sizeof(uidmap));
+ array_clear(&bbox->uids);
+
+ messages = mail_index_view_get_messages_count(ctx->sync_view);
+ for (vseq = 1; vseq <= messages; vseq++) {
+ mail_index_lookup_uid(ctx->sync_view, vseq, &vuid);
+ mail_index_lookup_ext(ctx->sync_view, vseq,
+ ctx->mbox->virtual_ext_id,
+ &data, &expunged);
+ vrec = data;
+ if (vrec->mailbox_id == bbox->mailbox_id) {
+ uidmap.real_uid = vrec->real_uid;
+ uidmap.virtual_uid = vuid;
+ array_append(&bbox->uids, &uidmap, 1);
+
+ if (mail_index_lookup_seq(ibox->view, vrec->real_uid,
+ &seq)) {
+ seq_range_array_add(&result->uids, 0,
+ vrec->real_uid);
+ } else {
+ seq_range_array_add(&result->removed_uids, 0,
+ vrec->real_uid);
+ }
+ }
+ }
+
+ /* the uidmap must be sorted by real_uids */
+ uids = array_get_modifiable(&bbox->uids, &uid_count);
+ qsort(uids, uid_count, sizeof(*uids), virtual_backend_uidmap_cmp);
+}
+
+static int virtual_sync_backend_box_continue(struct virtual_sync_context *ctx,
+ struct virtual_backend_box *bbox)
+{
+ const enum mailbox_search_result_flags result_flags =
+ MAILBOX_SEARCH_RESULT_FLAG_UPDATE |
+ MAILBOX_SEARCH_RESULT_FLAG_QUEUE_SYNC;
+ struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
+ struct mail_search_result *result;
+ ARRAY_TYPE(seq_range) removed_uids, added_uids, flag_updates;
+ uint64_t modseq;
+ uint32_t seq, old_msg_count;
+
+ /* initialize the search result from all the existing messages in
+ virtual index. */
+ result = mailbox_search_result_alloc(bbox->box, bbox->search_args,
+ result_flags);
+ mailbox_search_result_initial_done(result);
+ virtual_sync_backend_handle_old_vmsgs(ctx, bbox, result);
+
+ /* get list of changed old messages, based on modseq changes.
+ (we'll assume all modseq changes are due to flag changes, which
+ may not be true in future.) */
+ if (bbox->sync_next_uid <= 1 ||
+ !mail_index_lookup_seq_range(ibox->view, 1, bbox->sync_next_uid-1,
+ &seq, &old_msg_count))
+ old_msg_count = 0;
+ t_array_init(&flag_updates, I_MIN(128, old_msg_count));
+ for (seq = 1; seq <= old_msg_count; seq++) {
+ modseq = mail_index_modseq_lookup(ibox->view, seq);
+ if (modseq > bbox->sync_highest_modseq)
+ seq_range_array_add(&flag_updates, 0, seq);
+ }
+
+ /* update the search result based on the flag changes and
+ new messages */
+ if (index_search_result_update_flags(result, &flag_updates) < 0 ||
+ index_search_result_update_appends(result, old_msg_count) < 0) {
+ mailbox_search_result_free(&result);
+ return -1;
+ }
+
+ t_array_init(&removed_uids, 128);
+ t_array_init(&added_uids, 128);
+ mailbox_search_result_sync(result, &removed_uids, &added_uids);
+ virtual_sync_mailbox_box_remove(ctx, bbox, &removed_uids);
+ virtual_sync_mailbox_box_add(ctx, bbox, &added_uids);
+
+ bbox->search_result = result;
+ return 0;
}
static void virtual_sync_mailbox_box_update(struct virtual_sync_context *ctx,
@@ -768,11 +769,12 @@ static int virtual_sync_backend_box_sync
struct virtual_backend_box *bbox,
enum mailbox_sync_flags sync_flags)
{
+ struct index_mailbox *ibox = (struct index_mailbox *)bbox->box;
struct mailbox_sync_context *sync_ctx;
const struct virtual_backend_uidmap *uidmap;
struct mailbox_sync_rec sync_rec;
unsigned int idx1, idx2;
- uint32_t vseq, vuid;
+ uint32_t vseq, vuid, uid1, uid2;
sync_ctx = mailbox_sync_init(bbox->box, sync_flags);
virtual_backend_box_sync_mail_set(bbox);
@@ -783,8 +785,10 @@ static int virtual_sync_backend_box_sync
/* no need to keep track of expunges */
break;
}
+ mail_index_lookup_uid(ibox->view, sync_rec.seq1, &uid1);
+ mail_index_lookup_uid(ibox->view, sync_rec.seq2, &uid2);
seq_range_array_add_range(&ctx->sync_expunges,
- sync_rec.seq1, sync_rec.seq2);
+ uid1, uid2);
break;
case MAILBOX_SYNC_TYPE_FLAGS:
if (!virtual_sync_find_seqs(bbox, &sync_rec,
@@ -884,12 +888,8 @@ static int virtual_sync_backend_box(stru
the first sync), do a full search */
ret = virtual_sync_backend_box_init(bbox);
} else {
- /* build the initial search using the saved modseq.
- we can't directly update the search result because
- uidmap isn't finished for all messages yet, so
- mark the sync to be retried. */
+ /* build the initial search using the saved modseq. */
ret = virtual_sync_backend_box_continue(ctx, bbox);
- ctx->retry = TRUE;
More information about the dovecot-cvs
mailing list