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