From: Timo Sirainen Date: Tue, 18 Jan 2022 14:34:25 +0000 (+0100) Subject: anvil: Add command, user-kick and user-list counts to ps title X-Git-Tag: 2.4.0~4473 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=aea75ddd385f795b7e77313183da0ec5fdf45dbc;p=thirdparty%2Fdovecot%2Fcore.git anvil: Add command, user-kick and user-list counts to ps title This may be useful in debugging any potential performance issues with the anvil process. --- diff --git a/src/anvil/anvil-connection.c b/src/anvil/anvil-connection.c index 7d6657513c..2c773c7187 100644 --- a/src/anvil/anvil-connection.c +++ b/src/anvil/anvil-connection.c @@ -65,6 +65,9 @@ struct anvil_cmd_kick { static struct connection_list *anvil_connections; static HASH_TABLE(struct anvil_connection_key *, struct anvil_connection *) anvil_connections_hash; +static unsigned int anvil_global_kick_count = 0; +static unsigned int anvil_global_cmd_counter = 0; +static unsigned int anvil_global_connect_dump_count = 0; static void anvil_connection_destroy(struct connection *_conn); @@ -179,7 +182,10 @@ kick_user_callback(const char *reply, const char *error, unsigned int count; i_assert(kick->cmd_refcount > 0); + i_assert(anvil_global_kick_count > 0); + anvil_global_kick_count--; + anvil_refresh_proctitle_delayed(); if (error != NULL) ; else if (reply[0] == '+' && str_to_uint(reply+1, &count) == 0) @@ -234,6 +240,7 @@ kick_user_iter(struct anvil_connection *conn, struct connect_limit_iter *iter, guid_128_to_string(result.conn_guid)); } + anvil_global_kick_count++; kick->cmd_refcount++; admin_cmd_send(result.service, result.pid, str_c(cmd), kick_user_callback, kick); @@ -278,6 +285,9 @@ anvil_connection_request(struct anvil_connection *conn, time_t stamp; pid_t pid; + anvil_global_cmd_counter++; + anvil_refresh_proctitle_delayed(); + args++; if (strcmp(cmd, "CONNECT") == 0) { if (args[0] == NULL || args[1] == NULL) { @@ -346,6 +356,7 @@ anvil_connection_request(struct anvil_connection *conn, } connect_limit_disconnect(connect_limit, pid, &key, conn_guid); } else if (strcmp(cmd, "CONNECT-DUMP") == 0) { + anvil_global_connect_dump_count++; connect_limit_dump(connect_limit, conn->conn.output); } else if (strcmp(cmd, "KICK-USER") == 0) { if (args[0] == NULL) { @@ -640,6 +651,17 @@ void anvil_connection_send_cmd(struct anvil_connection *conn, cmd->context = context; } +void anvil_get_global_counts(unsigned int *connection_count_r, + unsigned int *kicks_pending_count_r, + unsigned int *cmd_counter_r, + unsigned int *connect_dump_counter_r) +{ + *connection_count_r = anvil_connections->connections_count; + *kicks_pending_count_r = anvil_global_kick_count; + *cmd_counter_r = anvil_global_cmd_counter; + *connect_dump_counter_r = anvil_global_connect_dump_count; +} + static struct connection_settings anvil_connections_set = { .dont_send_version = TRUE, .input_max_size = MAX_INBUF_SIZE, diff --git a/src/anvil/anvil-connection.h b/src/anvil/anvil-connection.h index f9244b8621..ec16577b9e 100644 --- a/src/anvil/anvil-connection.h +++ b/src/anvil/anvil-connection.h @@ -16,6 +16,11 @@ void anvil_connection_send_cmd(struct anvil_connection *conn, anvil_connection_cmd_callback_t *callback, void *context); +void anvil_get_global_counts(unsigned int *connection_count_r, + unsigned int *kicks_pending_count_r, + unsigned int *cmd_counter_r, + unsigned int *connect_dump_counter_r); + void anvil_connections_init(void); void anvil_connections_deinit(void); diff --git a/src/anvil/common.h b/src/anvil/common.h index 4768ab14a4..0fbc9d042b 100644 --- a/src/anvil/common.h +++ b/src/anvil/common.h @@ -11,6 +11,8 @@ extern struct connect_limit *connect_limit; extern struct penalty *penalty; extern bool anvil_restarted; +void anvil_refresh_proctitle_delayed(void); + void admin_cmd_send(const char *service, pid_t pid, const char *cmd, admin_cmd_callback_t *callback, void *context); #define admin_cmd_send(service, pid, cmd, callback, context) \ diff --git a/src/anvil/main.c b/src/anvil/main.c index 4169027c38..af8f21cca3 100644 --- a/src/anvil/main.c +++ b/src/anvil/main.c @@ -2,9 +2,11 @@ #include "common.h" #include "array.h" +#include "str.h" #include "env-util.h" #include "fdpass.h" #include "ioloop.h" +#include "process-title.h" #include "restrict-access.h" #include "master-service.h" #include "master-service-settings.h" @@ -17,13 +19,63 @@ #include #define ANVIL_CLIENT_POOL_MAX_CONNECTIONS 100 +#define ANVIL_PROCTITLE_REFRESH_INTERVAL_MSECS 1000 struct connect_limit *connect_limit; struct penalty *penalty; bool anvil_restarted; +static bool verbose_proctitle = FALSE; static struct io *log_fdpass_io; static struct admin_client_pool *admin_pool; +static struct timeout *to_refresh; +static unsigned int prev_cmd_counter = 0; +static unsigned int prev_connect_dump_counter = 0; + +static void anvil_refresh_proctitle(void *context ATTR_UNUSED) +{ + unsigned int connections_count; + unsigned int kicks_pending_count; + unsigned int cmd_counter, cmd_diff; + unsigned int connect_dump_counter, connect_dump_diff; + anvil_get_global_counts(&connections_count, &kicks_pending_count, + &cmd_counter, &connect_dump_counter); + if (cmd_counter >= prev_cmd_counter) + cmd_diff = cmd_counter - prev_cmd_counter; + else { + /* wrapped */ + cmd_diff = (UINT_MAX - prev_cmd_counter + 1) + cmd_counter; + } + if (connect_dump_counter >= prev_connect_dump_counter) { + connect_dump_diff = connect_dump_counter - + prev_connect_dump_counter; + } else { + /* wrapped */ + connect_dump_diff = (UINT_MAX - prev_connect_dump_counter + 1) + + connect_dump_counter; + } + prev_cmd_counter = cmd_counter; + prev_connect_dump_counter = connect_dump_counter; + + process_title_set(t_strdup_printf( + "[%u connections, %u requests, %u user-lists, %u user-kicks]", + connections_count, cmd_diff, + connect_dump_diff, kicks_pending_count)); + + if (cmd_diff == 0 && connect_dump_diff == 0 && kicks_pending_count == 0) + timeout_remove(&to_refresh); +} + +void anvil_refresh_proctitle_delayed(void) +{ + if (!verbose_proctitle) + return; + + if (to_refresh != NULL) + return; + to_refresh = timeout_add(ANVIL_PROCTITLE_REFRESH_INTERVAL_MSECS, + anvil_refresh_proctitle, NULL); +} #undef admin_cmd_send void admin_cmd_send(const char *service, pid_t pid, const char *cmd, @@ -76,6 +128,7 @@ static void main_init(void) /* delay dying until all of our clients are gone */ master_service_set_die_with_master(master_service, FALSE); + verbose_proctitle = set->verbose_proctitle; anvil_restarted = getenv("ANVIL_RESTARTED") != NULL; anvil_connections_init(); admin_clients_init(); @@ -95,13 +148,13 @@ static void main_deinit(void) admin_client_pool_deinit(&admin_pool); admin_clients_deinit(); anvil_connections_deinit(); + timeout_remove(&to_refresh); } int main(int argc, char *argv[]) { const enum master_service_flags service_flags = - MASTER_SERVICE_FLAG_DONT_SEND_STATS | - MASTER_SERVICE_FLAG_UPDATE_PROCTITLE; + MASTER_SERVICE_FLAG_DONT_SEND_STATS; const char *error; master_service = master_service_init("anvil", service_flags,