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