dovecot-2.2: stats process/plugin redesign to be more modular.

dovecot at dovecot.org dovecot at dovecot.org
Thu Mar 5 21:05:30 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/a9952ceeac61
changeset: 18292:a9952ceeac61
user:      Timo Sirainen <tss at iki.fi>
date:      Thu Mar 05 23:02:48 2015 +0200
description:
stats process/plugin redesign to be more modular.
The visible functionality doesn't actually change with this patch yet, but
it allows other plugins/services to add their own fields to stats process.
For example auth process could send auth success/failures or auth cache
hits/misses.

diffstat:

 configure.ac                               |    3 +-
 src/Makefile.am                            |    1 +
 src/lib-dovecot/Makefile.am                |    1 +
 src/lib-stats/Makefile.am                  |   15 +
 src/lib-stats/stats-parser.c               |  180 +++++++++++++++
 src/lib-stats/stats-parser.h               |   29 ++
 src/lib-stats/stats.c                      |  220 +++++++++++++++++++
 src/lib-stats/stats.h                      |   69 ++++++
 src/lib-storage/mail-user.c                |   11 +
 src/lib-storage/mail-user.h                |    8 +-
 src/plugins/imap-stats/Makefile.am         |    1 +
 src/plugins/imap-stats/imap-stats-plugin.c |   36 +-
 src/plugins/stats/Makefile.am              |   12 +
 src/plugins/stats/mail-stats-fill.c        |  130 +++++++++++
 src/plugins/stats/mail-stats.c             |  168 ++++++++++++++
 src/plugins/stats/mail-stats.h             |   38 +++
 src/plugins/stats/stats-connection.c       |   14 +-
 src/plugins/stats/stats-connection.h       |    2 +-
 src/plugins/stats/stats-plugin.c           |  327 ++++------------------------
 src/plugins/stats/stats-plugin.h           |   43 +--
 src/stats/Makefile.am                      |    5 +-
 src/stats/client-export.c                  |  123 +++++-----
 src/stats/mail-command.c                   |   34 ++-
 src/stats/mail-domain.c                    |    7 +-
 src/stats/mail-domain.h                    |    4 +-
 src/stats/mail-ip.c                        |    7 +-
 src/stats/mail-ip.h                        |    2 +-
 src/stats/mail-server-connection.c         |   24 +-
 src/stats/mail-session.c                   |   36 ++-
 src/stats/mail-session.h                   |    4 +-
 src/stats/mail-stats.c                     |  277 +-----------------------
 src/stats/mail-stats.h                     |   40 +--
 src/stats/mail-user.c                      |    7 +-
 src/stats/mail-user.h                      |    4 +-
 src/stats/main.c                           |   22 +-
 35 files changed, 1164 insertions(+), 740 deletions(-)

diffs (truncated from 2751 to 300 lines):

diff -r c98991820dde -r a9952ceeac61 configure.ac
--- a/configure.ac	Thu Mar 05 22:19:02 2015 +0200
+++ b/configure.ac	Thu Mar 05 23:02:48 2015 +0200
@@ -2549,7 +2549,7 @@
   LIBDOVECOT_COMPRESS='$(top_builddir)/src/lib-compression/libcompression.la'
   LIBDOVECOT_LDA='$(top_builddir)/src/lib-lda/libdovecot-lda.la'
 else
-  LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-http/libhttp.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-sasl/libsasl.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la'
+  LIBDOVECOT_DEPS='$(top_builddir)/src/lib-master/libmaster.la $(top_builddir)/src/lib-settings/libsettings.la $(top_builddir)/src/lib-stats/libstats.la $(top_builddir)/src/lib-http/libhttp.la $(top_builddir)/src/lib-dict/libdict.la $(top_builddir)/src/lib-dns/libdns.la $(top_builddir)/src/lib-fs/libfs.la $(top_builddir)/src/lib-imap/libimap.la $(top_builddir)/src/lib-mail/libmail.la $(top_builddir)/src/lib-sasl/libsasl.la $(top_builddir)/src/lib-auth/libauth.la $(top_builddir)/src/lib-charset/libcharset.la $(top_builddir)/src/lib-ssl-iostream/libssl_iostream.la $(top_builddir)/src/lib-test/libtest.la $(top_builddir)/src/lib/liblib.la'
   LIBDOVECOT="$LIBDOVECOT_DEPS \$(LIBICONV) \$(MODULE_LIBS)"
   LIBDOVECOT_STORAGE_DEPS='$(top_builddir)/src/lib-storage/libstorage.la'
   LIBDOVECOT_LOGIN='$(top_builddir)/src/login-common/liblogin.la'
@@ -2849,6 +2849,7 @@
 src/lib-sasl/Makefile
 src/lib-settings/Makefile
 src/lib-ssl-iostream/Makefile
+src/lib-stats/Makefile
 src/lib-test/Makefile
 src/lib-storage/Makefile
 src/lib-storage/list/Makefile
diff -r c98991820dde -r a9952ceeac61 src/Makefile.am
--- a/src/Makefile.am	Thu Mar 05 22:19:02 2015 +0200
+++ b/src/Makefile.am	Thu Mar 05 23:02:48 2015 +0200
@@ -9,6 +9,7 @@
 	lib-dict \
 	lib-sasl \
 	lib-ssl-iostream \
+	lib-stats \
 	lib-http \
 	lib-fs \
 	lib-mail \
diff -r c98991820dde -r a9952ceeac61 src/lib-dovecot/Makefile.am
--- a/src/lib-dovecot/Makefile.am	Thu Mar 05 22:19:02 2015 +0200
+++ b/src/lib-dovecot/Makefile.am	Thu Mar 05 23:02:48 2015 +0200
@@ -3,6 +3,7 @@
 	../lib-master/libmaster.la \
 	../lib-fs/libfs.la \
 	../lib-settings/libsettings.la \
+	../lib-stats/libstats.la \
 	../lib-http/libhttp.la \
 	../lib-dict/libdict.la \
 	../lib-imap/libimap.la \
diff -r c98991820dde -r a9952ceeac61 src/lib-stats/Makefile.am
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-stats/Makefile.am	Thu Mar 05 23:02:48 2015 +0200
@@ -0,0 +1,15 @@
+noinst_LTLIBRARIES = libstats.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/lib
+
+libstats_la_SOURCES = \
+	stats.c \
+	stats-parser.c
+
+headers = \
+	stats.h \
+	stats-parser.h
+
+pkginc_libdir = $(pkgincludedir)
+pkginc_lib_HEADERS = $(headers)
diff -r c98991820dde -r a9952ceeac61 src/lib-stats/stats-parser.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-stats/stats-parser.c	Thu Mar 05 23:02:48 2015 +0200
@@ -0,0 +1,180 @@
+/* Copyright (c) 2011-2015 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 %llu < %llu",
+						fields[i].name,
+						(unsigned long long)*n2,
+						(unsigned long long)*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, "%llu", (unsigned long long)*n);
+			break;
+		}
+		default:
+			i_unreached();
+		}
+		break;
+	case STATS_PARSER_TYPE_TIMEVAL: {
+		const struct timeval *tv = ptr;
+
+		str_printfa(str, "%lu.%u", (unsigned long)tv->tv_sec,
+			    (unsigned int)tv->tv_usec);
+		break;
+	}
+	}
+}
diff -r c98991820dde -r a9952ceeac61 src/lib-stats/stats-parser.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-stats/stats-parser.h	Thu Mar 05 23:02:48 2015 +0200
@@ -0,0 +1,29 @@
+#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 -r c98991820dde -r a9952ceeac61 src/lib-stats/stats.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-stats/stats.c	Thu Mar 05 23:02:48 2015 +0200
@@ -0,0 +1,220 @@
+/* Copyright (c) 2015 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;


More information about the dovecot-cvs mailing list