dovecot-2.1: dsync: Added -l <timeout> parameter to lock the syn...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Mar 2 13:56:47 EET 2012
details: http://hg.dovecot.org/dovecot-2.1/rev/d4922e80ca05
changeset: 14213:d4922e80ca05
user: Timo Sirainen <tss at iki.fi>
date: Fri Mar 02 13:56:37 2012 +0200
description:
dsync: Added -l <timeout> parameter to lock the sync (via ~/.dovecot-sync.lock)
diffstat:
src/doveadm/dsync/doveadm-dsync.c | 169 +++++++++++++++++++++++++++++--------
1 files changed, 131 insertions(+), 38 deletions(-)
diffs (286 lines):
diff -r 1a33e3651c6d -r d4922e80ca05 src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c Fri Mar 02 13:15:15 2012 +0200
+++ b/src/doveadm/dsync/doveadm-dsync.c Fri Mar 02 13:56:37 2012 +0200
@@ -21,6 +21,8 @@
#include <unistd.h>
#include <ctype.h>
+#define DSYNC_LOCK_FILENAME ".dovecot-sync.lock"
+
struct dsync_cmd_context {
struct doveadm_mail_cmd_context ctx;
enum dsync_brain_flags brain_flags;
@@ -31,6 +33,9 @@
int fd_in, fd_out;
+ unsigned int lock_timeout;
+
+ unsigned int lock:1;
unsigned int reverse_workers:1;
};
@@ -100,7 +105,8 @@
*cmd_args_r = array_idx(&cmd_args, 0);
}
-static bool mirror_get_remote_cmd(const char *const *argv, const char *user,
+static bool mirror_get_remote_cmd(struct dsync_cmd_context *ctx,
+ const char *const *argv, const char *user,
const char *const **cmd_args_r)
{
ARRAY_TYPE(const_string) cmd_args;
@@ -146,6 +152,10 @@
array_append(&cmd_args, &host, 1);
p = "doveadm"; array_append(&cmd_args, &p, 1);
p = "dsync-server"; array_append(&cmd_args, &p, 1);
+ if (ctx->lock) {
+ p = "-l"; array_append(&cmd_args, &p, 1);
+ p = dec2str(ctx->lock_timeout); array_append(&cmd_args, &p, 1);
+ }
if (*user != '\0') {
p = "-u"; array_append(&cmd_args, &p, 1);
array_append(&cmd_args, &user, 1);
@@ -208,13 +218,75 @@
return dsync_worker_init_proxy_client(ctx->fd_in, ctx->fd_out);
}
+static int dsync_lock(struct mail_user *user, unsigned int lock_timeout,
+ const char **path_r, struct file_lock **lock_r)
+{
+ const char *home, *path;
+ int ret, fd;
+
+ if ((ret = mail_user_get_home(user, &home)) < 0) {
+ i_error("Couldn't look up user's home dir");
+ return -1;
+ }
+ if (ret == 0) {
+ i_error("User has no home directory");
+ return -1;
+ }
+
+ path = t_strconcat(home, "/"DSYNC_LOCK_FILENAME, NULL);
+ fd = creat(path, 0600);
+ if (fd == -1) {
+ i_error("Couldn't create lock %s: %m", path);
+ return -1;
+ }
+
+ if (file_wait_lock(fd, path, F_WRLCK, FILE_LOCK_METHOD_FCNTL,
+ lock_timeout, lock_r) <= 0) {
+ i_error("Couldn't lock %s: %m", path);
+ (void)close(fd);
+ return -1;
+ }
+ *path_r = path;
+ return fd;
+}
+
+static int
+cmd_dsync_start(struct dsync_cmd_context *ctx, struct dsync_worker *worker1,
+ struct dsync_worker *worker2)
+{
+ struct dsync_brain *brain;
+
+ /* create and run the brain */
+ brain = dsync_brain_init(worker1, worker2, ctx->mailbox,
+ ctx->brain_flags);
+ if (ctx->remote_cmd_args == NULL)
+ dsync_brain_sync_all(brain);
+ else {
+ dsync_brain_sync(brain);
+ if (!dsync_brain_has_failed(brain))
+ io_loop_run(current_ioloop);
+ }
+ /* deinit */
+ if (dsync_brain_has_unexpected_changes(brain)) {
+ i_warning("Mailbox changes caused a desync. "
+ "You may want to run dsync again.");
+ ctx->ctx.exit_code = 2;
+ }
+ if (dsync_brain_deinit(&brain) < 0) {
+ ctx->ctx.exit_code = EX_TEMPFAIL;
+ return -1;
+ }
+ return 0;
+}
+
static int
cmd_dsync_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
{
struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
struct dsync_worker *worker1, *worker2, *workertmp;
- struct dsync_brain *brain;
- int ret = 0;
+ const char *lock_path;
+ struct file_lock *lock;
+ int lock_fd, ret = 0;
user->admin = TRUE;
@@ -230,27 +302,20 @@
worker2 = workertmp;
}
- /* create and run the brain */
- brain = dsync_brain_init(worker1, worker2, ctx->mailbox,
- ctx->brain_flags);
- if (ctx->remote_cmd_args == NULL)
- dsync_brain_sync_all(brain);
+ if (!ctx->lock)
+ ret = cmd_dsync_start(ctx, worker1, worker2);
else {
- dsync_brain_sync(brain);
- if (!dsync_brain_has_failed(brain))
- io_loop_run(current_ioloop);
+ lock_fd = dsync_lock(user, ctx->lock_timeout, &lock_path, &lock);
+ if (lock_fd == -1) {
+ _ctx->exit_code = EX_TEMPFAIL;
+ ret = -1;
+ } else {
+ ret = cmd_dsync_start(ctx, worker1, worker2);
+ file_lock_free(&lock);
+ if (close(lock_fd) < 0)
+ i_error("close(%s) failed: %m", lock_path);
+ }
}
- /* deinit */
- if (dsync_brain_has_unexpected_changes(brain)) {
- i_warning("Mailbox changes caused a desync. "
- "You may want to run dsync again.");
- _ctx->exit_code = 2;
- }
- if (dsync_brain_deinit(&brain) < 0) {
- _ctx->exit_code = EX_TEMPFAIL;
- ret = -1;
- }
-
dsync_worker_deinit(&worker1);
dsync_worker_deinit(&worker2);
return ret;
@@ -276,7 +341,7 @@
if ((_ctx->service_flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0 &&
_ctx->cur_username != NULL)
username = _ctx->cur_username;
- if (!mirror_get_remote_cmd(args, username, &ctx->remote_cmd_args)) {
+ if (!mirror_get_remote_cmd(ctx, args, username, &ctx->remote_cmd_args)) {
/* it's a mail_location */
if (args[1] != NULL)
doveadm_mail_help_name(_ctx->cmd->name);
@@ -312,6 +377,11 @@
case 'f':
ctx->brain_flags |= DSYNC_BRAIN_FLAG_FULL_SYNC;
break;
+ case 'l':
+ ctx->lock = TRUE;
+ if (str_to_uint(optarg, &ctx->lock_timeout) < 0)
+ i_error("Invalid -l parameter: %s", optarg);
+ break;
case 'm':
ctx->mailbox = optarg;
break;
@@ -329,7 +399,7 @@
struct dsync_cmd_context *ctx;
ctx = doveadm_mail_cmd_alloc(struct dsync_cmd_context);
- ctx->ctx.getopt_args = "+EfRm:";
+ ctx->ctx.getopt_args = "+Efl:m:R";
ctx->ctx.v.parse_arg = cmd_mailbox_dsync_parse_arg;
ctx->ctx.v.preinit = cmd_dsync_preinit;
ctx->ctx.v.init = cmd_dsync_init;
@@ -349,35 +419,58 @@
}
static int
-cmd_dsync_server_run(struct doveadm_mail_cmd_context *ctx,
+cmd_dsync_server_run(struct doveadm_mail_cmd_context *_ctx,
struct mail_user *user)
{
+ struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
struct dsync_proxy_server *server;
struct dsync_worker *worker;
+ struct file_lock *lock;
+ const char *lock_path;
+ int lock_fd, ret = 0;
user->admin = TRUE;
i_set_failure_prefix(t_strdup_printf("dsync-remote(%s): ",
user->username));
- worker = dsync_worker_init_local(user, *ctx->set->dsync_alt_char);
+ worker = dsync_worker_init_local(user, *_ctx->set->dsync_alt_char);
server = dsync_proxy_server_init(STDIN_FILENO, STDOUT_FILENO, worker);
- io_loop_run(current_ioloop);
+ if (!ctx->lock)
+ io_loop_run(current_ioloop);
+ else {
+ lock_fd = dsync_lock(user, ctx->lock_timeout, &lock_path, &lock);
+ if (lock_fd == -1) {
+ _ctx->exit_code = EX_TEMPFAIL;
+ ret = -1;
+ } else {
+ io_loop_run(current_ioloop);
+ file_lock_free(&lock);
+ if (close(lock_fd) < 0)
+ i_error("close(%s) failed: %m", lock_path);
+ }
+ }
dsync_proxy_server_deinit(&server);
dsync_worker_deinit(&worker);
- return 0;
+ return ret;
}
static bool
-cmd_mailbox_dsync_server_parse_arg(struct doveadm_mail_cmd_context *_ctx ATTR_UNUSED,
- int c)
+cmd_mailbox_dsync_server_parse_arg(struct doveadm_mail_cmd_context *_ctx, int c)
{
+ struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
+
switch (c) {
case 'E':
/* dsync wrapper detection flag */
legacy_dsync = TRUE;
break;
+ case 'l':
+ ctx->lock = TRUE;
+ if (str_to_uint(optarg, &ctx->lock_timeout) < 0)
+ i_error("Invalid -l parameter: %s", optarg);
+ break;
default:
return FALSE;
}
@@ -386,21 +479,21 @@
static struct doveadm_mail_cmd_context *cmd_dsync_server_alloc(void)
{
- struct doveadm_mail_cmd_context *ctx;
+ struct dsync_cmd_context *ctx;
- ctx = doveadm_mail_cmd_alloc(struct doveadm_mail_cmd_context);
- ctx->getopt_args = "E";
- ctx->v.parse_arg = cmd_mailbox_dsync_server_parse_arg;
- ctx->v.run = cmd_dsync_server_run;
- return ctx;
+ ctx = doveadm_mail_cmd_alloc(struct dsync_cmd_context);
+ ctx->ctx.getopt_args = "El:";
+ ctx->ctx.v.parse_arg = cmd_mailbox_dsync_server_parse_arg;
+ ctx->ctx.v.run = cmd_dsync_server_run;
+ return &ctx->ctx;
}
struct doveadm_mail_cmd cmd_dsync_mirror = {
- cmd_dsync_alloc, "sync", "[-fR] [-m <mailbox>] <dest>"
+ cmd_dsync_alloc, "sync", "[-fR] [-l <secs>] [-m <mailbox>] <dest>"
};
struct doveadm_mail_cmd cmd_dsync_backup = {
cmd_dsync_backup_alloc, "backup",
- "[-fR] [-m <mailbox>] <dest>"
+ "[-fR] [-l <secs>] [-m <mailbox>] <dest>"
};
struct doveadm_mail_cmd cmd_dsync_server = {
cmd_dsync_server_alloc, "dsync-server", &doveadm_mail_cmd_hide
More information about the dovecot-cvs
mailing list