dovecot-2.0-sslstream: dsync: Added support for subscription syn...

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 13 02:56:24 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0-sslstream/rev/b63fd6156663
changeset: 10329:b63fd6156663
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Nov 13 20:55:05 2009 -0500
description:
dsync: Added support for subscription syncing.

diffstat:

15 files changed, 895 insertions(+), 27 deletions(-)
src/dsync/dsync-brain-private.h         |   23 ++
src/dsync/dsync-brain.c                 |  182 +++++++++++++++++++++
src/dsync/dsync-data.c                  |   14 +
src/dsync/dsync-data.h                  |    2 
src/dsync/dsync-proxy-client.c          |  126 ++++++++++++++
src/dsync/dsync-proxy-server-cmd.c      |   98 +++++++++++
src/dsync/dsync-proxy-server.h          |    2 
src/dsync/dsync-worker-local.c          |  266 +++++++++++++++++++++++++++----
src/dsync/dsync-worker-private.h        |   16 +
src/dsync/dsync-worker.c                |   34 +++
src/dsync/dsync-worker.h                |   17 +
src/dsync/test-dsync-brain.c            |   17 +
src/dsync/test-dsync-proxy-server-cmd.c |   39 ++++
src/dsync/test-dsync-worker.c           |   73 ++++++++
src/dsync/test-dsync-worker.h           |   13 +

diffs (truncated from 1291 to 300 lines):

diff -r 4267c30ded97 -r b63fd6156663 src/dsync/dsync-brain-private.h
--- a/src/dsync/dsync-brain-private.h	Fri Nov 13 20:54:50 2009 -0500
+++ b/src/dsync/dsync-brain-private.h	Fri Nov 13 20:55:05 2009 -0500
@@ -6,7 +6,9 @@
 
 enum dsync_state {
 	DSYNC_STATE_GET_MAILBOXES = 0,
+	DSYNC_STATE_GET_SUBSCRIPTIONS,
 	DSYNC_STATE_SYNC_MAILBOXES,
+	DSYNC_STATE_SYNC_SUBSCRIPTIONS,
 	DSYNC_STATE_SYNC_MSGS,
 	DSYNC_STATE_SYNC_MSGS_FLUSH,
 	DSYNC_STATE_SYNC_MSGS_FLUSH2,
@@ -23,6 +25,24 @@ struct dsync_brain_mailbox_list {
 	struct dsync_worker_mailbox_iter *iter;
 	ARRAY_TYPE(dsync_mailbox) mailboxes;
 	ARRAY_TYPE(dsync_mailbox) dirs;
+};
+
+struct dsync_brain_subscription {
+	const char *name;
+	time_t last_change;
+};
+struct dsync_brain_unsubscription {
+	mailbox_guid_t name_sha1;
+	time_t last_change;
+};
+
+struct dsync_brain_subs_list {
+	pool_t pool;
+	struct dsync_brain *brain;
+	struct dsync_worker *worker;
+	struct dsync_worker_subs_iter *iter;
+	ARRAY_DEFINE(subscriptions, struct dsync_brain_subscription);
+	ARRAY_DEFINE(unsubscriptions, struct dsync_brain_unsubscription);
 };
 
 struct dsync_brain_guid_instance {
@@ -103,6 +123,9 @@ struct dsync_brain {
 	struct dsync_brain_mailbox_list *src_mailbox_list;
 	struct dsync_brain_mailbox_list *dest_mailbox_list;
 
+	struct dsync_brain_subs_list *src_subs_list;
+	struct dsync_brain_subs_list *dest_subs_list;
+
 	struct dsync_brain_mailbox_sync *mailbox_sync;
 
 	unsigned int failed:1;
diff -r 4267c30ded97 -r b63fd6156663 src/dsync/dsync-brain.c
--- a/src/dsync/dsync-brain.c	Fri Nov 13 20:54:50 2009 -0500
+++ b/src/dsync/dsync-brain.c	Fri Nov 13 20:55:05 2009 -0500
@@ -9,6 +9,8 @@
 
 static void
 dsync_brain_mailbox_list_deinit(struct dsync_brain_mailbox_list **list);
+static void
+dsync_brain_subs_list_deinit(struct dsync_brain_subs_list **list);
 
 struct dsync_brain *
 dsync_brain_init(struct dsync_worker *src_worker,
@@ -49,10 +51,16 @@ int dsync_brain_deinit(struct dsync_brai
 
 	if (brain->mailbox_sync != NULL)
 		dsync_brain_msg_sync_deinit(&brain->mailbox_sync);
+
 	if (brain->src_mailbox_list != NULL)
 		dsync_brain_mailbox_list_deinit(&brain->src_mailbox_list);
 	if (brain->dest_mailbox_list != NULL)
 		dsync_brain_mailbox_list_deinit(&brain->dest_mailbox_list);
+
+	if (brain->src_subs_list != NULL)
+		dsync_brain_subs_list_deinit(&brain->src_subs_list);
+	if (brain->dest_subs_list != NULL)
+		dsync_brain_subs_list_deinit(&brain->dest_subs_list);
 
 	*_brain = NULL;
 	i_free(brain->mailbox);
@@ -128,6 +136,96 @@ dsync_brain_mailbox_list_deinit(struct d
 
 	if (list->iter != NULL)
 		(void)dsync_worker_mailbox_iter_deinit(&list->iter);
+	pool_unref(&list->pool);
+}
+
+static void dsync_brain_subs_list_finished(struct dsync_brain *brain)
+{
+	if (brain->src_subs_list->iter != NULL ||
+	    brain->dest_subs_list->iter != NULL)
+		return;
+
+	/* both lists are finished */
+	brain->state++;
+	dsync_brain_sync(brain);
+}
+
+static int
+dsync_brain_subscription_cmp(const struct dsync_brain_subscription *s1,
+			     const struct dsync_brain_subscription *s2)
+{
+	return strcmp(s1->name, s2->name);
+}
+
+static int
+dsync_brain_unsubscription_cmp(const struct dsync_brain_unsubscription *u1,
+			       const struct dsync_brain_unsubscription *u2)
+{
+	return dsync_guid_cmp(&u1->name_sha1, &u2->name_sha1);
+}
+
+static void dsync_worker_subs_input(void *context)
+{
+	struct dsync_brain_subs_list *list = context;
+	struct dsync_brain_subscription subs;
+	struct dsync_brain_unsubscription unsubs;
+	int ret;
+
+	memset(&subs, 0, sizeof(subs));
+	while ((ret = dsync_worker_subs_iter_next(list->iter, &subs.name,
+						  &subs.last_change)) > 0) {
+		subs.name = p_strdup(list->pool, subs.name);
+		array_append(&list->subscriptions, &subs, 1);
+	}
+	if (ret == 0)
+		return;
+
+	memset(&unsubs, 0, sizeof(unsubs));
+	while ((ret = dsync_worker_subs_iter_next_un(list->iter,
+						     &unsubs.name_sha1,
+						     &unsubs.last_change)) > 0)
+		array_append(&list->unsubscriptions, &unsubs, 1);
+
+	if (ret < 0) {
+		/* finished listing subscriptions */
+		if (dsync_worker_subs_iter_deinit(&list->iter) < 0)
+			dsync_brain_fail(list->brain);
+		array_sort(&list->subscriptions,
+			   dsync_brain_subscription_cmp);
+		array_sort(&list->unsubscriptions,
+			   dsync_brain_unsubscription_cmp);
+		dsync_brain_subs_list_finished(list->brain);
+	}
+}
+
+static struct dsync_brain_subs_list *
+dsync_brain_subs_list_init(struct dsync_brain *brain,
+			      struct dsync_worker *worker)
+{
+	struct dsync_brain_subs_list *list;
+	pool_t pool;
+
+	pool = pool_alloconly_create("dsync brain subs list", 1024*4);
+	list = p_new(pool, struct dsync_brain_subs_list, 1);
+	list->pool = pool;
+	list->brain = brain;
+	list->worker = worker;
+	list->iter = dsync_worker_subs_iter_init(worker);
+	p_array_init(&list->subscriptions, pool, 128);
+	p_array_init(&list->unsubscriptions, pool, 64);
+	dsync_worker_set_input_callback(worker, dsync_worker_subs_input, list);
+	return list;
+}
+
+static void
+dsync_brain_subs_list_deinit(struct dsync_brain_subs_list **_list)
+{
+	struct dsync_brain_subs_list *list = *_list;
+
+	*_list = NULL;
+
+	if (list->iter != NULL)
+		(void)dsync_worker_subs_iter_deinit(&list->iter);
 	pool_unref(&list->pool);
 }
 
@@ -209,6 +307,77 @@ static void dsync_brain_sync_mailboxes(s
 	}
 }
 
+static bool
+dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list,
+			    const struct dsync_brain_subscription *subs)
+{
+	const struct dsync_brain_unsubscription *unsubs;
+	struct dsync_brain_unsubscription lookup;
+
+	/* FIXME: doesn't work with namespace prefixes */
+	dsync_str_sha_to_guid(subs->name, &lookup.name_sha1);
+	unsubs = array_bsearch(&list->unsubscriptions, &lookup,
+			       dsync_brain_unsubscription_cmp);
+	if (unsubs == NULL)
+		return FALSE;
+	else
+		return unsubs->last_change > subs->last_change;
+}
+
+static void dsync_brain_sync_subscriptions(struct dsync_brain *brain)
+{
+	const struct dsync_brain_subscription *src_subs, *dest_subs;
+	unsigned int src, dest, src_count, dest_count;
+	int ret;
+
+	/* subscriptions are sorted by name. */
+	src_subs = array_get(&brain->src_subs_list->subscriptions, &src_count);
+	dest_subs = array_get(&brain->dest_subs_list->subscriptions, &dest_count);
+	for (src = dest = 0;; ) {
+		if (src == src_count) {
+			if (dest == dest_count)
+				break;
+			ret = 1;
+		} else if (dest == dest_count) {
+			ret = -1;
+		} else {
+			ret = strcmp(src_subs[src].name, dest_subs[dest].name);
+			if (ret == 0) {
+				src++; dest++;
+				continue;
+			}
+		}
+
+		if (ret < 0) {
+			/* subscribed only in source */
+			if (dsync_brain_is_unsubscribed(brain->dest_subs_list,
+							&src_subs[src])) {
+				dsync_worker_set_subscribed(brain->src_worker,
+							    src_subs[src].name,
+							    FALSE);
+			} else {
+				dsync_worker_set_subscribed(brain->dest_worker,
+							    src_subs[src].name,
+							    TRUE);
+			}
+			src++;
+		} else {
+			/* subscribed only in dest */
+			if (dsync_brain_is_unsubscribed(brain->src_subs_list,
+							&dest_subs[dest])) {
+				dsync_worker_set_subscribed(brain->dest_worker,
+							    dest_subs[dest].name,
+							    FALSE);
+			} else {
+				dsync_worker_set_subscribed(brain->src_worker,
+							    dest_subs[dest].name,
+							    TRUE);
+			}
+			dest++;
+		}
+	}
+}
+
 static bool dsync_mailbox_has_changed_msgs(struct dsync_brain *brain,
 					   const struct dsync_mailbox *box1,
 					   const struct dsync_mailbox *box2)
@@ -380,8 +549,21 @@ void dsync_brain_sync(struct dsync_brain
 		dsync_worker_mailbox_input(brain->src_mailbox_list);
 		dsync_worker_mailbox_input(brain->dest_mailbox_list);
 		break;
+	case DSYNC_STATE_GET_SUBSCRIPTIONS:
+		i_assert(brain->src_subs_list == NULL);
+		brain->src_subs_list =
+			dsync_brain_subs_list_init(brain, brain->src_worker);
+		brain->dest_subs_list =
+			dsync_brain_subs_list_init(brain, brain->dest_worker);
+		dsync_worker_subs_input(brain->src_subs_list);
+		dsync_worker_subs_input(brain->dest_subs_list);
+		break;
 	case DSYNC_STATE_SYNC_MAILBOXES:
 		dsync_brain_sync_mailboxes(brain);
+		brain->state++;
+		/* fall through */
+	case DSYNC_STATE_SYNC_SUBSCRIPTIONS:
+		dsync_brain_sync_subscriptions(brain);
 		brain->state++;
 		/* fall through */
 	case DSYNC_STATE_SYNC_MSGS:
diff -r 4267c30ded97 -r b63fd6156663 src/dsync/dsync-data.c
--- a/src/dsync/dsync-data.c	Fri Nov 13 20:54:50 2009 -0500
+++ b/src/dsync/dsync-data.c	Fri Nov 13 20:55:05 2009 -0500
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "buffer.h"
 #include "hex-binary.h"
+#include "sha1.h"
 #include "dsync-data.h"
 
 struct dsync_mailbox *
@@ -88,6 +89,11 @@ bool dsync_guid_equals(const mailbox_gui
 	return memcmp(guid1->guid, guid2->guid, sizeof(guid1->guid)) == 0;
 }
 
+int dsync_guid_cmp(const mailbox_guid_t *guid1, const mailbox_guid_t *guid2)
+{
+	return memcmp(guid1->guid, guid2->guid, sizeof(guid1->guid));
+}
+
 const char *dsync_guid_to_str(const mailbox_guid_t *guid)
 {
 	return binary_to_hex(guid->guid, sizeof(guid->guid));
@@ -108,3 +114,11 @@ const char *dsync_get_guid_128_str(const
 	buffer_append_c(&guid_128_buf, '\0');
 	return guid_128_buf.data;


More information about the dovecot-cvs mailing list