]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Fixes/optimizations to SEARCH_MAILBOX*.
authorTimo Sirainen <tss@iki.fi>
Fri, 30 Apr 2010 13:14:42 +0000 (16:14 +0300)
committerTimo Sirainen <tss@iki.fi>
Fri, 30 Apr 2010 13:14:42 +0000 (16:14 +0300)
--HG--
branch : HEAD

src/lib-storage/index/index-search.c
src/lib-storage/mail-search.c
src/lib-storage/mail-search.h

index 2ff9b298d537b9febd1232920ded00c18254d94c..738e106eef3d751c01fdc39b03f7dc9f5a0f5c45 100644 (file)
@@ -58,6 +58,7 @@ struct index_search_context {
        unsigned int sorted:1;
        unsigned int have_seqsets:1;
        unsigned int have_index_args:1;
+       unsigned int have_mailbox_args:1;
 };
 
 struct search_header_context {
@@ -87,6 +88,9 @@ static void search_parse_msgset_args(unsigned int messages_count,
 static void search_init_arg(struct mail_search_arg *arg,
                            struct index_search_context *ctx)
 {
+       uint8_t guid[MAIL_GUID_128_SIZE];
+       bool match;
+
        switch (arg->type) {
        case SEARCH_SEQSET:
                ctx->have_seqsets = TRUE;
@@ -100,9 +104,28 @@ static void search_init_arg(struct mail_search_arg *arg,
                        mail_index_modseq_enable(ctx->box->index);
                ctx->have_index_args = TRUE;
                break;
+       case SEARCH_MAILBOX_GUID:
+               if (mailbox_get_guid(ctx->box, guid) < 0) {
+                       /* result will be unknown */
+                       break;
+               }
+
+               match = strcmp(mail_guid_128_to_string(guid),
+                              arg->value.str) == 0;
+               if (match != arg->not)
+                       arg->match_always = TRUE;
+               else
+                       arg->nonmatch_always = TRUE;
+               break;
+       case SEARCH_MAILBOX:
+       case SEARCH_MAILBOX_GLOB:
+               ctx->have_mailbox_args = TRUE;
+               break;
        case SEARCH_ALL:
                if (!arg->not)
                        arg->match_always = TRUE;
+               else
+                       arg->nonmatch_always = TRUE;
                break;
        default:
                break;
@@ -150,8 +173,6 @@ static int search_arg_match_index(struct index_search_context *ctx,
                                  struct mail_search_arg *arg,
                                  const struct mail_index_record *rec)
 {
-       uint8_t guid[MAIL_GUID_128_SIZE];
-       const char *str;
        enum mail_flags flags;
        uint64_t modseq;
        int ret;
@@ -186,6 +207,37 @@ static int search_arg_match_index(struct index_search_context *ctx,
                }
                return modseq >= arg->value.modseq->modseq;
        }
+       default:
+               return -1;
+       }
+}
+
+static void search_index_arg(struct mail_search_arg *arg,
+                            struct index_search_context *ctx)
+{
+       const struct mail_index_record *rec;
+
+       rec = mail_index_lookup(ctx->view, ctx->mail_ctx.seq);
+       switch (search_arg_match_index(ctx, arg, rec)) {
+       case -1:
+               /* unknown */
+               break;
+       case 0:
+               ARG_SET_RESULT(arg, 0);
+               break;
+       default:
+               ARG_SET_RESULT(arg, 1);
+               break;
+       }
+}
+
+/* Returns >0 = matched, 0 = not matched, -1 = unknown */
+static int search_arg_match_mailbox(struct index_search_context *ctx,
+                                   struct mail_search_arg *arg)
+{
+       const char *str;
+
+       switch (arg->type) {
        case SEARCH_MAILBOX:
                if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME,
                                     &str) < 0)
@@ -194,12 +246,6 @@ static int search_arg_match_index(struct index_search_context *ctx,
                if (strcasecmp(str, "INBOX") == 0)
                        return strcasecmp(arg->value.str, "INBOX") == 0;
                return strcmp(str, arg->value.str) == 0;
-       case SEARCH_MAILBOX_GUID:
-               if (mailbox_get_guid(ctx->mail->box, guid) < 0)
-                       return -1;
-
-               return strcmp(mail_guid_128_to_string(guid),
-                             arg->value.str) == 0;
        case SEARCH_MAILBOX_GLOB:
                if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME,
                                     &str) < 0)
@@ -210,13 +256,10 @@ static int search_arg_match_index(struct index_search_context *ctx,
        }
 }
 
-static void search_index_arg(struct mail_search_arg *arg,
-                            struct index_search_context *ctx)
+static void search_mailbox_arg(struct mail_search_arg *arg,
+                              struct index_search_context *ctx)
 {
-       const struct mail_index_record *rec;
-
-       rec = mail_index_lookup(ctx->view, ctx->mail_ctx.seq);
-       switch (search_arg_match_index(ctx, arg, rec)) {
+       switch (search_arg_match_mailbox(ctx, arg)) {
        case -1:
                /* unknown */
                break;
@@ -1104,6 +1147,13 @@ static bool search_match_next(struct index_search_context *ctx)
        unsigned int i;
        int ret = -1;
 
+       if (ctx->have_mailbox_args) {
+               ret = mail_search_args_foreach(ctx->mail_ctx.args->args,
+                                              search_mailbox_arg, ctx);
+               if (ret >= 0)
+                       return ret > 0;
+       }
+
        /* try to avoid doing extra work for as long as possible */
        for (i = 0; i < N_ELEMENTS(cache_lookups) && ret < 0; i++) {
                ctx->mail->lookup_abort = cache_lookups[i];
index bb5de76b455505aa6d38d6cfc2c886b6551c71eb..893233d0d423286163e19016cd3c403ee0b9832c 100644 (file)
@@ -268,6 +268,7 @@ mail_search_arg_dup_one(pool_t pool, const struct mail_search_arg *arg)
        new_arg->type = arg->type;
        new_arg->not = arg->not;
        new_arg->match_always = arg->match_always;
+       new_arg->nonmatch_always = arg->nonmatch_always;
        new_arg->value.search_flags = arg->value.search_flags;
 
        switch (arg->type) {
@@ -356,15 +357,22 @@ void mail_search_args_reset(struct mail_search_arg *args, bool full_reset)
                if (args->type == SEARCH_OR || args->type == SEARCH_SUB)
                        mail_search_args_reset(args->value.subargs, full_reset);
 
-               if (!args->match_always)
-                       args->result = -1;
-               else {
+               if (args->match_always) {
                        if (!full_reset)
                                args->result = 1;
                        else {
                                args->match_always = FALSE;
                                args->result = -1;
                        }
+               } else if (args->nonmatch_always) {
+                       if (!full_reset)
+                               args->result = 0;
+                       else {
+                               args->nonmatch_always = FALSE;
+                               args->result = -1;
+                       }
+               } else {
+                       args->result = -1;
                }
 
                args = args->next;
index 4e5021dee62ec63e57eae0cd83ae2e805a24fdcf..89e8590afa335efe8287e72dee76ab959ca8a229 100644 (file)
@@ -95,6 +95,7 @@ struct mail_search_arg {
        const char *hdr_field_name; /* for SEARCH_HEADER* */
        unsigned int not:1;
        unsigned int match_always:1; /* result = 1 always */
+       unsigned int nonmatch_always:1; /* result = 0 always */
 
        int result; /* -1 = unknown, 0 = unmatched, 1 = matched */
 };