From: Marco Bettini Date: Thu, 3 Feb 2022 14:08:39 +0000 (+0100) Subject: old-stats: Remove the plugin, lib-old-stats old-stats plugins/imap-old-stats plugins... X-Git-Tag: 2.4.0~4404 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3dd92c862e3e28fce8aefd491a292298f7b60aa0;p=thirdparty%2Fdovecot%2Fcore.git old-stats: Remove the plugin, lib-old-stats old-stats plugins/imap-old-stats plugins/old-stats --- diff --git a/.gitignore b/.gitignore index c0ffa02456..6a92599495 100644 --- a/.gitignore +++ b/.gitignore @@ -147,7 +147,6 @@ src/lmtp/lmtp src/master/dovecot src/ssl-params/ssl-params src/stats/stats -src/old-stats/old-stats src/plugins/fts-squat/squat-test src/pop3-login/pop3-login src/pop3/pop3 diff --git a/configure.ac b/configure.ac index b3616d49bf..5494910151 100644 --- a/configure.ac +++ b/configure.ac @@ -624,7 +624,6 @@ LIBDOVECOT_LA_LIBS='\ $(top_builddir)/src/lib-program-client/libprogram_client.la \ $(top_builddir)/src/lib-master/libmaster.la \ $(top_builddir)/src/lib-settings/libsettings.la \ - $(top_builddir)/src/lib-old-stats/libold_stats.la \ $(top_builddir)/src/lib-http/libhttp.la \ $(top_builddir)/src/lib-fs/libfs.la \ $(top_builddir)/src/lib-dict/libdict.la \ @@ -862,7 +861,6 @@ src/lib-sasl/Makefile src/lib-settings/Makefile src/lib-smtp/Makefile src/lib-ssl-iostream/Makefile -src/lib-old-stats/Makefile src/lib-test/Makefile src/lib-storage/Makefile src/lib-storage/list/Makefile @@ -902,7 +900,6 @@ src/replication/Makefile src/replication/aggregator/Makefile src/replication/replicator/Makefile src/stats/Makefile -src/old-stats/Makefile src/util/Makefile src/plugins/Makefile src/plugins/acl/Makefile @@ -926,8 +923,6 @@ src/plugins/quota/Makefile src/plugins/quota-clone/Makefile src/plugins/imap-quota/Makefile src/plugins/replication/Makefile -src/plugins/old-stats/Makefile -src/plugins/imap-old-stats/Makefile src/plugins/trash/Makefile src/plugins/virtual/Makefile src/plugins/welcome/Makefile diff --git a/dovecot-config.in.in b/dovecot-config.in.in index 93b79e3bbf..4458eee526 100644 --- a/dovecot-config.in.in +++ b/dovecot-config.in.in @@ -28,7 +28,7 @@ LIBDOVECOT_DSYNC_DEPS="@LIBDOVECOT_DSYNC@" LIBDOVECOT_LIBFTS_DEPS="@LIBDOVECOT_LIBFTS@" LIBDOVECOT_LUA_DEPS="@LIBDOVECOT_LUA@" -LIBDOVECOT_INCLUDE="-I$(incdir) -I$(incdir)/src/lib -I$(incdir)/src/lib-dict -I$(incdir)/src/lib-dns -I$(incdir)/src/lib-http -I$(incdir)/src/lib-mail -I$(incdir)/src/lib-smtp -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-fs -I$(incdir)/src/lib-charset -I$(incdir)/src/lib-auth -I$(incdir)/src/lib-master -I$(incdir)/src/lib-ssl-iostream -I$(incdir)/src/lib-compression -I$(incdir)/src/lib-settings -I$(incdir)/src/lib-test -I$(incdir)/src/lib-sasl -I$(incdir)/src/lib-old-stats -I$(incdir)/src/lib-dcrypt -I$(incdir)/src/lib-program-client" +LIBDOVECOT_INCLUDE="-I$(incdir) -I$(incdir)/src/lib -I$(incdir)/src/lib-dict -I$(incdir)/src/lib-dns -I$(incdir)/src/lib-http -I$(incdir)/src/lib-mail -I$(incdir)/src/lib-smtp -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-imap -I$(incdir)/src/lib-fs -I$(incdir)/src/lib-charset -I$(incdir)/src/lib-auth -I$(incdir)/src/lib-master -I$(incdir)/src/lib-ssl-iostream -I$(incdir)/src/lib-compression -I$(incdir)/src/lib-settings -I$(incdir)/src/lib-test -I$(incdir)/src/lib-sasl -I$(incdir)/src/lib-dcrypt -I$(incdir)/src/lib-program-client" LIBDOVECOT_LDA_INCLUDE="-I$(incdir)/src/lib-lda -I$(incdir)/src/lda" LIBDOVECOT_AUTH_INCLUDE="-I$(incdir)/src/auth" LIBDOVECOT_DOVEADM_INCLUDE="-I$(incdir)/src/lib-doveadm -I$(incdir)/src/doveadm" diff --git a/src/Makefile.am b/src/Makefile.am index d8954ff22d..07b99e143b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,7 +17,6 @@ LIBDOVECOT_SUBDIRS = \ lib-dcrypt \ lib-dict \ lib-sasl \ - lib-old-stats \ lib-http \ lib-fs \ lib-mail \ @@ -69,5 +68,4 @@ SUBDIRS = \ util \ doveadm \ stats \ - old-stats \ plugins diff --git a/src/lib-old-stats/Makefile.am b/src/lib-old-stats/Makefile.am deleted file mode 100644 index f97cf62261..0000000000 --- a/src/lib-old-stats/Makefile.am +++ /dev/null @@ -1,18 +0,0 @@ -noinst_LTLIBRARIES = libold_stats.la - -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-master - -libold_stats_la_SOURCES = \ - stats.c \ - stats-connection.c \ - stats-parser.c - -headers = \ - stats.h \ - stats-connection.h \ - stats-parser.h - -pkginc_libdir = $(pkgincludedir) -pkginc_lib_HEADERS = $(headers) diff --git a/src/lib-old-stats/stats-connection.c b/src/lib-old-stats/stats-connection.c deleted file mode 100644 index 24b5e73f40..0000000000 --- a/src/lib-old-stats/stats-connection.c +++ /dev/null @@ -1,119 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "str.h" -#include "master-service.h" -#include "stats-connection.h" - -#include -#include - -#define STATS_EAGAIN_WARN_INTERVAL_SECS 30 - -struct stats_connection { - int refcount; - - int fd; - char *path; - - bool open_failed; - time_t next_warning_timestamp; -}; - -static bool stats_connection_open(struct stats_connection *conn) -{ - if (conn->open_failed) - return FALSE; - - conn->fd = open(conn->path, O_WRONLY | O_NONBLOCK); - if (conn->fd == -1) { - i_error("stats: open(%s) failed: %m", conn->path); - conn->open_failed = TRUE; - return FALSE; - } - return TRUE; -} - -struct stats_connection * -stats_connection_create(const char *path) -{ - struct stats_connection *conn; - - conn = i_new(struct stats_connection, 1); - conn->refcount = 1; - conn->path = i_strdup(path); - (void)stats_connection_open(conn); - return conn; -} - -void stats_connection_ref(struct stats_connection *conn) -{ - conn->refcount++; -} - -void stats_connection_unref(struct stats_connection **_conn) -{ - struct stats_connection *conn = *_conn; - - i_assert(conn->refcount > 0); - if (--conn->refcount > 0) - return; - - *_conn = NULL; - i_close_fd_path(&conn->fd, conn->path); - i_free(conn->path); - i_free(conn); -} - -int stats_connection_send(struct stats_connection *conn, const string_t *str) -{ - static bool pipe_warned = FALSE; - ssize_t ret; - - /* if master process has been stopped (and restarted), don't even try - to notify the stats process anymore. even if one exists, it doesn't - know about us. */ - if (master_service_is_master_stopped(master_service)) - return -1; - - if (conn->fd == -1) { - if (!stats_connection_open(conn)) - return -1; - i_assert(conn->fd != -1); - } - - if (str_len(str) > PIPE_BUF && !pipe_warned) { - i_warning("stats update sent more bytes that PIPE_BUF " - "(%zu > %u), this may break statistics", - str_len(str), (unsigned int)PIPE_BUF); - pipe_warned = TRUE; - } - - ret = write(conn->fd, str_data(str), str_len(str)); - if (ret == (ssize_t)str_len(str)) { - /* success */ - return 0; - } else if (ret < 0 && errno == EAGAIN) { - /* stats process is busy */ - if (ioloop_time > conn->next_warning_timestamp) { - i_warning("write(%s) failed: %m (stats process is busy)", conn->path); - conn->next_warning_timestamp = ioloop_time + - STATS_EAGAIN_WARN_INTERVAL_SECS; - } - return -1; - } else { - /* error - reconnect */ - if (ret < 0) { - /* don't log EPIPE errors. they can happen when - Dovecot is stopped. */ - if (errno != EPIPE) - i_error("write(%s) failed: %m", conn->path); - } else if ((size_t)ret != str_len(str)) - i_error("write(%s) wrote partial update", conn->path); - if (close(conn->fd) < 0) - i_error("close(%s) failed: %m", conn->path); - conn->fd = -1; - return -1; - } -} diff --git a/src/lib-old-stats/stats-connection.h b/src/lib-old-stats/stats-connection.h deleted file mode 100644 index 2295e09ef3..0000000000 --- a/src/lib-old-stats/stats-connection.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef STATS_CONNECTION_H -#define STATS_CONNECTION_H - -struct stats_connection *stats_connection_create(const char *path); -void stats_connection_ref(struct stats_connection *conn); -void stats_connection_unref(struct stats_connection **conn); - -/* Returns 0 on success, -1 on failure. */ -int stats_connection_send(struct stats_connection *conn, const string_t *str); - -#endif diff --git a/src/lib-old-stats/stats-parser.c b/src/lib-old-stats/stats-parser.c deleted file mode 100644 index da009e9750..0000000000 --- a/src/lib-old-stats/stats-parser.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "str.h" -#include "time-util.h" -#include "stats-parser.h" - -#define USECS_PER_SEC 1000000 - -static bool stats_diff_timeval(struct timeval *dest, - const struct timeval *src1, - const struct timeval *src2) -{ - long long diff_usecs; - - diff_usecs = timeval_diff_usecs(src2, src1); - if (diff_usecs < 0) - return FALSE; - dest->tv_sec = diff_usecs / USECS_PER_SEC; - dest->tv_usec = diff_usecs % USECS_PER_SEC; - return TRUE; -} - -static bool -stats_diff_uint32(uint32_t *dest, const uint32_t *src1, const uint32_t *src2) -{ - if (*src1 > *src2) - return FALSE; - *dest = *src2 - *src1; - return TRUE; -} - -static bool -stats_diff_uint64(uint64_t *dest, const uint64_t *src1, const uint64_t *src2) -{ - if (*src1 > *src2) - return FALSE; - *dest = *src2 - *src1; - return TRUE; -} - -bool stats_parser_diff(const struct stats_parser_field *fields, - unsigned int fields_count, - const struct stats *stats1, const struct stats *stats2, - struct stats *diff_stats_r, const char **error_r) -{ - unsigned int i; - - for (i = 0; i < fields_count; i++) { - unsigned int offset = fields[i].offset; - void *dest = PTR_OFFSET(diff_stats_r, offset); - const void *src1 = CONST_PTR_OFFSET(stats1, offset); - const void *src2 = CONST_PTR_OFFSET(stats2, offset); - - switch (fields[i].type) { - case STATS_PARSER_TYPE_UINT: - switch (fields[i].size) { - case sizeof(uint32_t): - if (!stats_diff_uint32(dest, src1, src2)) { - *error_r = t_strdup_printf("%s %u < %u", - fields[i].name, - *(const uint32_t *)src2, - *(const uint32_t *)src1); - return FALSE; - } - break; - case sizeof(uint64_t): - if (!stats_diff_uint64(dest, src1, src2)) { - const uint64_t *n1 = src1, *n2 = src2; - - *error_r = t_strdup_printf("%s %"PRIu64" < %"PRIu64, - fields[i].name, *n2, *n1); - return FALSE; - } - break; - default: - i_unreached(); - } - break; - case STATS_PARSER_TYPE_TIMEVAL: - if (!stats_diff_timeval(dest, src1, src2)) { - const struct timeval *tv1 = src1, *tv2 = src2; - - *error_r = t_strdup_printf("%s %ld.%d < %ld.%d", - fields[i].name, - (long)tv2->tv_sec, (int)tv2->tv_usec, - (long)tv1->tv_sec, (int)tv1->tv_usec); - return FALSE; - } - break; - } - } - return TRUE; -} - -static void stats_timeval_add(struct timeval *dest, const struct timeval *src) -{ - dest->tv_sec += src->tv_sec; - dest->tv_usec += src->tv_usec; - if (dest->tv_usec > USECS_PER_SEC) { - dest->tv_usec -= USECS_PER_SEC; - dest->tv_sec++; - } -} - -void stats_parser_add(const struct stats_parser_field *fields, - unsigned int fields_count, - struct stats *dest, const struct stats *src) -{ - unsigned int i; - - for (i = 0; i < fields_count; i++) { - unsigned int offset = fields[i].offset; - void *f_dest = PTR_OFFSET(dest, offset); - const void *f_src = CONST_PTR_OFFSET(src, offset); - - switch (fields[i].type) { - case STATS_PARSER_TYPE_UINT: - switch (fields[i].size) { - case sizeof(uint32_t): { - uint32_t *n_dest = f_dest; - const uint32_t *n_src = f_src; - - *n_dest += *n_src; - break; - } - case sizeof(uint64_t): { - uint64_t *n_dest = f_dest; - const uint64_t *n_src = f_src; - - *n_dest += *n_src; - break; - } - default: - i_unreached(); - } - break; - case STATS_PARSER_TYPE_TIMEVAL: - stats_timeval_add(f_dest, f_src); - break; - } - } -} - -void stats_parser_value(string_t *str, - const struct stats_parser_field *field, - const void *data) -{ - const void *ptr = CONST_PTR_OFFSET(data, field->offset); - - switch (field->type) { - case STATS_PARSER_TYPE_UINT: - switch (field->size) { - case sizeof(uint32_t): { - const uint32_t *n = ptr; - - str_printfa(str, "%u", *n); - break; - } - case sizeof(uint64_t): { - const uint64_t *n = ptr; - - str_printfa(str, "%"PRIu64, *n); - break; - } - default: - i_unreached(); - } - break; - case STATS_PARSER_TYPE_TIMEVAL: { - const struct timeval *tv = ptr; - - str_printfa(str, "%"PRIdTIME_T".%u", - tv->tv_sec, (unsigned int)tv->tv_usec); - break; - } - } -} diff --git a/src/lib-old-stats/stats-parser.h b/src/lib-old-stats/stats-parser.h deleted file mode 100644 index ad701bf608..0000000000 --- a/src/lib-old-stats/stats-parser.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef STATS_PARSER_H -#define STATS_PARSER_H - -struct stats; - -enum stats_parser_type { - STATS_PARSER_TYPE_UINT, - STATS_PARSER_TYPE_TIMEVAL -}; - -struct stats_parser_field { - const char *name; - unsigned int offset; - unsigned int size; - enum stats_parser_type type; -}; - -bool stats_parser_diff(const struct stats_parser_field *fields, - unsigned int fields_count, - const struct stats *stats1, const struct stats *stats2, - struct stats *diff_stats_r, const char **error_r); -void stats_parser_add(const struct stats_parser_field *fields, - unsigned int fields_count, - struct stats *dest, const struct stats *src); -void stats_parser_value(string_t *str, - const struct stats_parser_field *field, - const void *data); - -#endif diff --git a/src/lib-old-stats/stats.c b/src/lib-old-stats/stats.c deleted file mode 100644 index 284de26373..0000000000 --- a/src/lib-old-stats/stats.c +++ /dev/null @@ -1,229 +0,0 @@ -/* Copyright (c) 2015-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "array.h" -#include "stats.h" - -struct stats_item { - struct stats_vfuncs v; - size_t pos; -}; - -static ARRAY(struct stats_item *) stats_items = ARRAY_INIT; -static unsigned int stats_total_size = 0; -static bool stats_allocated = FALSE; - -struct stats_item *stats_register(const struct stats_vfuncs *vfuncs) -{ - struct stats_item *item; - - if (stats_allocated) - i_panic("stats_register() called after stats_alloc_size() was already called - this will break existing allocations"); - - if (!array_is_created(&stats_items)) - i_array_init(&stats_items, 8); - - item = i_new(struct stats_item, 1); - item->v = *vfuncs; - item->pos = stats_total_size; - array_push_back(&stats_items, &item); - - stats_total_size += vfuncs->alloc_size(); - return item; -} - -static bool stats_item_find(struct stats_item *item, unsigned int *idx_r) -{ - struct stats_item *const *itemp; - - array_foreach(&stats_items, itemp) { - if (*itemp == item) { - *idx_r = array_foreach_idx(&stats_items, itemp); - return TRUE; - } - } - return FALSE; -} - -static struct stats_item *stats_item_find_by_name(const char *name) -{ - struct stats_item *item; - - array_foreach_elem(&stats_items, item) { - if (strcmp(item->v.short_name, name) == 0) - return item; - } - return NULL; -} - -void stats_unregister(struct stats_item **_item) -{ - struct stats_item *item = *_item; - unsigned int idx; - - *_item = NULL; - - if (!stats_item_find(item, &idx)) - i_unreached(); - array_delete(&stats_items, idx, 1); - - i_free(item); - if (array_count(&stats_items) == 0) { - array_free(&stats_items); - /* all stats should have been freed by now. allow - re-registering and using stats. */ - stats_allocated = FALSE; - } -} - -struct stats *stats_alloc(pool_t pool) -{ - return p_malloc(pool, stats_alloc_size()); -} - -size_t stats_alloc_size(void) -{ - stats_allocated = TRUE; - return stats_total_size; -} - -void stats_copy(struct stats *dest, const struct stats *src) -{ - memcpy(dest, src, stats_total_size); -} - -unsigned int stats_field_count(void) -{ - struct stats_item *item; - unsigned int count = 0; - - array_foreach_elem(&stats_items, item) - count += item->v.field_count(); - return count; -} - -const char *stats_field_name(unsigned int n) -{ - struct stats_item *item; - unsigned int i = 0, count; - - array_foreach_elem(&stats_items, item) { - count = item->v.field_count(); - if (i + count > n) - return item->v.field_name(n - i); - i += count; - } - i_unreached(); -} - -void stats_field_value(string_t *str, const struct stats *stats, - unsigned int n) -{ - struct stats_item *item; - unsigned int i = 0, count; - - array_foreach_elem(&stats_items, item) { - count = item->v.field_count(); - if (i + count > n) { - const void *item_stats = - CONST_PTR_OFFSET(stats, item->pos); - item->v.field_value(str, item_stats, n - i); - return; - } - i += count; - } - i_unreached(); -} - -bool stats_diff(const struct stats *stats1, const struct stats *stats2, - struct stats *diff_stats_r, const char **error_r) -{ - struct stats_item *item; - bool ret = TRUE; - - array_foreach_elem(&stats_items, item) { - if (!item->v.diff(CONST_PTR_OFFSET(stats1, item->pos), - CONST_PTR_OFFSET(stats2, item->pos), - PTR_OFFSET(diff_stats_r, item->pos), - error_r)) - ret = FALSE; - } - return ret; -} - -void stats_add(struct stats *dest, const struct stats *src) -{ - struct stats_item *item; - - array_foreach_elem(&stats_items, item) { - item->v.add(PTR_OFFSET(dest, item->pos), - CONST_PTR_OFFSET(src, item->pos)); - } -} - -bool stats_have_changed(const struct stats *prev, const struct stats *cur) -{ - struct stats_item *item; - - array_foreach_elem(&stats_items, item) { - if (item->v.have_changed(CONST_PTR_OFFSET(prev, item->pos), - CONST_PTR_OFFSET(cur, item->pos))) - return TRUE; - } - return FALSE; -} - -void stats_export(buffer_t *buf, const struct stats *stats) -{ - struct stats_item *item; - - array_foreach_elem(&stats_items, item) { - buffer_append(buf, item->v.short_name, - strlen(item->v.short_name)+1); - item->v.export(buf, CONST_PTR_OFFSET(stats, item->pos)); - } -} - -bool stats_import(const unsigned char *data, size_t size, - const struct stats *old_stats, struct stats *stats, - const char **error_r) -{ - struct stats_item *item; - const unsigned char *p; - size_t pos; - - memcpy(stats, old_stats, stats_total_size); - while (size > 0) { - const char *next_name = (const void *)data; - - p = memchr(data, '\0', size); - if (p == NULL) { - *error_r = "Expected name, but NUL is missing"; - return FALSE; - } - item = stats_item_find_by_name(next_name); - if (item == NULL) { - *error_r = t_strdup_printf("Unknown stats name: '%s'", next_name); - return FALSE; - } - size -= (p+1) - data; - data = p+1; - if (!item->v.import(data, size, &pos, - PTR_OFFSET(stats, item->pos), error_r)) - return FALSE; - i_assert(pos <= size); - data += pos; - size -= pos; - } - return TRUE; -} - -void *stats_fill_ptr(struct stats *stats, struct stats_item *item) -{ - return PTR_OFFSET(stats, item->pos); -} - -void stats_reset(struct stats *stats) -{ - memset(stats, 0, stats_total_size); -} diff --git a/src/lib-old-stats/stats.h b/src/lib-old-stats/stats.h deleted file mode 100644 index 0cd0dc3ce8..0000000000 --- a/src/lib-old-stats/stats.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef STATS_H -#define STATS_H - -struct stats; -struct stats_item; - -struct stats_vfuncs { - const char *short_name; - - size_t (*alloc_size)(void); - unsigned int (*field_count)(void); - const char *(*field_name)(unsigned int n); - void (*field_value)(string_t *str, const struct stats *stats, - unsigned int n); - - bool (*diff)(const struct stats *stats1, const struct stats *stats2, - struct stats *diff_stats_r, const char **error_r); - void (*add)(struct stats *dest, const struct stats *src); - bool (*have_changed)(const struct stats *prev, const struct stats *cur); - - void (*export)(buffer_t *buf, const struct stats *stats); - bool (*import)(const unsigned char *data, size_t size, size_t *pos_r, - struct stats *stats, const char **error_r); -}; - -struct stats_item *stats_register(const struct stats_vfuncs *vfuncs); -void stats_unregister(struct stats_item **item); - -/* Allocate struct stats from a given pool. */ -struct stats *stats_alloc(pool_t pool); -/* Returns the number of bytes allocated to stats. */ -size_t stats_alloc_size(void); -/* Copy all stats from src to dest. */ -void stats_copy(struct stats *dest, const struct stats *src); - -/* Returns the number of stats fields. */ -unsigned int stats_field_count(void); -/* Returns the name of a stats field (exported to doveadm). */ -const char *stats_field_name(unsigned int n); -/* Returns the value of a stats field as a string (exported to doveadm). */ -void stats_field_value(string_t *str, const struct stats *stats, - unsigned int n); - -/* Return diff_stats_r->field = stats2->field - stats1->field. - diff1 is supposed to have smaller values than diff2. Returns TRUE if this - is so, FALSE if not */ -bool stats_diff(const struct stats *stats1, const struct stats *stats2, - struct stats *diff_stats_r, const char **error_r); -/* dest->field += src->field */ -void stats_add(struct stats *dest, const struct stats *src); -/* Returns TRUE if any fields have changed in cur since prev in a way that - a plugin should send the updated statistics to the stats process. Not all - fields necessarily require sending an update. */ -bool stats_have_changed(const struct stats *prev, const struct stats *cur); - -/* Export stats into a buffer in binary format. */ -void stats_export(buffer_t *buf, const struct stats *stats); -/* Import stats from a buffer. The buffer doesn't need to contain an update to - all the stats items - old_stats are used for that item in such case. - Currently it's not allowed to have unknown items in the buffer. */ -bool stats_import(const unsigned char *data, size_t size, - const struct stats *old_stats, struct stats *stats, - const char **error_r); -/* Return a pointer to stats where the specified item starts. The returned - pointer can be used to fill up the item-specific stats (up to its - alloc_size() number of bytes). */ -void *stats_fill_ptr(struct stats *stats, struct stats_item *item); - -void stats_reset(struct stats *stats); - -#endif diff --git a/src/old-stats/Makefile.am b/src/old-stats/Makefile.am deleted file mode 100644 index 8cb9c2fa62..0000000000 --- a/src/old-stats/Makefile.am +++ /dev/null @@ -1,48 +0,0 @@ -old_stats_moduledir = $(moduledir)/old-stats -pkglibexecdir = $(libexecdir)/dovecot - -pkglibexec_PROGRAMS = old-stats - -AM_CPPFLAGS = \ - -DSTATS_MODULE_DIR=\""$(old_stats_moduledir)"\" \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-settings \ - -I$(top_srcdir)/src/lib-master \ - -I$(top_srcdir)/src/lib-old-stats \ - $(BINARY_CFLAGS) - -old_stats_LDADD = $(LIBDOVECOT) \ - $(BINARY_LDFLAGS) - -old_stats_DEPENDENCIES = $(LIBDOVECOT_DEPS) - -old_stats_SOURCES = \ - client.c \ - client-export.c \ - client-reset.c \ - fifo-input-connection.c \ - global-memory.c \ - mail-command.c \ - mail-domain.c \ - mail-ip.c \ - mail-session.c \ - mail-stats.c \ - mail-user.c \ - main.c \ - stats-carbon.c \ - stats-settings.c - -noinst_HEADERS = \ - client.h \ - client-export.h \ - client-reset.h \ - fifo-input-connection.h \ - global-memory.h \ - mail-command.h \ - mail-domain.h \ - mail-ip.h \ - mail-session.h \ - mail-stats.h \ - mail-user.h \ - stats-carbon.h \ - stats-settings.h diff --git a/src/old-stats/client-export.c b/src/old-stats/client-export.c deleted file mode 100644 index 34ace73ed4..0000000000 --- a/src/old-stats/client-export.c +++ /dev/null @@ -1,657 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "net.h" -#include "ostream.h" -#include "str.h" -#include "strescape.h" -#include "wildcard-match.h" -#include "mail-stats.h" -#include "mail-command.h" -#include "mail-session.h" -#include "mail-user.h" -#include "mail-domain.h" -#include "mail-ip.h" -#include "client.h" -#include "client-export.h" - -enum mail_export_level { - MAIL_EXPORT_LEVEL_COMMAND, - MAIL_EXPORT_LEVEL_SESSION, - MAIL_EXPORT_LEVEL_USER, - MAIL_EXPORT_LEVEL_DOMAIN, - MAIL_EXPORT_LEVEL_IP, - MAIL_EXPORT_LEVEL_GLOBAL -}; -static const char *mail_export_level_names[] = { - "command", "session", "user", "domain", "ip", "global" -}; - -struct mail_export_filter { - const char *user, *domain, *session; - struct ip_addr ip; - unsigned int ip_bits; - time_t since; - bool connected; -}; - -struct client_export_cmd { - enum mail_export_level level; - struct mail_export_filter filter; - string_t *str; - int (*export_iter)(struct client *client); - bool header_sent; -}; - -static int -mail_export_level_parse(const char *str, enum mail_export_level *level_r) -{ - unsigned int i; - - for (i = 0; i < N_ELEMENTS(mail_export_level_names); i++) { - if (strcmp(mail_export_level_names[i], str) == 0) { - *level_r = (enum mail_export_level)i; - return 0; - } - } - return -1; -} - -static int -mail_export_parse_filter(const char *const *args, pool_t pool, - struct mail_export_filter *filter_r, - const char **error_r) -{ - unsigned long l; - - /* filters: - user= | domain= | session= - ip=[/] - since= - connected - */ - i_zero(filter_r); - for (; *args != NULL; args++) { - if (str_begins(*args, "user=")) - filter_r->user = p_strdup(pool, *args + 5); - else if (str_begins(*args, "domain=")) - filter_r->domain = p_strdup(pool, *args + 7); - else if (str_begins(*args, "session=")) - filter_r->session = p_strdup(pool, *args + 8); - else if (str_begins(*args, "ip=")) { - if (net_parse_range(*args + 3, &filter_r->ip, - &filter_r->ip_bits) < 0) { - *error_r = "Invalid ip filter"; - return -1; - } - } else if (str_begins(*args, "since=")) { - if (str_to_ulong(*args + 6, &l) < 0) { - *error_r = "Invalid since filter"; - return -1; - } - filter_r->since = (time_t)l; - } else if (strcmp(*args, "connected") == 0) { - filter_r->connected = TRUE; - } - } - return 0; -} - -static void -client_export_stats_headers(struct client *client) -{ - unsigned int i, count = stats_field_count(); - string_t *str = t_str_new(128); - - i_assert(count > 0); - - str_append(str, stats_field_name(0)); - for (i = 1; i < count; i++) { - str_append_c(str, '\t'); - str_append(str, stats_field_name(i)); - } - str_append_c(str, '\n'); - o_stream_nsend(client->output, str_data(str), str_len(str)); -} - -static void -client_export_stats(string_t *str, const struct stats *stats) -{ - unsigned int i, count = stats_field_count(); - - i_assert(count > 0); - - stats_field_value(str, stats, 0); - for (i = 1; i < count; i++) { - str_append_c(str, '\t'); - stats_field_value(str, stats, i); - } -} - -static bool -mail_export_filter_match_session(const struct mail_export_filter *filter, - const struct mail_session *session) -{ - if (filter->connected && session->disconnected) - return FALSE; - if (filter->since > session->last_update.tv_sec) - return FALSE; - if (filter->session != NULL && - strcmp(session->id, filter->session) != 0) - return FALSE; - if (filter->user != NULL && - !wildcard_match(session->user->name, filter->user)) - return FALSE; - if (filter->domain != NULL && - !wildcard_match(session->user->domain->name, filter->domain)) - return FALSE; - if (filter->ip_bits > 0 && - !net_is_in_network(&session->ip->ip, &filter->ip, filter->ip_bits)) - return FALSE; - return TRUE; -} - -static bool -mail_export_filter_match_user_common(const struct mail_export_filter *filter, - const struct mail_user *user) -{ - struct mail_session *s; - bool connected = FALSE, ip_ok = FALSE; - - if (filter->user != NULL && - !wildcard_match(user->name, filter->user)) - return FALSE; - - if (filter->connected || filter->ip_bits > 0) { - for (s = user->sessions; s != NULL; s = s->user_next) { - if (!s->disconnected) - connected = TRUE; - if (filter->ip_bits > 0 && - net_is_in_network(&s->ip->ip, &filter->ip, - filter->ip_bits)) - ip_ok = TRUE; - - } - if (filter->connected && !connected) - return FALSE; - if (filter->ip_bits > 0 && !ip_ok) - return FALSE; - } - return TRUE; -} - -static bool -mail_export_filter_match_user(const struct mail_export_filter *filter, - const struct mail_user *user) -{ - if (filter->since > user->last_update.tv_sec) - return FALSE; - if (filter->domain != NULL && - !wildcard_match(user->domain->name, filter->domain)) - return FALSE; - return mail_export_filter_match_user_common(filter, user); -} - -static bool -mail_export_filter_match_domain(const struct mail_export_filter *filter, - const struct mail_domain *domain) -{ - struct mail_user *user; - - if (filter->since > domain->last_update.tv_sec) - return FALSE; - if (filter->domain != NULL && - !wildcard_match(domain->name, filter->domain)) - return FALSE; - - if (filter->user != NULL || filter->connected || filter->ip_bits > 0) { - for (user = domain->users; user != NULL; user = user->domain_next) { - if (mail_export_filter_match_user_common(filter, user)) - break; - } - if (user == NULL) - return FALSE; - } - return TRUE; -} - -static bool -mail_export_filter_match_ip(const struct mail_export_filter *filter, - const struct mail_ip *ip) -{ - struct mail_session *s; - bool connected = FALSE, user_ok = FALSE, domain_ok = FALSE; - - if (filter->connected || filter->ip_bits > 0) { - for (s = ip->sessions; s != NULL; s = s->ip_next) { - if (!s->disconnected) - connected = TRUE; - if (filter->user != NULL && - wildcard_match(s->user->name, filter->user)) - user_ok = TRUE; - if (filter->domain != NULL && - wildcard_match(s->user->domain->name, filter->domain)) - domain_ok = TRUE; - } - if (filter->connected && !connected) - return FALSE; - if (filter->user != NULL && !user_ok) - return FALSE; - if (filter->domain != NULL && !domain_ok) - return FALSE; - } - if (filter->since > ip->last_update.tv_sec) - return FALSE; - if (filter->ip_bits > 0 && - !net_is_in_network(&ip->ip, &filter->ip, filter->ip_bits)) - return FALSE; - return TRUE; -} - -static void client_export_timeval(string_t *str, const struct timeval *tv) -{ - str_printfa(str, "\t%ld.%06u", (long)tv->tv_sec, - (unsigned int)tv->tv_usec); -} - -static int client_export_iter_command(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - struct mail_command *command = client->mail_cmd_iter; - - i_assert(cmd->level == MAIL_EXPORT_LEVEL_COMMAND); - mail_command_unref(&client->mail_cmd_iter); - - if (!cmd->header_sent) { - o_stream_nsend_str(client->output, - "cmd\targs\tsession\tuser\tlast_update\t"); - client_export_stats_headers(client); - cmd->header_sent = TRUE; - } - - for (; command != NULL; command = command->stable_next) { - if (client_is_busy(client)) - break; - if (!mail_export_filter_match_session(&cmd->filter, - command->session)) - continue; - - str_truncate(cmd->str, 0); - str_append_tabescaped(cmd->str, command->name); - str_append_c(cmd->str, '\t'); - str_append_tabescaped(cmd->str, command->args); - str_append_c(cmd->str, '\t'); - str_append(cmd->str, command->session->id); - str_append_c(cmd->str, '\t'); - str_append_tabescaped(cmd->str, - command->session->user->name); - client_export_timeval(cmd->str, &command->last_update); - str_append_c(cmd->str, '\t'); - client_export_stats(cmd->str, command->stats); - str_append_c(cmd->str, '\n'); - o_stream_nsend(client->output, str_data(cmd->str), - str_len(cmd->str)); - } - - if (command != NULL) { - client->mail_cmd_iter = command; - mail_command_ref(command); - return 0; - } - return 1; -} - -static int client_export_iter_session(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - struct mail_session *session = client->mail_session_iter; - - i_assert(cmd->level == MAIL_EXPORT_LEVEL_SESSION); - mail_session_unref(&client->mail_session_iter); - - if (!cmd->header_sent) { - o_stream_nsend_str(client->output, - "session\tuser\tip\tservice\tpid\tconnected" - "\tlast_update\tnum_cmds\t"); - client_export_stats_headers(client); - cmd->header_sent = TRUE; - } - - for (; session != NULL; session = session->stable_next) { - if (client_is_busy(client)) - break; - if (!mail_export_filter_match_session(&cmd->filter, session)) - continue; - - str_truncate(cmd->str, 0); - str_append(cmd->str, session->id); - str_append_c(cmd->str, '\t'); - str_append_tabescaped(cmd->str, session->user->name); - str_append_c(cmd->str, '\t'); - if (session->ip != NULL) T_BEGIN { - str_append(cmd->str, net_ip2addr(&session->ip->ip)); - } T_END; - str_append_c(cmd->str, '\t'); - str_append_tabescaped(cmd->str, session->service); - str_printfa(cmd->str, "\t%lu", (unsigned long)session->pid); - str_printfa(cmd->str, "\t%d", !session->disconnected); - client_export_timeval(cmd->str, &session->last_update); - str_printfa(cmd->str, "\t%u\t", session->num_cmds); - client_export_stats(cmd->str, session->stats); - str_append_c(cmd->str, '\n'); - o_stream_nsend(client->output, str_data(cmd->str), - str_len(cmd->str)); - } - - if (session != NULL) { - client->mail_session_iter = session; - mail_session_ref(session); - return 0; - } - return 1; -} - -static int client_export_iter_user(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - struct mail_user *user = client->mail_user_iter; - - i_assert(cmd->level == MAIL_EXPORT_LEVEL_USER); - mail_user_unref(&client->mail_user_iter); - - if (!cmd->header_sent) { - o_stream_nsend_str(client->output, - "user\treset_timestamp\tlast_update" - "\tnum_logins\tnum_cmds\t"); - client_export_stats_headers(client); - cmd->header_sent = TRUE; - } - - for (; user != NULL; user = user->stable_next) { - if (client_is_busy(client)) - break; - if (!mail_export_filter_match_user(&cmd->filter, user)) - continue; - - str_truncate(cmd->str, 0); - str_append_tabescaped(cmd->str, user->name); - str_printfa(cmd->str, "\t%ld", (long)user->reset_timestamp); - client_export_timeval(cmd->str, &user->last_update); - str_printfa(cmd->str, "\t%u\t%u\t", - user->num_logins, user->num_cmds); - client_export_stats(cmd->str, user->stats); - str_append_c(cmd->str, '\n'); - o_stream_nsend(client->output, str_data(cmd->str), - str_len(cmd->str)); - } - - if (user != NULL) { - client->mail_user_iter = user; - mail_user_ref(user); - return 0; - } - return 1; -} - -static int client_export_iter_domain(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - struct mail_domain *domain = client->mail_domain_iter; - - i_assert(cmd->level == MAIL_EXPORT_LEVEL_DOMAIN); - mail_domain_unref(&client->mail_domain_iter); - - if (!cmd->header_sent) { - o_stream_nsend_str(client->output, - "domain\treset_timestamp\tlast_update" - "\tnum_logins\tnum_cmds\tnum_connected_sessions\t"); - client_export_stats_headers(client); - cmd->header_sent = TRUE; - } - - for (; domain != NULL; domain = domain->stable_next) { - if (client_is_busy(client)) - break; - if (!mail_export_filter_match_domain(&cmd->filter, domain)) - continue; - - str_truncate(cmd->str, 0); - str_append_tabescaped(cmd->str, domain->name); - str_printfa(cmd->str, "\t%ld", (long)domain->reset_timestamp); - client_export_timeval(cmd->str, &domain->last_update); - str_printfa(cmd->str, "\t%u\t%u\t%u\t", - domain->num_logins, domain->num_cmds, - domain->num_connected_sessions); - client_export_stats(cmd->str, domain->stats); - str_append_c(cmd->str, '\n'); - o_stream_nsend(client->output, str_data(cmd->str), - str_len(cmd->str)); - } - - if (domain != NULL) { - client->mail_domain_iter = domain; - mail_domain_ref(domain); - return 0; - } - return 1; -} - -static int client_export_iter_ip(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - struct mail_ip *ip = client->mail_ip_iter; - - i_assert(cmd->level == MAIL_EXPORT_LEVEL_IP); - mail_ip_unref(&client->mail_ip_iter); - - if (!cmd->header_sent) { - o_stream_nsend_str(client->output, - "ip\treset_timestamp\tlast_update" - "\tnum_logins\tnum_cmds\tnum_connected_sessions\t"); - client_export_stats_headers(client); - cmd->header_sent = TRUE; - } - - for (; ip != NULL; ip = ip->stable_next) { - if (client_is_busy(client)) - break; - if (!mail_export_filter_match_ip(&cmd->filter, ip)) - continue; - - str_truncate(cmd->str, 0); - T_BEGIN { - str_append(cmd->str, net_ip2addr(&ip->ip)); - } T_END; - str_printfa(cmd->str, "\t%ld", (long)ip->reset_timestamp); - client_export_timeval(cmd->str, &ip->last_update); - str_printfa(cmd->str, "\t%u\t%u\t%u\t", - ip->num_logins, ip->num_cmds, ip->num_connected_sessions); - client_export_stats(cmd->str, ip->stats); - str_append_c(cmd->str, '\n'); - o_stream_nsend(client->output, str_data(cmd->str), - str_len(cmd->str)); - } - - if (ip != NULL) { - client->mail_ip_iter = ip; - mail_ip_ref(ip); - return 0; - } - return 1; -} - -static int client_export_iter_global(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - struct mail_global *g = &mail_global_stats; - - i_assert(cmd->level == MAIL_EXPORT_LEVEL_GLOBAL); - - if (!cmd->header_sent) { - o_stream_nsend_str(client->output, - "reset_timestamp\tlast_update" - "\tnum_logins\tnum_cmds\tnum_connected_sessions\t"); - client_export_stats_headers(client); - cmd->header_sent = TRUE; - } - - str_truncate(cmd->str, 0); - str_printfa(cmd->str, "%ld", (long)g->reset_timestamp); - client_export_timeval(cmd->str, &g->last_update); - str_printfa(cmd->str, "\t%u\t%u\t%u\t", - g->num_logins, g->num_cmds, g->num_connected_sessions); - client_export_stats(cmd->str, g->stats); - str_append_c(cmd->str, '\n'); - o_stream_nsend(client->output, str_data(cmd->str), - str_len(cmd->str)); - return 1; -} - -static int client_export_more(struct client *client) -{ - if (client->cmd_export->export_iter(client) == 0) - return 0; - o_stream_nsend_str(client->output, "\n"); - return 1; -} - -static bool client_export_iter_init(struct client *client) -{ - struct client_export_cmd *cmd = client->cmd_export; - - if (cmd->filter.user != NULL && strchr(cmd->filter.user, '*') == NULL && - (cmd->level == MAIL_EXPORT_LEVEL_USER || - cmd->level == MAIL_EXPORT_LEVEL_SESSION)) { - /* exact user */ - struct mail_user *user = mail_user_lookup(cmd->filter.user); - if (user == NULL) - return FALSE; - if (cmd->level == MAIL_EXPORT_LEVEL_SESSION) { - client->mail_session_iter = user->sessions; - if (client->mail_session_iter == NULL) - return FALSE; - mail_session_ref(client->mail_session_iter); - cmd->export_iter = client_export_iter_session; - } else { - client->mail_user_iter = user; - mail_user_ref(user); - cmd->export_iter = client_export_iter_user; - } - return TRUE; - } - if (cmd->filter.ip_bits == IPADDR_BITS(&cmd->filter.ip) && - (cmd->level == MAIL_EXPORT_LEVEL_IP || - cmd->level == MAIL_EXPORT_LEVEL_SESSION)) { - /* exact IP address */ - struct mail_ip *ip = mail_ip_lookup(&cmd->filter.ip); - if (ip == NULL) - return FALSE; - if (cmd->level == MAIL_EXPORT_LEVEL_SESSION) { - client->mail_session_iter = ip->sessions; - if (client->mail_session_iter == NULL) - return FALSE; - mail_session_ref(client->mail_session_iter); - cmd->export_iter = client_export_iter_session; - } else { - client->mail_ip_iter = ip; - mail_ip_ref(ip); - cmd->export_iter = client_export_iter_ip; - } - return TRUE; - } - if (cmd->filter.domain != NULL && - strchr(cmd->filter.domain, '*') == NULL && - (cmd->level == MAIL_EXPORT_LEVEL_DOMAIN || - cmd->level == MAIL_EXPORT_LEVEL_USER)) { - /* exact domain */ - struct mail_domain *domain = - mail_domain_lookup(cmd->filter.domain); - if (domain == NULL) - return FALSE; - if (cmd->level == MAIL_EXPORT_LEVEL_USER) { - client->mail_user_iter = domain->users; - mail_user_ref(client->mail_user_iter); - cmd->export_iter = client_export_iter_user; - } else { - client->mail_domain_iter = domain; - mail_domain_ref(domain); - cmd->export_iter = client_export_iter_domain; - } - return TRUE; - } - - switch (cmd->level) { - case MAIL_EXPORT_LEVEL_COMMAND: - client->mail_cmd_iter = stable_mail_commands_head; - if (client->mail_cmd_iter == NULL) - return FALSE; - mail_command_ref(client->mail_cmd_iter); - cmd->export_iter = client_export_iter_command; - break; - case MAIL_EXPORT_LEVEL_SESSION: - client->mail_session_iter = stable_mail_sessions; - if (client->mail_session_iter == NULL) - return FALSE; - mail_session_ref(client->mail_session_iter); - cmd->export_iter = client_export_iter_session; - break; - case MAIL_EXPORT_LEVEL_USER: - client->mail_user_iter = stable_mail_users; - if (client->mail_user_iter == NULL) - return FALSE; - mail_user_ref(client->mail_user_iter); - cmd->export_iter = client_export_iter_user; - break; - case MAIL_EXPORT_LEVEL_DOMAIN: - client->mail_domain_iter = stable_mail_domains; - if (client->mail_domain_iter == NULL) - return FALSE; - mail_domain_ref(client->mail_domain_iter); - cmd->export_iter = client_export_iter_domain; - break; - case MAIL_EXPORT_LEVEL_IP: - client->mail_ip_iter = stable_mail_ips; - if (client->mail_ip_iter == NULL) - return FALSE; - mail_ip_ref(client->mail_ip_iter); - cmd->export_iter = client_export_iter_ip; - break; - case MAIL_EXPORT_LEVEL_GLOBAL: - cmd->export_iter = client_export_iter_global; - break; - } - i_assert(cmd->export_iter != NULL); - return TRUE; -} - -int client_export(struct client *client, const char *const *args, - const char **error_r) -{ - const char *level_str = args[0]; - struct client_export_cmd *cmd; - - p_clear(client->cmd_pool); - cmd = p_new(client->cmd_pool, struct client_export_cmd, 1); - cmd->str = str_new(client->cmd_pool, 256); - - if (level_str == NULL) { - *error_r = "Missing level parameter"; - return -1; - } - if (mail_export_level_parse(level_str, &cmd->level) < 0) { - *error_r = "Invalid level"; - return -1; - } - if (mail_export_parse_filter(args + 1, client->cmd_pool, - &cmd->filter, error_r) < 0) - return -1; - - client->cmd_export = cmd; - if (!client_export_iter_init(client)) { - /* nothing to export */ - o_stream_nsend_str(client->output, "\n"); - return 1; - } - client->cmd_more = client_export_more; - return client_export_more(client); -} diff --git a/src/old-stats/client-export.h b/src/old-stats/client-export.h deleted file mode 100644 index ddca1386f7..0000000000 --- a/src/old-stats/client-export.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CLIENT_EXPORT_H -#define CLIENT_EXPORT_H - -struct client; - -int client_export(struct client *client, const char *const *args, - const char **error_r); - -#endif diff --git a/src/old-stats/client-reset.c b/src/old-stats/client-reset.c deleted file mode 100644 index 965bb222e7..0000000000 --- a/src/old-stats/client-reset.c +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ostream.h" -#include "strescape.h" -#include "mail-stats.h" -#include "client.h" -#include "client-reset.h" - -int client_stats_reset(struct client *client, const char *const *args ATTR_UNUSED, - const char **error_r ATTR_UNUSED) -{ - struct mail_global *g = &mail_global_stats; - stats_reset(g->stats); - g->num_logins = 0; - g->num_cmds = 0; - g->reset_timestamp = ioloop_time; - i_zero(&g->last_update); - o_stream_nsend_str(client->output, "OK\n"); - return 0; -} diff --git a/src/old-stats/client-reset.h b/src/old-stats/client-reset.h deleted file mode 100644 index 7a84d610ff..0000000000 --- a/src/old-stats/client-reset.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef CLIENT_RESET_H -#define CLIENT_RESET_H - -struct client; - -int client_stats_reset(struct client *client, const char *const *args, - const char **error_r); - -#endif diff --git a/src/old-stats/client.c b/src/old-stats/client.c deleted file mode 100644 index 5a6d5cb329..0000000000 --- a/src/old-stats/client.c +++ /dev/null @@ -1,193 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "llist.h" -#include "ioloop.h" -#include "istream.h" -#include "ostream.h" -#include "strescape.h" -#include "master-service.h" -#include "mail-command.h" -#include "mail-session.h" -#include "mail-user.h" -#include "mail-domain.h" -#include "mail-ip.h" -#include "client-export.h" -#include "client-reset.h" -#include "client.h" - -#include - -#define CLIENT_MAX_SIMULTANEOUS_ITER_COUNT 1000 -#define MAX_INBUF_SIZE 1024 -#define OUTBUF_THROTTLE_SIZE (1024*64) - -static struct client *clients; - -bool client_is_busy(struct client *client) -{ - client->iter_count++; - if (client->iter_count % CLIENT_MAX_SIMULTANEOUS_ITER_COUNT == 0) - return TRUE; - if (o_stream_get_buffer_used_size(client->output) < OUTBUF_THROTTLE_SIZE) - return FALSE; - if (o_stream_flush(client->output) < 0) - return TRUE; - return o_stream_get_buffer_used_size(client->output) >= OUTBUF_THROTTLE_SIZE; -} - -static int -client_handle_request(struct client *client, const char *const *args, - const char **error_r) -{ - const char *cmd = args[0]; - - if (cmd == NULL) { - *error_r = "Missing command"; - return -1; - } - args++; - - if (strcmp(cmd, "EXPORT") == 0) - return client_export(client, args, error_r); - if (strcmp(cmd, "RESET") == 0) - return client_stats_reset(client, args, error_r); - - *error_r = "Unknown command"; - return -1; -} - -static const char *const* -client_read_next_line(struct client *client) -{ - const char *line; - - line = i_stream_next_line(client->input); - if (line == NULL) - return NULL; - - return t_strsplit_tabescaped(line); -} - -static void client_input(struct client *client) -{ - const char *const *args, *error; - int ret; - - timeout_remove(&client->to_pending); - - switch (i_stream_read(client->input)) { - case -2: - i_error("BUG: Stats client sent too much data"); - client_destroy(&client); - return; - case -1: - client_destroy(&client); - return; - } - - o_stream_cork(client->output); - while ((args = client_read_next_line(client)) != NULL) { - ret = client_handle_request(client, args, &error); - if (ret < 0) { - i_error("Stats client input error: %s", error); - client_destroy(&client); - return; - } - if (ret == 0) { - o_stream_set_flush_pending(client->output, TRUE); - io_remove(&client->io); - break; - } - client->cmd_more = NULL; - } - o_stream_uncork(client->output); -} - -static int client_output(struct client *client) -{ - int ret = 1; - - if (o_stream_flush(client->output) < 0) { - client_destroy(&client); - return 1; - } - if (client->cmd_more != NULL) - ret = client->cmd_more(client); - - if (ret > 0) { - client->cmd_more = NULL; - if (client->io == NULL) - client_enable_io(client); - } - return ret; -} - -void client_enable_io(struct client *client) -{ - i_assert(client->io == NULL); - - client->io = io_add(client->fd, IO_READ, client_input, client); - if (client->to_pending == NULL) - client->to_pending = timeout_add(0, client_input, client); -} - -struct client *client_create(int fd) -{ - struct client *client; - - client = i_new(struct client, 1); - client->fd = fd; - client->io = io_add(fd, IO_READ, client_input, client); - client->input = i_stream_create_fd(fd, MAX_INBUF_SIZE); - client->output = o_stream_create_fd(fd, SIZE_MAX); - o_stream_set_no_error_handling(client->output, TRUE); - o_stream_set_flush_callback(client->output, client_output, client); - client->cmd_pool = pool_alloconly_create("cmd pool", 1024); - - DLLIST_PREPEND(&clients, client); - return client; -} - -static void client_unref_iters(struct client *client) -{ - if (client->mail_cmd_iter != NULL) - mail_command_unref(&client->mail_cmd_iter); - if (client->mail_session_iter != NULL) - mail_session_unref(&client->mail_session_iter); - if (client->mail_user_iter != NULL) - mail_user_unref(&client->mail_user_iter); - if (client->mail_domain_iter != NULL) - mail_domain_unref(&client->mail_domain_iter); - if (client->mail_ip_iter != NULL) - mail_ip_unref(&client->mail_ip_iter); -} - -void client_destroy(struct client **_client) -{ - struct client *client = *_client; - - *_client = NULL; - - DLLIST_REMOVE(&clients, client); - io_remove(&client->io); - i_stream_destroy(&client->input); - o_stream_destroy(&client->output); - if (close(client->fd) < 0) - i_error("close(client) failed: %m"); - - client_unref_iters(client); - pool_unref(&client->cmd_pool); - i_free(client); - - master_service_client_connection_destroyed(master_service); -} - -void clients_destroy_all(void) -{ - while (clients != NULL) { - struct client *client = clients; - - client_destroy(&client); - } -} diff --git a/src/old-stats/client.h b/src/old-stats/client.h deleted file mode 100644 index 5650d7fc65..0000000000 --- a/src/old-stats/client.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef CLIENT_H -#define CLIENT_H - -struct client { - struct client *prev, *next; - - int fd; - struct io *io; - struct istream *input; - struct ostream *output; - struct timeout *to_pending; - - pool_t cmd_pool; - struct client_export_cmd *cmd_export; - int (*cmd_more)(struct client *client); - - /* command iterators. while non-NULL, they've increased the - struct's refcount so it won't be deleted during iteration */ - unsigned int iter_count; - struct mail_command *mail_cmd_iter; - struct mail_session *mail_session_iter; - struct mail_user *mail_user_iter; - struct mail_domain *mail_domain_iter; - struct mail_ip *mail_ip_iter; -}; - -struct client *client_create(int fd); -void client_destroy(struct client **client); - -bool client_is_busy(struct client *client); -void client_enable_io(struct client *client); - -void clients_destroy_all(void); - -#endif diff --git a/src/old-stats/fifo-input-connection.c b/src/old-stats/fifo-input-connection.c deleted file mode 100644 index 1b9759d39e..0000000000 --- a/src/old-stats/fifo-input-connection.c +++ /dev/null @@ -1,108 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "llist.h" -#include "strescape.h" -#include "istream.h" -#include "ostream.h" -#include "master-service.h" -#include "mail-session.h" -#include "mail-user.h" -#include "mail-command.h" -#include "fifo-input-connection.h" - -#include - -#define MAX_INBUF_SIZE (PIPE_BUF*2) - -struct fifo_input_connection { - struct fifo_input_connection *prev, *next; - - int fd; - struct istream *input; - struct io *io; -}; - -static struct fifo_input_connection *fifo_conns = NULL; - -static int -fifo_input_connection_request(const char *const *args, const char **error_r) -{ - const char *cmd = args[0]; - - if (cmd == NULL) { - *error_r = "Missing command"; - return -1; - } - args++; - - if (strcmp(cmd, "CONNECT") == 0) - return mail_session_connect_parse(args, error_r); - if (strcmp(cmd, "DISCONNECT") == 0) - return mail_session_disconnect_parse(args, error_r); - if (strcmp(cmd, "UPDATE-SESSION") == 0) - return mail_session_update_parse(args, error_r); - if (strcmp(cmd, "ADD-USER") == 0) - return mail_user_add_parse(args, error_r); - if (strcmp(cmd, "UPDATE-CMD") == 0) - return mail_command_update_parse(args, error_r); - - *error_r = "Unknown command"; - return -1; -} - -static void fifo_input_connection_input(struct fifo_input_connection *conn) -{ - const char *line, *const *args, *error; - - switch (i_stream_read(conn->input)) { - case -2: - i_error("BUG: Mail server sent too much data"); - fifo_input_connection_destroy(&conn); - return; - case -1: - fifo_input_connection_destroy(&conn); - return; - } - - while ((line = i_stream_next_line(conn->input)) != NULL) T_BEGIN { - args = t_strsplit_tabescaped(line); - if (fifo_input_connection_request(args, &error) < 0) - i_error("FIFO input error: %s", error); - } T_END; -} - -struct fifo_input_connection *fifo_input_connection_create(int fd) -{ - struct fifo_input_connection *conn; - - conn = i_new(struct fifo_input_connection, 1); - conn->fd = fd; - conn->input = i_stream_create_fd(fd, MAX_INBUF_SIZE); - conn->io = io_add(fd, IO_READ, fifo_input_connection_input, conn); - DLLIST_PREPEND(&fifo_conns, conn); - return conn; -} - -void fifo_input_connection_destroy(struct fifo_input_connection **_conn) -{ - struct fifo_input_connection *conn = *_conn; - - *_conn = NULL; - - DLLIST_REMOVE(&fifo_conns, conn); - io_remove(&conn->io); - i_stream_destroy(&conn->input); - if (close(conn->fd) < 0) - i_error("close(conn) failed: %m"); - i_free(conn); -} - -void fifo_input_connections_destroy_all(void) -{ - while (fifo_conns != NULL) { - struct fifo_input_connection *conn = fifo_conns; - - fifo_input_connection_destroy(&conn); - } -} diff --git a/src/old-stats/fifo-input-connection.h b/src/old-stats/fifo-input-connection.h deleted file mode 100644 index ff394a5060..0000000000 --- a/src/old-stats/fifo-input-connection.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef FIFO_INPUT_CONNECTION_H -#define FIFO_INPUT_CONNECTION_H - -struct fifo_input_connection *fifo_input_connection_create(int fd); -void fifo_input_connection_destroy(struct fifo_input_connection **conn); - -void fifo_input_connections_destroy_all(void); - -#endif diff --git a/src/old-stats/global-memory.c b/src/old-stats/global-memory.c deleted file mode 100644 index dc04bfb1af..0000000000 --- a/src/old-stats/global-memory.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "mail-command.h" -#include "mail-session.h" -#include "mail-user.h" -#include "mail-domain.h" -#include "mail-ip.h" -#include "stats-settings.h" -#include "global-memory.h" - -size_t global_used_memory = 0; - -static bool global_memory_free_something(void) -{ - size_t orig_used_memory = global_used_memory; - - mail_commands_free_memory(); - if (global_used_memory > stats_settings->memory_limit) - mail_sessions_free_memory(); - if (global_used_memory > stats_settings->memory_limit) - mail_users_free_memory(); - if (global_used_memory > stats_settings->memory_limit) - mail_ips_free_memory(); - if (global_used_memory > stats_settings->memory_limit) - mail_domains_free_memory(); - - return global_used_memory < orig_used_memory; -} - -void global_memory_alloc(size_t size) -{ - i_assert(size < SIZE_MAX - global_used_memory); - global_used_memory += size; - - while (global_used_memory > stats_settings->memory_limit) { - if (!global_memory_free_something()) - break; - } -} - -void global_memory_free(size_t size) -{ - i_assert(size <= global_used_memory); - global_used_memory -= size; -} diff --git a/src/old-stats/global-memory.h b/src/old-stats/global-memory.h deleted file mode 100644 index 840ffc77c2..0000000000 --- a/src/old-stats/global-memory.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef GLOBAL_MEMORY_H -#define GLOBAL_MEMORY_H - -extern size_t global_used_memory; - -void global_memory_alloc(size_t size); -void global_memory_free(size_t size); - -#endif diff --git a/src/old-stats/mail-command.c b/src/old-stats/mail-command.c deleted file mode 100644 index 98fdc9dd59..0000000000 --- a/src/old-stats/mail-command.c +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "buffer.h" -#include "base64.h" -#include "ioloop.h" -#include "llist.h" -#include "global-memory.h" -#include "stats-settings.h" -#include "mail-stats.h" -#include "mail-session.h" -#include "mail-command.h" - -#define MAIL_COMMAND_TIMEOUT_SECS (60*15) - -/* commands are sorted by their last_update timestamp, oldest first */ -struct mail_command *stable_mail_commands_head; -struct mail_command *stable_mail_commands_tail; - -static size_t mail_command_memsize(const struct mail_command *cmd) -{ - return sizeof(*cmd) + strlen(cmd->name) + 1 + strlen(cmd->args) + 1; -} - -static struct mail_command * -mail_command_find(struct mail_session *session, unsigned int id) -{ - struct mail_command *cmd; - - i_assert(id != 0); - - if (id > session->highest_cmd_id) { - /* fast path for new commands */ - return NULL; - } - for (cmd = session->commands; cmd != NULL; cmd = cmd->session_next) { - if (cmd->id == id) - return cmd; - } - /* expired */ - return NULL; -} - -static struct mail_command * -mail_command_add(struct mail_session *session, const char *name, - const char *args) -{ - struct mail_command *cmd; - - cmd = i_malloc(MALLOC_ADD(sizeof(struct mail_command), stats_alloc_size())); - cmd->stats = (void *)(cmd + 1); - cmd->refcount = 1; /* unrefed at "done" */ - cmd->session = session; - cmd->name = i_strdup(name); - cmd->args = i_strdup(args); - cmd->last_update = ioloop_timeval; - - DLLIST2_APPEND_FULL(&stable_mail_commands_head, - &stable_mail_commands_tail, cmd, - stable_prev, stable_next); - DLLIST_PREPEND_FULL(&session->commands, cmd, - session_prev, session_next); - mail_session_ref(cmd->session); - global_memory_alloc(mail_command_memsize(cmd)); - return cmd; -} - -static void mail_command_free(struct mail_command *cmd) -{ - i_assert(cmd->refcount == 0); - - global_memory_free(mail_command_memsize(cmd)); - - DLLIST2_REMOVE_FULL(&stable_mail_commands_head, - &stable_mail_commands_tail, cmd, - stable_prev, stable_next); - DLLIST_REMOVE_FULL(&cmd->session->commands, cmd, - session_prev, session_next); - mail_session_unref(&cmd->session); - i_free(cmd->name); - i_free(cmd->args); - i_free(cmd); -} - -void mail_command_ref(struct mail_command *cmd) -{ - cmd->refcount++; -} - -void mail_command_unref(struct mail_command **_cmd) -{ - struct mail_command *cmd = *_cmd; - - i_assert(cmd->refcount > 0); - cmd->refcount--; - - *_cmd = NULL; -} - -int mail_command_update_parse(const char *const *args, const char **error_r) -{ - struct mail_session *session; - struct mail_command *cmd; - struct stats *new_stats, *diff_stats; - buffer_t *buf; - const char *error; - unsigned int i, cmd_id; - bool done = FALSE, continued = FALSE; - - /* [d] - c[d] */ - if (str_array_length(args) < 3) { - *error_r = "UPDATE-CMD: Too few parameters"; - return -1; - } - if (mail_session_get(args[0], &session, error_r) < 0) - return -1; - - if (str_to_uint(args[1], &cmd_id) < 0 || cmd_id == 0) { - *error_r = "UPDATE-CMD: Invalid command id"; - return -1; - } - for (i = 0; args[2][i] != '\0'; i++) { - switch (args[2][i]) { - case 'd': - done = TRUE; - break; - case 'c': - continued = TRUE; - break; - default: - *error_r = "UPDATE-CMD: Invalid flags parameter"; - return -1; - } - } - - cmd = mail_command_find(session, cmd_id); - if (!continued) { - /* new command */ - if (cmd != NULL) { - *error_r = "UPDATE-CMD: Duplicate new command id"; - return -1; - } - if (str_array_length(args) < 5) { - *error_r = "UPDATE-CMD: Too few parameters"; - return -1; - } - cmd = mail_command_add(session, args[3], args[4]); - cmd->id = cmd_id; - - session->highest_cmd_id = - I_MAX(session->highest_cmd_id, cmd_id); - session->num_cmds++; - session->user->num_cmds++; - session->user->domain->num_cmds++; - if (session->ip != NULL) - session->ip->num_cmds++; - mail_global_stats.num_cmds++; - args += 5; - } else { - if (cmd == NULL) { - /* already expired command, ignore */ - i_warning("UPDATE-CMD: Already expired"); - return 0; - } - args += 3; - cmd->last_update = ioloop_timeval; - } - buf = t_buffer_create(256); - if (args[0] == NULL || - base64_decode(args[0], strlen(args[0]), NULL, buf) < 0) { - *error_r = t_strdup_printf("UPDATE-CMD: Invalid base64 input"); - return -1; - } - - new_stats = stats_alloc(pool_datastack_create()); - diff_stats = stats_alloc(pool_datastack_create()); - - if (!stats_import(buf->data, buf->used, cmd->stats, new_stats, &error)) { - *error_r = t_strdup_printf("UPDATE-CMD: %s", error); - return -1; - } - - if (!stats_diff(cmd->stats, new_stats, diff_stats, &error)) { - *error_r = t_strdup_printf("UPDATE-CMD: stats shrank: %s", error); - return -1; - } - stats_add(cmd->stats, diff_stats); - - if (done) { - cmd->id = 0; - mail_command_unref(&cmd); - } - mail_session_refresh(session, NULL); - return 0; -} - -static bool mail_command_is_timed_out(struct mail_command *cmd) -{ - /* some commands like IDLE can run forever */ - return ioloop_time - cmd->last_update.tv_sec > - MAIL_COMMAND_TIMEOUT_SECS; -} - -void mail_commands_free_memory(void) -{ - unsigned int diff; - - while (stable_mail_commands_head != NULL) { - struct mail_command *cmd = stable_mail_commands_head; - - if (cmd->refcount == 0) - i_assert(cmd->id == 0); - else if (cmd->refcount == 1 && - (cmd->session->disconnected || - mail_command_is_timed_out(cmd))) { - /* session was probably lost */ - mail_command_unref(&cmd); - } else { - break; - } - mail_command_free(stable_mail_commands_head); - - if (global_used_memory < stats_settings->memory_limit || - stable_mail_commands_head == NULL) - break; - - diff = ioloop_time - stable_mail_commands_head->last_update.tv_sec; - if (diff < stats_settings->command_min_time) - break; - } -} - -void mail_commands_init(void) -{ -} - -void mail_commands_deinit(void) -{ - while (stable_mail_commands_head != NULL) { - struct mail_command *cmd = stable_mail_commands_head; - - if (cmd->id != 0) - mail_command_unref(&cmd); - mail_command_free(stable_mail_commands_head); - } -} diff --git a/src/old-stats/mail-command.h b/src/old-stats/mail-command.h deleted file mode 100644 index 681af8320f..0000000000 --- a/src/old-stats/mail-command.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef MAIL_COMMAND_H -#define MAIL_COMMAND_H - -struct mail_command; - -extern struct mail_command *stable_mail_commands_head; -extern struct mail_command *stable_mail_commands_tail; - -int mail_command_update_parse(const char *const *args, const char **error_r); - -void mail_command_ref(struct mail_command *cmd); -void mail_command_unref(struct mail_command **cmd); - -void mail_commands_free_memory(void); -void mail_commands_init(void); -void mail_commands_deinit(void); - -#endif diff --git a/src/old-stats/mail-domain.c b/src/old-stats/mail-domain.c deleted file mode 100644 index 140fc15c62..0000000000 --- a/src/old-stats/mail-domain.c +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "hash.h" -#include "llist.h" -#include "global-memory.h" -#include "stats-settings.h" -#include "mail-stats.h" -#include "mail-domain.h" - -static HASH_TABLE(char *, struct mail_domain *) mail_domains_hash; -/* domains are sorted by their last_update timestamp, oldest first */ -static struct mail_domain *mail_domains_head, *mail_domains_tail; -struct mail_domain *stable_mail_domains; - -static size_t mail_domain_memsize(const struct mail_domain *domain) -{ - return sizeof(*domain) + strlen(domain->name) + 1; -} - -struct mail_domain *mail_domain_login_create(const char *name) -{ - struct mail_domain *domain; - - domain = hash_table_lookup(mail_domains_hash, name); - if (domain != NULL) { - return domain; - } - - domain = i_malloc(MALLOC_ADD(sizeof(struct mail_domain), stats_alloc_size())); - domain->stats = (void *)(domain + 1); - domain->name = i_strdup(name); - domain->reset_timestamp = ioloop_time; - - hash_table_insert(mail_domains_hash, domain->name, domain); - DLLIST_PREPEND_FULL(&stable_mail_domains, domain, - stable_prev, stable_next); - global_memory_alloc(mail_domain_memsize(domain)); - return domain; -} - -void mail_domain_login(struct mail_domain *domain) -{ - domain->num_logins++; - domain->num_connected_sessions++; - mail_domain_refresh(domain, NULL); -} - -void mail_domain_disconnected(struct mail_domain *domain) -{ - i_assert(domain->num_connected_sessions > 0); - domain->num_connected_sessions--; - mail_global_disconnected(); -} - -struct mail_domain *mail_domain_lookup(const char *name) -{ - return hash_table_lookup(mail_domains_hash, name); -} - -void mail_domain_ref(struct mail_domain *domain) -{ - domain->refcount++; -} - -void mail_domain_unref(struct mail_domain **_domain) -{ - struct mail_domain *domain = *_domain; - - i_assert(domain->refcount > 0); - domain->refcount--; - - *_domain = NULL; -} - -static void mail_domain_free(struct mail_domain *domain) -{ - i_assert(domain->refcount == 0); - i_assert(domain->users == NULL); - - global_memory_free(mail_domain_memsize(domain)); - hash_table_remove(mail_domains_hash, domain->name); - DLLIST_REMOVE_FULL(&stable_mail_domains, domain, - stable_prev, stable_next); - DLLIST2_REMOVE_FULL(&mail_domains_head, &mail_domains_tail, domain, - sorted_prev, sorted_next); - - i_free(domain->name); - i_free(domain); -} - -void mail_domain_refresh(struct mail_domain *domain, - const struct stats *diff_stats) -{ - if (diff_stats != NULL) - stats_add(domain->stats, diff_stats); - domain->last_update = ioloop_timeval; - DLLIST2_REMOVE_FULL(&mail_domains_head, &mail_domains_tail, domain, - sorted_prev, sorted_next); - DLLIST2_APPEND_FULL(&mail_domains_head, &mail_domains_tail, domain, - sorted_prev, sorted_next); - mail_global_refresh(diff_stats); -} - -void mail_domains_free_memory(void) -{ - unsigned int diff; - - while (mail_domains_head != NULL && mail_domains_head->refcount == 0) { - mail_domain_free(mail_domains_head); - - if (global_used_memory < stats_settings->memory_limit || - mail_domains_head == NULL) - break; - - diff = ioloop_time - mail_domains_head->last_update.tv_sec; - if (diff < stats_settings->domain_min_time) - break; - } -} - -void mail_domains_init(void) -{ - hash_table_create(&mail_domains_hash, default_pool, 0, str_hash, strcmp); -} - -void mail_domains_deinit(void) -{ - while (mail_domains_head != NULL) - mail_domain_free(mail_domains_head); - hash_table_destroy(&mail_domains_hash); -} diff --git a/src/old-stats/mail-domain.h b/src/old-stats/mail-domain.h deleted file mode 100644 index 23e2fbed44..0000000000 --- a/src/old-stats/mail-domain.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MAIL_DOMAIN_H -#define MAIL_DOMAIN_H - -struct stats; - -extern struct mail_domain *stable_mail_domains; - -struct mail_domain *mail_domain_login_create(const char *name); -void mail_domain_login(struct mail_domain *domain); -void mail_domain_disconnected(struct mail_domain *domain); -struct mail_domain *mail_domain_lookup(const char *name); -void mail_domain_refresh(struct mail_domain *domain, - const struct stats *diff_stats) ATTR_NULL(2); - -void mail_domain_ref(struct mail_domain *domain); -void mail_domain_unref(struct mail_domain **domain); - -void mail_domains_free_memory(void); -void mail_domains_init(void); -void mail_domains_deinit(void); - -#endif diff --git a/src/old-stats/mail-ip.c b/src/old-stats/mail-ip.c deleted file mode 100644 index bb0209f482..0000000000 --- a/src/old-stats/mail-ip.c +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "hash.h" -#include "llist.h" -#include "global-memory.h" -#include "stats-settings.h" -#include "mail-stats.h" -#include "mail-ip.h" - -static HASH_TABLE(struct ip_addr *, struct mail_ip *) mail_ips_hash; -/* ips are sorted by their last_update timestamp, oldest first */ -static struct mail_ip *mail_ips_head, *mail_ips_tail; -struct mail_ip *stable_mail_ips; - -static size_t mail_ip_memsize(const struct mail_ip *ip) -{ - return sizeof(*ip); -} - -struct mail_ip *mail_ip_login(const struct ip_addr *ip_addr) -{ - struct mail_ip *ip; - - ip = hash_table_lookup(mail_ips_hash, ip_addr); - if (ip != NULL) { - ip->num_logins++; - ip->num_connected_sessions++; - mail_ip_refresh(ip, NULL); - return ip; - } - - ip = i_malloc(MALLOC_ADD(sizeof(struct mail_ip), stats_alloc_size())); - ip->stats = (void *)(ip + 1); - ip->ip = *ip_addr; - ip->reset_timestamp = ioloop_time; - - hash_table_insert(mail_ips_hash, &ip->ip, ip); - DLLIST_PREPEND_FULL(&stable_mail_ips, ip, stable_prev, stable_next); - DLLIST2_APPEND_FULL(&mail_ips_head, &mail_ips_tail, ip, - sorted_prev, sorted_next); - ip->num_logins++; - ip->num_connected_sessions++; - ip->last_update = ioloop_timeval; - global_memory_alloc(mail_ip_memsize(ip)); - return ip; -} - -void mail_ip_disconnected(struct mail_ip *ip) -{ - i_assert(ip->num_connected_sessions > 0); - ip->num_connected_sessions--; -} - -struct mail_ip *mail_ip_lookup(const struct ip_addr *ip_addr) -{ - return hash_table_lookup(mail_ips_hash, ip_addr); -} - -void mail_ip_ref(struct mail_ip *ip) -{ - ip->refcount++; -} - -void mail_ip_unref(struct mail_ip **_ip) -{ - struct mail_ip *ip = *_ip; - - i_assert(ip->refcount > 0); - ip->refcount--; - - *_ip = NULL; -} - -static void mail_ip_free(struct mail_ip *ip) -{ - i_assert(ip->refcount == 0); - i_assert(ip->sessions == NULL); - - global_memory_free(mail_ip_memsize(ip)); - hash_table_remove(mail_ips_hash, &ip->ip); - DLLIST_REMOVE_FULL(&stable_mail_ips, ip, stable_prev, stable_next); - DLLIST2_REMOVE_FULL(&mail_ips_head, &mail_ips_tail, ip, - sorted_prev, sorted_next); - - i_free(ip); -} - -void mail_ip_refresh(struct mail_ip *ip, const struct stats *diff_stats) -{ - if (diff_stats != NULL) - stats_add(ip->stats, diff_stats); - ip->last_update = ioloop_timeval; - DLLIST2_REMOVE_FULL(&mail_ips_head, &mail_ips_tail, ip, - sorted_prev, sorted_next); - DLLIST2_APPEND_FULL(&mail_ips_head, &mail_ips_tail, ip, - sorted_prev, sorted_next); -} - -void mail_ips_free_memory(void) -{ - unsigned int diff; - - while (mail_ips_head != NULL && mail_ips_head->refcount == 0) { - mail_ip_free(mail_ips_head); - - if (global_used_memory < stats_settings->memory_limit || - mail_ips_head == NULL) - break; - - diff = ioloop_time - mail_ips_head->last_update.tv_sec; - if (diff < stats_settings->ip_min_time) - break; - } -} - -void mail_ips_init(void) -{ - hash_table_create(&mail_ips_hash, default_pool, 0, - net_ip_hash, net_ip_cmp); -} - -void mail_ips_deinit(void) -{ - while (mail_ips_head != NULL) - mail_ip_free(mail_ips_head); - hash_table_destroy(&mail_ips_hash); -} diff --git a/src/old-stats/mail-ip.h b/src/old-stats/mail-ip.h deleted file mode 100644 index f7ff864d63..0000000000 --- a/src/old-stats/mail-ip.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MAIL_IP_H -#define MAIL_IP_H - -extern struct mail_ip *stable_mail_ips; - -struct mail_ip *mail_ip_login(const struct ip_addr *ip_addr); -void mail_ip_disconnected(struct mail_ip *ip); -struct mail_ip *mail_ip_lookup(const struct ip_addr *ip_addr); -void mail_ip_refresh(struct mail_ip *ip, const struct stats *diff_stats) - ATTR_NULL(2); - -void mail_ip_ref(struct mail_ip *ip); -void mail_ip_unref(struct mail_ip **ip); - -void mail_ips_free_memory(void); -void mail_ips_init(void); -void mail_ips_deinit(void); - -#endif diff --git a/src/old-stats/mail-session.c b/src/old-stats/mail-session.c deleted file mode 100644 index db202b305a..0000000000 --- a/src/old-stats/mail-session.c +++ /dev/null @@ -1,343 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "buffer.h" -#include "base64.h" -#include "ioloop.h" -#include "hash.h" -#include "llist.h" -#include "str-table.h" -#include "global-memory.h" -#include "stats-settings.h" -#include "mail-stats.h" -#include "mail-user.h" -#include "mail-ip.h" -#include "mail-session.h" -#include "mail-domain.h" - -/* If session doesn't receive any updates for this long, assume that the - process associated with it has crashed, and forcibly disconnect the - session. Must be larger than SESSION_STATS_FORCE_REFRESH_SECS in - stats plugin */ -#define MAIL_SESSION_IDLE_TIMEOUT_MSECS (1000*60*15) -/* If stats process crashes/restarts, existing processes keep sending status - updates to it, but this process doesn't know their session IDs. If these - missing IDs are found within this many seconds of starting the stats process, - don't log a warning about them. (On a larger installation this avoids - flooding the error log with hundreds of warnings.) */ -#define SESSION_ID_WARN_HIDE_SECS (60*5) - -static HASH_TABLE(char *, struct mail_session *) mail_sessions_hash; -/* sessions are sorted by their last_update timestamp, oldest first */ -static struct mail_session *mail_sessions_head, *mail_sessions_tail; -static time_t session_id_warn_hide_until; -static bool session_id_hide_warned = FALSE; -static struct str_table *services; - -struct mail_session *stable_mail_sessions; - -static size_t mail_session_memsize(const struct mail_session *session) -{ - return sizeof(*session) + strlen(session->id) + 1; -} - -static void mail_session_disconnect(struct mail_session *session) -{ - i_assert(!session->disconnected); - - mail_user_disconnected(session->user); - if (session->ip != NULL) - mail_ip_disconnected(session->ip); - - hash_table_remove(mail_sessions_hash, session->id); - session->disconnected = TRUE; - timeout_remove(&session->to_idle); - mail_session_unref(&session); -} - -static void mail_session_idle_timeout(struct mail_session *session) -{ - /* user="" service="" pid=0 is used for incoming sessions that were - received after we detected a stats process crash/restart. there's - no point in logging anything about them, since they contain no - useful information. */ - if (session->user->name[0] == '\0' && session->service[0] != '\0' && - session->pid == 0) { - i_warning("Session %s (user %s, service %s) " - "appears to have crashed, disconnecting it", - session->id, session->user->name, session->service); - } - mail_session_disconnect(session); -} - -int mail_session_connect_parse(const char *const *args, const char **error_r) -{ - struct mail_session *session; - const char *session_id; - pid_t pid; - struct ip_addr ip; - unsigned int i; - - /* [key=value ..] */ - if (str_array_length(args) < 4) { - *error_r = "CONNECT: Too few parameters"; - return -1; - } - session_id = args[0]; - if (str_to_pid(args[3], &pid) < 0) { - *error_r = t_strdup_printf("CONNECT: Invalid pid %s for session ID %s", - args[3], session_id); - return -1; - } - - session = hash_table_lookup(mail_sessions_hash, session_id); - if (session != NULL) { - *error_r = t_strdup_printf( - "CONNECT: Duplicate session ID %s for user %s service %s (old PID %ld, new PID %ld)", - session_id, args[1], args[2], (long)session->pid, (long)pid); - return -1; - } - session = i_malloc(MALLOC_ADD(sizeof(struct mail_session), stats_alloc_size())); - session->stats = (void *)(session + 1); - session->refcount = 1; /* unrefed at disconnect */ - session->id = i_strdup(session_id); - session->service = str_table_ref(services, args[2]); - session->pid = pid; - session->last_update = ioloop_timeval; - session->to_idle = timeout_add(MAIL_SESSION_IDLE_TIMEOUT_MSECS, - mail_session_idle_timeout, session); - - session->user = mail_user_login(args[1]); - session->user->num_logins++; - mail_domain_login(session->user->domain); - - for (i = 3; args[i] != NULL; i++) { - if (str_begins(args[i], "rip=") && - net_addr2ip(args[i] + 4, &ip) == 0) - session->ip = mail_ip_login(&ip); - } - - hash_table_insert(mail_sessions_hash, session->id, session); - DLLIST_PREPEND_FULL(&stable_mail_sessions, session, - stable_prev, stable_next); - DLLIST2_APPEND_FULL(&mail_sessions_head, &mail_sessions_tail, session, - sorted_prev, sorted_next); - DLLIST_PREPEND_FULL(&session->user->sessions, session, - user_prev, user_next); - mail_user_ref(session->user); - if (session->ip != NULL) { - DLLIST_PREPEND_FULL(&session->ip->sessions, session, - ip_prev, ip_next); - mail_ip_ref(session->ip); - } - global_memory_alloc(mail_session_memsize(session)); - - mail_global_login(); - return 0; -} - -void mail_session_ref(struct mail_session *session) -{ - session->refcount++; -} - -void mail_session_unref(struct mail_session **_session) -{ - struct mail_session *session = *_session; - - i_assert(session->refcount > 0); - session->refcount--; - - *_session = NULL; -} - -static void mail_session_free(struct mail_session *session) -{ - i_assert(session->refcount == 0); - - global_memory_free(mail_session_memsize(session)); - - timeout_remove(&session->to_idle); - if (!session->disconnected) - hash_table_remove(mail_sessions_hash, session->id); - DLLIST_REMOVE_FULL(&stable_mail_sessions, session, - stable_prev, stable_next); - DLLIST2_REMOVE_FULL(&mail_sessions_head, &mail_sessions_tail, session, - sorted_prev, sorted_next); - DLLIST_REMOVE_FULL(&session->user->sessions, session, - user_prev, user_next); - mail_user_unref(&session->user); - if (session->ip != NULL) { - DLLIST_REMOVE_FULL(&session->ip->sessions, session, - ip_prev, ip_next); - mail_ip_unref(&session->ip); - } - - str_table_unref(services, &session->service); - i_free(session->id); - i_free(session); -} - -static void mail_session_id_lost(const char *session_id) -{ - if (ioloop_time < session_id_warn_hide_until) { - if (session_id_hide_warned) - return; - session_id_hide_warned = TRUE; - i_warning("stats process appears to have crashed/restarted, " - "hiding missing session ID warnings for %d seconds", - (int)(session_id_warn_hide_until - ioloop_time)); - return; - } - i_warning("Couldn't find session ID: %s", session_id); -} - -int mail_session_lookup(const char *id, struct mail_session **session_r, - const char **error_r) -{ - if (id == NULL) { - *error_r = "Too few parameters"; - return -1; - } - *session_r = hash_table_lookup(mail_sessions_hash, id); - if (*session_r == NULL) { - mail_session_id_lost(id); - return 0; - } - return 1; -} - -int mail_session_get(const char *id, struct mail_session **session_r, - const char **error_r) -{ - const char *new_args[5]; - int ret; - - if ((ret = mail_session_lookup(id, session_r, error_r)) != 0) - return ret; - - /* Create a new dummy session to avoid repeated warnings */ - new_args[0] = id; - new_args[1] = ""; /* username */ - new_args[2] = ""; /* service */ - new_args[3] = "0"; /* pid */ - new_args[4] = NULL; - if (mail_session_connect_parse(new_args, error_r) < 0) - i_unreached(); - if (mail_session_lookup(id, session_r, error_r) != 1) - i_unreached(); - return 0; -} - -int mail_session_disconnect_parse(const char *const *args, const char **error_r) -{ - struct mail_session *session; - int ret; - - /* */ - if ((ret = mail_session_lookup(args[0], &session, error_r)) <= 0) - return ret; - - if (!session->disconnected) - mail_session_disconnect(session); - return 0; -} - -void mail_session_refresh(struct mail_session *session, - const struct stats *diff_stats) -{ - timeout_reset(session->to_idle); - - if (diff_stats != NULL) - stats_add(session->stats, diff_stats); - session->last_update = ioloop_timeval; - DLLIST2_REMOVE_FULL(&mail_sessions_head, &mail_sessions_tail, session, - sorted_prev, sorted_next); - DLLIST2_APPEND_FULL(&mail_sessions_head, &mail_sessions_tail, session, - sorted_prev, sorted_next); - - mail_user_refresh(session->user, diff_stats); - if (session->ip != NULL) - mail_ip_refresh(session->ip, diff_stats); -} - -int mail_session_update_parse(const char *const *args, const char **error_r) -{ - struct mail_session *session; - struct stats *new_stats, *diff_stats; - buffer_t *buf; - const char *error; - - /* */ - if (mail_session_get(args[0], &session, error_r) < 0) - return -1; - - buf = t_buffer_create(256); - if (args[1] == NULL || - base64_decode(args[1], strlen(args[1]), NULL, buf) < 0) { - *error_r = t_strdup_printf("UPDATE-SESSION %s %s %s: Invalid base64 input", - session->user->name, - session->service, session->id); - return -1; - } - - new_stats = stats_alloc(pool_datastack_create()); - diff_stats = stats_alloc(pool_datastack_create()); - - if (!stats_import(buf->data, buf->used, session->stats, new_stats, &error)) { - *error_r = t_strdup_printf("UPDATE-SESSION %s %s %s: %s", - session->user->name, - session->service, session->id, error); - return -1; - } - - if (!stats_diff(session->stats, new_stats, diff_stats, &error)) { - *error_r = t_strdup_printf("UPDATE-SESSION %s %s %s: stats shrank: %s", - session->user->name, - session->service, session->id, error); - return -1; - } - mail_session_refresh(session, diff_stats); - return 0; -} - -void mail_sessions_free_memory(void) -{ - unsigned int diff; - - while (mail_sessions_head != NULL && - mail_sessions_head->refcount == 0) { - i_assert(mail_sessions_head->disconnected); - mail_session_free(mail_sessions_head); - - if (global_used_memory < stats_settings->memory_limit || - mail_sessions_head == NULL) - break; - - diff = ioloop_time - mail_sessions_head->last_update.tv_sec; - if (diff < stats_settings->session_min_time) - break; - } -} - -void mail_sessions_init(void) -{ - session_id_warn_hide_until = - ioloop_time + SESSION_ID_WARN_HIDE_SECS; - hash_table_create(&mail_sessions_hash, default_pool, 0, - str_hash, strcmp); - services = str_table_init(); -} - -void mail_sessions_deinit(void) -{ - while (mail_sessions_head != NULL) { - struct mail_session *session = mail_sessions_head; - - if (!session->disconnected) - mail_session_unref(&session); - mail_session_free(mail_sessions_head); - } - hash_table_destroy(&mail_sessions_hash); - str_table_deinit(&services); -} diff --git a/src/old-stats/mail-session.h b/src/old-stats/mail-session.h deleted file mode 100644 index efdc82a139..0000000000 --- a/src/old-stats/mail-session.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef MAIL_SESSION_H -#define MAIL_SESSION_H - -struct stats; -struct mail_session; - -extern struct mail_session *stable_mail_sessions; - -int mail_session_connect_parse(const char *const *args, const char **error_r); -int mail_session_disconnect_parse(const char *const *args, const char **error_r); -int mail_session_update_parse(const char *const *args, const char **error_r); -int mail_session_cmd_update_parse(const char *const *args, const char **error_r); - -void mail_session_ref(struct mail_session *session); -void mail_session_unref(struct mail_session **session); - -int mail_session_lookup(const char *guid, struct mail_session **session_r, - const char **error_r); -int mail_session_get(const char *guid, struct mail_session **session_r, - const char **error_r); -void mail_session_refresh(struct mail_session *session, - const struct stats *diff_stats) ATTR_NULL(2); - -void mail_sessions_free_memory(void); -void mail_sessions_init(void); -void mail_sessions_deinit(void); - -#endif diff --git a/src/old-stats/mail-stats.c b/src/old-stats/mail-stats.c deleted file mode 100644 index 6ba325005c..0000000000 --- a/src/old-stats/mail-stats.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "mail-stats.h" -#include "stats-carbon.h" -#include "stats-settings.h" -#include "str.h" - -struct mail_global mail_global_stats; - -static void -mail_global_stats_sent(void *ctx) -{ - struct mail_global *stats = ctx; - stats_carbon_destroy(&stats->stats_send_ctx); -} - -static void -mail_global_stats_send(void *u0 ATTR_UNUSED) -{ - time_t ts = ioloop_time; - if (*stats_settings->carbon_name != '\0' && - *stats_settings->carbon_server != '\0') { - string_t *str = t_str_new(256); - const char *prefix = t_strdup_printf("dovecot.%s.global", - stats_settings->carbon_name); - str_printfa(str, "%s.logins %u %"PRIdTIME_T"\r\n", prefix, - mail_global_stats.num_logins, ts); - str_printfa(str, "%s.cmds %u %"PRIdTIME_T"\r\n", prefix, - mail_global_stats.num_cmds, ts); - str_printfa(str, "%s.connected_sessions %u %"PRIdTIME_T"\r\n", - prefix, mail_global_stats.num_connected_sessions, - ts); - str_printfa(str, "%s.last_reset %"PRIdTIME_T" %"PRIdTIME_T"\r\n", - prefix, mail_global_stats.reset_timestamp, ts); - /* then export rest of the stats */ - for(size_t i = 0; i < stats_field_count(); i++) { - str_printfa(str, "%s.%s ", prefix, - stats_field_name(i)); - stats_field_value(str, mail_global_stats.stats, i); - str_printfa(str, " %"PRIdTIME_T"\r\n", ts); - } - - /* and send them along */ - (void)stats_carbon_send(stats_settings->carbon_server, str_c(str), - mail_global_stats_sent, &mail_global_stats, - &mail_global_stats.stats_send_ctx); - } -} - -void mail_global_init(void) -{ - mail_global_stats.reset_timestamp = ioloop_time; - mail_global_stats.stats = stats_alloc(default_pool); - mail_global_stats.to_stats_send = timeout_add(stats_settings->carbon_interval*1000, - mail_global_stats_send, - NULL); -} - -void mail_global_deinit(void) -{ - if (mail_global_stats.stats_send_ctx != NULL) - stats_carbon_destroy(&mail_global_stats.stats_send_ctx); - timeout_remove(&mail_global_stats.to_stats_send); - i_free(mail_global_stats.stats); -} - -void mail_global_login(void) -{ - mail_global_stats.num_logins++; - mail_global_stats.num_connected_sessions++; -} - -void mail_global_disconnected(void) -{ - i_assert(mail_global_stats.num_connected_sessions > 0); - mail_global_stats.num_connected_sessions--; -} - -void mail_global_refresh(const struct stats *diff_stats) -{ - if (diff_stats != NULL) - stats_add(mail_global_stats.stats, diff_stats); - mail_global_stats.last_update = ioloop_timeval; -} diff --git a/src/old-stats/mail-stats.h b/src/old-stats/mail-stats.h deleted file mode 100644 index efd08244e7..0000000000 --- a/src/old-stats/mail-stats.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef MAIL_STATS_H -#define MAIL_STATS_H - -#include - -#include "net.h" -#include "guid.h" -#include "stats.h" - -struct stats_send_ctx; - -struct mail_command { - struct mail_command *stable_prev, *stable_next; - struct mail_command *session_prev, *session_next; - - struct mail_session *session; - char *name, *args; - /* non-zero id means the command is still running */ - unsigned int id; - - struct timeval last_update; - struct stats *stats; - - int refcount; -}; - -struct mail_session { - struct mail_session *stable_prev, *stable_next; - struct mail_session *sorted_prev, *sorted_next; - struct mail_session *user_prev, *user_next; - struct mail_session *ip_prev, *ip_next; - - /* if id="", the session no longer exists */ - char *id; - struct mail_user *user; - const char *service; - pid_t pid; - /* ip address may be NULL if there's none */ - struct mail_ip *ip; - struct timeout *to_idle; - - struct stats *stats; - struct timeval last_update; - unsigned int num_cmds; - - bool disconnected; - unsigned int highest_cmd_id; - int refcount; - struct mail_command *commands; -}; - -struct mail_user { - struct mail_user *stable_prev, *stable_next; - struct mail_user *sorted_prev, *sorted_next; - struct mail_user *domain_prev, *domain_next; - char *name; - struct mail_domain *domain; - time_t reset_timestamp; - - struct timeval last_update; - struct stats *stats; - unsigned int num_logins; - unsigned int num_cmds; - - int refcount; - struct mail_session *sessions; -}; - -struct mail_domain { - struct mail_domain *stable_prev, *stable_next; - struct mail_domain *sorted_prev, *sorted_next; - char *name; - time_t reset_timestamp; - - struct timeval last_update; - struct stats *stats; - unsigned int num_logins; - unsigned int num_cmds; - unsigned int num_connected_sessions; - - int refcount; - struct mail_user *users; -}; - -struct mail_ip { - struct mail_ip *stable_prev, *stable_next; - struct mail_ip *sorted_prev, *sorted_next; - struct ip_addr ip; - time_t reset_timestamp; - - struct timeval last_update; - struct stats *stats; - unsigned int num_logins; - unsigned int num_cmds; - unsigned int num_connected_sessions; - - int refcount; - struct mail_session *sessions; -}; - -struct mail_global { - time_t reset_timestamp; - - struct timeval last_update; - struct stats *stats; - unsigned int num_logins; - unsigned int num_cmds; - unsigned int num_connected_sessions; - - struct timeout *to_stats_send; - struct stats_send_ctx *stats_send_ctx; -}; - -extern struct mail_global mail_global_stats; - -void mail_global_init(void); -void mail_global_deinit(void); - -void mail_global_login(void); -void mail_global_disconnected(void); -void mail_global_refresh(const struct stats *diff_stats); - -#endif diff --git a/src/old-stats/mail-user.c b/src/old-stats/mail-user.c deleted file mode 100644 index 7b3bc7abdb..0000000000 --- a/src/old-stats/mail-user.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "buffer.h" -#include "ioloop.h" -#include "hash.h" -#include "llist.h" -#include "base64.h" -#include "global-memory.h" -#include "stats-settings.h" -#include "mail-stats.h" -#include "mail-domain.h" -#include "mail-user.h" - -static HASH_TABLE(char *, struct mail_user *) mail_users_hash; -/* users are sorted by their last_update timestamp, oldest first */ -static struct mail_user *mail_users_head, *mail_users_tail; -struct mail_user *stable_mail_users; - -static size_t mail_user_memsize(const struct mail_user *user) -{ - return sizeof(*user) + strlen(user->name) + 1; -} - -struct mail_user *mail_user_login(const char *username) -{ - struct mail_user *user; - const char *domain; - - user = hash_table_lookup(mail_users_hash, username); - if (user != NULL) { - mail_user_refresh(user, NULL); - return user; - } - - domain = i_strchr_to_next(username, '@'); - if (domain == NULL) - domain = ""; - - user = i_malloc(MALLOC_ADD(sizeof(struct mail_user), stats_alloc_size())); - user->stats = (void *)(user + 1); - user->name = i_strdup(username); - user->reset_timestamp = ioloop_time; - user->domain = mail_domain_login_create(domain); - - hash_table_insert(mail_users_hash, user->name, user); - DLLIST_PREPEND_FULL(&stable_mail_users, user, - stable_prev, stable_next); - DLLIST2_APPEND_FULL(&mail_users_head, &mail_users_tail, user, - sorted_prev, sorted_next); - DLLIST_PREPEND_FULL(&user->domain->users, user, - domain_prev, domain_next); - mail_domain_ref(user->domain); - - user->last_update = ioloop_timeval; - global_memory_alloc(mail_user_memsize(user)); - return user; -} - -void mail_user_disconnected(struct mail_user *user) -{ - mail_domain_disconnected(user->domain); -} - -struct mail_user *mail_user_lookup(const char *username) -{ - return hash_table_lookup(mail_users_hash, username); -} - -void mail_user_ref(struct mail_user *user) -{ - user->refcount++; -} - -void mail_user_unref(struct mail_user **_user) -{ - struct mail_user *user = *_user; - - i_assert(user->refcount > 0); - user->refcount--; - - *_user = NULL; -} - -static void mail_user_free(struct mail_user *user) -{ - i_assert(user->refcount == 0); - i_assert(user->sessions == NULL); - - global_memory_free(mail_user_memsize(user)); - hash_table_remove(mail_users_hash, user->name); - DLLIST_REMOVE_FULL(&stable_mail_users, user, - stable_prev, stable_next); - DLLIST2_REMOVE_FULL(&mail_users_head, &mail_users_tail, user, - sorted_prev, sorted_next); - DLLIST_REMOVE_FULL(&user->domain->users, user, - domain_prev, domain_next); - mail_domain_unref(&user->domain); - - i_free(user->name); - i_free(user); -} - -void mail_user_refresh(struct mail_user *user, - const struct stats *diff_stats) -{ - if (diff_stats != NULL) - stats_add(user->stats, diff_stats); - user->last_update = ioloop_timeval; - DLLIST2_REMOVE_FULL(&mail_users_head, &mail_users_tail, user, - sorted_prev, sorted_next); - DLLIST2_APPEND_FULL(&mail_users_head, &mail_users_tail, user, - sorted_prev, sorted_next); - mail_domain_refresh(user->domain, diff_stats); -} - -int mail_user_add_parse(const char *const *args, const char **error_r) -{ - struct mail_user *user; - struct stats *empty_stats, *diff_stats; - buffer_t *buf; - const char *service, *error; - - /* */ - if (str_array_length(args) < 3) { - *error_r = "ADD-USER: Too few parameters"; - return -1; - } - - user = mail_user_login(args[0]); - service = args[1]; - - buf = t_buffer_create(256); - if (base64_decode(args[2], strlen(args[2]), NULL, buf) < 0) { - *error_r = t_strdup_printf("ADD-USER %s %s: Invalid base64 input", - user->name, service); - return -1; - } - empty_stats = stats_alloc(pool_datastack_create()); - diff_stats = stats_alloc(pool_datastack_create()); - if (!stats_import(buf->data, buf->used, empty_stats, diff_stats, &error)) { - *error_r = t_strdup_printf("ADD-USER %s %s: %s", - user->name, service, error); - return -1; - } - mail_user_refresh(user, diff_stats); - return 0; -} - -void mail_users_free_memory(void) -{ - unsigned int diff; - - while (mail_users_head != NULL && mail_users_head->refcount == 0) { - mail_user_free(mail_users_head); - - if (global_used_memory < stats_settings->memory_limit || - mail_users_head == NULL) - break; - - diff = ioloop_time - mail_users_head->last_update.tv_sec; - if (diff < stats_settings->user_min_time) - break; - } -} - -void mail_users_init(void) -{ - hash_table_create(&mail_users_hash, default_pool, 0, str_hash, strcmp); -} - -void mail_users_deinit(void) -{ - while (mail_users_head != NULL) - mail_user_free(mail_users_head); - hash_table_destroy(&mail_users_hash); -} diff --git a/src/old-stats/mail-user.h b/src/old-stats/mail-user.h deleted file mode 100644 index ff1949e497..0000000000 --- a/src/old-stats/mail-user.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MAIL_USER_H -#define MAIL_USER_H - -struct stats; - -extern struct mail_user *stable_mail_users; - -struct mail_user *mail_user_login(const char *username); -void mail_user_disconnected(struct mail_user *user); -struct mail_user *mail_user_lookup(const char *username); - -void mail_user_refresh(struct mail_user *user, - const struct stats *diff_stats) ATTR_NULL(2); -int mail_user_add_parse(const char *const *args, const char **error_r); - -void mail_user_ref(struct mail_user *user); -void mail_user_unref(struct mail_user **user); - -void mail_users_free_memory(void); -void mail_users_init(void); -void mail_users_deinit(void); - -#endif diff --git a/src/old-stats/main.c b/src/old-stats/main.c deleted file mode 100644 index 49f50f4c64..0000000000 --- a/src/old-stats/main.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "module-dir.h" -#include "restrict-access.h" -#include "master-service.h" -#include "master-service-settings.h" -#include "global-memory.h" -#include "stats-settings.h" -#include "fifo-input-connection.h" -#include "mail-command.h" -#include "mail-session.h" -#include "mail-user.h" -#include "mail-domain.h" -#include "mail-ip.h" -#include "mail-stats.h" -#include "client.h" - -static struct module *modules = NULL; - -static void client_connected(struct master_service_connection *conn) -{ - if (conn->fifo) - (void)fifo_input_connection_create(conn->fd); - else - (void)client_create(conn->fd); - master_service_client_connection_accept(conn); -} - -static void main_preinit(void) -{ - struct module_dir_load_settings mod_set; - - i_zero(&mod_set); - mod_set.abi_version = DOVECOT_ABI_VERSION; - mod_set.require_init_funcs = TRUE; - - modules = module_dir_load(STATS_MODULE_DIR, NULL, &mod_set); - module_dir_init(modules); - - restrict_access_by_env(RESTRICT_ACCESS_FLAG_ALLOW_ROOT, NULL); - restrict_access_allow_coredumps(TRUE); -} - -int main(int argc, char *argv[]) -{ - const struct setting_parser_info *set_roots[] = { - &old_stats_setting_parser_info, - NULL - }; - const enum master_service_flags service_flags = - MASTER_SERVICE_FLAG_DONT_SEND_STATS | - MASTER_SERVICE_FLAG_NO_IDLE_DIE | - MASTER_SERVICE_FLAG_UPDATE_PROCTITLE; - const char *error; - void **sets; - - master_service = master_service_init("stats", service_flags, - &argc, &argv, ""); - if (master_getopt(master_service) > 0) - return FATAL_DEFAULT; - if (master_service_settings_read_simple(master_service, set_roots, - &error) < 0) - i_fatal("Error reading configuration: %s", error); - master_service_init_log(master_service); - - main_preinit(); - - sets = master_service_settings_get_others(master_service); - stats_settings = sets[0]; - - mail_commands_init(); - mail_sessions_init(); - mail_users_init(); - mail_domains_init(); - mail_ips_init(); - mail_global_init(); - - master_service_init_finish(master_service); - master_service_run(master_service, client_connected); - - clients_destroy_all(); - fifo_input_connections_destroy_all(); - mail_commands_deinit(); - mail_sessions_deinit(); - mail_users_deinit(); - mail_domains_deinit(); - mail_ips_deinit(); - mail_global_deinit(); - - module_dir_unload(&modules); - i_assert(global_used_memory == 0); - master_service_deinit(&master_service); - return 0; -} diff --git a/src/old-stats/stats-carbon.c b/src/old-stats/stats-carbon.c deleted file mode 100644 index 8ef3b23403..0000000000 --- a/src/old-stats/stats-carbon.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "time-util.h" -#include "stats-settings.h" -#include "mail-stats.h" -#include "istream.h" -#include "ostream.h" -#include "net.h" -#include "str.h" -#include "write-full.h" -#include "stats-carbon.h" - -#define CARBON_SERVER_DEFAULT_PORT 2003 - -struct stats_send_ctx { - pool_t pool; - int fd; - unsigned long to_msecs; - const char *endpoint; - const char *str; - struct io *io; - struct timeout *to; - - void (*callback)(void *); - void *ctx; -}; - -void -stats_carbon_destroy(struct stats_send_ctx **_ctx) -{ - struct stats_send_ctx *ctx = *_ctx; - *_ctx = NULL; - - io_remove(&ctx->io); - timeout_remove(&ctx->to); - i_close_fd(&ctx->fd); - pool_unref(&ctx->pool); -} - -static void -stats_carbon_callback(struct stats_send_ctx *ctx) -{ - i_assert(ctx->callback != NULL); - void (*callback)(void *) = ctx->callback; - ctx->callback = NULL; - callback(ctx->ctx); -} - -static void -stats_carbon_timeout(struct stats_send_ctx *ctx) -{ - i_error("Stats submit(%s) failed: endpoint timeout after %lu msecs", - ctx->endpoint, ctx->to_msecs); - stats_carbon_callback(ctx); -} - -static void -stats_carbon_connected(struct stats_send_ctx *ctx) -{ - io_remove(&ctx->io); - if ((errno = net_geterror(ctx->fd)) != 0) { - i_error("connect(%s) failed: %m", - ctx->endpoint); - stats_carbon_callback(ctx); - return; - } - if (write_full(ctx->fd, ctx->str, strlen(ctx->str)) < 0) - i_error("write(%s) failed: %m", - ctx->endpoint); - stats_carbon_callback(ctx); -} - -int -stats_carbon_send(const char *endpoint, const char *data, - void (*callback)(void *), void *cb_ctx, - struct stats_send_ctx **ctx_r) -{ - const char *host; - in_port_t port; - struct ip_addr ip; - - if (net_str2hostport(endpoint, CARBON_SERVER_DEFAULT_PORT, - &host, &port) < 0 || - net_addr2ip(host, &ip) < 0) { - i_error("stats_submit: Cannot parse endpoint '%s'", - endpoint); - return -1; - } - - pool_t pool = pool_alloconly_create("stats carbon send", 1024); - struct stats_send_ctx *ctx = p_new(pool, - struct stats_send_ctx, 1); - ctx->pool = pool; - ctx->str = p_strdup(ctx->pool, data); - - ctx->fd = net_connect_ip(&ip, port, NULL); - if (ctx->fd < 0) { - i_error("connect(%s) failed: %m", endpoint); - stats_carbon_callback(ctx); - return -1; - } - ctx->io = io_add(ctx->fd, IO_WRITE, - stats_carbon_connected, - ctx); - - /* give time for almost until next update - this is to ensure we leave a little pause between - attempts. Multiplier 800 gives us 20% window, and - ensures the number stays positive. */ - ctx->to_msecs = stats_settings->carbon_interval*800; - ctx->to = timeout_add(ctx->to_msecs, - stats_carbon_timeout, - ctx); - ctx->endpoint = p_strdup(ctx->pool, net_ipport2str(&ip, port)); - ctx->callback = callback; - ctx->ctx = cb_ctx; - - *ctx_r = ctx; - - return 0; -} diff --git a/src/old-stats/stats-carbon.h b/src/old-stats/stats-carbon.h deleted file mode 100644 index 07859761d3..0000000000 --- a/src/old-stats/stats-carbon.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef STATS_CARBON -#define STATS_CARBON 1 - -struct stats_send_ctx; - -int -stats_carbon_send(const char *endpoint, const char *data, - void (*callback)(void *), void *cb_ctx, - struct stats_send_ctx **ctx_r); -void -stats_carbon_destroy(struct stats_send_ctx **ctx); - -#endif diff --git a/src/old-stats/stats-settings.c b/src/old-stats/stats-settings.c deleted file mode 100644 index 3aa65af0c5..0000000000 --- a/src/old-stats/stats-settings.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "buffer.h" -#include "settings-parser.h" -#include "service-settings.h" -#include "stats-settings.h" - -/* */ -static struct file_listener_settings old_stats_unix_listeners_array[] = { - { "old-stats", 0600, "", "" } -}; -static struct file_listener_settings *old_stats_unix_listeners[] = { - &old_stats_unix_listeners_array[0] -}; -static buffer_t old_stats_unix_listeners_buf = { - { { old_stats_unix_listeners, sizeof(old_stats_unix_listeners) } } -}; -static struct file_listener_settings old_stats_fifo_listeners_array[] = { - { "old-stats-mail", 0600, "", "" }, - { "old-stats-user", 0600, "", "" } -}; -static struct file_listener_settings *old_stats_fifo_listeners[] = { - &old_stats_fifo_listeners_array[0], - &old_stats_fifo_listeners_array[1] -}; -static buffer_t old_stats_fifo_listeners_buf = { - { { old_stats_fifo_listeners, sizeof(old_stats_fifo_listeners) } } -}; -/* */ - -struct service_settings old_stats_service_settings = { - .name = "old-stats", - .protocol = "", - .type = "", - .executable = "old-stats", - .user = "$default_internal_user", - .group = "", - .privileged_group = "", - .extra_groups = "", - .chroot = "empty", - - .drop_priv_before_exec = FALSE, - - .process_min_avail = 0, - .process_limit = 1, - .client_limit = 0, - .service_count = 0, - .idle_kill = UINT_MAX, - .vsz_limit = UOFF_T_MAX, - - .unix_listeners = { { &old_stats_unix_listeners_buf, - sizeof(old_stats_unix_listeners[0]) } }, - .fifo_listeners = { { &old_stats_fifo_listeners_buf, - sizeof(old_stats_fifo_listeners[0]) } }, - .inet_listeners = ARRAY_INIT, - - .process_limit_1 = TRUE -}; - -/* we're kind of kludging here to avoid "stats_" prefix in the struct fields */ -#undef DEF -#define DEF(type, name) \ - SETTING_DEFINE_STRUCT_##type("old_stats_"#name, name, struct old_stats_settings) - -static const struct setting_define old_stats_setting_defines[] = { - DEF(SIZE, memory_limit), - DEF(TIME, command_min_time), - DEF(TIME, session_min_time), - DEF(TIME, user_min_time), - DEF(TIME, domain_min_time), - DEF(TIME, ip_min_time), - DEF(STR, carbon_server), - DEF(TIME, carbon_interval), - DEF(STR, carbon_name), - SETTING_DEFINE_LIST_END -}; - -const struct old_stats_settings old_stats_default_settings = { - .memory_limit = 1024*1024*16, - - .command_min_time = 60, - .session_min_time = 60*15, - .user_min_time = 60*60, - .domain_min_time = 60*60*12, - .ip_min_time = 60*60*12, - - .carbon_interval = 30, - .carbon_server = "", - .carbon_name = "" -}; - -const struct setting_parser_info old_stats_setting_parser_info = { - .module_name = "stats", - .defines = old_stats_setting_defines, - .defaults = &old_stats_default_settings, - - .type_offset = SIZE_MAX, - .struct_size = sizeof(struct old_stats_settings), - - .parent_offset = SIZE_MAX -}; - -const struct old_stats_settings *stats_settings; diff --git a/src/old-stats/stats-settings.h b/src/old-stats/stats-settings.h deleted file mode 100644 index 6b50b64854..0000000000 --- a/src/old-stats/stats-settings.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef STATS_SETTINGS_H -#define STATS_SETTINGS_H - -struct old_stats_settings { - uoff_t memory_limit; - - unsigned int command_min_time; - unsigned int session_min_time; - unsigned int user_min_time; - unsigned int domain_min_time; - unsigned int ip_min_time; - - unsigned int carbon_interval; - const char *carbon_server; - const char *carbon_name; -}; - -extern const struct setting_parser_info old_stats_setting_parser_info; -extern const struct old_stats_settings *stats_settings; - -#endif - diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index ab0b9d14f8..73e3198548 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -37,8 +37,6 @@ SUBDIRS = \ imap-quota \ pop3-migration \ replication \ - old-stats \ - imap-old-stats \ mail-crypt \ trash \ virtual \ diff --git a/src/plugins/imap-old-stats/Makefile.am b/src/plugins/imap-old-stats/Makefile.am deleted file mode 100644 index ed07ed5393..0000000000 --- a/src/plugins/imap-old-stats/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-old-stats \ - -I$(top_srcdir)/src/lib-mail \ - -I$(top_srcdir)/src/lib-imap \ - -I$(top_srcdir)/src/lib-index \ - -I$(top_srcdir)/src/lib-storage \ - -I$(top_srcdir)/src/imap \ - -I$(top_srcdir)/src/plugins/old-stats - -imap_moduledir = $(moduledir) - -NOPLUGIN_LDFLAGS = -lib95_imap_old_stats_plugin_la_LDFLAGS = -module -avoid-version - -imap_module_LTLIBRARIES = \ - lib95_imap_old_stats_plugin.la - -if DOVECOT_PLUGIN_DEPS -lib95_imap_old_stats_plugin_la_LIBADD = \ - ../old-stats/lib90_old_stats_plugin.la -endif - -lib95_imap_old_stats_plugin_la_SOURCES = \ - imap-stats-plugin.c - -noinst_HEADERS = \ - imap-stats-plugin.h diff --git a/src/plugins/imap-old-stats/imap-stats-plugin.c b/src/plugins/imap-old-stats/imap-stats-plugin.c deleted file mode 100644 index 6c91aa78e3..0000000000 --- a/src/plugins/imap-old-stats/imap-stats-plugin.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "imap-common.h" -#include "base64.h" -#include "str.h" -#include "imap-commands.h" -#include "stats.h" -#include "stats-plugin.h" -#include "stats-connection.h" -#include "imap-stats-plugin.h" - -#define IMAP_STATS_IMAP_CONTEXT(obj) \ - MODULE_CONTEXT(obj, imap_stats_imap_module) - -struct stats_client_command { - union imap_module_context module_ctx; - - unsigned int id; - bool continued; - struct stats *stats, *pre_stats; -}; - -static MODULE_CONTEXT_DEFINE_INIT(imap_stats_imap_module, - &imap_module_register); - -const char *imap_stats_plugin_version = DOVECOT_ABI_VERSION; - -static void stats_command_pre(struct client_command_context *cmd) -{ - struct stats_user *suser = STATS_USER_CONTEXT(cmd->client->user); - struct stats_client_command *scmd; - static unsigned int stats_cmd_id_counter = 0; - - if (suser == NULL || !suser->track_commands) - return; - - if (strcasecmp(cmd->name, "IDLE") == 0) { - /* IDLE can run forever and waste stats process's memory while - waiting for it to timeout. don't send them. */ - return; - } - - scmd = IMAP_STATS_IMAP_CONTEXT(cmd); - if (scmd == NULL) { - scmd = p_new(cmd->pool, struct stats_client_command, 1); - scmd->id = ++stats_cmd_id_counter; - scmd->stats = stats_alloc(cmd->pool); - scmd->pre_stats = stats_alloc(cmd->pool); - MODULE_CONTEXT_SET(cmd, imap_stats_imap_module, scmd); - } - - mail_user_stats_fill(cmd->client->user, scmd->pre_stats); -} - -static void stats_command_post(struct client_command_context *cmd) -{ - struct stats_user *suser = STATS_USER_CONTEXT(cmd->client->user); - struct stats_client_command *scmd = IMAP_STATS_IMAP_CONTEXT(cmd); - struct stats *new_stats, *diff_stats; - const char *error; - size_t args_pos = 0, args_len = 0; - string_t *str; - buffer_t *buf; - - if (suser == NULL || scmd == NULL) - return; - - new_stats = stats_alloc(pool_datastack_create()); - diff_stats = stats_alloc(pool_datastack_create()); - - mail_user_stats_fill(cmd->client->user, new_stats); - if (!stats_diff(scmd->pre_stats, new_stats, diff_stats, &error)) - i_error("stats: command stats shrank: %s", error); - stats_add(scmd->stats, diff_stats); - - str = t_str_new(128); - str_append(str, "UPDATE-CMD\t"); - str_append(str, suser->stats_session_id); - - str_printfa(str, "\t%u\t", scmd->id); - if (cmd->state == CLIENT_COMMAND_STATE_DONE) - str_append_c(str, 'd'); - if (scmd->continued) - str_append_c(str, 'c'); - else { - str_append_c(str, '\t'); - str_append(str, cmd->name); - str_append_c(str, '\t'); - args_pos = str_len(str); - if (cmd->args != NULL) - str_append(str, cmd->args); - args_len = str_len(str) - args_pos; - scmd->continued = TRUE; - } - - buf = t_buffer_create(128); - stats_export(buf, scmd->stats); - str_append_c(str, '\t'); - base64_encode(buf->data, buf->used, str); - - str_append_c(str, '\n'); - - if (str_len(str) > PIPE_BUF) { - /* truncate the args so it fits */ - size_t delete_count = str_len(str) - PIPE_BUF; - - i_assert(args_pos != 0); - if (delete_count > args_len) - delete_count = args_len; - str_delete(str, args_pos + args_len - delete_count, - delete_count); - } - - stats_connection_send(suser->stats_conn, str); -} - -void imap_old_stats_plugin_init(struct module *module ATTR_UNUSED) -{ - command_hook_register(stats_command_pre, stats_command_post); -} - -void imap_old_stats_plugin_deinit(void) -{ - command_hook_unregister(stats_command_pre, stats_command_post); -} - -const char *imap_old_stats_plugin_dependencies[] = { "old_stats", NULL }; -const char imap_old_stats_plugin_binary_dependency[] = "imap"; diff --git a/src/plugins/imap-old-stats/imap-stats-plugin.h b/src/plugins/imap-old-stats/imap-stats-plugin.h deleted file mode 100644 index 2a95b53e14..0000000000 --- a/src/plugins/imap-old-stats/imap-stats-plugin.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef IMAP_STATS_PLUGIN_H -#define IMAP_STATS_PLUGIN_H - -struct module; - -extern const char *imap_stats_plugin_dependencies[]; -extern const char imap_stats_plugin_binary_dependency[]; - -void imap_old_stats_plugin_init(struct module *module); -void imap_old_stats_plugin_deinit(void); - -#endif diff --git a/src/plugins/old-stats/Makefile.am b/src/plugins/old-stats/Makefile.am deleted file mode 100644 index 8a95363575..0000000000 --- a/src/plugins/old-stats/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib \ - -I$(top_srcdir)/src/lib-settings \ - -I$(top_srcdir)/src/lib-mail \ - -I$(top_srcdir)/src/lib-master \ - -I$(top_srcdir)/src/lib-old-stats \ - -I$(top_srcdir)/src/lib-index \ - -I$(top_srcdir)/src/lib-storage - -NOPLUGIN_LDFLAGS = -lib90_old_stats_plugin_la_LDFLAGS = -module -avoid-version - -module_LTLIBRARIES = \ - lib90_old_stats_plugin.la - -lib90_old_stats_plugin_la_SOURCES = \ - mail-stats.c \ - mail-stats-fill.c \ - mail-stats-connection.c \ - stats-plugin.c - -noinst_HEADERS = \ - mail-stats.h \ - mail-stats-connection.h \ - stats-plugin.h - -old_stats_moduledir = $(moduledir)/old-stats -old_stats_module_LTLIBRARIES = libold_stats_mail.la - -libold_stats_mail_la_LDFLAGS = -module -avoid-version -libold_stats_mail_la_LIBADD = mail-stats.lo $(LIBDOVECOT) -libold_stats_mail_la_DEPENDENCIES = mail-stats.lo -libold_stats_mail_la_SOURCES = diff --git a/src/plugins/old-stats/mail-stats-connection.c b/src/plugins/old-stats/mail-stats-connection.c deleted file mode 100644 index ca20fcb517..0000000000 --- a/src/plugins/old-stats/mail-stats-connection.c +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "base64.h" -#include "hostpid.h" -#include "net.h" -#include "str.h" -#include "strescape.h" -#include "mail-storage.h" -#include "stats.h" -#include "stats-plugin.h" -#include "mail-stats-connection.h" - -int mail_stats_connection_connect(struct stats_connection *conn, - struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - string_t *str = t_str_new(128); - - str_append(str, "CONNECT\t"); - /* required fields */ - str_append(str, suser->stats_session_id); - str_append_c(str, '\t'); - str_append_tabescaped(str, user->username); - str_append_c(str, '\t'); - str_append_tabescaped(str, user->service); - str_printfa(str, "\t%s", my_pid); - - /* optional fields */ - if (user->conn.local_ip != NULL) { - str_append(str, "\tlip="); - str_append(str, net_ip2addr(user->conn.local_ip)); - } - if (user->conn.remote_ip != NULL) { - str_append(str, "\trip="); - str_append(str, net_ip2addr(user->conn.remote_ip)); - } - str_append_c(str, '\n'); - return stats_connection_send(conn, str); -} - -void mail_stats_connection_disconnect(struct stats_connection *conn, - struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - string_t *str = t_str_new(128); - - str_append(str, "DISCONNECT\t"); - str_append(str, suser->stats_session_id); - str_append_c(str, '\n'); - if (stats_connection_send(conn, str) < 0) { - /* we could retry this later, but stats process will forget it - anyway after 15 minutes. */ - } -} - -void mail_stats_connection_send_session(struct stats_connection *conn, - struct mail_user *user, - const struct stats *stats) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - string_t *str = t_str_new(256); - buffer_t *buf; - - buf = t_buffer_create(128); - stats_export(buf, stats); - - str_append(str, "UPDATE-SESSION\t"); - str_append(str, suser->stats_session_id); - str_append_c(str, '\t'); - base64_encode(buf->data, buf->used, str); - - str_append_c(str, '\n'); - (void)stats_connection_send(conn, str); -} diff --git a/src/plugins/old-stats/mail-stats-connection.h b/src/plugins/old-stats/mail-stats-connection.h deleted file mode 100644 index f98b691b0f..0000000000 --- a/src/plugins/old-stats/mail-stats-connection.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef MAIL_STATS_CONNECTION_H -#define MAIL_STATS_CONNECTION_H - -#include "stats-connection.h" - -struct mail_stats; -struct mail_user; - -int mail_stats_connection_connect(struct stats_connection *conn, - struct mail_user *user); -void mail_stats_connection_disconnect(struct stats_connection *conn, - struct mail_user *user); - -void mail_stats_connection_send_session(struct stats_connection *conn, - struct mail_user *user, - const struct stats *stats); -void mail_stats_connection_send(struct stats_connection *conn, const string_t *str); - -#endif diff --git a/src/plugins/old-stats/mail-stats-fill.c b/src/plugins/old-stats/mail-stats-fill.c deleted file mode 100644 index 10d8c398f9..0000000000 --- a/src/plugins/old-stats/mail-stats-fill.c +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "time-util.h" -#include "stats-plugin.h" -#include "mail-stats.h" - -#include - -#define PROC_IO_PATH "/proc/self/io" - -static bool proc_io_disabled = FALSE; -static int proc_io_fd = -1; - -static int -process_io_buffer_parse(const char *buf, struct mail_stats *stats) -{ - const char *const *tmp; - - tmp = t_strsplit(buf, "\n"); - for (; *tmp != NULL; tmp++) { - if (str_begins(*tmp, "rchar: ")) { - if (str_to_uint64(*tmp + 7, &stats->read_bytes) < 0) - return -1; - } else if (str_begins(*tmp, "wchar: ")) { - if (str_to_uint64(*tmp + 7, &stats->write_bytes) < 0) - return -1; - } else if (str_begins(*tmp, "syscr: ")) { - if (str_to_uint32(*tmp + 7, &stats->read_count) < 0) - return -1; - } else if (str_begins(*tmp, "syscw: ")) { - if (str_to_uint32(*tmp + 7, &stats->write_count) < 0) - return -1; - } - } - return 0; -} - -static int process_io_open(void) -{ - uid_t uid; - - if (proc_io_fd != -1) - return proc_io_fd; - - if (proc_io_disabled) - return -1; - - proc_io_fd = open(PROC_IO_PATH, O_RDONLY); - if (proc_io_fd == -1 && errno == EACCES) { - /* kludge: if we're running with permissions temporarily - dropped, get them temporarily back so we can open - /proc/self/io. */ - uid = geteuid(); - if (seteuid(0) == 0) { - proc_io_fd = open(PROC_IO_PATH, O_RDONLY); - if (seteuid(uid) < 0) { - /* oops, this is bad */ - i_fatal("stats: seteuid(%s) failed", dec2str(uid)); - } - } - errno = EACCES; - } - if (proc_io_fd == -1) { - /* ignore access errors too, certain security options can - prevent root access to this file when not owned by root */ - if (errno != ENOENT && errno != EACCES) - i_error("open(%s) failed: %m", PROC_IO_PATH); - proc_io_disabled = TRUE; - return -1; - } - return proc_io_fd; -} - -static void process_read_io_stats(struct mail_stats *stats) -{ - char buf[1024]; - int fd, ret; - - if ((fd = process_io_open()) == -1) - return; - - ret = pread(fd, buf, sizeof(buf), 0); - if (ret <= 0) { - if (ret == -1) - i_error("read(%s) failed: %m", PROC_IO_PATH); - else - i_error("read(%s) returned EOF", PROC_IO_PATH); - } else if (ret == sizeof(buf)) { - /* just shouldn't happen.. */ - i_error("%s is larger than expected", PROC_IO_PATH); - proc_io_disabled = TRUE; - } else { - buf[ret] = '\0'; - T_BEGIN { - if (process_io_buffer_parse(buf, stats) < 0) { - i_error("Invalid input in file %s", - PROC_IO_PATH); - proc_io_disabled = TRUE; - } - } T_END; - } -} - -static void -user_trans_stats_get(struct stats_user *suser, struct mail_stats *dest_r) -{ - struct stats_transaction_context *strans; - - mail_stats_add_transaction(dest_r, &suser->finished_transaction_stats); - for (strans = suser->transactions; strans != NULL; strans = strans->next) - mail_stats_add_transaction(dest_r, &strans->trans->stats); -} - -void mail_stats_fill(struct stats_user *suser, struct mail_stats *stats_r) -{ - static bool getrusage_broken = FALSE; - static struct rusage prev_usage; - struct rusage usage; - - i_zero(stats_r); - /* cputime */ - if (getrusage(RUSAGE_SELF, &usage) < 0) { - if (!getrusage_broken) { - i_error("getrusage() failed: %m"); - getrusage_broken = TRUE; - } - usage = prev_usage; - } else if (timeval_diff_usecs(&usage.ru_stime, &prev_usage.ru_stime) < 0) { - /* This seems to be a Linux bug. */ - usage.ru_stime = prev_usage.ru_stime; - } - prev_usage = usage; - - stats_r->user_cpu = usage.ru_utime; - stats_r->sys_cpu = usage.ru_stime; - stats_r->min_faults = usage.ru_minflt; - stats_r->maj_faults = usage.ru_majflt; - stats_r->vol_cs = usage.ru_nvcsw; - stats_r->invol_cs = usage.ru_nivcsw; - stats_r->disk_input = (unsigned long long)usage.ru_inblock * 512ULL; - stats_r->disk_output = (unsigned long long)usage.ru_oublock * 512ULL; - i_gettimeofday(&stats_r->clock_time); - process_read_io_stats(stats_r); - user_trans_stats_get(suser, stats_r); -} - -void mail_stats_global_preinit(void) -{ - (void)process_io_open(); -} - -void mail_stats_fill_global_deinit(void) -{ - i_close_fd(&proc_io_fd); -} diff --git a/src/plugins/old-stats/mail-stats.c b/src/plugins/old-stats/mail-stats.c deleted file mode 100644 index 3662d23a20..0000000000 --- a/src/plugins/old-stats/mail-stats.c +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "time-util.h" -#include "stats.h" -#include "stats-parser.h" -#include "mail-stats.h" - -static struct stats_parser_field mail_stats_fields[] = { -#define E(parsename, name, type) { parsename, offsetof(struct mail_stats, name), sizeof(((struct mail_stats *)0)->name), type } -#define EN(parsename, name) E(parsename, name, STATS_PARSER_TYPE_UINT) - E("user_cpu", user_cpu, STATS_PARSER_TYPE_TIMEVAL), - E("sys_cpu", sys_cpu, STATS_PARSER_TYPE_TIMEVAL), - E("clock_time", clock_time, STATS_PARSER_TYPE_TIMEVAL), - EN("min_faults", min_faults), - EN("maj_faults", maj_faults), - EN("vol_cs", vol_cs), - EN("invol_cs", invol_cs), - EN("disk_input", disk_input), - EN("disk_output", disk_output), - - EN("read_count", read_count), - EN("read_bytes", read_bytes), - EN("write_count", write_count), - EN("write_bytes", write_bytes), - - /*EN("mopen", trans_stats.open_lookup_count), - EN("mstat", trans_stats.stat_lookup_count), - EN("mfstat", trans_stats.fstat_lookup_count),*/ - EN("mail_lookup_path", trans_lookup_path), - EN("mail_lookup_attr", trans_lookup_attr), - EN("mail_read_count", trans_files_read_count), - EN("mail_read_bytes", trans_files_read_bytes), - EN("mail_cache_hits", trans_cache_hit_count) -}; - -static size_t mail_stats_alloc_size(void) -{ - return sizeof(struct mail_stats); -} - -static unsigned int mail_stats_field_count(void) -{ - return N_ELEMENTS(mail_stats_fields); -} - -static const char *mail_stats_field_name(unsigned int n) -{ - i_assert(n < N_ELEMENTS(mail_stats_fields)); - - return mail_stats_fields[n].name; -} - -static void -mail_stats_field_value(string_t *str, const struct stats *stats, - unsigned int n) -{ - i_assert(n < N_ELEMENTS(mail_stats_fields)); - - stats_parser_value(str, &mail_stats_fields[n], stats); -} - -static bool -mail_stats_diff(const struct stats *stats1, const struct stats *stats2, - struct stats *diff_stats_r, const char **error_r) -{ - return stats_parser_diff(mail_stats_fields, N_ELEMENTS(mail_stats_fields), - stats1, stats2, diff_stats_r, error_r); -} - -static void mail_stats_add(struct stats *dest, const struct stats *src) -{ - stats_parser_add(mail_stats_fields, N_ELEMENTS(mail_stats_fields), - dest, src); -} - -static bool -mail_stats_have_changed(const struct stats *_prev, const struct stats *_cur) -{ - const struct mail_stats *prev = (const struct mail_stats *)_prev; - const struct mail_stats *cur = (const struct mail_stats *)_cur; - - if (cur->disk_input != prev->disk_input || - cur->disk_output != prev->disk_output || - cur->trans_lookup_path != prev->trans_lookup_path || - cur->trans_lookup_attr != prev->trans_lookup_attr || - cur->trans_files_read_count != prev->trans_files_read_count || - cur->trans_files_read_bytes != prev->trans_files_read_bytes || - cur->trans_cache_hit_count != prev->trans_cache_hit_count) - return TRUE; - - /* allow a tiny bit of changes that are caused by this - timeout handling */ - if (timeval_diff_msecs(&cur->user_cpu, &prev->user_cpu) != 0) - return TRUE; - if (timeval_diff_msecs(&cur->sys_cpu, &prev->sys_cpu) != 0) - return TRUE; - - if (cur->maj_faults > prev->maj_faults+10) - return TRUE; - if (cur->invol_cs > prev->invol_cs+10) - return TRUE; - /* don't check for read/write count/bytes changes, since they get - changed by stats checking itself */ - return FALSE; -} - -static void mail_stats_export(buffer_t *buf, const struct stats *_stats) -{ - const struct mail_stats *stats = (const struct mail_stats *)_stats; - - buffer_append(buf, stats, sizeof(*stats)); -} - -static bool -mail_stats_import(const unsigned char *data, size_t size, size_t *pos_r, - struct stats *_stats, const char **error_r) -{ - struct mail_stats *stats = (struct mail_stats *)_stats; - - if (size < sizeof(*stats)) { - *error_r = "mail_stats too small"; - return FALSE; - } - memcpy(stats, data, sizeof(*stats)); - *pos_r = sizeof(*stats); - return TRUE; -} - -void mail_stats_add_transaction(struct mail_stats *stats, - const struct mailbox_transaction_stats *trans_stats) -{ - stats->trans_lookup_path += trans_stats->open_lookup_count; - stats->trans_lookup_attr += trans_stats->stat_lookup_count + - trans_stats->fstat_lookup_count; - stats->trans_files_read_count += trans_stats->files_read_count; - stats->trans_files_read_bytes += trans_stats->files_read_bytes; - stats->trans_cache_hit_count += trans_stats->cache_hit_count; -} - -const struct stats_vfuncs mail_stats_vfuncs = { - "mail", - mail_stats_alloc_size, - mail_stats_field_count, - mail_stats_field_name, - mail_stats_field_value, - mail_stats_diff, - mail_stats_add, - mail_stats_have_changed, - mail_stats_export, - mail_stats_import -}; - -/* for the stats_mail plugin: */ -void old_stats_mail_init(void); -void old_stats_mail_deinit(void); - -static struct stats_item *mail_stats_item; - -void old_stats_mail_init(void) -{ - mail_stats_item = stats_register(&mail_stats_vfuncs); -} - -void old_stats_mail_deinit(void) -{ - stats_unregister(&mail_stats_item); -} diff --git a/src/plugins/old-stats/mail-stats.h b/src/plugins/old-stats/mail-stats.h deleted file mode 100644 index 7254b696d0..0000000000 --- a/src/plugins/old-stats/mail-stats.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MAIL_STATS_H -#define MAIL_STATS_H - -#include -#include "mail-storage-private.h" - -struct stats_user; - -struct mail_stats { - /* user/system CPU time used */ - struct timeval user_cpu, sys_cpu; - /* clock time used (not counting the time in ioloop wait) */ - struct timeval clock_time; - /* minor / major page faults */ - uint32_t min_faults, maj_faults; - /* voluntary / involuntary context switches */ - uint32_t vol_cs, invol_cs; - /* disk input/output bytes */ - uint64_t disk_input, disk_output; - /* read()/write() syscall count and number of bytes */ - uint32_t read_count, write_count; - uint64_t read_bytes, write_bytes; - - /* based on struct mailbox_transaction_stats: */ - uint32_t trans_lookup_path; - uint32_t trans_lookup_attr; - uint32_t trans_files_read_count; - uint64_t trans_files_read_bytes; - uint64_t trans_cache_hit_count; -}; - -extern const struct stats_vfuncs mail_stats_vfuncs; - -void mail_stats_fill(struct stats_user *suser, struct mail_stats *mail_stats); -void mail_stats_add_transaction(struct mail_stats *stats, - const struct mailbox_transaction_stats *trans_stats); - -void mail_stats_global_preinit(void); -void mail_stats_fill_global_deinit(void); - -#endif diff --git a/src/plugins/old-stats/stats-plugin.c b/src/plugins/old-stats/stats-plugin.c deleted file mode 100644 index 9d33016f04..0000000000 --- a/src/plugins/old-stats/stats-plugin.c +++ /dev/null @@ -1,481 +0,0 @@ -/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */ - -#include "lib.h" -#include "ioloop.h" -#include "llist.h" -#include "str.h" -#include "time-util.h" -#include "settings-parser.h" -#include "mail-stats.h" -#include "stats.h" -#include "mail-stats-connection.h" -#include "stats-plugin.h" - -#define STATS_CONTEXT(obj) \ - MODULE_CONTEXT(obj, stats_storage_module) -#define STATS_CONTEXT_REQUIRE(obj) \ - MODULE_CONTEXT_REQUIRE(obj, stats_storage_module) - -/* If session isn't refreshed every 15 minutes, it's dropped. - Must be smaller than MAIL_SESSION_IDLE_TIMEOUT_MSECS in stats server */ -#define SESSION_STATS_FORCE_REFRESH_SECS (5*60) -#define REFRESH_CHECK_INTERVAL 100 -#define MAIL_STATS_FIFO_NAME "old-stats-mail" - -struct stats_storage { - union mail_storage_module_context module_ctx; - - struct mail_storage_callbacks old_callbacks; - void *old_context; -}; - -struct stats_mailbox { - union mailbox_module_context module_ctx; -}; - -const char *stats_plugin_version = DOVECOT_ABI_VERSION; - -struct stats_user_module stats_user_module = - MODULE_CONTEXT_INIT(&mail_user_module_register); -struct stats_storage_module stats_storage_module = - MODULE_CONTEXT_INIT(&mail_storage_module_register); - -static struct stats_item *mail_stats_item; -static struct stats_connection *global_stats_conn = NULL; -static struct mail_user *stats_global_user = NULL; -static unsigned int stats_user_count = 0; - -static void session_stats_refresh_timeout(struct mail_user *user); - -static void stats_io_activate(struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - struct mail_stats *mail_stats; - - if (stats_user_count == 1) { - /* the first user sets the global user. the second user sets - it to NULL. when we get back to one user we'll need to set - the global user again somewhere. do it here. */ - stats_global_user = user; - /* skip time spent waiting in ioloop */ - mail_stats = stats_fill_ptr(suser->pre_io_stats, mail_stats_item); - mail_stats->clock_time = ioloop_timeval; - } else { - i_assert(stats_global_user == NULL); - - mail_user_stats_fill(user, suser->pre_io_stats); - } -} - -static void stats_add_session(struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - struct stats *new_stats, *diff_stats; - const char *error; - - new_stats = stats_alloc(pool_datastack_create()); - diff_stats = stats_alloc(pool_datastack_create()); - - mail_user_stats_fill(user, new_stats); - /* we'll count new_stats-pre_io_stats and add the changes to - session_stats. the new_stats can't be directly copied to - session_stats because there are some fields that don't start from - zero, like clock_time. (actually with stats_global_user code we're - requiring that clock_time is the only such field..) */ - if (!stats_diff(suser->pre_io_stats, new_stats, diff_stats, &error)) - i_error("stats: session stats shrank: %s", error); - stats_add(suser->session_stats, diff_stats); - /* copying is only needed if stats_global_user=NULL */ - stats_copy(suser->pre_io_stats, new_stats); -} - -static bool -session_stats_need_send(struct stats_user *suser, time_t now, - bool *changed_r, unsigned int *to_next_secs_r) -{ - unsigned int diff; - - *to_next_secs_r = SESSION_STATS_FORCE_REFRESH_SECS; - - if (stats_have_changed(suser->last_sent_session_stats, - suser->session_stats)) { - *to_next_secs_r = suser->refresh_secs; - *changed_r = TRUE; - return TRUE; - } - *changed_r = FALSE; - - diff = now - suser->last_session_update; - if (diff >= SESSION_STATS_FORCE_REFRESH_SECS) - return TRUE; - *to_next_secs_r = SESSION_STATS_FORCE_REFRESH_SECS - diff; - - if (!suser->session_sent_duplicate) { - if (suser->last_session_update != now) { - /* send one duplicate notification so stats reader - knows that this session is idle now */ - return TRUE; - } - } - return FALSE; -} - -static void session_stats_refresh(struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - unsigned int to_next_secs; - time_t now = time(NULL); - bool changed; - - if (!suser->stats_connected) { - if (mail_stats_connection_connect(suser->stats_conn, user) == 0) - suser->stats_connected = TRUE; - } - if (session_stats_need_send(suser, now, &changed, &to_next_secs) && - suser->stats_connected) { - suser->session_sent_duplicate = !changed; - suser->last_session_update = now; - stats_copy(suser->last_sent_session_stats, suser->session_stats); - mail_stats_connection_send_session(suser->stats_conn, user, - suser->session_stats); - } - - timeout_remove(&suser->to_stats_timeout); - suser->to_stats_timeout = - timeout_add(to_next_secs*1000, - session_stats_refresh_timeout, user); -} - -static struct mailbox_transaction_context * -stats_transaction_begin(struct mailbox *box, - enum mailbox_transaction_flags flags, - const char *reason) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(box->storage->user); - struct stats_mailbox *sbox = STATS_CONTEXT_REQUIRE(box); - struct mailbox_transaction_context *trans; - struct stats_transaction_context *strans; - - trans = sbox->module_ctx.super.transaction_begin(box, flags, reason); - trans->stats_track = TRUE; - - strans = i_new(struct stats_transaction_context, 1); - strans->trans = trans; - DLLIST_PREPEND(&suser->transactions, strans); - - MODULE_CONTEXT_SET(trans, stats_storage_module, strans); - return trans; -} - -static void stats_transaction_free(struct stats_user *suser, - struct stats_transaction_context *strans) -{ - const struct mailbox_transaction_stats *src = &strans->trans->stats; - struct mailbox_transaction_stats *dest = - &suser->finished_transaction_stats; - - DLLIST_REMOVE(&suser->transactions, strans); - - dest->open_lookup_count += src->open_lookup_count; - dest->stat_lookup_count += src->stat_lookup_count; - dest->fstat_lookup_count += src->fstat_lookup_count; - dest->files_read_count += src->files_read_count; - dest->files_read_bytes += src->files_read_bytes; - dest->cache_hit_count += src->cache_hit_count; - i_free(strans); -} - -static int -stats_transaction_commit(struct mailbox_transaction_context *ctx, - struct mail_transaction_commit_changes *changes_r) -{ - struct stats_transaction_context *strans = STATS_CONTEXT_REQUIRE(ctx); - struct stats_mailbox *sbox = STATS_CONTEXT_REQUIRE(ctx->box); - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(ctx->box->storage->user); - - stats_transaction_free(suser, strans); - return sbox->module_ctx.super.transaction_commit(ctx, changes_r); -} - -static void -stats_transaction_rollback(struct mailbox_transaction_context *ctx) -{ - struct stats_transaction_context *strans = STATS_CONTEXT_REQUIRE(ctx); - struct stats_mailbox *sbox = STATS_CONTEXT_REQUIRE(ctx->box); - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(ctx->box->storage->user); - - stats_transaction_free(suser, strans); - sbox->module_ctx.super.transaction_rollback(ctx); -} - -static bool stats_search_next_nonblock(struct mail_search_context *ctx, - struct mail **mail_r, bool *tryagain_r) -{ - struct stats_mailbox *sbox = STATS_CONTEXT_REQUIRE(ctx->transaction->box); - struct mail_user *user = ctx->transaction->box->storage->user; - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - bool ret; - - ret = sbox->module_ctx.super. - search_next_nonblock(ctx, mail_r, tryagain_r); - if (!ret && !*tryagain_r) { - /* end of search */ - return FALSE; - } - - if (*tryagain_r || - ++suser->refresh_check_counter % REFRESH_CHECK_INTERVAL == 0) { - /* a) retrying, so this is a long running search. - b) we've returned enough matches */ - if (time(NULL) != suser->last_session_update) - session_stats_refresh(user); - } - return ret; -} - -static void -stats_notify_ok(struct mailbox *box, const char *text, void *context) -{ - struct stats_storage *sstorage = STATS_CONTEXT_REQUIRE(box->storage); - - /* most importantly we want to refresh stats for very long running - mailbox syncs */ - session_stats_refresh(box->storage->user); - - if (sstorage->old_callbacks.notify_ok != NULL) - sstorage->old_callbacks.notify_ok(box, text, context); -} - -static void stats_register_notify_callbacks(struct mail_storage *storage) -{ - struct stats_storage *sstorage = STATS_CONTEXT(storage); - - if (sstorage != NULL) - return; - - sstorage = p_new(storage->pool, struct stats_storage, 1); - sstorage->old_callbacks = storage->callbacks; - storage->callbacks.notify_ok = stats_notify_ok; - - MODULE_CONTEXT_SET(storage, stats_storage_module, sstorage); -} - -static void stats_mailbox_allocated(struct mailbox *box) -{ - struct mailbox_vfuncs *v = box->vlast; - struct stats_mailbox *sbox; - struct stats_user *suser = STATS_USER_CONTEXT(box->storage->user); - - if (suser == NULL) - return; - - stats_register_notify_callbacks(box->storage); - - sbox = p_new(box->pool, struct stats_mailbox, 1); - sbox->module_ctx.super = *v; - box->vlast = &sbox->module_ctx.super; - - v->transaction_begin = stats_transaction_begin; - v->transaction_commit = stats_transaction_commit; - v->transaction_rollback = stats_transaction_rollback; - v->search_next_nonblock = stats_search_next_nonblock; - MODULE_CONTEXT_SET(box, stats_storage_module, sbox); -} - -static void session_stats_refresh_timeout(struct mail_user *user) -{ - if (stats_global_user != NULL) - stats_add_session(user); - session_stats_refresh(user); -} - -static void stats_io_deactivate(struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - unsigned int last_update_secs; - - if (stats_global_user == NULL) - stats_add_session(user); - - last_update_secs = time(NULL) - suser->last_session_update; - if (last_update_secs >= suser->refresh_secs) { - if (stats_global_user != NULL) - stats_add_session(user); - session_stats_refresh(user); - } else if (suser->to_stats_timeout == NULL) { - suser->to_stats_timeout = - timeout_add(suser->refresh_secs*1000, - session_stats_refresh_timeout, user); - } -} - -static void stats_user_stats_fill(struct mail_user *user, struct stats *stats) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - struct mail_stats *mail_stats; - - mail_stats = stats_fill_ptr(stats, mail_stats_item); - mail_stats_fill(suser, mail_stats); - - suser->module_ctx.super.stats_fill(user, stats); -} - -static void stats_user_deinit(struct mail_user *user) -{ - struct stats_user *suser = STATS_USER_CONTEXT_REQUIRE(user); - struct stats_connection *stats_conn = suser->stats_conn; - - i_assert(stats_user_count > 0); - - stats_user_count--; - if (stats_global_user != NULL) { - /* we were updating the session lazily. do one final update. */ - i_assert(stats_global_user == user); - stats_add_session(user); - stats_global_user = NULL; - } - - io_loop_context_remove_callbacks(suser->ioloop_ctx, - stats_io_activate, - stats_io_deactivate, user); - /* send final stats before disconnection */ - session_stats_refresh(user); - if (suser->stats_connected) - mail_stats_connection_disconnect(stats_conn, user); - - timeout_remove(&suser->to_stats_timeout); - suser->module_ctx.super.deinit(user); - - stats_connection_unref(&stats_conn); -} - -static void stats_user_created(struct mail_user *user) -{ - struct ioloop_context *ioloop_ctx = - io_loop_get_current_context(current_ioloop); - struct stats_user *suser; - struct mail_user_vfuncs *v = user->vlast; - const char *path, *str, *error; - unsigned int refresh_secs; - - if (ioloop_ctx == NULL) { - /* we're probably running some test program, or at least - mail-storage-service wasn't used to create this user. - disable stats tracking. */ - return; - } - if (user->autocreated) { - /* lda / shared user. we're not tracking this one. */ - return; - } - - /* get refresh time */ - str = mail_user_plugin_getenv(user, "old_stats_refresh"); - if (str == NULL) - return; - if (settings_get_time(str, &refresh_secs, &error) < 0) { - i_error("stats: Invalid old_stats_refresh setting: %s", error); - return; - } - if (refresh_secs == 0) - return; - if (refresh_secs > SESSION_STATS_FORCE_REFRESH_SECS) { - i_warning("stats: stats_refresh too large, changing to %u", - SESSION_STATS_FORCE_REFRESH_SECS); - refresh_secs = SESSION_STATS_FORCE_REFRESH_SECS; - } - - if (global_stats_conn == NULL) { - path = mail_user_plugin_getenv(user, "old_stats_notify_path"); - if (path == NULL) - path = MAIL_STATS_FIFO_NAME; - if (path[0] != '/') - path = t_strconcat(user->set->base_dir, "/", path, NULL); - global_stats_conn = stats_connection_create(path); - } - stats_connection_ref(global_stats_conn); - - if (stats_user_count == 0) { - /* first user connection */ - stats_global_user = user; - } else if (stats_user_count == 1) { - /* second user connection. we'll need to start doing - per-io callback tracking now. (we might have been doing it - also previously but just temporarily quickly dropped to - having 1 user, in which case stats_global_user=NULL) */ - if (stats_global_user != NULL) { - stats_add_session(stats_global_user); - stats_global_user = NULL; - } - } - stats_user_count++; - - suser = p_new(user->pool, struct stats_user, 1); - suser->module_ctx.super = *v; - user->vlast = &suser->module_ctx.super; - v->deinit = stats_user_deinit; - v->stats_fill = stats_user_stats_fill; - - suser->refresh_secs = refresh_secs; - if (mail_user_plugin_getenv_bool(user, "old_stats_track_cmds")) - suser->track_commands = TRUE; - - suser->stats_conn = global_stats_conn; - if (user->session_id != NULL && user->session_id[0] != '\0') - suser->stats_session_id = user->session_id; - else { - guid_128_t guid; - - guid_128_generate(guid); - suser->stats_session_id = - p_strdup(user->pool, guid_128_to_string(guid)); - } - suser->last_session_update = time(NULL); - user->stats_enabled = TRUE; - - suser->ioloop_ctx = ioloop_ctx; - io_loop_context_add_callbacks(ioloop_ctx, - stats_io_activate, - stats_io_deactivate, user); - - suser->pre_io_stats = stats_alloc(user->pool); - suser->session_stats = stats_alloc(user->pool); - suser->last_sent_session_stats = stats_alloc(user->pool); - - MODULE_CONTEXT_SET(user, stats_user_module, suser); - if (mail_stats_connection_connect(suser->stats_conn, user) == 0) - suser->stats_connected = TRUE; - suser->to_stats_timeout = - timeout_add(suser->refresh_secs*1000, - session_stats_refresh_timeout, user); - /* fill the initial values. this is necessary for the process-global - values (e.g. getrusage()) if the process is reused for multiple - users. otherwise the next user will start with the previous one's - last values. */ - mail_user_stats_fill(user, suser->pre_io_stats); -} - -static struct mail_storage_hooks stats_mail_storage_hooks = { - .mailbox_allocated = stats_mailbox_allocated, - .mail_user_created = stats_user_created -}; - -void old_stats_plugin_init(struct module *module) -{ - mail_stats_item = stats_register(&mail_stats_vfuncs); - mail_storage_hooks_add(module, &stats_mail_storage_hooks); -} - -void old_stats_plugin_preinit(void) -{ - mail_stats_global_preinit(); -} - -void old_stats_plugin_deinit(void) -{ - if (global_stats_conn != NULL) - stats_connection_unref(&global_stats_conn); - mail_stats_fill_global_deinit(); - mail_storage_hooks_remove(&stats_mail_storage_hooks); - stats_unregister(&mail_stats_item); -} diff --git a/src/plugins/old-stats/stats-plugin.h b/src/plugins/old-stats/stats-plugin.h deleted file mode 100644 index dedcfbd176..0000000000 --- a/src/plugins/old-stats/stats-plugin.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef STATS_PLUGIN_H -#define STATS_PLUGIN_H - -#include "module-context.h" -#include "mail-user.h" -#include "mail-storage-private.h" - -#define STATS_USER_CONTEXT(obj) \ - MODULE_CONTEXT(obj, stats_user_module) - -#define STATS_USER_CONTEXT_REQUIRE(obj) \ - MODULE_CONTEXT_REQUIRE(obj, stats_user_module) - -struct stats_user { - union mail_user_module_context module_ctx; - - struct ioloop_context *ioloop_ctx; - struct stats_connection *stats_conn; - const char *stats_session_id; - bool stats_connected; - - unsigned int refresh_secs; - bool track_commands; - unsigned int refresh_check_counter; - - /* current session statistics */ - struct stats *session_stats; - /* cumulative trans_stats for all already freed transactions. */ - struct mailbox_transaction_stats finished_transaction_stats; - /* stats before calling IO callback. after IO callback this value is - compared to current stats to see the difference */ - struct stats *pre_io_stats; - - time_t last_session_update; - struct timeout *to_stats_timeout; - /* stats that were last sent to stats server */ - struct stats *last_sent_session_stats; - bool session_sent_duplicate; - - /* list of all currently existing transactions for this user */ - struct stats_transaction_context *transactions; -}; - -struct stats_transaction_context { - union mailbox_transaction_module_context module_ctx; - - struct stats_transaction_context *prev, *next; - struct mailbox_transaction_context *trans; - - struct mailbox_transaction_stats prev_stats; -}; - -extern MODULE_CONTEXT_DEFINE(stats_user_module, &mail_user_module_register); -extern MODULE_CONTEXT_DEFINE(stats_storage_module, &mail_storage_module_register); - -void old_stats_plugin_init(struct module *module); -void old_stats_plugin_preinit(void); -void old_stats_plugin_deinit(void); - -#endif