struct dsync_cmd_context {
struct doveadm_mail_cmd_context ctx;
enum dsync_brain_sync_type sync_type;
- const char *mailbox, *namespace_prefix;
+ const char *mailbox;
guid_128_t mailbox_guid;
const char *state_input, *rawlog_path;
ARRAY_TYPE(const_string) exclude_mailboxes;
+ ARRAY_TYPE(const_string) namespace_prefixes;
const char *remote_name;
const char *local_location;
struct dsync_ibc *ibc, *ibc2 = NULL;
struct dsync_brain *brain;
struct dsync_brain_settings set;
+ struct mail_namespace *ns;
+ const char *const *strp;
enum dsync_brain_flags brain_flags;
bool remote_errors_logged = FALSE;
bool changes_during_sync = FALSE;
}
doveadm_user_init_dsync(user);
- if (ctx->namespace_prefix != NULL) {
- set.sync_ns = mail_namespace_find(user->namespaces,
- ctx->namespace_prefix);
+ t_array_init(&set.sync_namespaces, array_count(&ctx->namespace_prefixes));
+ array_foreach(&ctx->namespace_prefixes, strp) {
+ ns = mail_namespace_find(user->namespaces, *strp);
+ if (ns == NULL) {
+ i_error("Namespace not found: '%s'", *strp);
+ ctx->ctx.exit_code = EX_USAGE;
+ return -1;
+ }
+ array_append(&set.sync_namespaces, &ns, 1);
}
if (ctx->run_type == DSYNC_RUN_TYPE_LOCAL)
array_append(&ctx->exclude_mailboxes, &str, 1);
break;
case 'n':
- ctx->namespace_prefix = optarg;
+ str = optarg;
+ array_append(&ctx->namespace_prefixes, &str, 1);
break;
case 'N':
ctx->sync_visible_namespaces = TRUE;
doveadm_print_header("state", "state",
DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE);
p_array_init(&ctx->exclude_mailboxes, ctx->ctx.pool, 4);
+ p_array_init(&ctx->namespace_prefixes, ctx->ctx.pool, 4);
return &ctx->ctx;
}
i_assert(brain->hierarchy_sep == '\0');
- if (brain->sync_ns != NULL) {
- brain->hierarchy_sep = mail_namespace_get_sep(brain->sync_ns);
- return;
- }
-
for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
if (!dsync_brain_want_namespace(brain, ns))
continue;
int ret;
*box_r = NULL;
- if (brain->sync_ns != NULL) {
- ret = ns_mailbox_try_alloc(brain->sync_ns, guid, box_r, error_r);
- if (ret < 0)
- brain->failed = TRUE;
- return ret;
- }
for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
if (!dsync_brain_want_namespace(brain, ns))
pool_t pool;
struct mail_user *user;
struct dsync_ibc *ibc;
- struct mail_namespace *sync_ns;
+ ARRAY(struct mail_namespace *) sync_namespaces;
const char *sync_box;
guid_128_t sync_box_guid;
const char *const *exclude_mailboxes;
{
struct dsync_ibc_settings ibc_set;
struct dsync_brain *brain;
+ struct mail_namespace *const *nsp;
+ string_t *sync_ns_str = NULL;
const char *error;
i_assert(sync_type != DSYNC_BRAIN_SYNC_TYPE_UNKNOWN);
brain = dsync_brain_common_init(user, ibc);
brain->sync_type = sync_type;
- if (set->sync_ns != NULL)
- brain->sync_ns = set->sync_ns;
+ if (array_count(&set->sync_namespaces) > 0) {
+ sync_ns_str = t_str_new(128);
+ p_array_init(&brain->sync_namespaces, brain->pool,
+ array_count(&set->sync_namespaces));
+ array_foreach(&set->sync_namespaces, nsp) {
+ if (str_len(sync_ns_str) > 0)
+ str_append_c(sync_ns_str, '\n');
+ str_append(sync_ns_str, (*nsp)->prefix);
+ array_append(&brain->sync_namespaces, nsp, 1);
+ }
+ }
brain->sync_box = p_strdup(brain->pool, set->sync_box);
brain->exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL :
p_strarray_dup(brain->pool, set->exclude_mailboxes);
memset(&ibc_set, 0, sizeof(ibc_set));
ibc_set.hostname = my_hostdomain();
- ibc_set.sync_ns_prefix = set->sync_ns == NULL ? NULL :
- set->sync_ns->prefix;
+ ibc_set.sync_ns_prefixes = sync_ns_str == NULL ?
+ NULL : str_c(sync_ns_str);
ibc_set.sync_box = set->sync_box;
ibc_set.exclude_mailboxes = set->exclude_mailboxes;
memcpy(ibc_set.sync_box_guid, set->sync_box_guid,
static bool dsync_brain_slave_recv_handshake(struct dsync_brain *brain)
{
const struct dsync_ibc_settings *ibc_set;
+ struct mail_namespace *ns;
+ const char *const *prefixes;
i_assert(!brain->master_brain);
}
}
- if (ibc_set->sync_ns_prefix != NULL) {
- brain->sync_ns = mail_namespace_find(brain->user->namespaces,
- ibc_set->sync_ns_prefix);
+ if (ibc_set->sync_ns_prefixes != NULL) {
+ p_array_init(&brain->sync_namespaces, brain->pool, 4);
+ prefixes = t_strsplit(ibc_set->sync_ns_prefixes, "\n");
+ for (; *prefixes != NULL; prefixes++) {
+ ns = mail_namespace_find(brain->user->namespaces,
+ *prefixes);
+ if (ns == NULL) {
+ i_error("Namespace not found: '%s'", *prefixes);
+ brain->failed = TRUE;
+ return FALSE;
+ }
+ array_append(&brain->sync_namespaces, &ns, 1);
+ }
}
brain->sync_box = p_strdup(brain->pool, ibc_set->sync_box);
brain->exclude_mailboxes = ibc_set->exclude_mailboxes == NULL ? NULL :
bool dsync_brain_want_namespace(struct dsync_brain *brain,
struct mail_namespace *ns)
{
- if (brain->sync_ns != NULL)
- return brain->sync_ns == ns;
+ struct mail_namespace *const *nsp;
+
+ if (array_is_created(&brain->sync_namespaces)) {
+ array_foreach(&brain->sync_namespaces, nsp) {
+ if (ns == *nsp)
+ return TRUE;
+ }
+ return FALSE;
+ }
if (ns->alias_for != NULL) {
/* always skip aliases */
return FALSE;
};
struct dsync_brain_settings {
- /* Sync only this namespace */
- struct mail_namespace *sync_ns;
+ /* Sync only these namespaces */
+ ARRAY(struct mail_namespace *) sync_namespaces;
/* Sync only this mailbox name */
const char *sync_box;
/* Sync only this mailbox GUID */
item = dsync_ibc_pipe_push_item(pipe->remote, ITEM_HANDSHAKE);
item->u.set = *set;
- item->u.set.sync_ns_prefix = p_strdup(item->pool, set->sync_ns_prefix);
+ item->u.set.sync_ns_prefixes =
+ p_strdup(item->pool, set->sync_ns_prefixes);
item->u.set.sync_box = p_strdup(item->pool, set->sync_box);
item->u.set.exclude_mailboxes = set->exclude_mailboxes == NULL ? NULL :
p_strarray_dup(item->pool, set->exclude_mailboxes);
str_append_c(str, items[ITEM_HANDSHAKE].chr);
encoder = dsync_serializer_encode_begin(ibc->serializers[ITEM_HANDSHAKE]);
dsync_serializer_encode_add(encoder, "hostname", set->hostname);
- if (set->sync_ns_prefix != NULL) {
+ if (set->sync_ns_prefixes != NULL) {
dsync_serializer_encode_add(encoder, "sync_ns_prefix",
- set->sync_ns_prefix);
+ set->sync_ns_prefixes);
}
if (set->sync_box != NULL)
dsync_serializer_encode_add(encoder, "sync_box", set->sync_box);
ibc->name = i_strdup(set->hostname);
if (dsync_deserializer_decode_try(decoder, "sync_ns_prefix", &value))
- set->sync_ns_prefix = p_strdup(pool, value);
+ set->sync_ns_prefixes = p_strdup(pool, value);
if (dsync_deserializer_decode_try(decoder, "sync_box", &value))
set->sync_box = p_strdup(pool, value);
if (dsync_deserializer_decode_try(decoder, "sync_box_guid", &value) &&
/* Server hostname. Used for determining which server does the
locking. */
const char *hostname;
- /* if non-NULL, sync only this namespace */
- const char *sync_ns_prefix;
+ /* if non-NULL, sync only these namespaces (LF-separated) */
+ const char *sync_ns_prefixes;
/* if non-NULL, sync only this mailbox name */
const char *sync_box;
/* if non-empty, sync only this mailbox GUID */