summaryrefslogtreecommitdiffstats
path: root/src/old-stats/stats-carbon.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/old-stats/stats-carbon.c')
-rw-r--r--src/old-stats/stats-carbon.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/src/old-stats/stats-carbon.c b/src/old-stats/stats-carbon.c
new file mode 100644
index 0000000..7e984cf
--- /dev/null
+++ b/src/old-stats/stats-carbon.c
@@ -0,0 +1,125 @@
+/* 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);
+ if (net_ipport2str(&ip, port, &host) < 0)
+ i_unreached();
+ ctx->endpoint = p_strdup(ctx->pool, host);
+ ctx->callback = callback;
+ ctx->ctx = cb_ctx;
+
+ *ctx_r = ctx;
+
+ return 0;
+}