]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Moved non-syncing related search result updating code to a separate file and
authorTimo Sirainen <tss@iki.fi>
Wed, 18 Jun 2008 01:59:20 +0000 (04:59 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 18 Jun 2008 01:59:20 +0000 (04:59 +0300)
did some other cleanups.

--HG--
branch : HEAD

src/lib-storage/index/Makefile.am
src/lib-storage/index/index-search-result.c [new file with mode: 0644]
src/lib-storage/index/index-search-result.h [new file with mode: 0644]
src/lib-storage/index/index-sync-private.h
src/lib-storage/index/index-sync-search.c
src/lib-storage/index/index-sync.c

index 25a434f61765a00674c9201096aa6348030f552c..06e85554a7476f1459f24880e0ad3bdeb8823349 100644 (file)
@@ -15,6 +15,7 @@ libstorage_index_a_SOURCES = \
        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 @@ libstorage_index_a_SOURCES = \
 
 headers = \
        index-mail.h \
+       index-search-result.h \
        index-sort.h \
        index-sort-private.h \
        index-storage.h \
diff --git a/src/lib-storage/index/index-search-result.c b/src/lib-storage/index/index-search-result.c
new file mode 100644 (file)
index 0000000..7b2c092
--- /dev/null
@@ -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);
+               }
+       }
+}
diff --git a/src/lib-storage/index/index-search-result.h b/src/lib-storage/index/index-search-result.h
new file mode 100644 (file)
index 0000000..63bceaa
--- /dev/null
@@ -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
index f6700836c87b35839fc347c2c5227bd4ebde94a5..9531453c52583d5674ac6d11e48f97759284916e 100644 (file)
@@ -11,6 +11,7 @@ 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;
        const ARRAY_TYPE(seq_range) *expunges;
        unsigned int flag_update_idx, hidden_update_idx, expunge_pos;
 
index 914caa490a626fe550628e8447e83d59d459061e..4ba8e8a4caf98130c843eae4542672d08618f357 100644 (file)
 #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_merge_changes(struct index_mailbox_sync_context *ctx,
                /* 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;
-
-       /* 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;
+       /* both hidden and non-hidden changes. merge them */
+       count = array_count(&ctx->flag_updates) +
+               array_count(&ctx->hidden_updates);
 
-       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 @@ search_result_update(struct index_mailbox_sync_context *ctx,
                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_update(struct index_mailbox_sync_context *ctx)
 
 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);
        }
 }
index 74fe234b08247b6b0bc064110e8a167044f69bf9..cf68e35bb8d02b704ed5534a8f040b72e2651b25 100644 (file)
@@ -349,6 +349,8 @@ int index_mailbox_sync_deinit(struct mailbox_sync_context *_ctx,
                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;
 }