]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-imap, imap: Load and restore logout statistics when creating a client
authorKarl Fleischmann <karl.fleischmann@open-xchange.com>
Fri, 7 Mar 2025 09:02:22 +0000 (10:02 +0100)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 12 Mar 2025 06:40:04 +0000 (06:40 +0000)
src/imap/imap-client-hibernate.c
src/imap/imap-client.c
src/imap/imap-common.h
src/imap/imap-master-client.c
src/imap/main.c
src/imap/test-imap-client-hibernate.c
src/lib-imap/imap-stats.h

index e79082329a9b9f6d5bb533a8f8865d5547f600ef..ade5d250ead2415cc886ca2550244b9601841edb 100644 (file)
@@ -3,6 +3,7 @@
 #include "imap-common.h"
 #include "fdpass.h"
 #include "net.h"
+#include "istream.h"
 #include "ostream.h"
 #include "write-full.h"
 #include "base64.h"
@@ -116,6 +117,27 @@ static void imap_hibernate_write_cmd(struct client *client, string_t *cmd,
                str_append(cmd, "\tnotify_fd");
        str_append(cmd, "\tstate=");
        base64_encode(state->data, state->used, cmd);
+
+       /* For imap_logout_format statistics: */
+       str_printfa(cmd,
+                  "\tfetch_hdr_count=%u\tfetch_hdr_bytes=%"PRIu64
+                  "\tfetch_body_count=%u\tfetch_body_bytes=%"PRIu64
+                  "\tdeleted_count=%u\texpunged_count=%u\ttrashed_count=%u"
+                  "\tautoexpunged_count=%u\tappend_count=%u"
+                  "\tinput_bytes_extra=%"PRIuUOFF_T
+                  "\toutput_bytes_extra=%"PRIuUOFF_T,
+                  client->logout_stats.fetch_hdr_count,
+                  client->logout_stats.fetch_hdr_bytes,
+                  client->logout_stats.fetch_body_count,
+                  client->logout_stats.fetch_body_bytes,
+                  client->logout_stats.deleted_count,
+                  client->logout_stats.expunged_count,
+                  client->logout_stats.trashed_count,
+                  client->logout_stats.autoexpunged_count,
+                  client->logout_stats.append_count,
+                  i_stream_get_absolute_offset(client->input) + client->logout_stats.input_bytes_extra,
+                  client->output->offset + client->logout_stats.output_bytes_extra);
+
        str_append_c(cmd, '\n');
 }
 
index 1ec8400bc433cbd201b24c6212723b80d6134c4c..b21ede6cee73484a7f69b6d27249da4c22cee884 100644 (file)
@@ -309,8 +309,8 @@ void client_command_cancel(struct client_command_context **_cmd)
 const char *client_stats(struct client *client)
 {
        const struct var_expand_table logout_tab[] = {
-               { .key = "input", .value = dec2str(i_stream_get_absolute_offset(client->input)) },
-               { .key = "output", .value = dec2str(client->output->offset) },
+               { .key = "input", .value = dec2str(i_stream_get_absolute_offset(client->input) + client->logout_stats.input_bytes_extra) },
+               { .key = "output", .value = dec2str(client->output->offset + client->logout_stats.output_bytes_extra) },
                { .key = "session", .value = client->user->session_id },
                { .key = "fetch_hdr_count", .value = dec2str(client->logout_stats.fetch_hdr_count) },
                { .key = "fetch_hdr_bytes", .value = dec2str(client->logout_stats.fetch_hdr_bytes) },
index 438616ded2e03b8b5df4058fbdf627c53f45b855..4cb236799b6fa3c53324974d002fc32e98e02350 100644 (file)
@@ -34,6 +34,7 @@ void imap_refresh_proctitle(void);
 void imap_refresh_proctitle_delayed(void);
 
 int client_create_from_input(const struct mail_storage_service_input *input,
+                            const struct imap_logout_stats *stats,
                             int fd_in, int fd_out,
                             enum client_create_flags flags,
                             struct client **client_r, const char **error_r);
index 6e9836973362e45d338fd2ac7edf9d64ea0ec91e..b531d74f4407b6ec1ba01fc928f2b1d8f8e6a3ed 100644 (file)
@@ -9,6 +9,7 @@
 #include "str.h"
 #include "strescape.h"
 #include "str-sanitize.h"
+#include "strnum.h"
 #include "time-util.h"
 #include "process-title.h"
 #include "master-service.h"
@@ -58,6 +59,7 @@ static int
 imap_master_client_parse_input(const char *const *args, pool_t pool,
                               enum client_create_flags *create_flags,
                               struct mail_storage_service_input *input_r,
+                              struct imap_logout_stats *stats_r,
                               struct imap_master_input *master_input_r,
                               const char **error_r)
 {
@@ -65,6 +67,7 @@ imap_master_client_parse_input(const char *const *args, pool_t pool,
        unsigned int peer_dev_major = 0, peer_dev_minor = 0;
 
        i_zero(input_r);
+       i_zero(stats_r);
        i_zero(master_input_r);
        master_input_r->client_input = buffer_create_dynamic(pool, 64);
        master_input_r->client_output = buffer_create_dynamic(pool, 16);
@@ -177,6 +180,72 @@ imap_master_client_parse_input(const char *const *args, pool_t pool,
                        master_input_r->state_import_bad_idle_done = TRUE;
                } else if (strcmp(key, "idle-continue") == 0) {
                        master_input_r->state_import_idle_continue = TRUE;
+               } else if (strcmp(key, "fetch_hdr_count") == 0) {
+                       if (str_to_uint(value, &stats_r->fetch_hdr_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid fetch_hdr_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "fetch_hdr_bytes") == 0) {
+                       if (str_to_uint64(value, &stats_r->fetch_hdr_bytes) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid fetch_hdr_bytes value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "fetch_body_count") == 0) {
+                       if (str_to_uint(value, &stats_r->fetch_body_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid fetch_body_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "fetch_body_bytes") == 0) {
+                       if (str_to_uint64(value, &stats_r->fetch_body_bytes) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid fetch_body_bytes value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "deleted_count") == 0) {
+                       if (str_to_uint(value, &stats_r->deleted_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid deleted_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "expunged_count") == 0) {
+                       if (str_to_uint(value, &stats_r->expunged_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid expunged_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "trashed_count") == 0) {
+                       if (str_to_uint(value, &stats_r->trashed_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid trashed_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "autoexpunged_count") == 0) {
+                       if (str_to_uint(value, &stats_r->autoexpunged_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid autoexpunged_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "append_count") == 0) {
+                       if (str_to_uint(value, &stats_r->append_count) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid append_count value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "input_bytes_extra") == 0) {
+                       if (str_to_uoff(value, &stats_r->input_bytes_extra) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid input_bytes_extra value: %s", value);
+                               return -1;
+                       }
+               } else if (strcmp(key, "output_bytes_extra") == 0) {
+                       if (str_to_uoff(value, &stats_r->output_bytes_extra) < 0) {
+                               *error_r = t_strdup_printf(
+                                       "Invalid output_bytes_extra value: %s", value);
+                               return -1;
+                       }
                }
        }
        if (peer_dev_major != 0 || peer_dev_minor != 0) {
@@ -222,12 +291,13 @@ imap_master_client_input_args(struct connection *conn, const char *const *args,
        struct client *imap_client;
        enum client_create_flags create_flags = CLIENT_CREATE_FLAG_UNHIBERNATED;
        struct mail_storage_service_input input;
+       struct imap_logout_stats stats;
        struct imap_master_input master_input;
        const char *error = NULL, *reason;
        int ret;
 
        if (imap_master_client_parse_input(args, pool, &create_flags,
-                                          &input, &master_input, &error) < 0) {
+                                          &input, &stats, &master_input, &error) < 0) {
                e_error(conn->event, "imap-master: Failed to parse client input: %s", error);
                o_stream_nsend_str(conn->output, t_strdup_printf(
                        "-Failed to parse client input: %s\n", error));
@@ -245,7 +315,7 @@ imap_master_client_input_args(struct connection *conn, const char *const *args,
 
        /* NOTE: before client_create_from_input() on failures we need to close
           fd_client, but afterward it gets closed by client_destroy() */
-       ret = client_create_from_input(&input, fd_client, fd_client,
+       ret = client_create_from_input(&input, &stats, fd_client, fd_client,
                                       create_flags, &imap_client, &error);
        if (ret < 0) {
                e_error(conn->event,
index fa2fbe309e6aadcae067cbdfcaf11bdaede577f8..757b31e3b59beab78333434089ebab51db28fcbc 100644 (file)
@@ -244,6 +244,7 @@ client_add_input_finalize(struct client *client)
 }
 
 int client_create_from_input(const struct mail_storage_service_input *input,
+                            const struct imap_logout_stats *stats,
                             int fd_in, int fd_out,
                             enum client_create_flags flags,
                             struct client **client_r, const char **error_r)
@@ -299,6 +300,9 @@ int client_create_from_input(const struct mail_storage_service_input *input,
                               event, mail_user, imap_set, smtp_set);
        client->userdb_fields = input->userdb_fields == NULL ? NULL :
                p_strarray_dup(client->pool, input->userdb_fields);
+       /* For imap_logout_format statistics: */
+       if (stats != NULL)
+               client->logout_stats = *stats;
        event_unref(&event);
        *client_r = client;
        return 0;
@@ -323,7 +327,7 @@ static void main_stdio_run(const char *username)
        if ((value = getenv("LOCAL_IP")) != NULL)
                (void)net_addr2ip(value, &input.local_ip);
 
-       if (client_create_from_input(&input, STDIN_FILENO, STDOUT_FILENO,
+       if (client_create_from_input(&input, NULL, STDIN_FILENO, STDOUT_FILENO,
                                     0, &client, &error) < 0)
                i_fatal("%s", error);
 
@@ -383,7 +387,7 @@ login_request_finished(const struct login_server_request *request,
                                        request->auth_req.data_size,
                                        &imap_request);
 
-       if (client_create_from_input(&input, request->fd, request->fd,
+       if (client_create_from_input(&input, NULL, request->fd, request->fd,
                                     create_flags, &client, &error) < 0) {
                int fd = request->fd;
                struct ostream *output =
index 9f080ae595c62663062c49a7261280193ce2f95c..9f9eacaa58538f5e8e91d10ebac97760412815ea 100644 (file)
@@ -39,6 +39,7 @@ static struct mail_storage_service_ctx *storage_service;
 void imap_refresh_proctitle(void) { }
 void imap_refresh_proctitle_delayed(void) { }
 int client_create_from_input(const struct mail_storage_service_input *input ATTR_UNUSED,
+                            const struct imap_logout_stats *stats ATTR_UNUSED,
                             int fd_in ATTR_UNUSED, int fd_out ATTR_UNUSED,
                             enum client_create_flags flags ATTR_UNUSED,
                             struct client **client_r ATTR_UNUSED,
index 9cda562efcea01fe5c218bfe6ac02362fef15b1a..c70ba9860b8f3911d457cdda267ee2bd553ecdf8 100644 (file)
@@ -7,6 +7,7 @@ struct imap_logout_stats {
        uint64_t fetch_hdr_bytes, fetch_body_bytes;
        unsigned int deleted_count, expunged_count, trashed_count;
        unsigned int autoexpunged_count, append_count;
+       uoff_t input_bytes_extra, output_bytes_extra;
 };
 
 #endif /* IMAP_STATS_H */