dovecot-2.0: Tracking flag updates in saved search results was b...
dovecot at dovecot.org
dovecot at dovecot.org
Mon May 18 00:15:17 EEST 2009
details: http://hg.dovecot.org/dovecot-2.0/rev/b42ccb84887f
changeset: 9308:b42ccb84887f
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 789136ae7e21 -r b42ccb84887f 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 789136ae7e21 -r b42ccb84887f 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 789136ae7e21 -r b42ccb84887f 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 789136ae7e21 -r b42ccb84887f 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