# HG changeset patch # User Timo Sirainen # Date 1242594739 14400 # Node ID 387f84b2768ecac3eed8e9489894395031f8071e # Parent 2d5f38d2af311db9a2cbe47917e144a735cb85a3 Tracking flag updates in saved search results was broken when expunging messages. 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) + const ARRAY_TYPE(seq_range) *changed_uids_arr, + unsigned int *idx, + uint32_t *next_uid, uint32_t last_uid) { - struct index_mailbox *ibox = (struct index_mailbox *)result->box; - const struct seq_range *seqs; + const struct seq_range *uids; unsigned int i, count; - uint32_t seq, uid; + uint32_t 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); + /* 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; + uid = uids[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); + /* 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; + uid = 0; } } - *next_seq = seq; - *pos = i; + *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; + const struct seq_range *changed_uids; + unsigned int changed_count, changed_idx; + uint32_t next_uid; int ret; - search_seqs = array_get(search_seqs_range, &seqcount); - i_assert(seqcount > 0); - next_seq = search_seqs[0].seq1; - seqpos = 0; + 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 @@ mail = mail_alloc(t, 0, NULL); while (mailbox_search_next(search_ctx, mail) > 0) { - i_assert(next_seq != 0); + i_assert(next_uid != 0); - if (next_seq != mail->seq) { - /* some messages in search_seqs didn't match. + 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); + search_result_range_remove(result, changed_uids_arr, + &changed_idx, &next_uid, + mail->uid-1); + i_assert(next_uid == mail->uid); } - if (search_seqs[seqpos].seq2 > next_seq) { - next_seq++; - } else if (++seqpos < seqcount) { - next_seq = search_seqs[seqpos].seq1; + 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 @@ 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 @@ } 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 @@ 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; - if (array_count(&ctx->hidden_updates) == 0) { - ctx->all_flag_updates = &ctx->flag_updates; - return TRUE; + 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->flag_updates) == 0) { - ctx->all_flag_updates = &ctx->hidden_updates; - return TRUE; - } +} - /* both hidden and non-hidden changes. merge them */ +static void index_sync_uidify(struct index_mailbox_sync_context *ctx) +{ + unsigned int count; + 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; + } + } } static void @@ -53,9 +73,9 @@ return; } - if (search_result_merge_changes(ctx, result)) { + if (search_result_want_flag_updates(result)) { (void)index_search_result_update_flags(result, - ctx->all_flag_updates); + &ctx->all_flag_update_uids); } (void)index_search_result_update_appends(result, ctx->messages_count); } diff -r 2d5f38d2af31 -r 387f84b2768e src/lib-storage/index/index-sync.c --- a/src/lib-storage/index/index-sync.c Sun May 17 17:11:15 2009 -0400 +++ b/src/lib-storage/index/index-sync.c Sun May 17 17:12:19 2009 -0400 @@ -314,6 +314,9 @@ recent flags */ while (index_mailbox_sync_next_expunge(ctx, &sync_rec) > 0) ; + /* convert sequences to uids before syncing view */ + index_sync_search_results_uidify(ctx); + if (ctx->sync_ctx != NULL) { if (mail_index_view_sync_commit(&ctx->sync_ctx, &delayed_expunges) < 0) { @@ -349,8 +352,8 @@ array_free(&ctx->flag_updates); if (array_is_created(&ctx->hidden_updates)) array_free(&ctx->hidden_updates); - if (array_is_created(&ctx->all_flag_updates_merge)) - array_free(&ctx->all_flag_updates_merge); + if (array_is_created(&ctx->all_flag_update_uids)) + array_free(&ctx->all_flag_update_uids); i_free(ctx); return ret; }