Mercurial > dovecot > original-hg > dovecot-1.2
changeset 7888:3ffac3f6173f HEAD
Moved non-syncing related search result updating code to a separate file and
did some other cleanups.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Wed, 18 Jun 2008 04:59:20 +0300 |
parents | 38bdfafa655c |
children | ef8af0eb161a |
files | src/lib-storage/index/Makefile.am src/lib-storage/index/index-search-result.c src/lib-storage/index/index-search-result.h src/lib-storage/index/index-sync-private.h src/lib-storage/index/index-sync-search.c src/lib-storage/index/index-sync.c |
diffstat | 6 files changed, 242 insertions(+), 203 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/Makefile.am Wed Jun 18 04:34:46 2008 +0300 +++ b/src/lib-storage/index/Makefile.am Wed Jun 18 04:59:20 2008 +0300 @@ -15,6 +15,7 @@ index-mail-headers.c \ index-mailbox-check.c \ index-search.c \ + index-search-result.c \ index-sort.c \ index-sort-string.c \ index-status.c \ @@ -29,6 +30,7 @@ headers = \ index-mail.h \ + index-search-result.h \ index-sort.h \ index-sort-private.h \ index-storage.h \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/index-search-result.c Wed Jun 18 04:59:20 2008 +0300 @@ -0,0 +1,198 @@ +/* Copyright (c) 2002-2008 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "array.h" +#include "seq-range-array.h" +#include "mail-search.h" +#include "mailbox-search-result-private.h" +#include "index-storage.h" +#include "index-search-result.h" + +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; + 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); + 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); + mailbox_search_result_remove(result, uid); + } + if (seq > seqs[i].seq2) { + /* finished this range */ + if (++i < count) + seq = seqs[i].seq1; + else { + /* this was the last searched message */ + seq = 0; + } + } + + *next_seq = seq; + *pos = i; +} + +static int +search_result_update_search(struct mail_search_result *result, + const ARRAY_TYPE(seq_range) *search_seqs_range) +{ + 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; + + t = mailbox_transaction_begin(result->box, 0); + search_ctx = mailbox_search_init(t, result->search_args, NULL); + /* tell search that we're updating an existing search result, + so it can do some optimizations based on it */ + search_ctx->update_result = result; + + 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. + 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; + } else { + /* this was the last searched message */ + next_seq = 0; + } + /* match - make sure it exists in search result */ + mailbox_search_result_add(result, mail->uid); + } + mail_free(&mail); + ret = mailbox_search_deinit(&search_ctx); + + if (next_seq != 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); + } + + if (mailbox_transaction_commit(&t) < 0) + ret = -1; + return ret; +} + +int index_search_result_update_flags(struct mail_search_result *result, + const ARRAY_TYPE(seq_range) *changes) +{ + struct mail_search_arg search_arg; + int ret; + + /* 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.next = result->search_args->args; + result->search_args->args = &search_arg; + ret = search_result_update_search(result, changes); + i_assert(result->search_args->args == &search_arg); + result->search_args->args = search_arg.next; + return ret; +} + +int index_search_result_update_appends(struct mail_search_result *result, + unsigned int old_messages_count) +{ + struct index_mailbox *ibox = (struct index_mailbox *)result->box; + struct mailbox_transaction_context *t; + struct mail_search_context *search_ctx; + struct mail *mail; + struct mail_search_arg search_arg; + uint32_t message_count; + int ret; + + message_count = mail_index_view_get_messages_count(ibox->view); + if (old_messages_count == message_count) { + /* no new messages */ + return 0; + } + + /* add a temporary search parameter to limit the search only to + the new messages */ + memset(&search_arg, 0, sizeof(search_arg)); + search_arg.type = SEARCH_SEQSET; + t_array_init(&search_arg.value.seqset, 1); + seq_range_array_add_range(&search_arg.value.seqset, + old_messages_count + 1, message_count); + search_arg.next = result->search_args->args; + result->search_args->args = &search_arg; + + /* add all messages matching the search to search result */ + t = mailbox_transaction_begin(result->box, 0); + search_ctx = mailbox_search_init(t, result->search_args, NULL); + + mail = mail_alloc(t, 0, NULL); + while (mailbox_search_next(search_ctx, mail) > 0) + mailbox_search_result_add(result, mail->uid); + mail_free(&mail); + + ret = mailbox_search_deinit(&search_ctx); + if (mailbox_transaction_commit(&t) < 0) + ret = -1; + + i_assert(result->search_args->args == &search_arg); + result->search_args->args = search_arg.next; + return ret; +} + +void index_search_results_update_expunges(struct mailbox *box, + const ARRAY_TYPE(seq_range) *expunges) +{ + struct index_mailbox *ibox = (struct index_mailbox *)box; + const struct seq_range *seqs; + unsigned int i, count; + uint32_t seq, uid; + + if (array_count(&box->search_results) == 0) + return; + + seqs = array_get(expunges, &count); + for (i = 0; i < count; i++) { + for (seq = seqs[i].seq1; seq <= seqs[i].seq2; seq++) { + mail_index_lookup_uid(ibox->view, seq, &uid); + mailbox_search_results_remove(box, uid); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lib-storage/index/index-search-result.h Wed Jun 18 04:59:20 2008 +0300 @@ -0,0 +1,11 @@ +#ifndef INDEX_SEARCH_RESULT_H +#define INDEX_SEARCH_RESULT_H + +int index_search_result_update_flags(struct mail_search_result *result, + const ARRAY_TYPE(seq_range) *changes); +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, + const ARRAY_TYPE(seq_range) *expunges); + +#endif
--- a/src/lib-storage/index/index-sync-private.h Wed Jun 18 04:34:46 2008 +0300 +++ b/src/lib-storage/index/index-sync-private.h Wed Jun 18 04:59:20 2008 +0300 @@ -11,6 +11,7 @@ ARRAY_TYPE(seq_range) flag_updates; ARRAY_TYPE(seq_range) hidden_updates; + ARRAY_TYPE(seq_range) *all_flag_updates, all_flag_updates_merge; const ARRAY_TYPE(seq_range) *expunges; unsigned int flag_update_idx, hidden_update_idx, expunge_pos;
--- a/src/lib-storage/index/index-sync-search.c Wed Jun 18 04:34:46 2008 +0300 +++ b/src/lib-storage/index/index-sync-search.c Wed Jun 18 04:59:20 2008 +0300 @@ -5,119 +5,13 @@ #include "seq-range-array.h" #include "mail-search.h" #include "mailbox-search-result-private.h" +#include "index-search-result.h" #include "index-sync-private.h" -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; - 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); - 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); - mailbox_search_result_remove(result, uid); - } - if (seq > seqs[i].seq2) { - /* finished this range */ - if (++i < count) - seq = seqs[i].seq1; - else { - /* this was the last searched message */ - seq = 0; - } - } - - *next_seq = seq; - *pos = i; -} - -static int -search_result_update_search(struct mail_search_result *result, - const ARRAY_TYPE(seq_range) *search_seqs_range) -{ - 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; - - t = mailbox_transaction_begin(result->box, 0); - search_ctx = mailbox_search_init(t, result->search_args, NULL); - /* tell search that we're updating an existing search result, - so it can do some optimizations based on it */ - search_ctx->update_result = result; - - 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. - 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; - } else { - /* this was the last searched message */ - next_seq = 0; - } - /* match - make sure it exists in search result */ - mailbox_search_result_add(result, mail->uid); - } - mail_free(&mail); - ret = mailbox_search_deinit(&search_ctx); - - if (next_seq != 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); - } - - if (mailbox_transaction_commit(&t) < 0) - ret = -1; - return ret; -} - static bool search_result_merge_changes(struct index_mailbox_sync_context *ctx, - struct mail_search_result *result, - ARRAY_TYPE(seq_range) *changes) + const struct mail_search_result *result) { - /* @UNSAFE */ unsigned int count; if (!result->args_have_flags && !result->args_have_keywords && @@ -125,84 +19,29 @@ /* search result doesn't care about flag changes */ return FALSE; } - count = array_count(&ctx->flag_updates) + - array_count(&ctx->hidden_updates); - if (count == 0) { - /* no changes */ - return FALSE; + if (ctx->all_flag_updates != NULL) { + /* already merged */ + return TRUE; } - /* merge the changed sequences */ - t_array_init(changes, count); - seq_range_array_merge(changes, &ctx->flag_updates); - seq_range_array_merge(changes, &ctx->hidden_updates); - return TRUE; -} - -static int -search_result_update_existing(struct mail_search_result *result, - const ARRAY_TYPE(seq_range) *changes) -{ - struct mail_search_arg search_arg; - int ret; - - /* 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.next = result->search_args->args; - result->search_args->args = &search_arg; - ret = search_result_update_search(result, changes); - i_assert(result->search_args->args == &search_arg); - result->search_args->args = search_arg.next; - return ret; -} - -static int -search_result_update_appends(struct mail_index_view *view, - unsigned int old_messages_count, - struct mail_search_result *result) -{ - struct mailbox_transaction_context *t; - struct mail_search_context *search_ctx; - struct mail *mail; - struct mail_search_arg search_arg; - uint32_t message_count; - int ret; - - message_count = mail_index_view_get_messages_count(view); - if (old_messages_count == message_count) { - /* no new messages */ - return 0; + 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; } - /* add a temporary search parameter to limit the search only to - the new messages */ - memset(&search_arg, 0, sizeof(search_arg)); - search_arg.type = SEARCH_SEQSET; - t_array_init(&search_arg.value.seqset, 1); - seq_range_array_add_range(&search_arg.value.seqset, - old_messages_count + 1, message_count); - search_arg.next = result->search_args->args; - result->search_args->args = &search_arg; + /* both hidden and non-hidden changes. merge them */ + count = array_count(&ctx->flag_updates) + + array_count(&ctx->hidden_updates); - /* add all messages matching the search to search result */ - t = mailbox_transaction_begin(result->box, 0); - search_ctx = mailbox_search_init(t, result->search_args, NULL); - - mail = mail_alloc(t, 0, NULL); - while (mailbox_search_next(search_ctx, mail) > 0) - mailbox_search_result_add(result, mail->uid); - mail_free(&mail); - - ret = mailbox_search_deinit(&search_ctx); - if (mailbox_transaction_commit(&t) < 0) - ret = -1; - - i_assert(result->search_args->args == &search_arg); - result->search_args->args = search_arg.next; - return ret; + 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; } static void @@ -214,14 +53,11 @@ return; } - T_BEGIN { - ARRAY_TYPE(seq_range) changes; - - if (search_result_merge_changes(ctx, result, &changes)) - (void)search_result_update_existing(result, &changes); - } T_END; - (void)search_result_update_appends(ctx->ibox->view, ctx->messages_count, - result); + if (search_result_merge_changes(ctx, result)) { + (void)index_search_result_update_flags(result, + ctx->all_flag_updates); + } + (void)index_search_result_update_appends(result, ctx->messages_count); } void index_sync_search_results_update(struct index_mailbox_sync_context *ctx) @@ -236,19 +72,8 @@ void index_sync_search_results_expunge(struct index_mailbox_sync_context *ctx) { - struct mailbox *box = &ctx->ibox->box; - const struct seq_range *seqs; - unsigned int i, count; - uint32_t seq, uid; - - if (ctx->expunges == NULL || array_count(&box->search_results) == 0) - return; - - seqs = array_get(ctx->expunges, &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); - mailbox_search_results_remove(box, uid); - } + if (ctx->expunges != NULL) { + index_search_results_update_expunges(&ctx->ibox->box, + ctx->expunges); } }
--- a/src/lib-storage/index/index-sync.c Wed Jun 18 04:34:46 2008 +0300 +++ b/src/lib-storage/index/index-sync.c Wed Jun 18 04:59:20 2008 +0300 @@ -349,6 +349,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); i_free(ctx); return ret; }