From 5e9bb72de1209cd39fdf3e95bdb26e047cc5594e Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Thu, 20 May 2010 13:35:38 +0200 Subject: [PATCH] Added doveadm director flush command for dropping user associations from memory. This should probably mainly be used for testing. --HG-- branch : HEAD --- src/director/director-connection.c | 21 ++++++++++ src/director/director.c | 8 ++++ src/director/director.h | 2 + src/director/doveadm-connection.c | 66 +++++++++++++++++++++++++----- src/doveadm/doveadm-director.c | 65 ++++++++++++++++++++++++++++- 5 files changed, 151 insertions(+), 11 deletions(-) diff --git a/src/director/director-connection.c b/src/director/director-connection.c index a416c98cf4..5de7be91c4 100644 --- a/src/director/director-connection.c +++ b/src/director/director-connection.c @@ -317,6 +317,25 @@ director_cmd_host_remove(struct director_connection *conn, return TRUE; } +static bool +director_cmd_host_flush(struct director_connection *conn, + const char *const *args) +{ + struct mail_host *host; + struct ip_addr ip; + + if (str_array_length(args) != 1 || + net_addr2ip(args[0], &ip) < 0) { + i_error("director(%s): Invalid HOST-FLUSH args", conn->name); + return FALSE; + } + + host = mail_host_lookup(conn->dir->mail_hosts, &ip); + if (host != NULL) + director_flush_host(conn->dir, conn->host, host); + return TRUE; +} + static void director_handshake_cmd_done(struct director_connection *conn) { struct director *dir = conn->dir; @@ -513,6 +532,8 @@ director_connection_handle_line(struct director_connection *conn, return director_cmd_host(conn, args); if (strcmp(cmd, "HOST-REMOVE") == 0) return director_cmd_host_remove(conn, args); + if (strcmp(cmd, "HOST-FLUSH") == 0) + return director_cmd_host_flush(conn, args); if (strcmp(cmd, "DIRECTOR") == 0) return director_cmd_director(conn, args); if (strcmp(cmd, "SYNC") == 0) diff --git a/src/director/director.c b/src/director/director.c index d938e9da94..9a19eaacbf 100644 --- a/src/director/director.c +++ b/src/director/director.c @@ -150,6 +150,14 @@ void director_remove_host(struct director *dir, struct director_host *src, mail_host_remove(dir->mail_hosts, host); } +void director_flush_host(struct director *dir, struct director_host *src, + struct mail_host *host) +{ + director_update_send(dir, src, t_strdup_printf( + "HOST-FLUSH\t%s\n", net_ip2addr(&host->ip))); + user_directory_remove_host(dir->users, host); +} + void director_update_user(struct director *dir, struct director_host *src, struct user *user) { diff --git a/src/director/director.h b/src/director/director.h index fcfd19960f..dd65931fd5 100644 --- a/src/director/director.h +++ b/src/director/director.h @@ -81,6 +81,8 @@ void director_update_host(struct director *dir, struct director_host *src, struct mail_host *host); void director_remove_host(struct director *dir, struct director_host *src, struct mail_host *host); +void director_flush_host(struct director *dir, struct director_host *src, + struct mail_host *host); void director_update_user(struct director *dir, struct director_host *src, struct user *user); diff --git a/src/director/doveadm-connection.c b/src/director/doveadm-connection.c index 28f8d7e52a..6ee4c15092 100644 --- a/src/director/doveadm-connection.c +++ b/src/director/doveadm-connection.c @@ -103,7 +103,7 @@ doveadm_cmd_host_remove(struct doveadm_connection *conn, const char *line) struct ip_addr ip; if (net_addr2ip(line, &ip) < 0) { - i_error("doveadm sent invalid HOST-SET parameters"); + i_error("doveadm sent invalid HOST-REMOVE parameters"); return FALSE; } host = mail_host_lookup(conn->dir->mail_hosts, &ip); @@ -116,6 +116,41 @@ doveadm_cmd_host_remove(struct doveadm_connection *conn, const char *line) return TRUE; } +static void +doveadm_cmd_host_flush_all(struct doveadm_connection *conn) +{ + struct mail_host *const *hostp; + + array_foreach(mail_hosts_get(conn->dir->mail_hosts), hostp) + director_flush_host(conn->dir, conn->dir->self_host, *hostp); + o_stream_send(conn->output, "OK\n", 3); +} + +static bool +doveadm_cmd_host_flush(struct doveadm_connection *conn, const char *line) +{ + struct mail_host *host; + struct ip_addr ip; + + if (*line == '\0') { + doveadm_cmd_host_flush_all(conn); + return TRUE; + } + + if (net_addr2ip(line, &ip) < 0) { + i_error("doveadm sent invalid HOST-FLUSH parameters"); + return FALSE; + } + host = mail_host_lookup(conn->dir->mail_hosts, &ip); + if (host == NULL) + o_stream_send_str(conn->output, "NOTFOUND\n"); + else { + director_flush_host(conn->dir, conn->dir->self_host, host); + o_stream_send(conn->output, "OK\n", 3); + } + return TRUE; +} + static bool doveadm_cmd_user_lookup(struct doveadm_connection *conn, const char *line) { @@ -156,7 +191,7 @@ doveadm_cmd_user_lookup(struct doveadm_connection *conn, const char *line) static void doveadm_connection_input(struct doveadm_connection *conn) { - const char *line; + const char *line, *cmd, *args; bool ret = TRUE; if (!conn->handshaked) { @@ -174,16 +209,27 @@ static void doveadm_connection_input(struct doveadm_connection *conn) } while ((line = i_stream_read_next_line(conn->input)) != NULL && ret) { - if (strcmp(line, "HOST-LIST") == 0) + args = strchr(line, '\t'); + if (args == NULL) { + cmd = line; + args = ""; + } else { + cmd = t_strdup_until(line, args); + args++; + } + + if (strcmp(cmd, "HOST-LIST") == 0) doveadm_cmd_host_list(conn); - else if (strcmp(line, "DIRECTOR-LIST") == 0) + else if (strcmp(cmd, "DIRECTOR-LIST") == 0) doveadm_cmd_director_list(conn); - else if (strncmp(line, "HOST-SET\t", 9) == 0) - ret = doveadm_cmd_host_set(conn, line + 9); - else if (strncmp(line, "HOST-REMOVE\t", 12) == 0) - ret = doveadm_cmd_host_remove(conn, line + 12); - else if (strncmp(line, "USER-LOOKUP\t", 12) == 0) - ret = doveadm_cmd_user_lookup(conn, line + 12); + else if (strcmp(cmd, "HOST-SET") == 0) + ret = doveadm_cmd_host_set(conn, args); + else if (strcmp(cmd, "HOST-REMOVE") == 0) + ret = doveadm_cmd_host_remove(conn, args); + else if (strcmp(cmd, "HOST-FLUSH") == 0) + ret = doveadm_cmd_host_flush(conn, args); + else if (strcmp(cmd, "USER-LOOKUP") == 0) + ret = doveadm_cmd_user_lookup(conn, args); else { i_error("doveadm sent unknown command: %s", line); ret = FALSE; diff --git a/src/doveadm/doveadm-director.c b/src/doveadm/doveadm-director.c index 988e3746e6..a90815efa1 100644 --- a/src/doveadm/doveadm-director.c +++ b/src/doveadm/doveadm-director.c @@ -225,13 +225,76 @@ static void cmd_director_remove(int argc, char *argv[]) director_disconnect(ctx); } +static void cmd_director_flush_all(struct director_context *ctx) +{ + const char *line; + + director_send(ctx, "HOST-FLUSH\n"); + + line = i_stream_read_next_line(ctx->input); + if (line == NULL) + fprintf(stderr, "failed\n"); + else if (strcmp(line, "OK") != 0) + fprintf(stderr, "%s\n", line); + else if (doveadm_verbose) + printf("flushed\n"); + director_disconnect(ctx); +} + +static void cmd_director_flush(int argc, char *argv[]) +{ + struct director_context *ctx; + struct ip_addr *ips; + unsigned int i, ips_count; + struct ip_addr ip; + const char *host, *line; + + ctx = cmd_director_init(argc, argv, 0); + host = argv[optind++]; + if (host == NULL || argv[optind] != NULL) + help(&doveadm_cmd_director[2]); + + if (strcmp(host, "all") == 0) { + cmd_director_flush_all(ctx); + return; + } + if (net_addr2ip(host, &ip) == 0) { + ips = &ip; + ips_count = 1; + } else { + if (net_gethostbyname(host, &ips, &ips_count) < 0) + i_fatal("gethostname(%s) failed: %m", host); + } + + for (i = 0; i < ips_count; i++) { + director_send(ctx, + t_strdup_printf("HOST-FLUSH\t%s\n", net_ip2addr(&ip))); + } + for (i = 0; i < ips_count; i++) { + line = i_stream_read_next_line(ctx->input); + if (line == NULL || strcmp(line, "OK") != 0) { + fprintf(stderr, "%s: %s\n", net_ip2addr(&ips[i]), + line == NULL ? "failed" : + (strcmp(line, "NOTFOUND") == 0 ? + "doesn't exist" : line)); + } else if (doveadm_verbose) { + printf("%s: flushed\n", net_ip2addr(&ips[i])); + } + } + if (i != ips_count) + i_fatal("director flush failed"); + director_disconnect(ctx); +} + struct doveadm_cmd doveadm_cmd_director[] = { { cmd_director_status, "director status", "[-a ] []", NULL }, { cmd_director_add, "director add", "[-a ] []", NULL }, { cmd_director_remove, "director remove", - "[-a ] ", NULL } + "[-a ] ", NULL }, + { cmd_director_flush, "director flush", + "[-a ] |all", NULL } }; -- 2.47.3