diff options
author | Gilles Chehade <gilles@poolp.org> | 2020-04-30 02:01:35 +0200 |
---|---|---|
committer | Gilles Chehade <gilles@poolp.org> | 2020-04-30 02:01:35 +0200 |
commit | 6fb3965e81d9e4278ee5d96c2d68c014df1f3802 (patch) | |
tree | c3c895a4a39d4888e0ff978c97587120712a6b9d /foobar/portable/smtpd/stat_ramstat.c | |
parent | plug ubuntu-gcc10 to CI (diff) | |
download | OpenSMTPD-6fb3965e81d9e4278ee5d96c2d68c014df1f3802.tar.xz OpenSMTPD-6fb3965e81d9e4278ee5d96c2d68c014df1f3802.zip |
move
Diffstat (limited to 'foobar/portable/smtpd/stat_ramstat.c')
-rw-r--r-- | foobar/portable/smtpd/stat_ramstat.c | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/foobar/portable/smtpd/stat_ramstat.c b/foobar/portable/smtpd/stat_ramstat.c new file mode 100644 index 00000000..bbf1541a --- /dev/null +++ b/foobar/portable/smtpd/stat_ramstat.c @@ -0,0 +1,162 @@ +/* $OpenBSD: stat_ramstat.c,v 1.11 2018/05/31 21:06:12 gilles Exp $ */ + +/* + * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "includes.h" + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <sys/tree.h> + +#include <event.h> +#include <imsg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> + +#include "smtpd.h" +#include "log.h" + + +static void ramstat_init(void); +static void ramstat_close(void); +static void ramstat_increment(const char *, size_t); +static void ramstat_decrement(const char *, size_t); +static void ramstat_set(const char *, const struct stat_value *); +static int ramstat_iter(void **, char **, struct stat_value *); + +struct ramstat_entry { + RB_ENTRY(ramstat_entry) entry; + char key[STAT_KEY_SIZE]; + struct stat_value value; +}; +RB_HEAD(stats_tree, ramstat_entry) stats; +RB_PROTOTYPE(stats_tree, ramstat_entry, entry, ramstat_entry_cmp); + +struct stat_backend stat_backend_ramstat = { + ramstat_init, + ramstat_close, + ramstat_increment, + ramstat_decrement, + ramstat_set, + ramstat_iter +}; + +static void +ramstat_init(void) +{ + log_trace(TRACE_STAT, "ramstat: init"); + + RB_INIT(&stats); + + /* ramstat_set() should be called for each key we want + * to have displayed by smtpctl show stats at startup. + */ + ramstat_set("uptime", stat_timestamp(env->sc_uptime)); +} + +static void +ramstat_close(void) +{ + log_trace(TRACE_STAT, "ramstat: close"); +} + +static void +ramstat_increment(const char *name, size_t val) +{ + struct ramstat_entry *np, lk; + + log_trace(TRACE_STAT, "ramstat: increment: %s", name); + (void)strlcpy(lk.key, name, sizeof (lk.key)); + np = RB_FIND(stats_tree, &stats, &lk); + if (np == NULL) { + np = xcalloc(1, sizeof *np); + (void)strlcpy(np->key, name, sizeof (np->key)); + RB_INSERT(stats_tree, &stats, np); + } + log_trace(TRACE_STAT, "ramstat: %s (%p): %zd -> %zd", + name, name, np->value.u.counter, np->value.u.counter + val); + np->value.u.counter += val; +} + +static void +ramstat_decrement(const char *name, size_t val) +{ + struct ramstat_entry *np, lk; + + log_trace(TRACE_STAT, "ramstat: decrement: %s", name); + (void)strlcpy(lk.key, name, sizeof (lk.key)); + np = RB_FIND(stats_tree, &stats, &lk); + if (np == NULL) { + np = xcalloc(1, sizeof *np); + (void)strlcpy(np->key, name, sizeof (np->key)); + RB_INSERT(stats_tree, &stats, np); + } + log_trace(TRACE_STAT, "ramstat: %s (%p): %zd -> %zd", + name, name, np->value.u.counter, np->value.u.counter - val); + np->value.u.counter -= val; +} + +static void +ramstat_set(const char *name, const struct stat_value *val) +{ + struct ramstat_entry *np, lk; + + log_trace(TRACE_STAT, "ramstat: set: %s", name); + (void)strlcpy(lk.key, name, sizeof (lk.key)); + np = RB_FIND(stats_tree, &stats, &lk); + if (np == NULL) { + np = xcalloc(1, sizeof *np); + (void)strlcpy(np->key, name, sizeof (np->key)); + RB_INSERT(stats_tree, &stats, np); + } + log_trace(TRACE_STAT, "ramstat: %s: n/a -> n/a", name); + np->value = *val; +} + +static int +ramstat_iter(void **iter, char **name, struct stat_value *val) +{ + struct ramstat_entry *np; + + log_trace(TRACE_STAT, "ramstat: iter"); + if (RB_EMPTY(&stats)) + return 0; + + if (*iter == NULL) + np = RB_MIN(stats_tree, &stats); + else + np = RB_NEXT(stats_tree, &stats, *iter); + + *iter = np; + if (np == NULL) + return 0; + + *name = np->key; + *val = np->value; + return 1; +} + + +static int +ramstat_entry_cmp(struct ramstat_entry *e1, struct ramstat_entry *e2) +{ + return strcmp(e1->key, e2->key); +} + +RB_GENERATE(stats_tree, ramstat_entry, entry, ramstat_entry_cmp); |