dovecot-1.2: Search code cleanups and minor optimizations.

dovecot at dovecot.org dovecot at dovecot.org
Fri Jun 20 05:37:40 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/1e69c84a1e5a
changeset: 7908:1e69c84a1e5a
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 20 05:35:05 2008 +0300
description:
Search code cleanups and minor optimizations.

diffstat:

4 files changed, 64 insertions(+), 31 deletions(-)
src/lib-storage/index/index-search.c |   28 ++++++++++++-----
src/lib-storage/mail-search.c        |   55 +++++++++++++++++++++-------------
src/lib-storage/mail-search.h        |    9 +++--
src/lib-storage/mail-storage.c       |    3 +

diffs (229 lines):

diff -r 021c39f58af3 -r 1e69c84a1e5a src/lib-storage/index/index-search.c
--- a/src/lib-storage/index/index-search.c	Fri Jun 20 05:30:00 2008 +0300
+++ b/src/lib-storage/index/index-search.c	Fri Jun 20 05:35:05 2008 +0300
@@ -688,17 +688,23 @@ static void search_or_parse_msgset_args(
 	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(con
 				     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 
 				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 -r 021c39f58af3 -r 1e69c84a1e5a src/lib-storage/mail-search.c
--- a/src/lib-storage/mail-search.c	Fri Jun 20 05:30:00 2008 +0300
+++ b/src/lib-storage/mail-search.c	Fri Jun 20 05:35:05 2008 +0300
@@ -56,36 +56,38 @@ mailbox_uidset_change(struct mail_search
 }
 
 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_s
 			   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(
 
 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 mai
 
 	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 mai
 		}
 
 		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 mai
 	}
 }
 
-void mail_search_args_simplify(struct mail_search_arg *args)
-{
-	mail_search_args_simplify_sub(args, TRUE);
-}
+void mail_search_args_simplify(struct mail_search_args *args)
+{
+	args->simplified = TRUE;
+	mail_search_args_simplify_sub(args->args, TRUE);
+}
diff -r 021c39f58af3 -r 1e69c84a1e5a src/lib-storage/mail-search.h
--- a/src/lib-storage/mail-search.h	Fri Jun 20 05:30:00 2008 +0300
+++ b/src/lib-storage/mail-search.h	Fri Jun 20 05:35:05 2008 +0300
@@ -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 @@ mail_search_args_analyze(struct mail_sea
 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 -r 021c39f58af3 -r 1e69c84a1e5a src/lib-storage/mail-storage.c
--- a/src/lib-storage/mail-storage.c	Fri Jun 20 05:30:00 2008 +0300
+++ b/src/lib-storage/mail-storage.c	Fri Jun 20 05:35:05 2008 +0300
@@ -643,7 +643,8 @@ mailbox_search_init(struct mailbox_trans
 		    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);
 }
 


More information about the dovecot-cvs mailing list