dovecot-1.2: Added alias_for setting for namespaces. Fixes names...

dovecot at dovecot.org dovecot at dovecot.org
Sun Nov 30 02:09:20 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/3efcdc45d111
changeset: 8500:3efcdc45d111
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Nov 30 02:09:16 2008 +0200
description:
Added alias_for setting for namespaces. Fixes namespace issues with fts.

diffstat:

7 files changed, 126 insertions(+), 38 deletions(-)
src/lib-storage/mail-namespace.c        |   25 ++++++++-
src/lib-storage/mail-namespace.h        |   10 +++
src/master/mail-process.c               |    4 +
src/master/master-settings.c            |   28 +++++++++-
src/master/master-settings.h            |    1 
src/plugins/fts-solr/fts-backend-solr.c |   79 +++++++++++++++++++------------
src/plugins/fts/fts-storage.c           |   17 +++++-

diffs (truncated from 366 to 300 lines):

diff -r 252b29ac5f43 -r 3efcdc45d111 src/lib-storage/mail-namespace.c
--- a/src/lib-storage/mail-namespace.c	Sun Nov 30 01:27:19 2008 +0200
+++ b/src/lib-storage/mail-namespace.c	Sun Nov 30 02:09:16 2008 +0200
@@ -38,10 +38,11 @@ static struct mail_namespace *
 static struct mail_namespace *
 namespace_add_env(const char *data, unsigned int num,
 		  struct mail_user *user, enum mail_storage_flags flags,
-		  enum file_lock_method lock_method)
+		  enum file_lock_method lock_method,
+		  struct mail_namespace *prev_namespaces)
 {
         struct mail_namespace *ns;
-	const char *sep, *type, *prefix, *driver, *error, *list;
+	const char *sep, *type, *prefix, *driver, *error, *list, *alias_for;
 
 	ns = i_new(struct mail_namespace, 1);
 
@@ -49,6 +50,7 @@ namespace_add_env(const char *data, unsi
 	type = getenv(t_strdup_printf("NAMESPACE_%u_TYPE", num));
 	prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num));
 	list = getenv(t_strdup_printf("NAMESPACE_%u_LIST", num));
+	alias_for = getenv(t_strdup_printf("NAMESPACE_%u_ALIAS", num));
 	if (getenv(t_strdup_printf("NAMESPACE_%u_INBOX", num)) != NULL)
 		ns->flags |= NAMESPACE_FLAG_INBOX;
 	if (getenv(t_strdup_printf("NAMESPACE_%u_HIDDEN", num)) != NULL)
@@ -75,6 +77,23 @@ namespace_add_env(const char *data, unsi
 		return NULL;
 	}
 
+	if (alias_for != NULL) {
+		ns->alias_for = mail_namespace_find_prefix(prev_namespaces,
+							   alias_for);
+		if (ns->alias_for == NULL) {
+			i_error("Invalid namespace alias_for: %s", alias_for);
+			mail_namespace_free(ns);
+			return NULL;
+		}
+		if (ns->alias_for->alias_for != NULL) {
+			i_error("Chained namespace alias_for: %s", alias_for);
+			mail_namespace_free(ns);
+			return NULL;
+		}
+		ns->alias_chain_next = ns->alias_for->alias_chain_next;
+		ns->alias_for->alias_chain_next = ns;
+	}
+
 	if (prefix == NULL)
 		prefix = "";
 
@@ -207,7 +226,7 @@ int mail_namespaces_init(struct mail_use
 
 		T_BEGIN {
 			*ns_p = namespace_add_env(data, i, user, flags,
-						  lock_method);
+						  lock_method, namespaces);
 		} T_END;
 
 		if (*ns_p == NULL)
diff -r 252b29ac5f43 -r 3efcdc45d111 src/lib-storage/mail-namespace.h
--- a/src/lib-storage/mail-namespace.h	Sun Nov 30 01:27:19 2008 +0200
+++ b/src/lib-storage/mail-namespace.h	Sun Nov 30 02:09:16 2008 +0200
@@ -40,6 +40,16 @@ struct mail_namespace {
 
 	char *prefix;
 	size_t prefix_len;
+
+	/* If non-NULL, this points to a namespace with identical mail location
+	   and it should be considered as the primary way to access the
+	   mailboxes. This allows for example FTS plugin to avoid duplicating
+	   indexes for same mailboxes when they're accessed via different
+	   namespaces. */
+	struct mail_namespace *alias_for;
+	/* alias_for->alias_chain_next starts each chain. The chain goes
+	   through all namespaces that have the same alias_for. */
+	struct mail_namespace *alias_chain_next;
 
 	struct mail_user *user, *owner;
 	struct mailbox_list *list;
diff -r 252b29ac5f43 -r 3efcdc45d111 src/master/mail-process.c
--- a/src/master/mail-process.c	Sun Nov 30 01:27:19 2008 +0200
+++ b/src/master/mail-process.c	Sun Nov 30 02:09:16 2008 +0200
@@ -267,6 +267,10 @@ env_put_namespace(struct namespace_setti
 		if (ns->type != NULL) {
 			env_put(t_strdup_printf("NAMESPACE_%u_TYPE=%s",
 						i, ns->type));
+		}
+		if (ns->alias_for != NULL) {
+			env_put(t_strdup_printf("NAMESPACE_%u_ALIAS=%s",
+						i, ns->alias_for));
 		}
 		if (ns->prefix != NULL) {
 			/* expand variables, eg. ~%u/ can be useful */
diff -r 252b29ac5f43 -r 3efcdc45d111 src/master/master-settings.c
--- a/src/master/master-settings.c	Sun Nov 30 01:27:19 2008 +0200
+++ b/src/master/master-settings.c	Sun Nov 30 02:09:16 2008 +0200
@@ -158,6 +158,7 @@ static struct setting_def namespace_sett
 	DEF_STR(separator),
 	DEF_STR(prefix),
 	DEF_STR(location),
+	DEF_STR(alias_for),
 	DEF_BOOL(inbox),
 	DEF_BOOL(hidden),
 	DEF_STR(list),
@@ -359,6 +360,7 @@ struct namespace_settings default_namesp
 	MEMBER(separator) "",
 	MEMBER(prefix) "",
 	MEMBER(location) "",
+	MEMBER(alias_for) NULL,
 
 	MEMBER(inbox) FALSE,
 	MEMBER(hidden) FALSE,
@@ -489,8 +491,10 @@ static bool auth_settings_verify(struct 
 	return TRUE;
 }
 
-static bool namespace_settings_verify(struct namespace_settings *ns)
-{
+static bool namespace_settings_verify(struct server_settings *server,
+				      struct namespace_settings *ns)
+{
+	struct namespace_settings *n;
 	const char *name;
 
 	name = ns->prefix != NULL ? ns->prefix : "";
@@ -508,6 +512,24 @@ static bool namespace_settings_verify(st
 		i_error("Namespace '%s': Invalid list value: %s",
 			name, ns->list);
 		return FALSE;
+	}
+
+	if (ns->alias_for != NULL) {
+		for (n = server->namespaces; n != ns; n = n->next) {
+			if (strcmp(n->prefix, ns->alias_for) == 0)
+				break;
+		}
+		if (n == NULL) {
+			i_error("Namespace '%s': alias_for points to "
+				"unknown namespace: %s", name, ns->alias_for);
+			return FALSE;
+		}
+		if (n->alias_for != NULL) {
+			i_error("Namespace '%s': alias_for chaining isn't "
+				"allowed: %s -> %s", name, ns->alias_for,
+				n->alias_for);
+			return FALSE;
+		}
 	}
 
 	return TRUE;
@@ -1559,7 +1581,7 @@ bool master_settings_read(const char *pa
 				}
 				ns = server->namespaces;
 				for (; ns != NULL; ns = ns->next) {
-					if (!namespace_settings_verify(ns))
+					if (!namespace_settings_verify(server, ns))
 						return FALSE;
 				}
 			}
diff -r 252b29ac5f43 -r 3efcdc45d111 src/master/master-settings.h
--- a/src/master/master-settings.h	Sun Nov 30 01:27:19 2008 +0200
+++ b/src/master/master-settings.h	Sun Nov 30 02:09:16 2008 +0200
@@ -240,6 +240,7 @@ struct namespace_settings {
 	const char *separator;
 	const char *prefix;
 	const char *location;
+	const char *alias_for;
 
 	bool inbox;
 	bool hidden;
diff -r 252b29ac5f43 -r 3efcdc45d111 src/plugins/fts-solr/fts-backend-solr.c
--- a/src/plugins/fts-solr/fts-backend-solr.c	Sun Nov 30 01:27:19 2008 +0200
+++ b/src/plugins/fts-solr/fts-backend-solr.c	Sun Nov 30 02:09:16 2008 +0200
@@ -127,6 +127,9 @@ fts_backend_solr_init(struct mailbox *bo
 	struct mail_namespace *ns = box->storage->ns;
 	const char *str;
 
+	while (ns->alias_for != NULL)
+		ns = ns->alias_for;
+
 	if (solr_conn == NULL)
 		solr_conn = solr_connection_init(set->url, set->debug);
 
@@ -143,9 +146,12 @@ fts_backend_solr_init(struct mailbox *bo
 		backend->default_ns =
 			mail_namespace_find_inbox(ns->user->namespaces);
 	}
+	while (backend->default_ns->alias_for != NULL)
+		backend->default_ns = backend->default_ns->alias_for;
+
 	str = solr_escape_id_str(ns->user->username);
 	backend->id_username = i_strdup(str);
-	if (box->storage->ns != backend->default_ns) {
+	if (ns != backend->default_ns) {
 		str = solr_escape_id_str(ns->prefix);
 		backend->id_namespace = i_strdup(str);
 	}
@@ -170,6 +176,9 @@ solr_add_ns_query(string_t *str, struct 
 		  struct mail_namespace *ns)
 {
 	struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
+
+	while (ns->alias_for != NULL)
+		ns = ns->alias_for;
 
 	if (ns == backend->default_ns || *ns->prefix == '\0')
 		str_append(str, " -ns:[* TO *]");
@@ -268,23 +277,17 @@ static int fts_backend_solr_get_last_uid
 	return 0;
 }
 
-static const char *
-solr_get_vmailbox(struct fts_backend *_backend,
-		  struct mailbox *box, const char *ns_prefix,
-		  const char *mailbox, string_t *dest)
+static struct mail_namespace *
+solr_get_namespaces(struct fts_backend *_backend,
+		    struct mailbox *box, const char *ns_prefix)
 {
 	struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
 	struct mail_namespace *namespaces = box->storage->ns->user->namespaces;
-	struct mail_namespace *ns;
 
 	if (ns_prefix == NULL)
-		ns = backend->default_ns;
-	else {
-		ns = mail_namespace_find_prefix(namespaces, ns_prefix);
-		if (ns == NULL)
-			return FALSE;
-	}
-	return mail_namespace_get_vname(ns, dest, mailbox);
+		return backend->default_ns;
+	else
+		return mail_namespace_find_prefix(namespaces, ns_prefix);
 }
 
 static bool
@@ -293,15 +296,17 @@ solr_virtual_get_last_uids(const char *n
 {
 	struct fts_backend_solr_get_last_uids_context *ctx = context;
 	struct fts_backend_uid_map *map;
+	struct mail_namespace *ns;
 	const char *vname;
 
-	vname = solr_get_vmailbox(ctx->backend, ctx->box, ns_prefix,
-				  mailbox, ctx->vname);
-
-	map = array_append_space(ctx->last_uids);
-	map->mailbox = p_strdup(ctx->pool, vname);
-	map->uidvalidity = uidvalidity;
-	map->uid = *uid;
+	ns = solr_get_namespaces(ctx->backend, ctx->box, ns_prefix);
+	for (; ns != NULL; ns = ns->alias_chain_next) {
+		vname = mail_namespace_get_vname(ns, ctx->vname, mailbox);
+		map = array_append_space(ctx->last_uids);
+		map->mailbox = p_strdup(ctx->pool, vname);
+		map->uidvalidity = uidvalidity;
+		map->uid = *uid;
+	}
 	return FALSE;
 }
 
@@ -344,6 +349,7 @@ fts_backend_solr_filter_mailboxes(struct
 {
 	struct solr_fts_backend *backend = (struct solr_fts_backend *)_backend;
 	ARRAY_TYPE(mailbox_virtual_patterns) includes_arr, excludes_arr;
+	struct mail_namespace *ns;
 	const struct mailbox_virtual_pattern *includes, *excludes;
 	unsigned int i, inc_count, exc_count, len;
 	string_t *fq;
@@ -386,12 +392,15 @@ fts_backend_solr_filter_mailboxes(struct
 		str_append_c(fq, '(');
 		str_append(fq, "-box:");
 		solr_add_pattern(fq, &excludes[i]);
-		if (excludes[i].ns == backend->default_ns) {
+
+		for (ns = excludes[i].ns; ns->alias_for != NULL; )
+			ns = ns->alias_for;
+		if (ns == backend->default_ns) {
 			str_append(fq, " OR NOT");
-			solr_add_ns_query(fq, _backend, excludes[i].ns);
-		} else if (*excludes[i].ns->prefix != '\0') {
+			solr_add_ns_query(fq, _backend, ns);
+		} else if (*ns->prefix != '\0') {
 			str_append(fq, " OR -ns:");
-			solr_quote(fq, excludes[i].ns->prefix);
+			solr_quote(fq, ns->prefix);
 		}
 		str_append_c(fq, ')');
 	}
@@ -453,21 +462,25 @@ fts_backend_solr_add_doc_prefix(struct s
 	struct solr_fts_backend *backend =
 		(struct solr_fts_backend *)ctx->ctx.backend;
 	struct mailbox *box = ctx->ctx.backend->box;
+	struct mail_namespace *ns = box->storage->ns;
 
 	str_printfa(ctx->cmd, "<doc>"
 		    "<field name=\"uid\">%u</field>"
 		    "<field name=\"uidv\">%u</field>",
 		    uid, ctx->uid_validity);
 


More information about the dovecot-cvs mailing list