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 {
}
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)
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);
}
}
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
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;
} 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;
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++;
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++;
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;
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;
}
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;
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;
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;
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;
/* 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;
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;
}
}
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);
}
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)
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,
/* 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 */
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");
/* 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;
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;
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;
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;
}
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;
};