dovecot-2.1: doveadm: When AND-search includes mailbox names, do...

dovecot at dovecot.org dovecot at dovecot.org
Wed Apr 4 09:42:46 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/1b6fb6363e7f
changeset: 14390:1b6fb6363e7f
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Apr 04 09:42:34 2012 +0300
description:
doveadm: When AND-search includes mailbox names, don't bother going through them by list iteration.

diffstat:

 src/doveadm/doveadm-mailbox-list-iter.c |  63 +++++++++++++++++++++++++-------
 1 files changed, 48 insertions(+), 15 deletions(-)

diffs (141 lines):

diff -r 200af5e4c44f -r 1b6fb6363e7f src/doveadm/doveadm-mailbox-list-iter.c
--- a/src/doveadm/doveadm-mailbox-list-iter.c	Wed Apr 04 09:41:15 2012 +0300
+++ b/src/doveadm/doveadm-mailbox-list-iter.c	Wed Apr 04 09:42:34 2012 +0300
@@ -10,18 +10,24 @@
 #include "doveadm-mailbox-list-iter.h"
 
 struct doveadm_mailbox_list_iter {
+	struct mail_user *user;
 	struct doveadm_mail_cmd_context *ctx;
 	struct mail_search_args *search_args;
 	enum mailbox_list_iter_flags iter_flags;
 
 	struct mailbox_list_iterate_context *iter;
+
+	struct mailbox_info info;
+	ARRAY_TYPE(const_string) patterns;
+	unsigned int pattern_idx;
+
 	bool only_selectable;
 };
 
 static int
 search_args_get_mailbox_patterns(const struct mail_search_arg *args,
 				 ARRAY_TYPE(const_string) *patterns,
-				 bool *have_guid_r)
+				 bool *have_guid, bool *have_wildcards)
 {
 	const struct mail_search_arg *subargs;
 
@@ -35,12 +41,15 @@
 			subargs = args->value.subargs;
 			for (; subargs != NULL; subargs = subargs->next) {
 				if (!search_args_get_mailbox_patterns(subargs,
-							patterns, have_guid_r))
+							patterns, have_guid,
+							have_wildcards))
 					return 0;
 			}
 			break;
+		case SEARCH_MAILBOX_GLOB:
+			*have_wildcards = TRUE;
+			/* fall through */
 		case SEARCH_MAILBOX:
-		case SEARCH_MAILBOX_GLOB:
 			if (args->match_not) {
 				array_clear(patterns);
 				return 0;
@@ -48,7 +57,7 @@
 			array_append(patterns, &args->value.str, 1);
 			break;
 		case SEARCH_MAILBOX_GUID:
-			*have_guid_r = TRUE;
+			*have_guid = TRUE;
 			break;
 		default:
 			break;
@@ -66,31 +75,36 @@
 {
 	static const char *all_pattern = "*";
 	struct doveadm_mailbox_list_iter *iter;
-	ARRAY_TYPE(const_string) patterns;
-	bool have_guid = FALSE;
+	bool have_guid = FALSE, have_wildcards = FALSE;
 
 	iter = i_new(struct doveadm_mailbox_list_iter, 1);
 	iter->ctx = ctx;
 	iter->search_args = search_args;
+	iter->user = user;
+	i_array_init(&iter->patterns, 16);
+	search_args_get_mailbox_patterns(search_args->args, &iter->patterns,
+					 &have_guid, &have_wildcards);
 
-	t_array_init(&patterns, 16);
-	search_args_get_mailbox_patterns(search_args->args, &patterns,
-					 &have_guid);
-	if (array_count(&patterns) == 0) {
+	if (array_count(&iter->patterns) == 0) {
 		iter_flags |= MAILBOX_LIST_ITER_SKIP_ALIASES;
 		if (have_guid)
 			ns_mask |= NAMESPACE_SHARED | NAMESPACE_PUBLIC;
-		array_append(&patterns, &all_pattern, 1);
-	} else {
+		array_append(&iter->patterns, &all_pattern, 1);
+	} else if (have_wildcards) {
 		iter_flags |= MAILBOX_LIST_ITER_STAR_WITHIN_NS;
 		ns_mask |= NAMESPACE_SHARED | NAMESPACE_PUBLIC;
+	} else {
+		/* just return the listed mailboxes without actually
+		   iterating through. this also allows accessing mailboxes
+		   without lookup ACL right */
+		return iter;
 	}
-	(void)array_append_space(&patterns);
+	(void)array_append_space(&iter->patterns);
 
 	iter->only_selectable = TRUE;
 	iter->iter_flags = iter_flags;
 	iter->iter = mailbox_list_iter_init_namespaces(user->namespaces,
-						       array_idx(&patterns, 0),
+						       array_idx(&iter->patterns, 0),
 						       ns_mask, iter_flags);
 	return iter;
 }
@@ -130,10 +144,13 @@
 
 	*_iter = NULL;
 
-	if ((ret = mailbox_list_iter_deinit(&iter->iter)) < 0) {
+	if (iter->iter == NULL)
+		ret = 0;
+	else if ((ret = mailbox_list_iter_deinit(&iter->iter)) < 0) {
 		i_error("Listing mailboxes failed");
 		doveadm_mail_failed_error(iter->ctx, MAIL_ERROR_TEMP);
 	}
+	array_free(&iter->patterns);
 	i_free(iter);
 	return ret;
 }
@@ -142,6 +159,22 @@
 doveadm_mailbox_list_iter_next(struct doveadm_mailbox_list_iter *iter)
 {
 	const struct mailbox_info *info;
+	const char *const *patterns;
+	unsigned int count;
+
+	while (iter->iter == NULL) {
+		patterns = array_get(&iter->patterns, &count);
+		if (iter->pattern_idx == count)
+			return NULL;
+
+		iter->info.name = patterns[iter->pattern_idx++];
+		iter->info.ns = mail_namespace_find(iter->user->namespaces,
+						    iter->info.name);
+		if (iter->info.ns != NULL)
+			return &iter->info;
+		/* FIXME: maybe fail?.. or just wait for v2.2 to get rid of
+		   this error condition */
+	}
 
 	while ((info = mailbox_list_iter_next(iter->iter)) != NULL) {
 		char sep = mail_namespace_get_sep(info->ns);


More information about the dovecot-cvs mailing list