dovecot-2.2: dsync: Added tcp:host[:port] target for syncing via...
dovecot at dovecot.org
dovecot at dovecot.org
Sun Feb 24 19:39:58 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/08edb5716823
changeset: 15924:08edb5716823
user: Timo Sirainen <tss at iki.fi>
date: Sun Feb 24 19:39:52 2013 +0200
description:
dsync: Added tcp:host[:port] target for syncing via doveadm-server.
diffstat:
src/doveadm/client-connection.c | 16 +---
src/doveadm/client-connection.h | 16 +++
src/doveadm/doveadm-mail.h | 2 +
src/doveadm/dsync/doveadm-dsync.c | 175 ++++++++++++++++++++++++++++++++-----
src/doveadm/server-connection.c | 5 +
src/doveadm/server-connection.h | 2 +
6 files changed, 175 insertions(+), 41 deletions(-)
diffs (truncated from 389 to 300 lines):
diff -r 8e54e73bdade -r 08edb5716823 src/doveadm/client-connection.c
--- a/src/doveadm/client-connection.c Sun Feb 24 19:38:27 2013 +0200
+++ b/src/doveadm/client-connection.c Sun Feb 24 19:39:52 2013 +0200
@@ -23,20 +23,6 @@
static void client_connection_input(struct client_connection *conn);
-struct client_connection {
- pool_t pool;
-
- int fd;
- struct io *io;
- struct istream *input;
- struct ostream *output;
- struct ip_addr local_ip, remote_ip;
- const struct doveadm_settings *set;
-
- unsigned int handshaked:1;
- unsigned int authenticated:1;
-};
-
static struct doveadm_mail_cmd_context *
doveadm_mail_cmd_server_parse(const char *cmd_name,
const struct doveadm_settings *set,
@@ -119,6 +105,8 @@
const char *error;
int ret;
+ ctx->conn = conn;
+
if (ctx->v.preinit != NULL)
ctx->v.preinit(ctx);
diff -r 8e54e73bdade -r 08edb5716823 src/doveadm/client-connection.h
--- a/src/doveadm/client-connection.h Sun Feb 24 19:38:27 2013 +0200
+++ b/src/doveadm/client-connection.h Sun Feb 24 19:39:52 2013 +0200
@@ -1,6 +1,22 @@
#ifndef CLIENT_CONNECTION_H
#define CLIENT_CONNECTION_H
+#include "net.h"
+
+struct client_connection {
+ pool_t pool;
+
+ int fd;
+ struct io *io;
+ struct istream *input;
+ struct ostream *output;
+ struct ip_addr local_ip, remote_ip;
+ const struct doveadm_settings *set;
+
+ unsigned int handshaked:1;
+ unsigned int authenticated:1;
+};
+
struct client_connection *client_connection_create(int fd, int listen_fd);
void client_connection_destroy(struct client_connection **conn);
diff -r 8e54e73bdade -r 08edb5716823 src/doveadm/doveadm-mail.h
--- a/src/doveadm/doveadm-mail.h Sun Feb 24 19:38:27 2013 +0200
+++ b/src/doveadm/doveadm-mail.h Sun Feb 24 19:39:52 2013 +0200
@@ -43,6 +43,8 @@
const char *const *args;
/* args including -options */
const char *const *full_args;
+ /* connection via doveadm-server */
+ struct client_connection *conn;
const char *getopt_args;
const struct doveadm_settings *set;
diff -r 8e54e73bdade -r 08edb5716823 src/doveadm/dsync/doveadm-dsync.c
--- a/src/doveadm/dsync/doveadm-dsync.c Sun Feb 24 19:38:27 2013 +0200
+++ b/src/doveadm/dsync/doveadm-dsync.c Sun Feb 24 19:39:52 2013 +0200
@@ -10,6 +10,7 @@
#include "iostream-rawlog.h"
#include "write-full.h"
#include "str.h"
+#include "strescape.h"
#include "var-expand.h"
#include "settings-parser.h"
#include "master-service.h"
@@ -20,6 +21,9 @@
#include "doveadm-settings.h"
#include "doveadm-mail.h"
#include "doveadm-print.h"
+#include "doveadm-server.h"
+#include "client-connection.h"
+#include "server-connection.h"
#include "dsync-brain.h"
#include "dsync-ibc.h"
#include "doveadm-dsync.h"
@@ -33,6 +37,12 @@
#define DSYNC_COMMON_GETOPT_ARGS "+dEfl:m:n:Nr:Rs:"
#define DSYNC_REMOTE_CMD_EXIT_WAIT_SECS 30
+enum dsync_run_type {
+ DSYNC_RUN_TYPE_LOCAL,
+ DSYNC_RUN_TYPE_STREAM,
+ DSYNC_RUN_TYPE_CMD
+};
+
struct dsync_cmd_context {
struct doveadm_mail_cmd_context ctx;
enum dsync_brain_sync_type sync_type;
@@ -47,6 +57,10 @@
struct io *io_err;
struct istream *err_stream;
+ enum dsync_run_type run_type;
+ struct server_connection *tcp_conn;
+ const char *error;
+
unsigned int lock_timeout;
unsigned int lock:1;
@@ -54,7 +68,6 @@
unsigned int default_replica_location:1;
unsigned int backup:1;
unsigned int reverse_backup:1;
- unsigned int remote:1;
unsigned int remote_user_prefix:1;
};
@@ -423,15 +436,17 @@
ctx->namespace_prefix);
}
- if (!ctx->remote)
+ if (ctx->run_type == DSYNC_RUN_TYPE_LOCAL)
dsync_ibc_init_pipe(&ibc, &ibc2);
else {
string_t *temp_prefix = t_str_new(64);
mail_user_set_get_temp_prefix(temp_prefix, user->set);
ibc = cmd_dsync_icb_stream_init(ctx, ctx->remote_name,
str_c(temp_prefix));
- ctx->io_err = io_add(ctx->fd_err, IO_READ,
- remote_error_input, ctx);
+ if (ctx->fd_err != -1) {
+ ctx->io_err = io_add(ctx->fd_err, IO_READ,
+ remote_error_input, ctx);
+ }
}
brain_flags = DSYNC_BRAIN_FLAG_SEND_MAIL_REQUESTS;
@@ -451,7 +466,7 @@
ctx->state_input == NULL ? "" :
ctx->state_input);
- if (!ctx->remote) {
+ if (ctx->run_type == DSYNC_RUN_TYPE_LOCAL) {
if (cmd_dsync_run_local(ctx, user, brain, ibc2) < 0)
ret = -1;
} else {
@@ -474,7 +489,7 @@
i_close_fd(&ctx->fd_out);
i_close_fd(&ctx->fd_in);
}
- if (ctx->remote)
+ if (ctx->run_type == DSYNC_RUN_TYPE_CMD)
cmd_dsync_wait_remote(ctx, &status);
/* print any final errors after the process has died. not closing
@@ -486,7 +501,7 @@
remote_errors_logged = ctx->err_stream->v_offset > 0;
i_stream_destroy(&ctx->err_stream);
}
- if (ctx->remote)
+ if (ctx->run_type == DSYNC_RUN_TYPE_CMD)
cmd_dsync_log_remote_status(status, remote_errors_logged);
if (ctx->io_err != NULL)
io_remove(&ctx->io_err);
@@ -495,6 +510,109 @@
return ret;
}
+static void dsync_connected_callback(enum server_cmd_reply reply, void *context)
+{
+ struct dsync_cmd_context *ctx = context;
+
+ switch (reply) {
+ case SERVER_CMD_REPLY_UNKNOWN_USER:
+ ctx->error = "Unknown user in remote";
+ ctx->ctx.exit_code = EX_NOUSER;
+ break;
+ case SERVER_CMD_REPLY_FAIL:
+ ctx->error = "Failed to start dsync-server command";
+ break;
+ case SERVER_CMD_REPLY_OK:
+ ctx->fd_in = ctx->fd_out =
+ dup(server_connection_get_fd(ctx->tcp_conn));
+ if (ctx->fd_in == -1)
+ ctx->error = t_strdup_printf("dup() failed: %m");
+ break;
+ case SERVER_CMD_REPLY_INTERNAL_FAILURE:
+ ctx->error = "Disconnected from remote";
+ break;
+ default:
+ i_unreached();
+ }
+ io_loop_stop(current_ioloop);
+}
+
+static int dsync_connect_tcp(struct dsync_cmd_context *ctx, const char *target,
+ const char **error_r)
+{
+ struct doveadm_server *server;
+ struct server_connection *conn;
+ struct ioloop *ioloop;
+ string_t *cmd;
+
+ server = p_new(ctx->ctx.pool, struct doveadm_server, 1);
+ server->name = p_strdup(ctx->ctx.pool, target);
+ p_array_init(&server->connections, ctx->ctx.pool, 1);
+ p_array_init(&server->queue, ctx->ctx.pool, 1);
+
+ ioloop = io_loop_create();
+
+ if (server_connection_create(server, &conn) < 0) {
+ *error_r = "Couldn't create server connection";
+ return -1;
+ }
+
+ /* <flags> <username> <command> [<args>] */
+ cmd = t_str_new(256);
+ if (doveadm_debug)
+ str_append_c(cmd, 'D');
+ str_append_c(cmd, '\t');
+ str_append_tabescaped(cmd, ctx->ctx.cur_username);
+ str_append(cmd, "\tdsync-server\t-u");
+ str_append_tabescaped(cmd, ctx->ctx.cur_username);
+ str_append_c(cmd, '\n');
+
+ ctx->tcp_conn = conn;
+ server_connection_cmd(conn, str_c(cmd),
+ dsync_connected_callback, ctx);
+ io_loop_run(ioloop);
+ ctx->tcp_conn = NULL;
+
+ if (array_count(&server->connections) > 0)
+ server_connection_destroy(&conn);
+ io_loop_destroy(&ioloop);
+
+ if (ctx->error != NULL) {
+ *error_r = ctx->error;
+ return -1;
+ }
+ ctx->run_type = DSYNC_RUN_TYPE_STREAM;
+ return 0;
+}
+
+static int
+parse_location(struct dsync_cmd_context *ctx, const char *location,
+ const char *const **remote_cmd_args_r, const char **error_r)
+{
+ if (strncmp(location, "tcp:", 4) == 0) {
+ /* TCP connection to remote dsync */
+ ctx->remote_name = location+4;
+ return dsync_connect_tcp(ctx, ctx->remote_name, error_r);
+ }
+
+ if (strncmp(location, "remote:", 7) == 0) {
+ /* this is a remote (ssh) command */
+ ctx->remote_name = location+7;
+ } else if (strncmp(location, "remoteprefix:", 13) == 0) {
+ /* this is a remote (ssh) command with a "user\n"
+ prefix sent before dsync actually starts */
+ ctx->remote_name = location+13;
+ ctx->remote_user_prefix = TRUE;
+ } else {
+ /* local with e.g. maildir:path */
+ ctx->remote_name = NULL;
+ return 0;
+ }
+ *remote_cmd_args_r =
+ parse_ssh_location(ctx->remote_name, ctx->ctx.cur_username);
+ return 0;
+}
+
static int cmd_dsync_prerun(struct doveadm_mail_cmd_context *_ctx,
struct mail_storage_service_user *service_user,
const char **error_r)
@@ -509,7 +627,7 @@
ctx->fd_in = STDIN_FILENO;
ctx->fd_out = STDOUT_FILENO;
ctx->fd_err = -1;
- ctx->remote = FALSE;
+ ctx->run_type = DSYNC_RUN_TYPE_LOCAL;
ctx->remote_name = "remote";
if (ctx->default_replica_location) {
@@ -536,29 +654,20 @@
}
if (remote_cmd_args == NULL && ctx->local_location != NULL) {
- if (strncmp(ctx->local_location, "remote:", 7) == 0) {
- /* this is a remote (ssh) command */
- ctx->remote_name = ctx->local_location+7;
- } else if (strncmp(ctx->local_location, "remoteprefix:", 13) == 0) {
- /* this is a remote (ssh) command with a "user\n"
More information about the dovecot-cvs
mailing list