]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
anvil: Add command, user-kick and user-list counts to ps title
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 18 Jan 2022 14:34:25 +0000 (15:34 +0100)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 8 Feb 2022 09:48:24 +0000 (10:48 +0100)
This may be useful in debugging any potential performance issues with the
anvil process.

src/anvil/anvil-connection.c
src/anvil/anvil-connection.h
src/anvil/common.h
src/anvil/main.c

index 7d6657513cb5c38c7a7cb87154616375b99498cb..2c773c718776871220d513b06a3a7a37fb4421f4 100644 (file)
@@ -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,
index f9244b8621e4c21685763f46fd6c4c16af2edb5e..ec16577b9eec70716978d36024f576aa810c6f50 100644 (file)
@@ -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);
 
index 4768ab14a46d23298a1bc9e261234be0d233ef9a..0fbc9d042b14704426d7bbeae7c8ff00067666f1 100644 (file)
@@ -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) \
index 4169027c38376708783c2214cd07bff1a2ad0cfe..af8f21cca30492ca6c7a2ecd66642bff1567e816 100644 (file)
@@ -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"
 #include <unistd.h>
 
 #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,