#include <ctype.h>
#include <sys/wait.h>
-#define DSYNC_COMMON_GETOPT_ARGS "+1dEfg:l:m:n:Nr:Rs:Ux:"
+#define DSYNC_COMMON_GETOPT_ARGS "+1dEfg:l:m:n:NPr:Rs:Ux:"
#define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30
/* The broken_char is mainly set to get a proper error message when trying to
convert a mailbox with a name that can't be used properly translated between
unsigned int lock_timeout;
unsigned int lock:1;
+ unsigned int purge_remote:1;
unsigned int sync_visible_namespaces:1;
unsigned int default_replica_location:1;
unsigned int oneway:1;
}
brain2 = dsync_brain_slave_init(user2, ibc2, TRUE);
+ mail_user_unref(&user2);
brain1_running = brain2_running = TRUE;
changed1 = changed2 = TRUE;
brain1_running = dsync_brain_run(brain, &changed1);
brain2_running = dsync_brain_run(brain2, &changed2);
}
- mail_user_unref(&user2);
*changes_during_sync_r = dsync_brain_has_unexpected_changes(brain2);
if (dsync_brain_deinit(&brain2) < 0) {
ctx->ctx.exit_code = EX_TEMPFAIL;
brain_flags = DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS;
if (ctx->sync_visible_namespaces)
brain_flags |= DSYNC_BRAIN_FLAG_SYNC_VISIBLE_NAMESPACES;
+ if (ctx->purge_remote)
+ brain_flags |= DSYNC_BRAIN_FLAG_PURGE_REMOTE;
if (ctx->reverse_backup)
brain_flags |= DSYNC_BRAIN_FLAG_BACKUP_RECV;
case 'N':
ctx->sync_visible_namespaces = TRUE;
break;
+ case 'P':
+ ctx->purge_remote = TRUE;
+ break;
case 'r':
ctx->rawlog_path = optarg;
break;
unsigned int mail_requests:1;
unsigned int backup_send:1;
unsigned int backup_recv:1;
+ unsigned int purge:1;
unsigned int debug:1;
unsigned int sync_visible_namespaces:1;
unsigned int no_mail_sync:1;
pool_t pool;
service_set = master_service_settings_get(master_service);
+ mail_user_ref(user);
pool = pool_alloconly_create("dsync brain", 10240);
brain = p_new(pool, struct dsync_brain, 1);
return brain;
}
+static void dsync_brain_purge(struct dsync_brain *brain)
+{
+ struct mail_namespace *ns;
+ struct mail_storage *storage;
+
+ for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
+ if (!dsync_brain_want_namespace(brain, ns))
+ continue;
+
+ storage = mail_namespace_get_default_storage(ns);
+ if (mail_storage_purge(storage) < 0) {
+ i_error("Purging namespace '%s' failed: %s", ns->prefix,
+ mail_storage_get_last_error(storage, NULL));
+ }
+ }
+}
+
int dsync_brain_deinit(struct dsync_brain **_brain)
{
struct dsync_brain *brain = *_brain;
brain->failed = TRUE;
dsync_ibc_close_mail_streams(brain->ibc);
+ if (brain->purge && !brain->failed)
+ dsync_brain_purge(brain);
+
if (brain->box != NULL)
dsync_brain_sync_mailbox_deinit(brain);
if (brain->local_tree_iter != NULL)
}
ret = brain->failed ? -1 : 0;
+ mail_user_unref(&brain->user);
pool_unref(&brain->pool);
return ret;
}
sizeof(brain->sync_box_guid));
i_assert(brain->sync_type == DSYNC_BRAIN_SYNC_TYPE_UNKNOWN);
brain->sync_type = ibc_set->sync_type;
+
dsync_brain_set_flags(brain, ibc_set->brain_flags);
+ /* this flag is only set on the remote slave brain */
+ brain->purge = (ibc_set->brain_flags &
+ DSYNC_BRAIN_FLAG_PURGE_REMOTE) != 0;
dsync_brain_mailbox_trees_init(brain);
/* Used with BACKUP_SEND/RECV: Don't force the
Use the two-way syncing algorithm, but don't actually modify
anything locally. (Useful during migration.) */
- DSYNC_BRAIN_FLAG_NO_BACKUP_OVERWRITE = 0x40
+ DSYNC_BRAIN_FLAG_NO_BACKUP_OVERWRITE = 0x40,
+ /* Run storage purge on the remote after syncing.
+ Useful with e.g. a nightly doveadm backup. */
+ DSYNC_BRAIN_FLAG_PURGE_REMOTE = 0x80
};
enum dsync_brain_sync_type {
.optional_keys = "sync_ns_prefix sync_box sync_box_guid sync_type "
"debug sync_visible_namespaces exclude_mailboxes "
"send_mail_requests backup_send backup_recv lock_timeout "
- "no_mail_sync no_backup_overwrite"
+ "no_mail_sync no_backup_overwrite purge_remote"
},
{ .name = "mailbox_state",
.chr = 'S',
dsync_serializer_encode_add(encoder, "no_mail_sync", "");
if ((set->brain_flags & DSYNC_BRAIN_FLAG_NO_BACKUP_OVERWRITE) != 0)
dsync_serializer_encode_add(encoder, "no_backup_overwrite", "");
+ if ((set->brain_flags & DSYNC_BRAIN_FLAG_PURGE_REMOTE) != 0)
+ dsync_serializer_encode_add(encoder, "purge_remote", "");
dsync_serializer_encode_finish(&encoder, str);
dsync_ibc_stream_send_string(ibc, str);
set->brain_flags |= DSYNC_BRAIN_FLAG_NO_MAIL_SYNC;
if (dsync_deserializer_decode_try(decoder, "no_backup_overwrite", &value))
set->brain_flags |= DSYNC_BRAIN_FLAG_NO_BACKUP_OVERWRITE;
+ if (dsync_deserializer_decode_try(decoder, "purge_remote", &value))
+ set->brain_flags |= DSYNC_BRAIN_FLAG_PURGE_REMOTE;
*set_r = set;
return DSYNC_IBC_RECV_RET_OK;