dovecot-2.0: dsync: Handle syncing subscriptions correctly for s...

dovecot at dovecot.org dovecot at dovecot.org
Tue Aug 3 18:49:47 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/62abbfe45cde
changeset: 11922:62abbfe45cde
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Aug 03 16:49:43 2010 +0100
description:
dsync: Handle syncing subscriptions correctly for subscriptions=no namespaces.

diffstat:

 src/dsync/dsync-worker-local.c |  82 ++++++++++++++++++++++++++++++++++-------
 1 files changed, 68 insertions(+), 14 deletions(-)

diffs (168 lines):

diff -r e31570bccb92 -r 62abbfe45cde src/dsync/dsync-worker-local.c
--- a/src/dsync/dsync-worker-local.c	Tue Aug 03 15:42:34 2010 +0100
+++ b/src/dsync/dsync-worker-local.c	Tue Aug 03 16:49:43 2010 +0100
@@ -90,6 +90,7 @@
 	struct hash_table *dir_changes_hash;
 
 	char alt_char;
+	ARRAY_DEFINE(subs_namespaces, struct mail_namespace *);
 
 	mailbox_guid_t selected_box_guid;
 	struct mailbox *selected_box;
@@ -146,8 +147,24 @@
 	return h;
 }
 
-static void dsync_drop_extra_namespaces(struct mail_user *user)
+static struct mail_namespace *
+namespace_find_set(struct mail_user *user,
+		   const struct mail_namespace_settings *set)
 {
+	struct mail_namespace *ns;
+
+	for (ns = user->namespaces; ns != NULL; ns = ns->next) {
+		/* compare settings pointers so that it'll work
+		   for shared namespaces */
+		if (ns->set == set)
+			return ns;
+	}
+	return NULL;
+}
+
+static void dsync_drop_extra_namespaces(struct local_dsync_worker *worker)
+{
+	struct mail_user *user = worker->user;
 	struct mail_namespace_settings *const *ns_unset, *const *ns_set;
 	struct mail_namespace *ns;
 	unsigned int i, count, count2;
@@ -164,15 +181,16 @@
 			   SETTING_STRVAR_UNEXPANDED) == 0)
 			continue;
 
-		for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-			/* compare settings pointers so that it'll work
-			   for shared namespaces */
-			if (ns->set == ns_set[i]) {
-				mail_namespace_destroy(ns);
-				break;
-			}
+		ns = namespace_find_set(user, ns_set[i]);
+		i_assert(ns != NULL);
+		if ((ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0) {
+			/* remember the subscriptions=no namespaces so we can
+			   handle their subscriptions in parent namespaces
+			   properly */
+			mail_namespace_ref(ns);
+			array_append(&worker->subs_namespaces, &ns, 1);
 		}
-		i_assert(ns != NULL);
+		mail_namespace_destroy(ns);
 	}
 	if (user->namespaces == NULL) {
 		i_fatal("All your namespaces have a location setting. "
@@ -187,8 +205,6 @@
 	struct local_dsync_worker *worker;
 	pool_t pool;
 
-	dsync_drop_extra_namespaces(user);
-
 	pool = pool_alloconly_create("local dsync worker", 10240);
 	worker = p_new(pool, struct local_dsync_worker, 1);
 	worker->worker.v = local_dsync_worker;
@@ -200,6 +216,8 @@
 				  mailbox_guid_hash, mailbox_guid_cmp);
 	i_array_init(&worker->saved_uids, 128);
 	i_array_init(&worker->msg_get_queue, 32);
+	p_array_init(&worker->subs_namespaces, pool, 8);
+	dsync_drop_extra_namespaces(worker);
 	return &worker->worker;
 }
 
@@ -207,9 +225,13 @@
 {
 	struct local_dsync_worker *worker =
 		(struct local_dsync_worker *)_worker;
+	struct mail_namespace **nsp;
 
 	i_assert(worker->save_input == NULL);
 
+	array_foreach_modifiable(&worker->subs_namespaces, nsp)
+		mail_namespace_unref(nsp);
+
 	local_worker_msg_box_close(worker);
 	local_worker_mailbox_close(worker);
 	hash_table_destroy(&worker->mailbox_hash);
@@ -620,6 +642,18 @@
 	return &iter->iter;
 }
 
+static struct mail_namespace *
+find_subscription_ns(struct local_dsync_worker *worker, const char *vname)
+{
+	struct mail_namespace *const *nsp;
+
+	array_foreach(&worker->subs_namespaces, nsp) {
+		if (strncmp((*nsp)->prefix, vname, (*nsp)->prefix_len) == 0)
+			return *nsp;
+	}
+	return NULL;
+}
+
 static int
 local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter,
 			    struct dsync_worker_subscription *rec_r)
@@ -630,6 +664,7 @@
 		(struct local_dsync_worker *)_iter->worker;
 	struct local_dsync_dir_change *change, change_lookup;
 	const struct mailbox_info *info;
+	struct mail_namespace *subs_ns;
 	const char *storage_name;
 
 	memset(rec_r, 0, sizeof(*rec_r));
@@ -638,7 +673,13 @@
 	if (info == NULL)
 		return -1;
 
-	storage_name = mail_namespace_get_storage_name(info->ns, info->name);
+	subs_ns = find_subscription_ns(worker, info->name);
+	if (subs_ns == NULL)
+		subs_ns = info->ns;
+	storage_name = mail_namespace_get_storage_name(subs_ns, info->name);
+	if (subs_ns != info->ns)
+		storage_name = t_strconcat(subs_ns->prefix, storage_name, NULL);
+
 	dsync_str_sha_to_guid(storage_name, &change_lookup.name_sha1);
 	change_lookup.list = info->ns->list;
 
@@ -707,16 +748,29 @@
 {
 	struct local_dsync_worker *worker =
 		(struct local_dsync_worker *)_worker;
-	struct mail_namespace *ns;
+	struct mail_namespace *ns, *subs_ns;
 	const char *storage_name;
 
 	storage_name = name;
-	ns = mail_namespace_find(worker->user->namespaces, &storage_name);
+	ns = mail_namespace_find(worker->user->namespaces,
+				 &storage_name);
 	if (ns == NULL) {
 		i_error("Can't find namespace for mailbox %s", name);
 		return;
 	}
 
+	subs_ns = find_subscription_ns(worker, name);
+	if (subs_ns != NULL) {
+		/* subscription is being written to a different namespace
+		   than where the mailbox exists. */
+		storage_name = mail_namespace_get_storage_name(subs_ns, name);
+		storage_name = t_strconcat(subs_ns->prefix, storage_name, NULL);
+		/* drop the common prefix */
+		i_assert(strncmp(ns->prefix, storage_name,
+				 strlen(ns->prefix)) == 0);
+		storage_name += strlen(ns->prefix);
+	}
+
 	mailbox_list_set_changelog_timestamp(ns->list, last_change);
 	if (mailbox_list_set_subscribed(ns->list, storage_name, set) < 0) {
 		dsync_worker_set_failure(_worker);


More information about the dovecot-cvs mailing list