doveadm-replicator.c (dovecot-2.3.16) | : | doveadm-replicator.c (dovecot-2.3.17) | ||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
#include "doveadm.h" | #include "doveadm.h" | |||
#include "doveadm-print.h" | #include "doveadm-print.h" | |||
#include <stdio.h> | #include <stdio.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include <fcntl.h> | #include <fcntl.h> | |||
struct replicator_context { | struct replicator_context { | |||
const char *socket_path; | const char *socket_path; | |||
const char *priority; | const char *priority; | |||
const char *user_mask, *username; | ||||
struct istream *input; | struct istream *input; | |||
bool full_sync; | bool full_sync; | |||
}; | }; | |||
extern struct doveadm_cmd doveadm_cmd_replicator[]; | extern struct doveadm_cmd_ver2 doveadm_cmd_replicator[]; | |||
static void replicator_cmd_help(doveadm_command_t *cmd) ATTR_NORETURN; | static void replicator_cmd_help(const struct doveadm_cmd_ver2 *cmd) ATTR_NORETUR N; | |||
static void | static void | |||
replicator_send(struct replicator_context *ctx, const char *data) | replicator_send(struct replicator_context *ctx, const char *data) | |||
{ | { | |||
if (write_full(i_stream_get_fd(ctx->input), data, strlen(data)) < 0) | if (write_full(i_stream_get_fd(ctx->input), data, strlen(data)) < 0) | |||
i_fatal("write(%s) failed: %m", ctx->socket_path); | i_fatal("write(%s) failed: %m", ctx->socket_path); | |||
} | } | |||
static void replicator_connect(struct replicator_context *ctx) | static void replicator_connect(struct replicator_context *ctx) | |||
{ | { | |||
skipping to change at line 76 | skipping to change at line 77 | |||
static void replicator_disconnect(struct replicator_context *ctx) | static void replicator_disconnect(struct replicator_context *ctx) | |||
{ | { | |||
if (ctx->input->stream_errno != 0) { | if (ctx->input->stream_errno != 0) { | |||
i_fatal("read(%s) failed: %s", ctx->socket_path, | i_fatal("read(%s) failed: %s", ctx->socket_path, | |||
i_stream_get_error(ctx->input)); | i_stream_get_error(ctx->input)); | |||
} | } | |||
i_stream_destroy(&ctx->input); | i_stream_destroy(&ctx->input); | |||
} | } | |||
static struct replicator_context * | static struct replicator_context * | |||
cmd_replicator_init(int *argc, char **argv[], const char *getopt_args, | cmd_replicator_init(struct doveadm_cmd_context *cctx) | |||
doveadm_command_t *cmd) | ||||
{ | { | |||
struct replicator_context *ctx; | struct replicator_context *ctx; | |||
int c; | ||||
ctx = t_new(struct replicator_context, 1); | ctx = t_new(struct replicator_context, 1); | |||
ctx->socket_path = t_strconcat(doveadm_settings->base_dir, | ctx->socket_path = t_strconcat(doveadm_settings->base_dir, | |||
"/replicator-doveadm", NULL); | "/replicator-doveadm", NULL); | |||
while ((c = getopt(*argc, *argv, getopt_args)) > 0) { | (void)doveadm_cmd_param_str(cctx, "socket-path", &ctx->socket_path); | |||
switch (c) { | (void)doveadm_cmd_param_bool(cctx, "full-sync", &ctx->full_sync); | |||
case 'a': | (void)doveadm_cmd_param_str(cctx, "priority", &ctx->priority); | |||
ctx->socket_path = optarg; | (void)doveadm_cmd_param_str(cctx, "user-mask", &ctx->user_mask); | |||
break; | (void)doveadm_cmd_param_str(cctx, "user", &ctx->username); | |||
case 'f': | ||||
ctx->full_sync = TRUE; | ||||
break; | ||||
case 'p': | ||||
ctx->priority = optarg; | ||||
break; | ||||
default: | ||||
replicator_cmd_help(cmd); | ||||
} | ||||
} | ||||
*argc -= optind-1; | ||||
*argv += optind-1; | ||||
replicator_connect(ctx); | replicator_connect(ctx); | |||
return ctx; | return ctx; | |||
} | } | |||
static const char *time_ago(time_t t) | static const char *time_ago(time_t t) | |||
{ | { | |||
int diff = ioloop_time - t; | int diff = ioloop_time - t; | |||
if (t == 0) | if (t == 0) | |||
return "-"; | return "-"; | |||
skipping to change at line 142 | skipping to change at line 130 | |||
if (value != NULL) | if (value != NULL) | |||
*value++ = '\0'; | *value++ = '\0'; | |||
else | else | |||
value = ""; | value = ""; | |||
doveadm_print(line); | doveadm_print(line); | |||
doveadm_print(value); | doveadm_print(value); | |||
} | } | |||
replicator_disconnect(ctx); | replicator_disconnect(ctx); | |||
} | } | |||
static void cmd_replicator_status(int argc, char *argv[]) | static void cmd_replicator_status(struct doveadm_cmd_context *cctx) | |||
{ | { | |||
struct replicator_context *ctx; | struct replicator_context *ctx; | |||
const char *line, *const *args; | const char *line, *const *args; | |||
time_t last_fast, last_full, last_success; | time_t last_fast, last_full, last_success; | |||
ctx = cmd_replicator_init(&argc, &argv, "a:", cmd_replicator_status); | ctx = cmd_replicator_init(cctx); | |||
if (ctx->user_mask == NULL) { | ||||
if (argv[1] == NULL) { | cmd_replicator_status_overview(ctx); | |||
cmd_replicator_status_overview(ctx); | ||||
return; | return; | |||
} | } | |||
doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); | doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); | |||
doveadm_print_header("username", "username", | doveadm_print_header("username", "username", | |||
DOVEADM_PRINT_HEADER_FLAG_EXPAND); | DOVEADM_PRINT_HEADER_FLAG_EXPAND); | |||
doveadm_print_header_simple("priority"); | doveadm_print_header_simple("priority"); | |||
doveadm_print_header_simple("fast sync"); | doveadm_print_header_simple("fast sync"); | |||
doveadm_print_header_simple("full sync"); | doveadm_print_header_simple("full sync"); | |||
doveadm_print_header_simple("success sync"); | doveadm_print_header_simple("success sync"); | |||
doveadm_print_header_simple("failed"); | doveadm_print_header_simple("failed"); | |||
replicator_send(ctx, t_strdup_printf("STATUS\t%s\n", | replicator_send(ctx, t_strdup_printf("STATUS\t%s\n", | |||
str_tabescape(argv[1]))); | str_tabescape(ctx->user_mask))); | |||
while ((line = i_stream_read_next_line(ctx->input)) != NULL) { | while ((line = i_stream_read_next_line(ctx->input)) != NULL) { | |||
if (*line == '\0') | if (*line == '\0') | |||
break; | break; | |||
T_BEGIN { | T_BEGIN { | |||
args = t_strsplit_tabescaped(line); | args = t_strsplit_tabescaped(line); | |||
if (str_array_length(args) >= 5 && | if (str_array_length(args) >= 5 && | |||
str_to_time(args[2], &last_fast) == 0 && | str_to_time(args[2], &last_fast) == 0 && | |||
str_to_time(args[3], &last_full) == 0 && | str_to_time(args[3], &last_full) == 0 && | |||
str_to_time(args[5], &last_success) == 0) { | str_to_time(args[5], &last_success) == 0) { | |||
doveadm_print(args[0]); | doveadm_print(args[0]); | |||
skipping to change at line 191 | skipping to change at line 178 | |||
} | } | |||
} T_END; | } T_END; | |||
} | } | |||
if (line == NULL) { | if (line == NULL) { | |||
i_error("Replicator disconnected unexpectedly"); | i_error("Replicator disconnected unexpectedly"); | |||
doveadm_exit_code = EX_TEMPFAIL; | doveadm_exit_code = EX_TEMPFAIL; | |||
} | } | |||
replicator_disconnect(ctx); | replicator_disconnect(ctx); | |||
} | } | |||
static void cmd_replicator_dsync_status(int argc, char *argv[]) | static void cmd_replicator_dsync_status(struct doveadm_cmd_context *cctx) | |||
{ | { | |||
struct replicator_context *ctx; | struct replicator_context *ctx; | |||
const char *line; | const char *line; | |||
unsigned int i; | unsigned int i; | |||
ctx = cmd_replicator_init(&argc, &argv, "a:", cmd_replicator_dsync_status ); | ctx = cmd_replicator_init(cctx); | |||
doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); | doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE); | |||
doveadm_print_header("username", "username", | doveadm_print_header("username", "username", | |||
DOVEADM_PRINT_HEADER_FLAG_EXPAND); | DOVEADM_PRINT_HEADER_FLAG_EXPAND); | |||
doveadm_print_header_simple("type"); | doveadm_print_header_simple("type"); | |||
doveadm_print_header_simple("status"); | doveadm_print_header_simple("status"); | |||
replicator_send(ctx, "STATUS-DSYNC\n"); | replicator_send(ctx, "STATUS-DSYNC\n"); | |||
while ((line = i_stream_read_next_line(ctx->input)) != NULL) { | while ((line = i_stream_read_next_line(ctx->input)) != NULL) { | |||
if (*line == '\0') | if (*line == '\0') | |||
skipping to change at line 224 | skipping to change at line 211 | |||
break; | break; | |||
doveadm_print(args[i]); | doveadm_print(args[i]); | |||
} | } | |||
for (; i < 3; i++) | for (; i < 3; i++) | |||
doveadm_print(""); | doveadm_print(""); | |||
} T_END; | } T_END; | |||
} | } | |||
replicator_disconnect(ctx); | replicator_disconnect(ctx); | |||
} | } | |||
static void cmd_replicator_replicate(int argc, char *argv[]) | static void cmd_replicator_replicate(struct doveadm_cmd_context *cctx) | |||
{ | { | |||
struct replicator_context *ctx; | struct replicator_context *ctx; | |||
string_t *str; | string_t *str; | |||
const char *line; | const char *line; | |||
if (argv[1] == NULL) | ctx = cmd_replicator_init(cctx); | |||
replicator_cmd_help(cmd_replicator_replicate); | if (ctx->user_mask == NULL) | |||
replicator_cmd_help(cctx->cmd); | ||||
ctx = cmd_replicator_init(&argc, &argv, "a:fp:", cmd_replicator_replicate | ||||
); | ||||
str = t_str_new(128); | str = t_str_new(128); | |||
str_append(str, "REPLICATE\t"); | str_append(str, "REPLICATE\t"); | |||
if (ctx->priority == NULL) | if (ctx->priority == NULL) | |||
str_append_tabescaped(str, "low"); | str_append_tabescaped(str, "low"); | |||
else | else | |||
str_append_tabescaped(str, ctx->priority); | str_append_tabescaped(str, ctx->priority); | |||
str_append_c(str, '\t'); | str_append_c(str, '\t'); | |||
if (ctx->full_sync) | if (ctx->full_sync) | |||
str_append_c(str, 'f'); | str_append_c(str, 'f'); | |||
str_append_c(str, '\t'); | str_append_c(str, '\t'); | |||
str_append_tabescaped(str, argv[1]); | str_append_tabescaped(str, ctx->user_mask); | |||
str_append_c(str, '\n'); | str_append_c(str, '\n'); | |||
replicator_send(ctx, str_c(str)); | replicator_send(ctx, str_c(str)); | |||
doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); | doveadm_print_init(DOVEADM_PRINT_TYPE_FLOW); | |||
doveadm_print_header("result", "result", | doveadm_print_header("result", "result", | |||
DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); | DOVEADM_PRINT_HEADER_FLAG_HIDE_TITLE); | |||
line = i_stream_read_next_line(ctx->input); | line = i_stream_read_next_line(ctx->input); | |||
if (line == NULL) { | if (line == NULL) { | |||
i_error("Replicator disconnected unexpectedly"); | i_error("Replicator disconnected unexpectedly"); | |||
doveadm_exit_code = EX_TEMPFAIL; | doveadm_exit_code = EX_TEMPFAIL; | |||
} else if (line[0] != '+') { | } else if (line[0] != '+') { | |||
i_error("Replicator failed: %s", line+1); | i_error("Replicator failed: %s", line+1); | |||
doveadm_exit_code = EX_USAGE; | doveadm_exit_code = EX_USAGE; | |||
} else { | } else { | |||
doveadm_print(t_strdup_printf("%s users updated", line+1)); | doveadm_print(t_strdup_printf("%s users updated", line+1)); | |||
} | } | |||
replicator_disconnect(ctx); | replicator_disconnect(ctx); | |||
} | } | |||
static void cmd_replicator_add(int argc, char *argv[]) | static void cmd_replicator_add(struct doveadm_cmd_context *cctx) | |||
{ | { | |||
struct replicator_context *ctx; | struct replicator_context *ctx; | |||
string_t *str; | string_t *str; | |||
const char *line; | const char *line; | |||
if (argv[1] == NULL) | ctx = cmd_replicator_init(cctx); | |||
replicator_cmd_help(cmd_replicator_add); | if (ctx->user_mask == NULL) | |||
replicator_cmd_help(cctx->cmd); | ||||
ctx = cmd_replicator_init(&argc, &argv, "a:", cmd_replicator_add); | ||||
str = t_str_new(128); | str = t_str_new(128); | |||
str_append(str, "ADD\t"); | str_append(str, "ADD\t"); | |||
str_append_tabescaped(str, argv[1]); | str_append_tabescaped(str, ctx->user_mask); | |||
str_append_c(str, '\n'); | str_append_c(str, '\n'); | |||
replicator_send(ctx, str_c(str)); | replicator_send(ctx, str_c(str)); | |||
line = i_stream_read_next_line(ctx->input); | line = i_stream_read_next_line(ctx->input); | |||
if (line == NULL) { | if (line == NULL) { | |||
i_error("Replicator disconnected unexpectedly"); | i_error("Replicator disconnected unexpectedly"); | |||
doveadm_exit_code = EX_TEMPFAIL; | doveadm_exit_code = EX_TEMPFAIL; | |||
} else if (line[0] != '+') { | } else if (line[0] != '+') { | |||
i_error("Replicator failed: %s", line+1); | i_error("Replicator failed: %s", line+1); | |||
doveadm_exit_code = EX_USAGE; | doveadm_exit_code = EX_USAGE; | |||
} | } | |||
replicator_disconnect(ctx); | replicator_disconnect(ctx); | |||
} | } | |||
static void cmd_replicator_remove(int argc, char *argv[]) | static void cmd_replicator_remove(struct doveadm_cmd_context *cctx) | |||
{ | { | |||
struct replicator_context *ctx; | struct replicator_context *ctx; | |||
string_t *str; | string_t *str; | |||
const char *line; | const char *line; | |||
if (argv[1] == NULL) | ctx = cmd_replicator_init(cctx); | |||
replicator_cmd_help(cmd_replicator_remove); | if (ctx->username == NULL) | |||
replicator_cmd_help(cctx->cmd); | ||||
ctx = cmd_replicator_init(&argc, &argv, "a:", cmd_replicator_remove); | ||||
str = t_str_new(128); | str = t_str_new(128); | |||
str_append(str, "REMOVE\t"); | str_append(str, "REMOVE\t"); | |||
str_append_tabescaped(str, argv[1]); | str_append_tabescaped(str, ctx->username); | |||
str_append_c(str, '\n'); | str_append_c(str, '\n'); | |||
replicator_send(ctx, str_c(str)); | replicator_send(ctx, str_c(str)); | |||
line = i_stream_read_next_line(ctx->input); | line = i_stream_read_next_line(ctx->input); | |||
if (line == NULL) { | if (line == NULL) { | |||
i_error("Replicator disconnected unexpectedly"); | i_error("Replicator disconnected unexpectedly"); | |||
doveadm_exit_code = EX_TEMPFAIL; | doveadm_exit_code = EX_TEMPFAIL; | |||
} else if (line[0] != '+') { | } else if (line[0] != '+') { | |||
i_error("Replicator failed: %s", line+1); | i_error("Replicator failed: %s", line+1); | |||
doveadm_exit_code = EX_USAGE; | doveadm_exit_code = EX_USAGE; | |||
} | } | |||
replicator_disconnect(ctx); | replicator_disconnect(ctx); | |||
} | } | |||
struct doveadm_cmd doveadm_cmd_replicator[] = { | struct doveadm_cmd_ver2 doveadm_cmd_replicator[] = { | |||
{ cmd_replicator_status, "replicator status", | { | |||
"[-a <replicator socket path>] [<user mask>]" }, | .name = "replicator status", | |||
{ cmd_replicator_dsync_status, "replicator dsync-status", | .cmd = cmd_replicator_status, | |||
"[-a <replicator socket path>]" }, | .usage = "[-a <replicator socket path>] [<user mask>]", | |||
{ cmd_replicator_replicate, "replicator replicate", | DOVEADM_CMD_PARAMS_START | |||
"[-a <replicator socket path>] [-f] [-p <priority>] <user mask>" }, | DOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0) | |||
{ cmd_replicator_add, "replicator add", | DOVEADM_CMD_PARAM('\0', "user-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) | |||
"[-a <replicator socket path>] <user mask>" }, | DOVEADM_CMD_PARAMS_END | |||
{ cmd_replicator_remove, "replicator remove", | }, | |||
"[-a <replicator socket path>] <username>" }, | { | |||
.name = "replicator dsync-status", | ||||
.cmd = cmd_replicator_dsync_status, | ||||
.usage = "[-a <replicator socket path>]", | ||||
DOVEADM_CMD_PARAMS_START | ||||
DOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0) | ||||
DOVEADM_CMD_PARAMS_END | ||||
}, | ||||
{ | ||||
.name = "replicator replicate", | ||||
.cmd = cmd_replicator_replicate, | ||||
.usage = "[-a <replicator socket path>] [-f] [-p <priority>] <user mask>" | ||||
, | ||||
DOVEADM_CMD_PARAMS_START | ||||
DOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0) | ||||
DOVEADM_CMD_PARAM('f', "full-sync", CMD_PARAM_BOOL, 0) | ||||
DOVEADM_CMD_PARAM('p', "priority", CMD_PARAM_STR, 0) | ||||
DOVEADM_CMD_PARAM('\0', "user-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) | ||||
DOVEADM_CMD_PARAMS_END | ||||
}, | ||||
{ | ||||
.name = "replicator add", | ||||
.cmd = cmd_replicator_add, | ||||
.usage = "[-a <replicator socket path>] <user mask>", | ||||
DOVEADM_CMD_PARAMS_START | ||||
DOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0) | ||||
DOVEADM_CMD_PARAM('\0', "user-mask", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) | ||||
DOVEADM_CMD_PARAMS_END | ||||
}, | ||||
{ | ||||
.name = "replicator remove", | ||||
.cmd = cmd_replicator_remove, | ||||
.usage = "[-a <replicator socket path>] <username>", | ||||
DOVEADM_CMD_PARAMS_START | ||||
DOVEADM_CMD_PARAM('a', "socket-path", CMD_PARAM_STR, 0) | ||||
DOVEADM_CMD_PARAM('\0', "user", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL) | ||||
DOVEADM_CMD_PARAMS_END | ||||
}, | ||||
}; | }; | |||
static void replicator_cmd_help(doveadm_command_t *cmd) | static void replicator_cmd_help(const struct doveadm_cmd_ver2 *cmd) | |||
{ | { | |||
unsigned int i; | unsigned int i; | |||
for (i = 0; i < N_ELEMENTS(doveadm_cmd_replicator); i++) { | for (i = 0; i < N_ELEMENTS(doveadm_cmd_replicator); i++) { | |||
if (doveadm_cmd_replicator[i].cmd == cmd) | if (doveadm_cmd_replicator[i].cmd == cmd->cmd) | |||
help(&doveadm_cmd_replicator[i]); | help_ver2(&doveadm_cmd_replicator[i]); | |||
} | } | |||
i_unreached(); | i_unreached(); | |||
} | } | |||
void doveadm_register_replicator_commands(void) | void doveadm_register_replicator_commands(void) | |||
{ | { | |||
unsigned int i; | unsigned int i; | |||
for (i = 0; i < N_ELEMENTS(doveadm_cmd_replicator); i++) | for (i = 0; i < N_ELEMENTS(doveadm_cmd_replicator); i++) | |||
doveadm_register_cmd(&doveadm_cmd_replicator[i]); | doveadm_cmd_register_ver2(&doveadm_cmd_replicator[i]); | |||
} | } | |||
End of changes. 24 change blocks. | ||||
64 lines changed or deleted | 84 lines changed or added |