From: Timo Sirainen Date: Fri, 30 Apr 2010 13:14:42 +0000 (+0300) Subject: lib-storage: Fixes/optimizations to SEARCH_MAILBOX*. X-Git-Tag: 2.0.beta5~36 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d8256deeb5a94a6e27f4762bdb77ce284b7dc517;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Fixes/optimizations to SEARCH_MAILBOX*. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index 2ff9b298d5..738e106eef 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -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]; diff --git a/src/lib-storage/mail-search.c b/src/lib-storage/mail-search.c index bb5de76b45..893233d0d4 100644 --- a/src/lib-storage/mail-search.c +++ b/src/lib-storage/mail-search.c @@ -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; diff --git a/src/lib-storage/mail-search.h b/src/lib-storage/mail-search.h index 4e5021dee6..89e8590afa 100644 --- a/src/lib-storage/mail-search.h +++ b/src/lib-storage/mail-search.h @@ -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 */ };