#include "imap-common.h"
#include "fdpass.h"
#include "net.h"
+#include "istream.h"
#include "ostream.h"
#include "write-full.h"
#include "base64.h"
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');
}
#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"
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)
{
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);
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) {
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));
/* 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,
}
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)
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;
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);
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 =