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