Mercurial > dovecot > original-hg > dovecot-1.2
changeset 6966:7bb6ef75715c HEAD
Optimize searching flags and keywords.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sat, 08 Dec 2007 19:36:11 +0200 |
parents | ae369569e7de |
children | 4c3002f3cd51 |
files | src/lib-storage/index/index-search.c |
diffstat | 1 files changed, 56 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/index-search.c Sat Dec 08 19:21:27 2007 +0200 +++ b/src/lib-storage/index/index-search.c Sat Dec 08 19:36:11 2007 +0200 @@ -40,7 +40,7 @@ unsigned int failed:1; unsigned int sorted:1; unsigned int have_seqsets:1; - unsigned int have_flags:1; + unsigned int have_flags_or_keywords:1; }; struct search_header_context { @@ -67,6 +67,26 @@ struct mail_search_arg *args, uint32_t *seq1_r, uint32_t *seq2_r); +static void search_init_arg(struct mail_search_arg *arg, + struct index_search_context *ctx) +{ + switch (arg->type) { + case SEARCH_SEQSET: + ctx->have_seqsets = TRUE; + break; + case SEARCH_FLAGS: + case SEARCH_KEYWORDS: + ctx->have_flags_or_keywords = TRUE; + break; + case SEARCH_ALL: + if (!arg->not) + arg->match_always = TRUE; + break; + default: + break; + } +} + static int seqset_contains(struct mail_search_seqset *set, uint32_t seq) { while (set != NULL) { @@ -78,7 +98,18 @@ return FALSE; } -static int search_arg_match_keywords(struct index_mail *imail, +static void search_seqset_arg(struct mail_search_arg *arg, + struct index_search_context *ctx) +{ + if (arg->type == SEARCH_SEQSET) { + if (seqset_contains(arg->value.seqset, ctx->mail_ctx.seq)) + ARG_SET_RESULT(arg, 1); + else + ARG_SET_RESULT(arg, 0); + } +} + +static int search_arg_match_keywords(struct index_search_context *ctx, struct mail_search_arg *arg) { ARRAY_TYPE(keyword_indexes) keyword_indexes_arr; @@ -87,7 +118,7 @@ unsigned int i, j, count; t_array_init(&keyword_indexes_arr, 128); - mail_index_lookup_keywords(imail->ibox->view, imail->mail.mail.seq, + mail_index_lookup_keywords(ctx->view, ctx->mail_ctx.seq, &keyword_indexes_arr); keyword_indexes = array_get(&keyword_indexes_arr, &count); @@ -104,22 +135,23 @@ } /* Returns >0 = matched, 0 = not matched, -1 = unknown */ -static int search_arg_match_index(struct index_mail *imail, - struct mail_search_arg *arg) +static int search_arg_match_index(struct index_search_context *ctx, + struct mail_search_arg *arg, + const struct mail_index_record *rec) { enum mail_flags flags; int ret; switch (arg->type) { case SEARCH_FLAGS: - flags = imail->data.flags; + flags = rec->flags; if ((arg->value.flags & MAIL_RECENT) != 0 && - index_mailbox_is_recent(imail->ibox, imail->mail.mail.uid)) + index_mailbox_is_recent(ctx->ibox, rec->uid)) flags |= MAIL_RECENT; return (flags & arg->value.flags) == arg->value.flags; case SEARCH_KEYWORDS: T_FRAME( - ret = search_arg_match_keywords(imail, arg); + ret = search_arg_match_keywords(ctx, arg); ); return ret; @@ -128,37 +160,13 @@ } } -static void search_init_seqset_arg(struct mail_search_arg *arg, - struct index_search_context *ctx) -{ - switch (arg->type) { - case SEARCH_SEQSET: - ctx->have_seqsets = TRUE; - break; - case SEARCH_ALL: - if (!arg->not) - arg->match_always = TRUE; - break; - default: - break; - } -} - -static void search_seqset_arg(struct mail_search_arg *arg, - struct index_search_context *ctx) -{ - if (arg->type == SEARCH_SEQSET) { - if (seqset_contains(arg->value.seqset, ctx->mail_ctx.seq)) - ARG_SET_RESULT(arg, 1); - else - ARG_SET_RESULT(arg, 0); - } -} - static void search_index_arg(struct mail_search_arg *arg, struct index_search_context *ctx) { - switch (search_arg_match_index(ctx->imail, arg)) { + 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; @@ -862,7 +870,7 @@ mail_search_args_reset(ctx->mail_ctx.args, TRUE); search_get_seqset(ctx, args); - (void)mail_search_args_foreach(args, search_init_seqset_arg, ctx); + (void)mail_search_args_foreach(args, search_init_arg, ctx); /* Need to reset results for match_always cases */ mail_search_args_reset(ctx->mail_ctx.args, FALSE); @@ -912,12 +920,6 @@ struct mail_search_arg *arg; int ret; - /* check the index matches first */ - ret = mail_search_args_foreach(ctx->mail_ctx.args, - search_index_arg, ctx); - if (ret >= 0) - return ret > 0; - /* next search only from cached arguments */ ret = mail_search_args_foreach(ctx->mail_ctx.args, search_cached_arg, ctx); @@ -1048,7 +1050,7 @@ _ctx->seq++; } - if (!ctx->have_seqsets) + if (!ctx->have_seqsets && !ctx->have_flags_or_keywords) return _ctx->seq <= ctx->seq2 ? 1 : 0; ret = 0; @@ -1056,8 +1058,16 @@ /* check if the sequence matches */ ret = mail_search_args_foreach(ctx->mail_ctx.args, search_seqset_arg, ctx); - if (ret != 0) - break; + if (ret != 0) { + /* check if flags/keywords match before anything else + is done. mail_set_seq() can be a bit slow. */ + if (!ctx->have_flags_or_keywords) + break; + ret = mail_search_args_foreach(ctx->mail_ctx.args, + search_index_arg, ctx); + if (ret != 0) + break; + } /* doesn't, try next one */ _ctx->seq++;