From: Timo Sirainen Date: Mon, 16 Nov 2009 19:40:59 +0000 (-0500) Subject: dsync: Fixed subscription syncing to work with namespace prefixes. X-Git-Tag: 2.0.beta1~148 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9de1785b6358348def74de6da664ffa3d765fb60;p=thirdparty%2Fdovecot%2Fcore.git dsync: Fixed subscription syncing to work with namespace prefixes. --HG-- branch : HEAD --- diff --git a/src/dsync/dsync-brain-private.h b/src/dsync/dsync-brain-private.h index 5a3852faf8..2a309c3422 100644 --- a/src/dsync/dsync-brain-private.h +++ b/src/dsync/dsync-brain-private.h @@ -27,22 +27,13 @@ struct dsync_brain_mailbox_list { 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); + ARRAY_DEFINE(subscriptions, struct dsync_worker_subscription); + ARRAY_DEFINE(unsubscriptions, struct dsync_worker_unsubscription); }; struct dsync_brain_guid_instance { diff --git a/src/dsync/dsync-brain.c b/src/dsync/dsync-brain.c index 4d7368634a..a8c744f6e4 100644 --- a/src/dsync/dsync-brain.c +++ b/src/dsync/dsync-brain.c @@ -151,30 +151,35 @@ static void dsync_brain_subs_list_finished(struct dsync_brain *brain) } static int -dsync_brain_subscription_cmp(const struct dsync_brain_subscription *s1, - const struct dsync_brain_subscription *s2) +dsync_worker_subscription_cmp(const struct dsync_worker_subscription *s1, + const struct dsync_worker_subscription *s2) { - return strcmp(s1->name, s2->name); + return strcmp(s1->vname, s2->vname); } static int -dsync_brain_unsubscription_cmp(const struct dsync_brain_unsubscription *u1, - const struct dsync_brain_unsubscription *u2) +dsync_worker_unsubscription_cmp(const struct dsync_worker_unsubscription *u1, + const struct dsync_worker_unsubscription *u2) { - return dsync_guid_cmp(&u1->name_sha1, &u2->name_sha1); + int ret; + + ret = strcmp(u1->ns_prefix, u2->ns_prefix); + return ret != 0 ? ret : + 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; + struct dsync_worker_subscription subs; + struct dsync_worker_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); + while ((ret = dsync_worker_subs_iter_next(list->iter, &subs)) > 0) { + subs.vname = p_strdup(list->pool, subs.vname); + subs.storage_name = p_strdup(list->pool, subs.storage_name); + subs.ns_prefix = p_strdup(list->pool, subs.ns_prefix); array_append(&list->subscriptions, &subs, 1); } if (ret == 0) @@ -182,18 +187,19 @@ static void dsync_worker_subs_input(void *context) memset(&unsubs, 0, sizeof(unsubs)); while ((ret = dsync_worker_subs_iter_next_un(list->iter, - &unsubs.name_sha1, - &unsubs.last_change)) > 0) + &unsubs)) > 0) { + unsubs.ns_prefix = p_strdup(list->pool, unsubs.ns_prefix); 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); + dsync_worker_subscription_cmp); array_sort(&list->unsubscriptions, - dsync_brain_unsubscription_cmp); + dsync_worker_unsubscription_cmp); dsync_brain_subs_list_finished(list->brain); } } @@ -309,15 +315,15 @@ static void dsync_brain_sync_mailboxes(struct dsync_brain *brain) static bool dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list, - const struct dsync_brain_subscription *subs) + const struct dsync_worker_subscription *subs) { - const struct dsync_brain_unsubscription *unsubs; - struct dsync_brain_unsubscription lookup; + const struct dsync_worker_unsubscription *unsubs; + struct dsync_worker_unsubscription lookup; - /* FIXME: doesn't work with namespace prefixes */ - dsync_str_sha_to_guid(subs->name, &lookup.name_sha1); + lookup.ns_prefix = subs->ns_prefix; + dsync_str_sha_to_guid(subs->storage_name, &lookup.name_sha1); unsubs = array_bsearch(&list->unsubscriptions, &lookup, - dsync_brain_unsubscription_cmp); + dsync_worker_unsubscription_cmp); if (unsubs == NULL) return FALSE; else @@ -326,7 +332,7 @@ dsync_brain_is_unsubscribed(struct dsync_brain_subs_list *list, static void dsync_brain_sync_subscriptions(struct dsync_brain *brain) { - const struct dsync_brain_subscription *src_subs, *dest_subs; + const struct dsync_worker_subscription *src_subs, *dest_subs; unsigned int src, dest, src_count, dest_count; int ret; @@ -341,7 +347,8 @@ static void dsync_brain_sync_subscriptions(struct dsync_brain *brain) } else if (dest == dest_count) { ret = -1; } else { - ret = strcmp(src_subs[src].name, dest_subs[dest].name); + ret = strcmp(src_subs[src].vname, + dest_subs[dest].vname); if (ret == 0) { src++; dest++; continue; @@ -353,11 +360,11 @@ static void dsync_brain_sync_subscriptions(struct dsync_brain *brain) if (dsync_brain_is_unsubscribed(brain->dest_subs_list, &src_subs[src])) { dsync_worker_set_subscribed(brain->src_worker, - src_subs[src].name, + src_subs[src].vname, FALSE); } else { dsync_worker_set_subscribed(brain->dest_worker, - src_subs[src].name, + src_subs[src].vname, TRUE); } src++; @@ -366,11 +373,11 @@ static void dsync_brain_sync_subscriptions(struct dsync_brain *brain) if (dsync_brain_is_unsubscribed(brain->src_subs_list, &dest_subs[dest])) { dsync_worker_set_subscribed(brain->dest_worker, - dest_subs[dest].name, + dest_subs[dest].vname, FALSE); } else { dsync_worker_set_subscribed(brain->src_worker, - dest_subs[dest].name, + dest_subs[dest].vname, TRUE); } dest++; diff --git a/src/dsync/dsync-proxy-client.c b/src/dsync/dsync-proxy-client.c index 692069d7f8..d0f1413a2f 100644 --- a/src/dsync/dsync-proxy-client.c +++ b/src/dsync/dsync-proxy-client.c @@ -431,8 +431,8 @@ proxy_client_worker_subs_iter_init(struct dsync_worker *_worker) static int proxy_client_worker_subs_iter_next_line(struct proxy_client_dsync_worker_subs_iter *iter, - const char **name_r, - time_t *last_change_r) + unsigned int wanted_arg_count, + char ***args_r) { struct proxy_client_dsync_worker *worker = (struct proxy_client_dsync_worker *)iter->iter.worker; @@ -455,48 +455,57 @@ proxy_client_worker_subs_iter_next_line(struct proxy_client_dsync_worker_subs_it p_clear(iter->pool); args = p_strsplit(iter->pool, line, "\t"); - if (args[0] == NULL || args[1] == NULL) { + if (str_array_length((const char *const *)args) < wanted_arg_count) { i_error("Invalid subscription input from worker server"); iter->iter.failed = TRUE; return -1; } - *name_r = args[0]; - *last_change_r = strtoul(args[1], NULL, 10); + *args_r = args; return 1; } static int proxy_client_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter, - const char **name_r, time_t *last_change_r) + struct dsync_worker_subscription *rec_r) { struct proxy_client_dsync_worker_subs_iter *iter = (struct proxy_client_dsync_worker_subs_iter *)_iter; + char **args; + int ret; - return proxy_client_worker_subs_iter_next_line(iter, name_r, - last_change_r); + ret = proxy_client_worker_subs_iter_next_line(iter, 4, &args); + if (ret <= 0) + return ret; + + rec_r->vname = str_tabunescape(args[0]); + rec_r->storage_name = str_tabunescape(args[1]); + rec_r->ns_prefix = str_tabunescape(args[2]); + rec_r->last_change = strtoul(args[3], NULL, 10); + return 1; } static int proxy_client_worker_subs_iter_next_un(struct dsync_worker_subs_iter *_iter, - mailbox_guid_t *name_sha1_r, - time_t *last_change_r) + struct dsync_worker_unsubscription *rec_r) { struct proxy_client_dsync_worker_subs_iter *iter = (struct proxy_client_dsync_worker_subs_iter *)_iter; - const char *name; + char **args; int ret; - ret = proxy_client_worker_subs_iter_next_line(iter, &name, - last_change_r); + ret = proxy_client_worker_subs_iter_next_line(iter, 3, &args); if (ret <= 0) return ret; - if (dsync_proxy_mailbox_guid_import(name, name_sha1_r) < 0) { + memset(rec_r, 0, sizeof(*rec_r)); + if (dsync_proxy_mailbox_guid_import(args[0], &rec_r->name_sha1) < 0) { i_error("Invalid subscription input from worker server: " "Invalid unsubscription mailbox GUID"); iter->iter.failed = TRUE; return -1; } + rec_r->ns_prefix = str_tabunescape(args[1]); + rec_r->last_change = strtoul(args[2], NULL, 10); return 1; } diff --git a/src/dsync/dsync-proxy-server-cmd.c b/src/dsync/dsync-proxy-server-cmd.c index 3e714d9990..c68056a961 100644 --- a/src/dsync/dsync-proxy-server-cmd.c +++ b/src/dsync/dsync-proxy-server-cmd.c @@ -64,17 +64,20 @@ cmd_box_list(struct dsync_proxy_server *server, static bool cmd_subs_list_subscriptions(struct dsync_proxy_server *server) { - const char *name; - time_t last_change; + struct dsync_worker_subscription rec; string_t *str; int ret; str = t_str_new(256); while ((ret = dsync_worker_subs_iter_next(server->subs_iter, - &name, &last_change)) > 0) { + &rec)) > 0) { str_truncate(str, 0); - str_tabescape_write(str, name); - str_printfa(str, "\t%ld\n", (long)last_change); + str_tabescape_write(str, rec.vname); + str_append_c(str, '\t'); + str_tabescape_write(str, rec.storage_name); + str_append_c(str, '\t'); + str_tabescape_write(str, rec.ns_prefix); + str_printfa(str, "\t%ld\n", (long)rec.last_change); o_stream_send(server->output, str_data(str), str_len(str)); if (proxy_server_is_output_full(server)) break; @@ -89,18 +92,18 @@ static bool cmd_subs_list_subscriptions(struct dsync_proxy_server *server) static bool cmd_subs_list_unsubscriptions(struct dsync_proxy_server *server) { - mailbox_guid_t name_sha1; - time_t last_change; + struct dsync_worker_unsubscription rec; string_t *str; int ret; str = t_str_new(256); while ((ret = dsync_worker_subs_iter_next_un(server->subs_iter, - &name_sha1, - &last_change)) > 0) { + &rec)) > 0) { str_truncate(str, 0); - dsync_proxy_mailbox_guid_export(str, &name_sha1); - str_printfa(str, "\t%ld\n", (long)last_change); + dsync_proxy_mailbox_guid_export(str, &rec.name_sha1); + str_append_c(str, '\t'); + str_tabescape_write(str, rec.ns_prefix); + str_printfa(str, "\t%ld\n", (long)rec.last_change); o_stream_send(server->output, str_data(str), str_len(str)); if (proxy_server_is_output_full(server)) break; diff --git a/src/dsync/dsync-worker-local.c b/src/dsync/dsync-worker-local.c index f0eca099b0..dd57f6f299 100644 --- a/src/dsync/dsync-worker-local.c +++ b/src/dsync/dsync-worker-local.c @@ -506,7 +506,7 @@ local_worker_subs_iter_init(struct dsync_worker *_worker) static int local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter, - const char **name_r, time_t *last_change_r) + struct dsync_worker_subscription *rec_r) { struct local_dsync_worker_subs_iter *iter = (struct local_dsync_worker_subs_iter *)_iter; @@ -516,6 +516,8 @@ local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter, const struct mailbox_info *info; const char *storage_name; + memset(rec_r, 0, sizeof(*rec_r)); + info = mailbox_list_iter_next(iter->list_iter); if (info == NULL) return -1; @@ -530,18 +532,17 @@ local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter, /* it shouldn't be marked as unsubscribed, but drop it to be sure */ change->unsubscribed = FALSE; - *last_change_r = change->last_change; - } else { - *last_change_r = 0; + rec_r->last_change = change->last_change; } - *name_r = info->name; + rec_r->ns_prefix = info->ns->prefix; + rec_r->vname = info->name; + rec_r->storage_name = storage_name; return 1; } static int local_worker_subs_iter_next_un(struct dsync_worker_subs_iter *_iter, - mailbox_guid_t *name_sha1_r, - time_t *last_change_r) + struct dsync_worker_unsubscription *rec_r) { struct local_dsync_worker_subs_iter *iter = (struct local_dsync_worker_subs_iter *)_iter; @@ -558,8 +559,12 @@ local_worker_subs_iter_next_un(struct dsync_worker_subs_iter *_iter, if (change->unsubscribed) { /* the name doesn't matter */ - *name_sha1_r = change->name_sha1; - *last_change_r = change->last_change; + struct mail_namespace *ns = + mailbox_list_get_namespace(change->list); + memset(rec_r, 0, sizeof(*rec_r)); + rec_r->name_sha1 = change->name_sha1; + rec_r->ns_prefix = ns->prefix; + rec_r->last_change = change->last_change; return 1; } } diff --git a/src/dsync/dsync-worker-private.h b/src/dsync/dsync-worker-private.h index 0e7b90cafb..9fcec1bc5b 100644 --- a/src/dsync/dsync-worker-private.h +++ b/src/dsync/dsync-worker-private.h @@ -20,10 +20,9 @@ struct dsync_worker_vfuncs { struct dsync_worker_subs_iter * (*subs_iter_init)(struct dsync_worker *worker); int (*subs_iter_next)(struct dsync_worker_subs_iter *iter, - const char **name_r, time_t *last_change_r); + struct dsync_worker_subscription *rec_r); int (*subs_iter_next_un)(struct dsync_worker_subs_iter *iter, - mailbox_guid_t *name_sha1_r, - time_t *last_change_r); + struct dsync_worker_unsubscription *rec_r); int (*subs_iter_deinit)(struct dsync_worker_subs_iter *iter); void (*set_subscribed)(struct dsync_worker *worker, const char *name, bool set); diff --git a/src/dsync/dsync-worker.c b/src/dsync/dsync-worker.c index ac62543f07..c7bd5b229d 100644 --- a/src/dsync/dsync-worker.c +++ b/src/dsync/dsync-worker.c @@ -68,17 +68,15 @@ dsync_worker_subs_iter_init(struct dsync_worker *worker) } int dsync_worker_subs_iter_next(struct dsync_worker_subs_iter *iter, - const char **name_r, time_t *last_change_r) + struct dsync_worker_subscription *rec_r) { - return iter->worker->v.subs_iter_next(iter, name_r, last_change_r); + return iter->worker->v.subs_iter_next(iter, rec_r); } int dsync_worker_subs_iter_next_un(struct dsync_worker_subs_iter *iter, - mailbox_guid_t *sha1_name_r, - time_t *last_change_r) + struct dsync_worker_unsubscription *rec_r) { - return iter->worker->v.subs_iter_next_un(iter, sha1_name_r, - last_change_r); + return iter->worker->v.subs_iter_next_un(iter, rec_r); } int dsync_worker_subs_iter_deinit(struct dsync_worker_subs_iter **_iter) diff --git a/src/dsync/dsync-worker.h b/src/dsync/dsync-worker.h index 67851b71b6..9c9ef4d566 100644 --- a/src/dsync/dsync-worker.h +++ b/src/dsync/dsync-worker.h @@ -10,6 +10,18 @@ enum dsync_msg_get_result { DSYNC_MSG_GET_RESULT_FAILED }; +struct dsync_worker_subscription { + const char *vname, *storage_name, *ns_prefix; + time_t last_change; +}; +struct dsync_worker_unsubscription { + /* SHA1 sum of the mailbox's storage name, i.e. without namespace + prefix */ + mailbox_guid_t name_sha1; + const char *ns_prefix; + time_t last_change; +}; + typedef void dsync_worker_copy_callback_t(bool success, void *context); typedef void dsync_worker_msg_callback_t(enum dsync_msg_get_result result, const struct dsync_msg_static_data *data, @@ -54,11 +66,10 @@ dsync_worker_subs_iter_init(struct dsync_worker *worker); /* Get the next subscription. Returns 1 if ok, 0 if waiting for more data, -1 if there are no more subscriptions. */ int dsync_worker_subs_iter_next(struct dsync_worker_subs_iter *iter, - const char **name_r, time_t *last_change_r); + struct dsync_worker_subscription *rec_r); /* Like _iter_next(), but list known recent unsubscriptions. */ int dsync_worker_subs_iter_next_un(struct dsync_worker_subs_iter *iter, - mailbox_guid_t *name_sha1_r, - time_t *last_change_r); + struct dsync_worker_unsubscription *rec_r); /* Finish subscription iteration. Returns 0 if ok, -1 if iteration failed. */ int dsync_worker_subs_iter_deinit(struct dsync_worker_subs_iter **iter); /* Subscribe/unsubscribe mailbox */ diff --git a/src/dsync/test-dsync-proxy-server-cmd.c b/src/dsync/test-dsync-proxy-server-cmd.c index 52d433b00c..c46c099933 100644 --- a/src/dsync/test-dsync-proxy-server-cmd.c +++ b/src/dsync/test-dsync-proxy-server-cmd.c @@ -115,7 +115,8 @@ static void test_dsync_proxy_box_list(void) static void test_dsync_proxy_subs_list(void) { const char *name; - mailbox_guid_t name_sha1; + struct dsync_worker_subscription subs; + struct dsync_worker_unsubscription unsubs; test_begin("proxy server subs list"); @@ -123,11 +124,17 @@ static void test_dsync_proxy_subs_list(void) /* subscription */ name = "\t\001\r\nname\t\001\n\r"; - test_worker->subs_iter.next_name = name; - test_worker->subs_iter.next_last_change = 1234567890; + subs.vname = name; + subs.storage_name = "\tstorage_name\n"; + subs.last_change = 1234567890; + subs.ns_prefix = "\t\001\r\nprefix\t\001\n\r"; + test_worker->subs_iter.next_subscription = &subs; test_assert(run_more() == 0); test_assert(strcmp(str_c(out), t_strconcat( - str_tabescape(name), "\t1234567890\n", NULL)) == 0); + str_tabescape(name), "\t", + str_tabescape(subs.storage_name), "\t", + str_tabescape(subs.ns_prefix), + "\t1234567890\n", NULL)) == 0); out_clear(); test_worker->subs_iter.last_subs = TRUE; @@ -136,10 +143,14 @@ static void test_dsync_proxy_subs_list(void) out_clear(); /* unsubscription */ - memcpy(name_sha1.guid, test_mailbox_guid1, sizeof(name_sha1.guid)); - test_worker->subs_iter.next_unsubscription = &name_sha1; + memcpy(unsubs.name_sha1.guid, test_mailbox_guid1, + sizeof(unsubs.name_sha1.guid)); + unsubs.ns_prefix = "\t\001\r\nprefix2\t\001\n\r"; + unsubs.last_change = 987654321; + test_worker->subs_iter.next_unsubscription = &unsubs; test_assert(run_more() == 0); - test_assert(strcmp(str_c(out), TEST_MAILBOX_GUID1"\t1234567890\n") == 0); + test_assert(strcmp(str_c(out), t_strconcat(TEST_MAILBOX_GUID1, "\t", + str_tabescape(unsubs.ns_prefix), "\t987654321\n", NULL)) == 0); out_clear(); test_worker->subs_iter.last_unsubs = TRUE; diff --git a/src/dsync/test-dsync-worker.c b/src/dsync/test-dsync-worker.c index daa2cf7155..39ce380972 100644 --- a/src/dsync/test-dsync-worker.c +++ b/src/dsync/test-dsync-worker.c @@ -93,24 +93,22 @@ test_worker_subs_iter_init(struct dsync_worker *_worker) static int test_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter, - const char **name_r, time_t *last_change_r) + struct dsync_worker_subscription *rec_r) { struct test_dsync_worker_subs_iter *iter = (struct test_dsync_worker_subs_iter *)_iter; - if (iter->next_name == NULL) + if (iter->next_subscription == NULL) return iter->last_subs ? -1 : 0; - *name_r = iter->next_name; - *last_change_r = iter->next_last_change; - iter->next_name = NULL; + *rec_r = *iter->next_subscription; + iter->next_subscription = NULL; return 1; } static int test_worker_subs_iter_next_un(struct dsync_worker_subs_iter *_iter, - mailbox_guid_t *name_sha1_r, - time_t *last_change_r) + struct dsync_worker_unsubscription *rec_r) { struct test_dsync_worker_subs_iter *iter = (struct test_dsync_worker_subs_iter *)_iter; @@ -118,8 +116,7 @@ test_worker_subs_iter_next_un(struct dsync_worker_subs_iter *_iter, if (iter->next_unsubscription == NULL) return iter->last_unsubs ? -1 : 0; - *name_sha1_r = *iter->next_unsubscription; - *last_change_r = iter->next_last_change; + *rec_r = *iter->next_unsubscription; iter->next_unsubscription = NULL; return 1; } diff --git a/src/dsync/test-dsync-worker.h b/src/dsync/test-dsync-worker.h index c2f4e78abf..dad6206e6a 100644 --- a/src/dsync/test-dsync-worker.h +++ b/src/dsync/test-dsync-worker.h @@ -28,9 +28,8 @@ struct test_dsync_worker_mailbox_iter { struct test_dsync_worker_subs_iter { struct dsync_worker_subs_iter iter; - const char *next_name; - mailbox_guid_t *next_unsubscription; - time_t next_last_change; + struct dsync_worker_subscription *next_subscription; + struct dsync_worker_unsubscription *next_unsubscription; bool last_subs, last_unsubs; };