dovecot-2.2: dsync: -l parameter locking is now done on the serv...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Feb 16 16:47:46 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/6f024e0289da
changeset: 15782:6f024e0289da
user: Timo Sirainen <tss at iki.fi>
date: Sat Feb 16 16:47:40 2013 +0200
description:
dsync: -l parameter locking is now done on the server with "lower" hostname.
This allows running multi-master replication on two servers without two
dsyncs mixing up changes by running at the same time.
diffstat:
src/doveadm/dsync/doveadm-dsync.c | 75 +---------------
src/doveadm/dsync/dsync-brain-private.h | 8 +
src/doveadm/dsync/dsync-brain.c | 135 ++++++++++++++++++++++++++++---
src/doveadm/dsync/dsync-brain.h | 2 +-
src/doveadm/dsync/dsync-ibc-stream.c | 22 ++++-
src/doveadm/dsync/dsync-ibc.h | 4 +
6 files changed, 161 insertions(+), 85 deletions(-)
diffs (truncated from 501 to 300 lines):
diff -r 5a3586ffc644 -r 6f024e0289da src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c Sat Feb 16 16:45:47 2013 +0200
+++ b/src/doveadm/dsync/doveadm-dsync.c Sat Feb 16 16:47:40 2013 +0200
@@ -30,7 +30,6 @@
#include <ctype.h>
#include <sys/wait.h>
-#define DSYNC_LOCK_FILENAME ".dovecot-sync.lock"
#define DSYNC_COMMON_GETOPT_ARGS "+adEfl:m:n:r:Rs:"
#define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30
@@ -165,14 +164,12 @@
}
static const char *const *
-get_ssh_cmd_args(struct dsync_cmd_context *ctx,
- const char *host, const char *login, const char *mail_user)
+get_ssh_cmd_args(const char *host, const char *login, const char *mail_user)
{
static struct var_expand_table static_tab[] = {
{ 'u', NULL, "user" },
{ '\0', NULL, "login" },
{ '\0', NULL, "host" },
- { '\0', NULL, "lock_timeout" },
{ '\0', NULL, NULL }
};
struct var_expand_table *tab;
@@ -186,7 +183,6 @@
tab[0].value = mail_user;
tab[1].value = login;
tab[2].value = host;
- tab[3].value = dec2str(ctx->lock_timeout);
t_array_init(&cmd_args, 8);
str = t_str_new(128);
@@ -255,7 +251,7 @@
/* we'll assume virtual users, so in user at host it really means not to
give ssh a username, but to give dsync -u user parameter. */
- *cmd_args_r = get_ssh_cmd_args(ctx, host, "", user);
+ *cmd_args_r = get_ssh_cmd_args(host, "", user);
return TRUE;
}
@@ -371,8 +367,7 @@
}
static const char *const *
-parse_ssh_location(struct dsync_cmd_context *ctx,
- const char *location, const char *username)
+parse_ssh_location(const char *location, const char *username)
{
const char *host, *login;
@@ -383,7 +378,7 @@
host = location;
login = "";
}
- return get_ssh_cmd_args(ctx, host, login, username);
+ return get_ssh_cmd_args(host, login, username);
}
static struct dsync_ibc *
@@ -404,8 +399,9 @@
}
static int
-cmd_dsync_run_real(struct dsync_cmd_context *ctx, struct mail_user *user)
+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_ibc *ibc, *ibc2 = NULL;
struct dsync_brain *brain;
struct mail_namespace *sync_ns = NULL;
@@ -445,6 +441,7 @@
brain_flags |= DSYNC_BRAIN_FLAG_DEBUG;
brain = dsync_brain_master_init(user, ibc, sync_ns, ctx->mailbox,
ctx->sync_type, brain_flags,
+ ctx->lock_timeout,
ctx->state_input == NULL ? "" :
ctx->state_input);
@@ -490,62 +487,6 @@
return ret;
}
-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_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
-{
- struct dsync_cmd_context *ctx = (struct dsync_cmd_context *)_ctx;
- const char *lock_path;
- struct file_lock *lock;
- int lock_fd, ret;
-
- if (!ctx->lock)
- return cmd_dsync_run_real(ctx, user);
-
- lock_fd = dsync_lock(user, ctx->lock_timeout, &lock_path, &lock);
- if (lock_fd == -1) {
- _ctx->exit_code = EX_TEMPFAIL;
- return -1;
- } else {
- ret = cmd_dsync_run_real(ctx, user);
- file_lock_free(&lock);
- if (close(lock_fd) < 0)
- i_error("close(%s) failed: %m", lock_path);
- return ret;
- }
-}
-
static int cmd_dsync_prerun(struct doveadm_mail_cmd_context *_ctx,
struct mail_storage_service_user *service_user,
const char **error_r)
@@ -599,7 +540,7 @@
ctx->remote_name = NULL;
}
remote_cmd_args = ctx->remote_name == NULL ? NULL :
- parse_ssh_location(ctx, ctx->remote_name,
+ parse_ssh_location(ctx->remote_name,
_ctx->cur_username);
}
diff -r 5a3586ffc644 -r 6f024e0289da src/doveadm/dsync/dsync-brain-private.h
--- a/src/doveadm/dsync/dsync-brain-private.h Sat Feb 16 16:45:47 2013 +0200
+++ b/src/doveadm/dsync/dsync-brain-private.h Sat Feb 16 16:47:40 2013 +0200
@@ -6,9 +6,12 @@
#include "dsync-mailbox.h"
#include "dsync-mailbox-state.h"
+#define DSYNC_LOCK_FILENAME ".dovecot-sync.lock"
+
struct dsync_mailbox_tree_sync_change;
enum dsync_state {
+ DSYNC_STATE_MASTER_RECV_HANDSHAKE,
DSYNC_STATE_SLAVE_RECV_HANDSHAKE,
/* if sync_type=STATE, the master brain knows the saved "last common
mailbox state". this state is sent to the slave. */
@@ -49,6 +52,11 @@
char *sync_box;
enum dsync_brain_sync_type sync_type;
+ unsigned int lock_timeout;
+ int lock_fd;
+ const char *lock_path;
+ struct file_lock *lock;
+
char hierarchy_sep;
struct dsync_mailbox_tree *local_mailbox_tree;
struct dsync_mailbox_tree *remote_mailbox_tree;
diff -r 5a3586ffc644 -r 6f024e0289da src/doveadm/dsync/dsync-brain.c
--- a/src/doveadm/dsync/dsync-brain.c Sat Feb 16 16:45:47 2013 +0200
+++ b/src/doveadm/dsync/dsync-brain.c Sat Feb 16 16:47:40 2013 +0200
@@ -3,11 +3,14 @@
#include "lib.h"
#include "array.h"
#include "hash.h"
+#include "hostpid.h"
#include "mail-namespace.h"
#include "dsync-mailbox-tree.h"
#include "dsync-ibc.h"
#include "dsync-brain-private.h"
+#include <sys/stat.h>
+
static const char *dsync_state_names[DSYNC_STATE_DONE+1] = {
"recv_handshake",
"send_last_common",
@@ -61,6 +64,7 @@
brain->user = user;
brain->ibc = ibc;
brain->sync_type = DSYNC_BRAIN_SYNC_TYPE_UNKNOWN;
+ brain->lock_fd = -1;
hash_table_create(&brain->mailbox_states, pool, 0,
guid_128_hash, guid_128_cmp);
p_array_init(&brain->remote_mailbox_states, pool, 64);
@@ -83,7 +87,7 @@
dsync_brain_master_init(struct mail_user *user, struct dsync_ibc *ibc,
struct mail_namespace *sync_ns, const char *sync_box,
enum dsync_brain_sync_type sync_type,
- enum dsync_brain_flags flags,
+ enum dsync_brain_flags flags, unsigned int lock_timeout,
const char *state)
{
struct dsync_ibc_settings ibc_set;
@@ -98,29 +102,26 @@
if (sync_ns != NULL)
brain->sync_ns = sync_ns;
brain->sync_box = p_strdup(brain->pool, sync_box);
+ brain->lock_timeout = lock_timeout;
brain->master_brain = TRUE;
dsync_brain_set_flags(brain, flags);
- brain->state = DSYNC_STATE_SEND_MAILBOX_TREE;
- if (sync_type == DSYNC_BRAIN_SYNC_TYPE_STATE) {
- if (dsync_mailbox_states_import(brain->mailbox_states,
- brain->pool, state,
- &error) < 0) {
- hash_table_clear(brain->mailbox_states, FALSE);
- i_error("Saved sync state is invalid, "
- "falling back to full sync: %s", error);
- brain->sync_type = sync_type =
- DSYNC_BRAIN_SYNC_TYPE_FULL;
- } else {
- brain->state = DSYNC_STATE_MASTER_SEND_LAST_COMMON;
- }
+ if (sync_type == DSYNC_BRAIN_SYNC_TYPE_STATE &&
+ dsync_mailbox_states_import(brain->mailbox_states,
+ brain->pool, state, &error) < 0) {
+ hash_table_clear(brain->mailbox_states, FALSE);
+ i_error("Saved sync state is invalid, "
+ "falling back to full sync: %s", error);
+ brain->sync_type = sync_type = DSYNC_BRAIN_SYNC_TYPE_FULL;
}
dsync_brain_mailbox_trees_init(brain);
memset(&ibc_set, 0, sizeof(ibc_set));
+ ibc_set.hostname = my_hostname;
ibc_set.sync_ns_prefix = sync_ns == NULL ? NULL : sync_ns->prefix;
ibc_set.sync_box = sync_box;
ibc_set.sync_type = sync_type;
+ ibc_set.lock_timeout = lock_timeout;
/* reverse the backup direction for the slave */
ibc_set.brain_flags = flags & ~(DSYNC_BRAIN_FLAG_BACKUP_SEND |
DSYNC_BRAIN_FLAG_BACKUP_RECV);
@@ -131,17 +132,23 @@
dsync_ibc_send_handshake(ibc, &ibc_set);
dsync_ibc_set_io_callback(ibc, dsync_brain_run_io, brain);
+ brain->state = DSYNC_STATE_MASTER_RECV_HANDSHAKE;
return brain;
}
struct dsync_brain *
dsync_brain_slave_init(struct mail_user *user, struct dsync_ibc *ibc)
{
+ struct dsync_ibc_settings ibc_set;
struct dsync_brain *brain;
brain = dsync_brain_common_init(user, ibc);
brain->state = DSYNC_STATE_SLAVE_RECV_HANDSHAKE;
+ memset(&ibc_set, 0, sizeof(ibc_set));
+ ibc_set.hostname = my_hostname;
+ dsync_ibc_send_handshake(ibc, &ibc_set);
+
dsync_ibc_set_io_callback(ibc, dsync_brain_run_io, brain);
return brain;
}
@@ -166,11 +173,102 @@
hash_table_iterate_deinit(&brain->mailbox_states_iter);
hash_table_destroy(&brain->mailbox_states);
+ if (brain->lock_fd != -1) {
+ /* unlink the lock file before it gets unlocked */
+ if (unlink(brain->lock_path) < 0)
+ i_error("unlink(%s) failed: %m", brain->lock_path);
+ file_lock_free(&brain->lock);
+ i_close_fd(&brain->lock_fd);
+ }
+
ret = brain->failed ? -1 : 0;
pool_unref(&brain->pool);
return ret;
}
+static int
+dsync_brain_lock(struct dsync_brain *brain, const char *remote_hostname)
More information about the dovecot-cvs
mailing list