dovecot-2.0: dsync: Fixed syncing \noselect mailboxes.

dovecot at dovecot.org dovecot at dovecot.org
Sat Jun 12 00:36:45 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/c955d4789553
changeset: 11524:c955d4789553
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 11 22:36:38 2010 +0100
description:
dsync: Fixed syncing \noselect mailboxes.

diffstat:

 src/dsync/dsync-brain.c            |  73 ++++++++++++++++++++++++++++++++++++-
 src/dsync/dsync-data.c             |  17 ++++++--
 src/dsync/dsync-data.h             |   8 ++--
 src/dsync/dsync-proxy-client.c     |  20 ++++++++++
 src/dsync/dsync-proxy-server-cmd.c |  16 ++++++++
 src/dsync/dsync-worker-local.c     |  38 ++++++++++++++++---
 src/dsync/dsync-worker-private.h   |   2 +
 src/dsync/dsync-worker.c           |   8 ++++
 src/dsync/dsync-worker.h           |   3 +
 src/dsync/test-dsync-worker.c      |  15 +++++++
 src/dsync/test-dsync-worker.h      |   1 +
 11 files changed, 185 insertions(+), 16 deletions(-)

diffs (truncated from 386 to 300 lines):

diff -r b135e13f42b2 -r c955d4789553 src/dsync/dsync-brain.c
--- a/src/dsync/dsync-brain.c	Fri Jun 11 21:45:51 2010 +0100
+++ b/src/dsync/dsync-brain.c	Fri Jun 11 22:36:38 2010 +0100
@@ -102,7 +102,7 @@
 		if (dsync_worker_mailbox_iter_deinit(&list->iter) < 0)
 			dsync_brain_fail(list->brain);
 		array_sort(&list->mailboxes, dsync_mailbox_p_guid_cmp);
-		array_sort(&list->dirs, dsync_mailbox_p_name_cmp);
+		array_sort(&list->dirs, dsync_mailbox_p_name_sha1_cmp);
 		dsync_brain_mailbox_list_finished(list->brain);
 	}
 }
@@ -313,6 +313,76 @@
 	}
 }
 
+static void dsync_brain_sync_dirs(struct dsync_brain *brain)
+{
+	struct dsync_mailbox *const *src_boxes, *const *dest_boxes, new_box;
+	unsigned int src, dest, src_count, dest_count;
+	bool src_deleted, dest_deleted;
+	int ret;
+
+	memset(&new_box, 0, sizeof(new_box));
+
+	/* create/delete missing directories. */
+	src_boxes = array_get(&brain->src_mailbox_list->dirs, &src_count);
+	dest_boxes = array_get(&brain->dest_mailbox_list->dirs, &dest_count);
+	for (src = dest = 0; src < src_count && dest < dest_count; ) {
+		src_deleted = (src_boxes[src]->flags &
+			       DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0;
+		dest_deleted = (dest_boxes[dest]->flags &
+				DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0;
+		ret = memcmp(src_boxes[src]->name_sha1.guid,
+			     dest_boxes[dest]->name_sha1.guid,
+			     sizeof(src_boxes[src]->name_sha1.guid));
+		if (ret < 0) {
+			/* exists only in source */
+			if (!src_deleted) {
+				new_box = *src_boxes[src];
+				dsync_worker_create_mailbox(brain->dest_worker,
+							    &new_box);
+			}
+			src++;
+		} else if (ret > 0) {
+			/* exists only in dest */
+			if (!dest_deleted) {
+				new_box = *dest_boxes[dest];
+				dsync_worker_create_mailbox(brain->src_worker,
+							    &new_box);
+			}
+			dest++;
+		} else if (src_deleted) {
+			/* delete from dest too */
+			if (!dest_deleted) {
+				dsync_worker_delete_dir(brain->dest_worker,
+							dest_boxes[dest]);
+			}
+			src++; dest++;
+		} else if (dest_deleted) {
+			/* delete from src too */
+			dsync_worker_delete_dir(brain->src_worker,
+						src_boxes[src]);
+			src++; dest++;
+		} else {
+			src++; dest++;
+		}
+	}
+	for (; src < src_count; src++) {
+		if ((src_boxes[src]->flags &
+		     DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0)
+			continue;
+
+		new_box = *src_boxes[src];
+		dsync_worker_create_mailbox(brain->dest_worker, &new_box);
+	}
+	for (; dest < dest_count; dest++) {
+		if ((dest_boxes[dest]->flags &
+		     DSYNC_MAILBOX_FLAG_DELETED_DIR) != 0)
+			continue;
+
+		new_box = *dest_boxes[dest];
+		dsync_worker_create_mailbox(brain->src_worker, &new_box);
+	}
+}
+
 static bool
 dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list,
 			    const struct dsync_worker_subscription *subs,
@@ -612,6 +682,7 @@
 		break;
 	case DSYNC_STATE_SYNC_MAILBOXES:
 		dsync_brain_sync_mailboxes(brain);
+		dsync_brain_sync_dirs(brain);
 		brain->state++;
 		/* fall through */
 	case DSYNC_STATE_SYNC_SUBSCRIPTIONS:
diff -r b135e13f42b2 -r c955d4789553 src/dsync/dsync-data.c
--- a/src/dsync/dsync-data.c	Fri Jun 11 21:45:51 2010 +0100
+++ b/src/dsync/dsync-data.c	Fri Jun 11 22:36:38 2010 +0100
@@ -62,16 +62,23 @@
 	return dsync_mailbox_guid_cmp(*box1, *box2);
 }
 
-int dsync_mailbox_name_cmp(const struct dsync_mailbox *box1,
-			   const struct dsync_mailbox *box2)
+int dsync_mailbox_name_sha1_cmp(const struct dsync_mailbox *box1,
+				const struct dsync_mailbox *box2)
 {
+	int ret;
+
+	ret = memcmp(box1->name_sha1.guid, box2->name_sha1.guid,
+		     sizeof(box1->name_sha1.guid));
+	if (ret != 0)
+		return ret;
+
 	return strcmp(box1->name, box2->name);
 }
 
-int dsync_mailbox_p_name_cmp(struct dsync_mailbox *const *box1,
-			     struct dsync_mailbox *const *box2)
+int dsync_mailbox_p_name_sha1_cmp(struct dsync_mailbox *const *box1,
+				  struct dsync_mailbox *const *box2)
 {
-	return dsync_mailbox_name_cmp(*box1, *box2);
+	return dsync_mailbox_name_sha1_cmp(*box1, *box2);
 }
 
 bool dsync_keyword_list_equals(const char *const *k1, const char *const *k2)
diff -r b135e13f42b2 -r c955d4789553 src/dsync/dsync-data.h
--- a/src/dsync/dsync-data.h	Fri Jun 11 21:45:51 2010 +0100
+++ b/src/dsync/dsync-data.h	Fri Jun 11 22:36:38 2010 +0100
@@ -66,10 +66,10 @@
 int dsync_mailbox_p_guid_cmp(struct dsync_mailbox *const *box1,
 			     struct dsync_mailbox *const *box2);
 
-int dsync_mailbox_name_cmp(const struct dsync_mailbox *box1,
-			   const struct dsync_mailbox *box2);
-int dsync_mailbox_p_name_cmp(struct dsync_mailbox *const *box1,
-			     struct dsync_mailbox *const *box2);
+int dsync_mailbox_name_sha1_cmp(const struct dsync_mailbox *box1,
+				const struct dsync_mailbox *box2);
+int dsync_mailbox_p_name_sha1_cmp(struct dsync_mailbox *const *box1,
+				  struct dsync_mailbox *const *box2);
 
 bool dsync_keyword_list_equals(const char *const *k1, const char *const *k2);
 
diff -r b135e13f42b2 -r c955d4789553 src/dsync/dsync-proxy-client.c
--- a/src/dsync/dsync-proxy-client.c	Fri Jun 11 21:45:51 2010 +0100
+++ b/src/dsync/dsync-proxy-client.c	Fri Jun 11 22:36:38 2010 +0100
@@ -727,6 +727,25 @@
 }
 
 static void
+proxy_client_worker_delete_dir(struct dsync_worker *_worker,
+			       const struct dsync_mailbox *dsync_box)
+{
+	struct proxy_client_dsync_worker *worker =
+		(struct proxy_client_dsync_worker *)_worker;
+
+	i_assert(worker->save_input == NULL);
+
+	T_BEGIN {
+		string_t *str = t_str_new(128);
+
+		str_append(str, "DIR-DELETE\t");
+		str_tabescape_write(str, dsync_box->name);
+		str_printfa(str, "\t%s\n", dec2str(dsync_box->last_change));
+		o_stream_send(worker->output, str_data(str), str_len(str));
+	} T_END;
+}
+
+static void
 proxy_client_worker_rename_mailbox(struct dsync_worker *_worker,
 				   const mailbox_guid_t *mailbox,
 				   const struct dsync_mailbox *dsync_box)
@@ -1037,6 +1056,7 @@
 
 	proxy_client_worker_create_mailbox,
 	proxy_client_worker_delete_mailbox,
+	proxy_client_worker_delete_dir,
 	proxy_client_worker_rename_mailbox,
 	proxy_client_worker_update_mailbox,
 
diff -r b135e13f42b2 -r c955d4789553 src/dsync/dsync-proxy-server-cmd.c
--- a/src/dsync/dsync-proxy-server-cmd.c	Fri Jun 11 21:45:51 2010 +0100
+++ b/src/dsync/dsync-proxy-server-cmd.c	Fri Jun 11 22:36:38 2010 +0100
@@ -262,6 +262,21 @@
 }
 
 static int
+cmd_dir_delete(struct dsync_proxy_server *server, const char *const *args)
+{
+	struct dsync_mailbox dsync_box;
+
+	if (str_array_length(args) < 2)
+		return -1;
+
+	memset(&dsync_box, 0, sizeof(dsync_box));
+	dsync_box.name = str_tabunescape(t_strdup_noconst(args[0]));
+	dsync_box.last_change = strtoul(args[1], NULL, 10);
+	dsync_worker_delete_dir(server->worker, &dsync_box);
+	return 1;
+}
+
+static int
 cmd_box_rename(struct dsync_proxy_server *server, const char *const *args)
 {
 	mailbox_guid_t guid;
@@ -552,6 +567,7 @@
 	{ "MSG-LIST", cmd_msg_list },
 	{ "BOX-CREATE", cmd_box_create },
 	{ "BOX-DELETE", cmd_box_delete },
+	{ "DIR-DELETE", cmd_dir_delete },
 	{ "BOX-RENAME", cmd_box_rename },
 	{ "BOX-UPDATE", cmd_box_update },
 	{ "BOX-SELECT", cmd_box_select },
diff -r b135e13f42b2 -r c955d4789553 src/dsync/dsync-worker-local.c
--- a/src/dsync/dsync-worker-local.c	Fri Jun 11 21:45:51 2010 +0100
+++ b/src/dsync/dsync-worker-local.c	Fri Jun 11 22:36:38 2010 +0100
@@ -454,7 +454,8 @@
 			dsync_box_r->name = "";
 			dsync_box_r->name_sha1 = change->name_sha1;
 			dsync_box_r->last_change = change->last_delete;
-			dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_DELETED_DIR;
+			dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_NOSELECT |
+				DSYNC_MAILBOX_FLAG_DELETED_DIR;
 			return 1;
 		}
 	}
@@ -478,7 +479,7 @@
 	struct mailbox_status status;
 	uint8_t mailbox_guid[MAIL_GUID_128_SIZE];
 	struct local_dsync_mailbox_change *change;
-	struct local_dsync_dir_change *dir_change;
+	struct local_dsync_dir_change *dir_change, change_lookup;
 	const char *const *fields;
 	unsigned int i, field_count;
 
@@ -491,17 +492,20 @@
 	dsync_box_r->name = info->name;
 	dsync_box_r->name_sep = info->ns->sep;
 
+	storage_name = mail_namespace_get_storage_name(info->ns, info->name);
+	dsync_str_sha_to_guid(storage_name, &dsync_box_r->name_sha1);
+
 	/* get last change timestamp */
-	dsync_str_sha_to_guid(info->name, &dsync_box_r->name_sha1);
-	dir_change = hash_table_lookup(worker->mailbox_changes_hash,
-				       dsync_box_r->name_sha1.guid);
+	change_lookup.list = info->ns->list;
+	change_lookup.name_sha1 = dsync_box_r->name_sha1;
+	dir_change = hash_table_lookup(worker->dir_changes_hash,
+				       &change_lookup);
 	if (dir_change != NULL) {
 		/* it shouldn't be marked as deleted, but drop it to be sure */
 		dir_change->deleted_dir = FALSE;
 		dsync_box_r->last_change = dir_change->last_rename;
 	}
 
-	storage_name = mail_namespace_get_storage_name(info->ns, info->name);
 	if ((info->flags & MAILBOX_NOSELECT) != 0) {
 		dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_NOSELECT;
 		local_dsync_worker_add_mailbox(worker, info->ns, storage_name,
@@ -1136,6 +1140,27 @@
 }
 
 static void
+local_worker_delete_dir(struct dsync_worker *_worker,
+			const struct dsync_mailbox *dsync_box)
+{
+	struct local_dsync_worker *worker =
+		(struct local_dsync_worker *)_worker;
+	struct mail_namespace *ns;
+	const char *storage_name;
+
+	storage_name = dsync_box->name;
+	ns = mail_namespace_find(worker->user->namespaces, &storage_name);
+
+	mailbox_list_set_changelog_timestamp(ns->list, dsync_box->last_change);
+	if (mailbox_list_delete_dir(ns->list, storage_name) < 0) {
+		i_error("Can't delete mailbox directory %s: %s",
+			dsync_box->name,
+			mailbox_list_get_last_error(ns->list, NULL));
+	}
+	mailbox_list_set_changelog_timestamp(ns->list, (time_t)-1);
+}
+
+static void
 local_worker_rename_mailbox(struct dsync_worker *_worker,
 			    const mailbox_guid_t *mailbox,
 			    const struct dsync_mailbox *dsync_box)
@@ -1632,6 +1657,7 @@
 
 	local_worker_create_mailbox,
 	local_worker_delete_mailbox,
+	local_worker_delete_dir,
 	local_worker_rename_mailbox,
 	local_worker_update_mailbox,
 


More information about the dovecot-cvs mailing list