dovecot-1.2: Tracking flag updates in saved search results was b...

dovecot at dovecot.org dovecot at dovecot.org
Mon May 18 00:15:09 EEST 2009


details:   http://hg.dovecot.org/dovecot-1.2/rev/387f84b2768e
changeset: 9037:387f84b2768e
user:      Timo Sirainen <tss at iki.fi>
date:      Sun May 17 17:12:19 2009 -0400
description:
Tracking flag updates in saved search results was broken when expunging messages.

diffstat:

5 files changed, 112 insertions(+), 90 deletions(-)
src/lib-storage/index/index-search-result.c |  124 +++++++++++++--------------
src/lib-storage/index/index-search-result.h |    2 
src/lib-storage/index/index-sync-private.h  |    3 
src/lib-storage/index/index-sync-search.c   |   66 +++++++++-----
src/lib-storage/index/index-sync.c          |    7 +

diffs (truncated from 339 to 300 lines):

diff -r 2d5f38d2af31 -r 387f84b2768e src/lib-storage/index/index-search-result.c
--- a/src/lib-storage/index/index-search-result.c	Sun May 17 17:11:15 2009 -0400
+++ b/src/lib-storage/index/index-search-result.c	Sun May 17 17:12:19 2009 -0400
@@ -10,63 +10,61 @@
 
 static void
 search_result_range_remove(struct mail_search_result *result,
-			   const ARRAY_TYPE(seq_range) *search_seqs_range,
-			   unsigned int *pos,
-			   uint32_t *next_seq, uint32_t last_seq)
-{
-	struct index_mailbox *ibox = (struct index_mailbox *)result->box;
-	const struct seq_range *seqs;
+			   const ARRAY_TYPE(seq_range) *changed_uids_arr,
+			   unsigned int *idx,
+			   uint32_t *next_uid, uint32_t last_uid)
+{
+	const struct seq_range *uids;
 	unsigned int i, count;
-	uint32_t seq, uid;
-
-	seq = *next_seq;
-	seqs = array_get(search_seqs_range, &count);
-	for (i = *pos; seqs[i].seq2 < last_seq;) {
-		i_assert(seqs[i].seq1 <= seq);
-		for (; seq <= seqs[i].seq2; seq++) {
-			mail_index_lookup_uid(ibox->view, seq, &uid);
+	uint32_t uid;
+
+	/* remove full seq_ranges */
+	uid = *next_uid;
+	uids = array_get(changed_uids_arr, &count);
+	for (i = *idx; uids[i].seq2 < last_uid;) {
+		i_assert(uids[i].seq1 <= uid);
+		for (; uid <= uids[i].seq2; uid++)
 			mailbox_search_result_remove(result, uid);
-		}
 		i++;
 		i_assert(i < count);
-		seq = seqs[i].seq1;
-	}
-
-	i_assert(seqs[i].seq1 <= seq && seqs[i].seq2 >= last_seq);
-	for (; seq <= last_seq; seq++) {
-		mail_index_lookup_uid(ibox->view, seq, &uid);
+		uid = uids[i].seq1;
+	}
+
+	/* remove the last seq_range */
+	i_assert(uids[i].seq1 <= uid && uids[i].seq2 >= last_uid);
+	for (; uid <= last_uid; uid++)
 		mailbox_search_result_remove(result, uid);
-	}
-	if (seq > seqs[i].seq2) {
+
+	if (uid > uids[i].seq2) {
 		/* finished this range */
 		if (++i < count)
-			seq = seqs[i].seq1;
+			uid = uids[i].seq1;
 		else {
 			/* this was the last searched message */
-			seq = 0;
-		}
-	}
-
-	*next_seq = seq;
-	*pos = i;
+			uid = 0;
+		}
+	}
+
+	*next_uid = uid;
+	*idx = i;
 }
 
 static int
 search_result_update_search(struct mail_search_result *result,
-			    const ARRAY_TYPE(seq_range) *search_seqs_range)
+			    const ARRAY_TYPE(seq_range) *changed_uids_arr)
 {
 	struct mailbox_transaction_context *t;
 	struct mail_search_context *search_ctx;
 	struct mail *mail;
-	const struct seq_range *search_seqs;
-	unsigned int seqcount, seqpos;
-	uint32_t next_seq;
-	int ret;
-
-	search_seqs = array_get(search_seqs_range, &seqcount);
-	i_assert(seqcount > 0);
-	next_seq = search_seqs[0].seq1;
-	seqpos = 0;
+	const struct seq_range *changed_uids;
+	unsigned int changed_count, changed_idx;
+	uint32_t next_uid;
+	int ret;
+
+	changed_uids = array_get(changed_uids_arr, &changed_count);
+	i_assert(changed_count > 0);
+	next_uid = changed_uids[0].seq1;
+	changed_idx = 0;
 
 	mail_search_args_init(result->search_args, result->box, FALSE, NULL);
 
@@ -78,23 +76,23 @@ search_result_update_search(struct mail_
 
 	mail = mail_alloc(t, 0, NULL);
 	while (mailbox_search_next(search_ctx, mail) > 0) {
-		i_assert(next_seq != 0);
-
-		if (next_seq != mail->seq) {
-			/* some messages in search_seqs didn't match.
+		i_assert(next_uid != 0);
+
+		if (next_uid != mail->uid) {
+			/* some messages in changed_uids didn't match.
 			   make sure they don't exist in the search result. */
-			search_result_range_remove(result, search_seqs_range,
-						   &seqpos, &next_seq,
-						   mail->seq-1);
-			i_assert(next_seq == mail->seq);
-		}
-		if (search_seqs[seqpos].seq2 > next_seq) {
-			next_seq++;
-		} else if (++seqpos < seqcount) {
-			next_seq = search_seqs[seqpos].seq1;
+			search_result_range_remove(result, changed_uids_arr,
+						   &changed_idx, &next_uid,
+						   mail->uid-1);
+			i_assert(next_uid == mail->uid);
+		}
+		if (changed_uids[changed_idx].seq2 > next_uid) {
+			next_uid++;
+		} else if (++changed_idx < changed_count) {
+			next_uid = changed_uids[changed_idx].seq1;
 		} else {
 			/* this was the last searched message */
-			next_seq = 0;
+			next_uid = 0;
 		}
 		/* match - make sure it exists in search result */
 		mailbox_search_result_add(result, mail->uid);
@@ -103,12 +101,12 @@ search_result_update_search(struct mail_
 	ret = mailbox_search_deinit(&search_ctx);
 	mail_search_args_deinit(result->search_args);
 
-	if (next_seq != 0 && ret == 0) {
+	if (next_uid != 0 && ret == 0) {
 		/* last message(s) didn't match. make sure they don't exist
 		   in the search result. */
-		search_result_range_remove(result, search_seqs_range, &seqpos,
-					   &next_seq,
-					   search_seqs[seqcount-1].seq2);
+		search_result_range_remove(result, changed_uids_arr,
+					   &changed_idx, &next_uid,
+					   changed_uids[changed_count-1].seq2);
 	}
 
 	if (mailbox_transaction_commit(&t) < 0)
@@ -117,22 +115,22 @@ search_result_update_search(struct mail_
 }
 
 int index_search_result_update_flags(struct mail_search_result *result,
-				     const ARRAY_TYPE(seq_range) *changes)
+				     const ARRAY_TYPE(seq_range) *uids)
 {
 	struct mail_search_arg search_arg;
 	int ret;
 
-	if (array_count(changes) == 0)
+	if (array_count(uids) == 0)
 		return 0;
 
 	/* add a temporary search parameter to limit the search only to
 	   the changed messages */
 	memset(&search_arg, 0, sizeof(search_arg));
-	search_arg.type = SEARCH_SEQSET;
-	search_arg.value.seqset = *changes;
+	search_arg.type = SEARCH_UIDSET;
+	search_arg.value.seqset = *uids;
 	search_arg.next = result->search_args->args;
 	result->search_args->args = &search_arg;
-	ret = search_result_update_search(result, changes);
+	ret = search_result_update_search(result, uids);
 	i_assert(result->search_args->args == &search_arg);
 	result->search_args->args = search_arg.next;
 	return ret;
diff -r 2d5f38d2af31 -r 387f84b2768e src/lib-storage/index/index-search-result.h
--- a/src/lib-storage/index/index-search-result.h	Sun May 17 17:11:15 2009 -0400
+++ b/src/lib-storage/index/index-search-result.h	Sun May 17 17:12:19 2009 -0400
@@ -2,7 +2,7 @@
 #define INDEX_SEARCH_RESULT_H
 
 int index_search_result_update_flags(struct mail_search_result *result,
-				     const ARRAY_TYPE(seq_range) *changes);
+				     const ARRAY_TYPE(seq_range) *uids);
 int index_search_result_update_appends(struct mail_search_result *result,
 				       unsigned int old_messages_count);
 void index_search_results_update_expunges(struct mailbox *box,
diff -r 2d5f38d2af31 -r 387f84b2768e src/lib-storage/index/index-sync-private.h
--- a/src/lib-storage/index/index-sync-private.h	Sun May 17 17:11:15 2009 -0400
+++ b/src/lib-storage/index/index-sync-private.h	Sun May 17 17:12:19 2009 -0400
@@ -11,13 +11,14 @@ struct index_mailbox_sync_context {
 
 	ARRAY_TYPE(seq_range) flag_updates;
 	ARRAY_TYPE(seq_range) hidden_updates;
-	ARRAY_TYPE(seq_range) *all_flag_updates, all_flag_updates_merge;
+	ARRAY_TYPE(seq_range) all_flag_update_uids;
 	const ARRAY_TYPE(seq_range) *expunges;
 	unsigned int flag_update_idx, hidden_update_idx, expunge_pos;
 
 	bool failed;
 };
 
+void index_sync_search_results_uidify(struct index_mailbox_sync_context *ctx);
 void index_sync_search_results_update(struct index_mailbox_sync_context *ctx);
 void index_sync_search_results_expunge(struct index_mailbox_sync_context *ctx);
 
diff -r 2d5f38d2af31 -r 387f84b2768e src/lib-storage/index/index-sync-search.c
--- a/src/lib-storage/index/index-sync-search.c	Sun May 17 17:11:15 2009 -0400
+++ b/src/lib-storage/index/index-sync-search.c	Sun May 17 17:12:19 2009 -0400
@@ -9,39 +9,59 @@
 #include "index-sync-private.h"
 
 static bool
-search_result_merge_changes(struct index_mailbox_sync_context *ctx,
-			    const struct mail_search_result *result)
+search_result_want_flag_updates(const struct mail_search_result *result)
 {
-	unsigned int count;
-
 	if (!result->args_have_flags && !result->args_have_keywords &&
 	    !result->args_have_modseq) {
 		/* search result doesn't care about flag changes */
 		return FALSE;
 	}
-	if (ctx->all_flag_updates != NULL) {
-		/* already merged */
-		return TRUE;
+	return TRUE;
+}
+
+static void index_sync_uidify_array(struct index_mailbox_sync_context *ctx,
+				    const ARRAY_TYPE(seq_range) *changes)
+{
+	const struct seq_range *seqs;
+	unsigned int i, count;
+	uint32_t seq, uid;
+
+	seqs = array_get(changes, &count);
+	for (i = 0; i < count; i++) {
+		for (seq = seqs[i].seq1; seq <= seqs[i].seq2; seq++) {
+			mail_index_lookup_uid(ctx->ibox->view, seq, &uid);
+			seq_range_array_add(&ctx->all_flag_update_uids, 0, uid);
+		}
 	}
+}
 
-	if (array_count(&ctx->hidden_updates) == 0) {
-		ctx->all_flag_updates = &ctx->flag_updates;
-		return TRUE;
-	}
-	if (array_count(&ctx->flag_updates) == 0) {
-		ctx->all_flag_updates = &ctx->hidden_updates;
-		return TRUE;
-	}
+static void index_sync_uidify(struct index_mailbox_sync_context *ctx)
+{
+	unsigned int count;
 
-	/* both hidden and non-hidden changes. merge them */
 	count = array_count(&ctx->flag_updates) +
 		array_count(&ctx->hidden_updates);
+	i_array_init(&ctx->all_flag_update_uids, count*2);
 
-	ctx->all_flag_updates = &ctx->all_flag_updates_merge;
-	i_array_init(ctx->all_flag_updates, count);
-	seq_range_array_merge(ctx->all_flag_updates, &ctx->flag_updates);
-	seq_range_array_merge(ctx->all_flag_updates, &ctx->hidden_updates);
-	return TRUE;
+	index_sync_uidify_array(ctx, &ctx->flag_updates);
+	index_sync_uidify_array(ctx, &ctx->hidden_updates);
+}
+
+void index_sync_search_results_uidify(struct index_mailbox_sync_context *ctx)
+{
+	struct mail_search_result *const *results;
+	unsigned int i, count;
+
+	i_assert(!array_is_created(&ctx->all_flag_update_uids));
+
+	results = array_get(&ctx->ibox->box.search_results, &count);
+	for (i = 0; i < count; i++) {
+		if ((results[i]->flags & MAILBOX_SEARCH_RESULT_FLAG_UPDATE) != 0 &&
+		    search_result_want_flag_updates(results[i])) {
+			index_sync_uidify(ctx);
+			break;
+		}
+	}


More information about the dovecot-cvs mailing list