dovecot: Optimize searching flags and keywords.
dovecot at dovecot.org
dovecot at dovecot.org
Sat Dec 8 19:36:15 EET 2007
details: http://hg.dovecot.org/dovecot/rev/7bb6ef75715c
changeset: 6966:7bb6ef75715c
user: Timo Sirainen <tss at iki.fi>
date: Sat Dec 08 19:36:11 2007 +0200
description:
Optimize searching flags and keywords.
diffstat:
1 file changed, 56 insertions(+), 46 deletions(-)
src/lib-storage/index/index-search.c | 102 ++++++++++++++++++----------------
diffs (189 lines):
diff -r ae369569e7de -r 7bb6ef75715c src/lib-storage/index/index-search.c
--- 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 @@ struct index_search_context {
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 @@ static void search_parse_msgset_args(con
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 @@ static int seqset_contains(struct mail_s
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 @@ static int search_arg_match_keywords(str
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 @@ static int search_arg_match_keywords(str
}
/* 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 int search_arg_match_index(struct
}
}
-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 @@ index_storage_search_init(struct mailbox
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);
@@ -911,12 +919,6 @@ static bool search_match_next(struct ind
{
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,
@@ -1048,7 +1050,7 @@ int index_storage_search_next_update_seq
_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 @@ int index_storage_search_next_update_seq
/* 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++;
More information about the dovecot-cvs
mailing list