From: Timo Sirainen Date: Fri, 20 Jun 2008 02:35:05 +0000 (+0300) Subject: Search code cleanups and minor optimizations. X-Git-Tag: 1.2.alpha1~253 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=908bffbaff7230e31a887aab75572cc2549cb6fe;p=thirdparty%2Fdovecot%2Fcore.git Search code cleanups and minor optimizations. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/index-search.c b/src/lib-storage/index/index-search.c index c1856322ca..416807f4fe 100644 --- a/src/lib-storage/index/index-search.c +++ b/src/lib-storage/index/index-search.c @@ -688,17 +688,23 @@ static void search_or_parse_msgset_args(const struct mail_index_header *hdr, for (; args != NULL; args = args->next) { seq1 = 1; seq2 = hdr->messages_count; - if (args->type == SEARCH_SUB) { + switch (args->type) { + case SEARCH_SUB: i_assert(!args->not); search_parse_msgset_args(hdr, args->value.subargs, &seq1, &seq2); - } else if (args->type == SEARCH_OR) { + break; + case SEARCH_OR: i_assert(!args->not); search_or_parse_msgset_args(hdr, args->value.subargs, &seq1, &seq2); - } else if (args->type == SEARCH_SEQSET) { + break; + case SEARCH_SEQSET: search_msgset_fix(hdr, &args->value.seqset, &seq1, &seq2, args->not); + break; + default: + break; } if (min_seq1 == 0) { @@ -724,19 +730,25 @@ static void search_parse_msgset_args(const struct mail_index_header *hdr, uint32_t *seq1_r, uint32_t *seq2_r) { for (; args != NULL; args = args->next) { - if (args->type == SEARCH_SUB) { + switch (args->type) { + case SEARCH_SUB: i_assert(!args->not); search_parse_msgset_args(hdr, args->value.subargs, seq1_r, seq2_r); - } else if (args->type == SEARCH_OR) { + break; + case SEARCH_OR: /* go through our children and use the widest seqset range */ i_assert(!args->not); search_or_parse_msgset_args(hdr, args->value.subargs, seq1_r, seq2_r); - } else if (args->type == SEARCH_SEQSET) { + break; + case SEARCH_SEQSET: search_msgset_fix(hdr, &args->value.seqset, seq1_r, seq2_r, args->not); + break; + default: + break; } } } @@ -983,7 +995,9 @@ static bool search_arg_is_static(struct mail_search_arg *arg) return FALSE; } return TRUE; - case SEARCH_SEQSET: /* changes between syncs */ + case SEARCH_SEQSET: + /* changes between syncs, but we can't really handle this + currently. seqsets should be converted to uidsets first. */ case SEARCH_FLAGS: case SEARCH_KEYWORDS: case SEARCH_MODSEQ: diff --git a/src/lib-storage/mail-search.c b/src/lib-storage/mail-search.c index e5ee628ec3..532e2078c1 100644 --- a/src/lib-storage/mail-search.c +++ b/src/lib-storage/mail-search.c @@ -56,36 +56,38 @@ mailbox_uidset_change(struct mail_search_arg *arg, struct mailbox *box, } static void -mail_search_args_init_sub(struct mail_search_arg *args, - struct mailbox *box, bool change_uidsets, +mail_search_args_init_sub(struct mail_search_args *args, + struct mail_search_arg *arg, + bool change_uidsets, const ARRAY_TYPE(seq_range) *search_saved_uidset) { const char *keywords[2]; - for (; args != NULL; args = args->next) { - switch (args->type) { + for (; arg != NULL; arg = arg->next) { + switch (arg->type) { case SEARCH_UIDSET: if (change_uidsets) T_BEGIN { - mailbox_uidset_change(args, box, + mailbox_uidset_change(arg, args->box, search_saved_uidset); } T_END; break; case SEARCH_MODSEQ: - if (args->value.str == NULL) + if (arg->value.str == NULL) break; /* modseq with keyword */ case SEARCH_KEYWORDS: - keywords[0] = args->value.str; + keywords[0] = arg->value.str; keywords[1] = NULL; - i_assert(args->value.keywords == NULL); - args->value.keywords = - mailbox_keywords_create_valid(box, keywords); + i_assert(arg->value.keywords == NULL); + arg->value.keywords = + mailbox_keywords_create_valid(args->box, + keywords); break; case SEARCH_SUB: case SEARCH_OR: - mail_search_args_init_sub(args->value.subargs, box, + mail_search_args_init_sub(args, arg->value.subargs, change_uidsets, search_saved_uidset); break; @@ -99,8 +101,15 @@ void mail_search_args_init(struct mail_search_args *args, struct mailbox *box, bool change_uidsets, const ARRAY_TYPE(seq_range) *search_saved_uidset) { + if (args->initialized) { + i_assert(args->box == box); + return; + } + args->box = box; - mail_search_args_init_sub(args->args, box, change_uidsets, + if (!args->simplified) + mail_search_args_simplify(args); + mail_search_args_init_sub(args, args->args, change_uidsets, search_saved_uidset); } @@ -127,10 +136,12 @@ static void mail_search_args_deinit_sub(struct mail_search_args *args, void mail_search_args_deinit(struct mail_search_args *args) { - if (args->refcount > 1) + if (args->refcount > 1 || !args->initialized) return; mail_search_args_deinit_sub(args, args->args); + args->initialized = FALSE; + args->box = NULL; } static void mail_search_args_seq2uid_sub(struct mail_search_args *args, @@ -407,7 +418,7 @@ mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and) prev_flags_arg = prev_not_flags_arg = NULL; prev_kw_arg = prev_not_kw_arg = NULL; - for (; args != NULL;) { + while (args != NULL) { if (args->not && (args->type == SEARCH_SUB || args->type == SEARCH_OR)) { /* neg(p and q and ..) == neg(p) or neg(q) or .. @@ -421,9 +432,12 @@ mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and) } if ((args->type == SEARCH_SUB && parent_and) || - (args->type == SEARCH_OR && !parent_and)) { + (args->type == SEARCH_OR && !parent_and) || + ((args->type == SEARCH_SUB || args->type == SEARCH_OR) && + args->value.subargs->next == NULL)) { /* p and (q and ..) == p and q and .. - p or (q or ..) == p or q or .. */ + p or (q or ..) == p or q or .. + (p) = p */ sub = args->value.subargs; for (; sub->next != NULL; sub = sub->next) ; sub->next = args->next; @@ -493,7 +507,8 @@ mail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and) } } -void mail_search_args_simplify(struct mail_search_arg *args) +void mail_search_args_simplify(struct mail_search_args *args) { - mail_search_args_simplify_sub(args, TRUE); + args->simplified = TRUE; + mail_search_args_simplify_sub(args->args, TRUE); } diff --git a/src/lib-storage/mail-search.h b/src/lib-storage/mail-search.h index 639eea97b1..8cccb03308 100644 --- a/src/lib-storage/mail-search.h +++ b/src/lib-storage/mail-search.h @@ -91,6 +91,10 @@ struct mail_search_args { struct mailbox *box; struct mail_search_arg *args; const char *charset; + + unsigned int initialized:1; + unsigned int simplified:1; + unsigned int have_inthreads:1; }; #define ARG_SET_RESULT(arg, res) \ @@ -142,8 +146,7 @@ const char *const * mail_search_args_analyze(struct mail_search_arg *args, bool *have_headers, bool *have_body); -/* 1) Change args so that SEARCH_SUB and SEARCH_OR will never have "not" set - 2) Drop unnecessary nested SEARCH_SUB and SEARCH_ORs */ -void mail_search_args_simplify(struct mail_search_arg *args); +/* Simplify/optimize search arguments */ +void mail_search_args_simplify(struct mail_search_args *args); #endif diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index d5bee42b52..d0587927ec 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -643,7 +643,8 @@ mailbox_search_init(struct mailbox_transaction_context *t, const enum mail_sort_type *sort_program) { mail_search_args_ref(args); - mail_search_args_simplify(args->args); + if (!args->simplified) + mail_search_args_simplify(args); return t->box->v.search_init(t, args, sort_program); }