diff options
author | Gilles Chehade <gilles@cvs.openbsd.org> | 2012-08-18 18:18:24 +0000 |
---|---|---|
committer | Gilles Chehade <gilles@cvs.openbsd.org> | 2012-08-18 18:18:24 +0000 |
commit | 9228f249a15e8408c65a9892fe8c9d845c867714 (patch) | |
tree | bbf9e12e35607c9a3c09a8c68ea4650040b414eb | |
parent | 3da4234ae91599a538335d99a70e54983df19d04 (diff) |
- introduce stat_backend, an API for pluggable statistic backends
> statistics are no longer static structures in shared memory
> statistics are only set, smtpd never uses them in its logic
> each statistic is a key/value where key can be any (dynamic) string
- convert all uses of the former API to use the new one
- implement stat_ramstat that keeps non-persistent stats in ram structure
ok eric@, ok chl@
-rw-r--r-- | usr.sbin/smtpd/control.c | 70 | ||||
-rw-r--r-- | usr.sbin/smtpd/dns.c | 16 | ||||
-rw-r--r-- | usr.sbin/smtpd/lka.c | 5 | ||||
-rw-r--r-- | usr.sbin/smtpd/queue.c | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/scheduler.c | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/scheduler_ramqueue.c | 15 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp.c | 25 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtp_session.c | 29 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl.c | 179 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpctl/Makefile | 4 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.c | 22 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd.h | 115 | ||||
-rw-r--r-- | usr.sbin/smtpd/smtpd/Makefile | 7 | ||||
-rw-r--r-- | usr.sbin/smtpd/stat_backend.c | 82 | ||||
-rw-r--r-- | usr.sbin/smtpd/stat_ramstat.c | 165 | ||||
-rw-r--r-- | usr.sbin/smtpd/stats.c | 79 |
16 files changed, 472 insertions, 349 deletions
diff --git a/usr.sbin/smtpd/control.c b/usr.sbin/smtpd/control.c index ce9356e18f6..969a437e7cb 100644 --- a/usr.sbin/smtpd/control.c +++ b/usr.sbin/smtpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.67 2012/08/10 09:16:02 eric Exp $ */ +/* $OpenBSD: control.c,v 1.68 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -61,10 +61,17 @@ void control_dispatch_ext(int, short, void *); struct ctl_connlist ctl_conns; +static struct stat_backend *stat_backend = NULL; +extern const char *backend_stat; + +static size_t sessions; + void control_imsg(struct imsgev *iev, struct imsg *imsg) { struct ctl_conn *c; + char *key; + struct stat_kv *stat_kv; log_imsg(PROC_CONTROL, iev->proc, imsg); @@ -80,6 +87,24 @@ control_imsg(struct imsgev *iev, struct imsg *imsg) } } + switch (imsg->hdr.type) { + case IMSG_STAT_INCREMENT: + key = imsg->data; + if (stat_backend) + stat_backend->increment(key); + return; + case IMSG_STAT_DECREMENT: + key = imsg->data; + if (stat_backend) + stat_backend->decrement(key); + return; + case IMSG_STAT_SET: + stat_kv = (struct stat_kv *)imsg->data; + if (stat_backend) + stat_backend->set(stat_kv->key, stat_kv->val); + return; + } + errx(1, "control_imsg: unexpected %s imsg", imsg_to_str(imsg->hdr.type)); } @@ -109,11 +134,12 @@ control(void) struct event ev_sigint; struct event ev_sigterm; struct peer peers [] = { - { PROC_SCHEDULER, imsg_dispatch }, - { PROC_QUEUE, imsg_dispatch }, - { PROC_SMTP, imsg_dispatch }, - { PROC_MFA, imsg_dispatch }, - { PROC_PARENT, imsg_dispatch }, + { PROC_SCHEDULER, imsg_dispatch }, + { PROC_QUEUE, imsg_dispatch }, + { PROC_SMTP, imsg_dispatch }, + { PROC_MFA, imsg_dispatch }, + { PROC_PARENT, imsg_dispatch }, + { PROC_LKA, imsg_dispatch } }; switch (pid = fork()) { @@ -160,6 +186,9 @@ control(void) session_socket_blockmode(fd, BM_NONBLOCK); control_state.fd = fd; + stat_backend = env->sc_stat; + stat_backend->init(); + if (chroot(pw->pw_dir) == -1) fatal("control: chroot"); if (chdir("/") == -1) @@ -255,7 +284,9 @@ control_accept(int listenfd, short event, void *arg) event_add(&c->iev.ev, NULL); TAILQ_INSERT_TAIL(&ctl_conns, c, entry); - if (stat_increment(STATS_CONTROL_SESSION) >= env->sc_maxconn) { + stat_backend->increment("control.session"); + + if (++sessions >= env->sc_maxconn) { log_warnx("ctl client limit hit, disabling new connections"); event_del(&control_state.ev); } @@ -288,7 +319,9 @@ control_close(int fd) close(fd); free(c); - if (stat_decrement(STATS_CONTROL_SESSION) < env->sc_maxconn && + stat_backend->decrement("control.session"); + + if (--sessions < env->sc_maxconn && !event_pending(&control_state.ev, EV_READ, NULL)) { log_warnx("re-enabling ctl connections"); event_add(&control_state.ev, NULL); @@ -305,6 +338,10 @@ control_dispatch_ext(int fd, short event, void *arg) uid_t euid; gid_t egid; uint64_t id; + struct stat_kv *kvp; + char *key; + size_t val; + if (getpeereid(fd, &euid, &egid) == -1) fatal("getpeereid"); @@ -352,8 +389,21 @@ control_dispatch_ext(int fd, short event, void *arg) case IMSG_STATS: if (euid) goto badcred; - imsg_compose_event(&c->iev, IMSG_STATS, 0, 0, -1, - env->stats, sizeof(struct stats)); + imsg_compose_event(&c->iev, IMSG_STATS, 0, 0, -1, NULL, 0); + break; + + case IMSG_STATS_GET: + if (euid) + goto badcred; + kvp = imsg.data; + if (! stat_backend->iter(&kvp->iter, &key, &val)) + kvp->iter = NULL; + else { + strlcpy(kvp->key, key, sizeof kvp->key); + kvp->val = val; + } + imsg_compose_event(&c->iev, IMSG_STATS_GET, 0, 0, -1, + kvp, sizeof *kvp); break; case IMSG_CTL_SHUTDOWN: diff --git a/usr.sbin/smtpd/dns.c b/usr.sbin/smtpd/dns.c index d502ef9396b..03746eb0987 100644 --- a/usr.sbin/smtpd/dns.c +++ b/usr.sbin/smtpd/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.51 2012/08/08 17:31:55 eric Exp $ */ +/* $OpenBSD: dns.c,v 1.52 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -145,14 +145,14 @@ dns_async(struct imsgev *asker, int type, struct dns *query) return; } dnssession_mx_insert(s, query->host, 0); - stat_increment(STATS_LKA_SESSION_HOST); + stat_increment("lka.session.host"); dns_asr_dispatch_host(s); return; case IMSG_DNS_PTR: s->as = getnameinfo_async((struct sockaddr*)&query->ss, query->ss.ss_len, s->query.host, sizeof(s->query.host), NULL, 0, 0, NULL); - stat_increment(STATS_LKA_SESSION_CNAME); + stat_increment("lka.session.cname"); if (s->as == NULL) { log_debug("dns_async: asr_query_cname error"); break; @@ -162,7 +162,7 @@ dns_async(struct imsgev *asker, int type, struct dns *query) case IMSG_DNS_MX: log_debug("dns: lookup mx \"%s\"", query->host); s->as = res_query_async(query->host, C_IN, T_MX, NULL, 0, NULL); - stat_increment(STATS_LKA_SESSION_MX); + stat_increment("lka.session.mx"); if (s->as == NULL) { log_debug("dns_async: asr_query_dns error"); break; @@ -174,7 +174,7 @@ dns_async(struct imsgev *asker, int type, struct dns *query) break; } - stat_increment(STATS_LKA_FAILURE); + stat_increment("lka.failure"); dnssession_destroy(s); } @@ -223,7 +223,7 @@ dns_asr_error(int ar_err) return DNS_OK; case NO_DATA: case NO_RECOVERY: - stat_increment(STATS_LKA_FAILURE); + stat_increment("lka.failure"); return DNS_EINVAL; default: return DNS_RETRY; @@ -354,7 +354,7 @@ dnssession_init(struct dns *query) if (s == NULL) fatal("dnssession_init: calloc"); - stat_increment(STATS_LKA_SESSION); + stat_increment("lka.session"); s->id = query->id; s->query = *query; @@ -365,7 +365,7 @@ dnssession_init(struct dns *query) static void dnssession_destroy(struct dnssession *s) { - stat_decrement(STATS_LKA_SESSION); + stat_decrement("lka.session"); SPLAY_REMOVE(dnstree, &dns_sessions, s); event_del(&s->ev); free(s); diff --git a/usr.sbin/smtpd/lka.c b/usr.sbin/smtpd/lka.c index 169662dd521..1e1bae88ee9 100644 --- a/usr.sbin/smtpd/lka.c +++ b/usr.sbin/smtpd/lka.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka.c,v 1.133 2012/05/12 15:31:43 gilles Exp $ */ +/* $OpenBSD: lka.c,v 1.134 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -256,7 +256,8 @@ lka(void) { PROC_MFA, imsg_dispatch }, { PROC_QUEUE, imsg_dispatch }, { PROC_SMTP, imsg_dispatch }, - { PROC_MTA, imsg_dispatch } + { PROC_MTA, imsg_dispatch }, + { PROC_CONTROL, imsg_dispatch } }; switch (pid = fork()) { diff --git a/usr.sbin/smtpd/queue.c b/usr.sbin/smtpd/queue.c index f7e4586057f..ece47ff5bc2 100644 --- a/usr.sbin/smtpd/queue.c +++ b/usr.sbin/smtpd/queue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: queue.c,v 1.125 2012/08/11 19:18:36 chl Exp $ */ +/* $OpenBSD: queue.c,v 1.126 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -85,7 +85,7 @@ queue_imsg(struct imsgev *iev, struct imsg *imsg) msgid = evpid_to_msgid(e->id); if (queue_message_commit(msgid)) { stat_increment(e->flags & DF_ENQUEUED ? - STATS_QUEUE_LOCAL : STATS_QUEUE_REMOTE); + "queue.local" : "queue.remote"); imsg_compose_event(env->sc_ievs[PROC_SCHEDULER], IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, &msgid, sizeof msgid); diff --git a/usr.sbin/smtpd/scheduler.c b/usr.sbin/smtpd/scheduler.c index b71249b4956..bf7ddf9d24d 100644 --- a/usr.sbin/smtpd/scheduler.c +++ b/usr.sbin/smtpd/scheduler.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scheduler.c,v 1.11 2012/08/09 19:16:26 eric Exp $ */ +/* $OpenBSD: scheduler.c,v 1.12 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -408,6 +408,4 @@ scheduler_process_mta(struct scheduler_batch *batch) imsg_compose_event(env->sc_ievs[PROC_QUEUE], IMSG_BATCH_CLOSE, 0, 0, -1, NULL, 0); - - stat_increment(STATS_MTA_SESSION); } diff --git a/usr.sbin/smtpd/scheduler_ramqueue.c b/usr.sbin/smtpd/scheduler_ramqueue.c index 1630d6e5cb2..44cbd31cf2c 100644 --- a/usr.sbin/smtpd/scheduler_ramqueue.c +++ b/usr.sbin/smtpd/scheduler_ramqueue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scheduler_ramqueue.c,v 1.13 2012/08/11 19:19:19 chl Exp $ */ +/* $OpenBSD: scheduler_ramqueue.c,v 1.14 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2012 Gilles Chehade <gilles@openbsd.org> @@ -160,8 +160,10 @@ scheduler_ramqueue_insert(struct scheduler_info *si) } /* find/prepare the host in ramqueue update */ - if ((host = rq_host_lookup(&update->hosts, si->destination)) == NULL) + if ((host = rq_host_lookup(&update->hosts, si->destination)) == NULL) { host = rq_host_create(&update->hosts, si->destination); + stat_increment("scheduler.ramqueue.host"); + } /* find/prepare the hosttree message in ramqueue update */ if ((batch = tree_get(&host->batches, msgid)) == NULL) { @@ -169,6 +171,7 @@ scheduler_ramqueue_insert(struct scheduler_info *si) batch->msgid = msgid; tree_init(&batch->envelopes); tree_xset(&host->batches, msgid, batch); + stat_increment("scheduler.ramqueue.batch"); } /* find/prepare the msgtree message in ramqueue update */ @@ -177,6 +180,7 @@ scheduler_ramqueue_insert(struct scheduler_info *si) message->msgid = msgid; tree_init(&message->envelopes); tree_xset(&update->messages, msgid, message); + stat_increment("scheduler.ramqueue.message"); } /* create envelope in ramqueue message */ @@ -188,6 +192,8 @@ scheduler_ramqueue_insert(struct scheduler_info *si) envelope->sched = scheduler_compute_schedule(si); envelope->expire = si->creation + si->expire; + stat_increment("scheduler.ramqueue.envelope"); + if (envelope->expire < envelope->sched) { envelope->flags |= RQ_ENVELOPE_EXPIRED; tree_xset(&update->expired, envelope->evpid, envelope); @@ -619,6 +625,7 @@ rq_envelope_delete(struct rq_queue *rq, struct rq_envelope *envelope) if (tree_empty(&message->envelopes)) { tree_xpop(&rq->messages, msgid); free(message); + stat_decrement("scheduler.ramqueue.message"); } tree_xpop(&batch->envelopes, envelope->evpid); @@ -627,10 +634,14 @@ rq_envelope_delete(struct rq_queue *rq, struct rq_envelope *envelope) if (tree_empty(&host->batches)) { SPLAY_REMOVE(hosttree, &rq->hosts, host); free(host); + stat_decrement("scheduler.ramqueue.host"); } free(batch); + stat_decrement("scheduler.ramqueue.batch"); } free(envelope); + + stat_decrement("scheduler.ramqueue.envelope"); } static const char * diff --git a/usr.sbin/smtpd/smtp.c b/usr.sbin/smtpd/smtp.c index a9b217df20e..c4d7ab3aa58 100644 --- a/usr.sbin/smtpd/smtp.c +++ b/usr.sbin/smtpd/smtp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp.c,v 1.103 2012/08/09 09:48:02 eric Exp $ */ +/* $OpenBSD: smtp.c,v 1.104 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -49,6 +49,7 @@ static void smtp_accept(int, short, void *); static struct session *smtp_new(struct listener *); static struct session *session_lookup(u_int64_t); +static size_t sessions; static void smtp_imsg(struct imsgev *iev, struct imsg *imsg) @@ -516,15 +517,17 @@ smtp_new(struct listener *l) strlcpy(s->s_msg.tag, l->tag, sizeof(s->s_msg.tag)); SPLAY_INSERT(sessiontree, &env->sc_sessions, s); - if (stat_increment(STATS_SMTP_SESSION) >= env->sc_maxconn) { + stat_increment("smtp.session"); + + if (++sessions >= env->sc_maxconn) { log_warnx("client limit hit, disabling incoming connections"); smtp_pause(); } if (s->s_l->ss.ss_family == AF_INET) - stat_increment(STATS_SMTP_SESSION_INET4); + stat_increment("smtp.session.inet4"); if (s->s_l->ss.ss_family == AF_INET6) - stat_increment(STATS_SMTP_SESSION_INET6); + stat_increment("smtp.session.inet6"); iobuf_init(&s->s_iobuf, MAX_LINE_SIZE, MAX_LINE_SIZE); io_init(&s->s_io, -1, s, session_io, &s->s_iobuf); @@ -533,6 +536,20 @@ smtp_new(struct listener *l) return (s); } +void +smtp_destroy(struct session *session) +{ + size_t resume; + + resume = env->sc_maxconn * 95 / 100; + + if (--sessions == resume) { + log_warnx("re-enabling incoming connections"); + smtp_resume(); + } +} + + /* * Helper function for handling IMSG replies. */ diff --git a/usr.sbin/smtpd/smtp_session.c b/usr.sbin/smtpd/smtp_session.c index 396f3ef3fb1..d173fef7599 100644 --- a/usr.sbin/smtpd/smtp_session.c +++ b/usr.sbin/smtpd/smtp_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtp_session.c,v 1.164 2012/08/18 16:05:54 chl Exp $ */ +/* $OpenBSD: smtp_session.c,v 1.165 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -610,9 +610,9 @@ session_io(struct io *io, int evt) case IO_TLSREADY: s->s_flags |= F_SECURE; if (s->s_l->flags & F_SMTPS) - stat_increment(STATS_SMTP_SMTPS); + stat_increment("smtp.smtps"); if (s->s_l->flags & F_STARTTLS) - stat_increment(STATS_SMTP_STARTTLS); + stat_increment("smtp.tls"); if (s->s_state == S_INIT) { io_set_write(&s->s_io); session_respond(s, SMTPD_BANNER, env->sc_hostname); @@ -694,7 +694,7 @@ session_pickup(struct session *s, struct submit_status *ss) if ((ss != NULL && ss->code == 421) || (s->s_dstatus & DS_TEMPFAILURE)) { - env->stats->smtp.tempfail++; + stat_increment("smtp.tempfail"); session_respond(s, "421 Service temporarily unavailable"); session_enter_state(s, S_QUIT); io_reload(&s->s_io); @@ -924,7 +924,7 @@ session_line(struct session *s, char *line, size_t len) tempfail: session_respond(s, "421 4.0.0 Service temporarily unavailable"); - env->stats->smtp.tempfail++; + stat_increment("smtp.tempfail"); session_enter_state(s, S_QUIT); } @@ -947,7 +947,7 @@ session_read_data(struct session *s, char *line) } else if (s->s_dstatus & DS_TEMPFAILURE) { session_respond(s, "421 4.0.0 Temporary failure"); session_enter_state(s, S_QUIT); - env->stats->smtp.tempfail++; + stat_increment("smtp.tempfail"); } else { session_imsg(s, PROC_QUEUE, IMSG_QUEUE_COMMIT_MESSAGE, 0, 0, -1, &s->s_msg, sizeof(s->s_msg)); @@ -991,8 +991,6 @@ session_read_data(struct session *s, char *line) void session_destroy(struct session *s, const char * reason) { - size_t resume; - log_debug("smtp: %p: deleting session: %s", s, reason); if (s->s_flags & F_ZOMBIE) @@ -1009,10 +1007,10 @@ session_destroy(struct session *s, const char * reason) if (s->s_ssl) { if (s->s_l->flags & F_SMTPS) if (s->s_flags & F_SECURE) - stat_decrement(STATS_SMTP_SMTPS); + stat_decrement("smtp.smtps"); if (s->s_l->flags & F_STARTTLS) if (s->s_flags & F_SECURE) - stat_decrement(STATS_SMTP_STARTTLS); + stat_decrement("smtp.tls"); } event_del(&s->s_ev); /* in case something was scheduled */ @@ -1020,11 +1018,7 @@ session_destroy(struct session *s, const char * reason) iobuf_clear(&s->s_iobuf); /* resume when session count decreases to 95% */ - resume = env->sc_maxconn * 95 / 100; - if (stat_decrement(STATS_SMTP_SESSION) == resume) { - log_warnx("re-enabling incoming connections"); - smtp_resume(); - } + stat_decrement("smtp.session"); /* If the session is waiting for an imsg, do not kill it now, since * the id must still be valid. @@ -1035,6 +1029,9 @@ session_destroy(struct session *s, const char * reason) } finalize: + + smtp_destroy(s); + SPLAY_REMOVE(sessiontree, &env->sc_sessions, s); bzero(s, sizeof(*s)); free(s); @@ -1130,7 +1127,7 @@ session_respond(struct session *s, char *fmt, ...) struct timeval tv = { delay, 0 }; io_pause(&s->s_io, IO_PAUSE_OUT); - env->stats->smtp.delays++; + stat_increment("smtp.delays"); /* in case session_respond is called multiple times */ evtimer_del(&s->s_ev); diff --git a/usr.sbin/smtpd/smtpctl.c b/usr.sbin/smtpd/smtpctl.c index af948be20fa..e8fb5e80f78 100644 --- a/usr.sbin/smtpd/smtpctl.c +++ b/usr.sbin/smtpd/smtpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpctl.c,v 1.85 2012/08/08 17:33:55 eric Exp $ */ +/* $OpenBSD: smtpctl.c,v 1.86 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2006 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -45,7 +45,7 @@ void usage(void); static void setup_env(struct smtpd *); static int show_command_output(struct imsg *); -static int show_stats_output(struct imsg *); +static void show_stats_output(void); static void show_queue(int); static void show_envelope(struct envelope *, int); static void getflag(u_int *, int, char *, char *, size_t); @@ -262,7 +262,8 @@ connected: done = show_command_output(&imsg); break; case SHOW_STATS: - done = show_stats_output(&imsg); + show_stats_output(); + done = 1; break; case NONE: break; @@ -299,141 +300,55 @@ show_command_output(struct imsg *imsg) } static void -stat_print(int stat, int what) +show_stats_output(void) { - static const char *names[STATS_MAX] = { - "smtp.sessions", - "smtp.sessions.inet4", - "smtp.sessions.inet6", - "smtp.sessions.smtps", - "smtp.sessions.starttls", - - "mta.sessions", - - "mda.sessions", - - "control.sessions", - - "lka.sessions", - "lka.sessions.mx", - "lka.sessions.host", - "lka.sessions.cname", - "lka.sessions.failure", - - "scheduler", - "scheduler.bounces", - - "queue.inserts.local", - "queue.inserts.remote", - - "ramqueue.envelopes", - "ramqueue.messages", - "ramqueue.batches", - "ramqueue.hosts", - }; - const char *sfx; - - if (what == STAT_ACTIVE) - sfx = ".active"; - else if (what == STAT_MAXACTIVE) - sfx = ".maxactive"; - else - sfx = ""; + struct stat_kv kv, *kvp; + struct imsg imsg; + int n; - printf("%s%s=%zd\n", names[stat], sfx, stat_get(stat, what)); -} -static int -show_stats_output(struct imsg *imsg) -{ - struct stats *stats; + bzero(&kv, sizeof kv); - if (imsg->hdr.type != IMSG_STATS) - errx(1, "show_stats_output: bad hdr type (%d)", imsg->hdr.type); +again: + imsg_compose(ibuf, IMSG_STATS_GET, 0, 0, -1, &kv, sizeof kv); - if (imsg->hdr.len - IMSG_HEADER_SIZE != sizeof(*stats)) - errx(1, "show_stats_output: bad data size"); - - stats = imsg->data; - stat_init(stats->counters, STATS_MAX); - - stat_print(STATS_CONTROL_SESSION, STAT_COUNT); - stat_print(STATS_CONTROL_SESSION, STAT_ACTIVE); - stat_print(STATS_CONTROL_SESSION, STAT_MAXACTIVE); - - stat_print(STATS_MDA_SESSION, STAT_COUNT); - stat_print(STATS_MDA_SESSION, STAT_ACTIVE); - stat_print(STATS_MDA_SESSION, STAT_MAXACTIVE); - - stat_print(STATS_MTA_SESSION, STAT_COUNT); - stat_print(STATS_MTA_SESSION, STAT_ACTIVE); - stat_print(STATS_MTA_SESSION, STAT_MAXACTIVE); - - stat_print(STATS_LKA_SESSION, STAT_COUNT); - stat_print(STATS_LKA_SESSION, STAT_ACTIVE); - stat_print(STATS_LKA_SESSION, STAT_MAXACTIVE); - stat_print(STATS_LKA_SESSION_MX, STAT_COUNT); - stat_print(STATS_LKA_SESSION_HOST, STAT_COUNT); - stat_print(STATS_LKA_SESSION_CNAME, STAT_COUNT); - stat_print(STATS_LKA_FAILURE, STAT_COUNT); - - printf("parent.uptime=%lld\n", - (long long int) (time(NULL) - stats->parent.start)); - - stat_print(STATS_QUEUE_LOCAL, STAT_COUNT); - stat_print(STATS_QUEUE_REMOTE, STAT_COUNT); - - stat_print(STATS_SCHEDULER, STAT_COUNT); - stat_print(STATS_SCHEDULER, STAT_ACTIVE); - stat_print(STATS_SCHEDULER, STAT_MAXACTIVE); - - stat_print(STATS_SCHEDULER_BOUNCES, STAT_COUNT); - stat_print(STATS_SCHEDULER_BOUNCES, STAT_ACTIVE); - stat_print(STATS_SCHEDULER_BOUNCES, STAT_MAXACTIVE); - - stat_print(STATS_RAMQUEUE_HOST, STAT_ACTIVE); - stat_print(STATS_RAMQUEUE_BATCH, STAT_ACTIVE); - stat_print(STATS_RAMQUEUE_MESSAGE, STAT_ACTIVE); - stat_print(STATS_RAMQUEUE_ENVELOPE, STAT_ACTIVE); - - stat_print(STATS_RAMQUEUE_HOST, STAT_MAXACTIVE); - stat_print(STATS_RAMQUEUE_BATCH, STAT_MAXACTIVE); - stat_print(STATS_RAMQUEUE_MESSAGE, STAT_MAXACTIVE); - stat_print(STATS_RAMQUEUE_ENVELOPE, STAT_MAXACTIVE); - - printf("smtp.errors.delays=%zd\n", stats->smtp.delays); - printf("smtp.errors.linetoolong=%zd\n", stats->smtp.linetoolong); - printf("smtp.errors.read_eof=%zd\n", stats->smtp.read_eof); - printf("smtp.errors.read_system=%zd\n", stats->smtp.read_error); - printf("smtp.errors.read_timeout=%zd\n", stats->smtp.read_timeout); - printf("smtp.errors.tempfail=%zd\n", stats->smtp.tempfail); - printf("smtp.errors.toofast=%zd\n", stats->smtp.toofast); - printf("smtp.errors.write_eof=%zd\n", stats->smtp.write_eof); - printf("smtp.errors.write_system=%zd\n", stats->smtp.write_error); - printf("smtp.errors.write_timeout=%zd\n", stats->smtp.write_timeout); - - stat_print(STATS_SMTP_SESSION, STAT_COUNT); - stat_print(STATS_SMTP_SESSION_INET4, STAT_COUNT); - stat_print(STATS_SMTP_SESSION_INET6, STAT_COUNT); - printf("smtp.sessions.aborted=%zd\n", stats->smtp.read_eof + - stats->smtp.read_error + stats->smtp.write_eof + - stats->smtp.write_error); - - stat_print(STATS_SMTP_SESSION, STAT_ACTIVE); - stat_print(STATS_SMTP_SESSION, STAT_MAXACTIVE); - - printf("smtp.sessions.timeout=%zd\n", stats->smtp.read_timeout + - stats->smtp.write_timeout); - - stat_print(STATS_SMTP_SMTPS, STAT_COUNT); - stat_print(STATS_SMTP_SMTPS, STAT_ACTIVE); - stat_print(STATS_SMTP_SMTPS, STAT_MAXACTIVE); - - stat_print(STATS_SMTP_STARTTLS, STAT_COUNT); - stat_print(STATS_SMTP_STARTTLS, STAT_ACTIVE); - stat_print(STATS_SMTP_STARTTLS, STAT_MAXACTIVE); + while (ibuf->w.queued) + if (msgbuf_write(&ibuf->w) < 0) + err(1, "write error"); - return (1); + do { + if ((n = imsg_read(ibuf)) == -1) + errx(1, "imsg_read error"); + if (n == 0) + errx(1, "pipe closed"); + + do { + if ((n = imsg_get(ibuf, &imsg)) == -1) + errx(1, "imsg_get error"); + if (n == 0) + break; + if (imsg.hdr.type != IMSG_STATS_GET) + errx(1, "invalid imsg type"); + + kvp = imsg.data; + if (kvp->iter == NULL) { + imsg_free(&imsg); + return; + } + + if (strcmp(kvp->key, "uptime") == 0) + printf("%s=%zd\n", kvp->key, time(NULL) - kvp->val); + else + printf("%s=%zd\n", kvp->key, kvp->val); + + kv = *kvp; + + imsg_free(&imsg); + goto again; + + } while (n != 0); + + } while (n != 0); } static void diff --git a/usr.sbin/smtpd/smtpctl/Makefile b/usr.sbin/smtpd/smtpctl/Makefile index aa80005a8d8..c55c89d1380 100644 --- a/usr.sbin/smtpd/smtpctl/Makefile +++ b/usr.sbin/smtpd/smtpctl/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.22 2012/01/11 22:24:37 gilles Exp $ +# $OpenBSD: Makefile,v 1.23 2012/08/18 18:18:23 gilles Exp $ .PATH: ${.CURDIR}/.. @@ -18,7 +18,7 @@ CFLAGS+= -Wsign-compare -Wbounded SRCS= enqueue.c parser.c log.c envelope.c SRCS+= queue_backend.c queue_fsqueue.c -SRCS+= smtpctl.c stats.c util.c +SRCS+= smtpctl.c util.c LDADD+= -lutil DPADD+= ${LIBUTIL} ${LIBEVENT} diff --git a/usr.sbin/smtpd/smtpd.c b/usr.sbin/smtpd/smtpd.c index 28cf891ed98..1d8e6e31d5e 100644 --- a/usr.sbin/smtpd/smtpd.c +++ b/usr.sbin/smtpd/smtpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.c,v 1.157 2012/08/09 09:48:02 eric Exp $ */ +/* $OpenBSD: smtpd.c,v 1.158 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -93,6 +93,7 @@ struct smtpd *env = NULL; const char *backend_queue = "fs"; const char *backend_scheduler = "ramqueue"; +const char *backend_stat = "ram"; static void parent_imsg(struct imsgev *iev, struct imsg *imsg) @@ -454,6 +455,8 @@ main(int argc, char *argv[]) backend_queue = strchr(optarg, '=') + 1; else if (strstr(optarg, "scheduler=") == optarg) backend_scheduler = strchr(optarg, '=') + 1; + else if (strstr(optarg, "stat=") == optarg) + backend_stat = strchr(optarg, '=') + 1; else log_warnx("invalid backend specifier %s", optarg); break; @@ -486,6 +489,8 @@ main(int argc, char *argv[]) verbose |= TRACE_BOUNCE; else if (!strcmp(optarg, "scheduler")) verbose |= TRACE_SCHEDULER; + else if (!strcmp(optarg, "stat")) + verbose |= TRACE_STAT; else if (!strcmp(optarg, "all")) verbose |= ~TRACE_VERBOSE; else @@ -548,6 +553,7 @@ main(int argc, char *argv[]) log_debug("using \"%s\" queue backend", backend_queue); log_debug("using \"%s\" scheduler backend", backend_scheduler); + log_debug("using \"%s\" stat backend", backend_stat); env->sc_queue = queue_backend_lookup(backend_queue); if (env->sc_queue == NULL) @@ -556,6 +562,10 @@ main(int argc, char *argv[]) if (!env->sc_queue->init(1)) errx(1, "could not initialize queue backend"); + env->sc_stat = stat_backend_lookup(backend_stat); + if (env->sc_stat == NULL) + errx(1, "could not find stat backend \"%s\"", backend_stat); + log_init(debug); log_verbose(verbose); @@ -567,15 +577,7 @@ main(int argc, char *argv[]) if (env->sc_hostname[0] == '\0') errx(1, "machine does not have a hostname set"); - - env->stats = mmap(NULL, sizeof(struct stats), PROT_WRITE|PROT_READ, - MAP_ANON|MAP_SHARED, -1, (off_t)0); - if (env->stats == MAP_FAILED) - fatal("mmap"); - bzero(env->stats, sizeof(struct stats)); - stat_init(env->stats->counters, STATS_MAX); - - env->stats->parent.start = time(NULL); + env->sc_uptime = time(NULL); fork_peers(); diff --git a/usr.sbin/smtpd/smtpd.h b/usr.sbin/smtpd/smtpd.h index d0b0f7222fd..3feb220ecdb 100644 --- a/usr.sbin/smtpd/smtpd.h +++ b/usr.sbin/smtpd/smtpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smtpd.h,v 1.321 2012/08/18 15:45:12 eric Exp $ */ +/* $OpenBSD: smtpd.h,v 1.322 2012/08/18 18:18:23 gilles Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -170,7 +170,6 @@ enum imsg_type { IMSG_PARENT_AUTHENTICATE, IMSG_PARENT_SEND_CONFIG, - IMSG_STATS, IMSG_SMTP_ENQUEUE, IMSG_SMTP_PAUSE, IMSG_SMTP_RESUME, @@ -178,7 +177,14 @@ enum imsg_type { IMSG_DNS_HOST, IMSG_DNS_HOST_END, IMSG_DNS_MX, - IMSG_DNS_PTR + IMSG_DNS_PTR, + + IMSG_STAT_INCREMENT, + IMSG_STAT_DECREMENT, + IMSG_STAT_SET, + + IMSG_STATS, + IMSG_STATS_GET, }; enum blockmodes { @@ -587,6 +593,9 @@ struct smtpd { char sc_hostname[MAXHOSTNAMELEN]; struct queue_backend *sc_queue; struct scheduler_backend *sc_scheduler; + struct stat_backend *sc_stat; + + time_t sc_uptime; TAILQ_HEAD(filterlist, filter) *sc_filters; @@ -600,7 +609,6 @@ struct smtpd { SPLAY_HEAD(mfatree, mfa_session) mfa_sessions; LIST_HEAD(mdalist, mda_session) mda_sessions; - struct stats *stats; u_int64_t filtermask; }; @@ -611,74 +619,8 @@ struct smtpd { #define TRACE_MTA 0x0010 #define TRACE_BOUNCE 0x0020 #define TRACE_SCHEDULER 0x0040 +#define TRACE_STAT 0x0080 -enum { - STATS_SMTP_SESSION = 0, - STATS_SMTP_SESSION_INET4, - STATS_SMTP_SESSION_INET6, - STATS_SMTP_SMTPS, - STATS_SMTP_STARTTLS, - - STATS_MTA_SESSION, - - STATS_MDA_SESSION, - - STATS_CONTROL_SESSION, - - STATS_LKA_SESSION, - STATS_LKA_SESSION_MX, - STATS_LKA_SESSION_HOST, - STATS_LKA_SESSION_CNAME, - STATS_LKA_FAILURE, - - STATS_SCHEDULER, - STATS_SCHEDULER_BOUNCES, - - STATS_QUEUE_LOCAL, - STATS_QUEUE_REMOTE, - - STATS_RAMQUEUE_ENVELOPE, - STATS_RAMQUEUE_MESSAGE, - STATS_RAMQUEUE_BATCH, - STATS_RAMQUEUE_HOST, - - STATS_MAX, -}; - -#define STAT_COUNT 0 -#define STAT_ACTIVE 1 -#define STAT_MAXACTIVE 2 - -struct stat_counter { - size_t count; - size_t active; - size_t maxactive; -}; - -struct s_parent { - time_t start; -}; - -struct s_session { - size_t read_error; - size_t read_timeout; - size_t read_eof; - size_t write_error; - size_t write_timeout; - size_t write_eof; - size_t toofast; - size_t tempfail; - size_t linetoolong; - size_t delays; -}; - -struct stats { - struct s_parent parent; - struct s_session mta; - struct s_session smtp; - - struct stat_counter counters[STATS_MAX]; -}; struct submit_status { u_int64_t id; @@ -954,6 +896,24 @@ struct scheduler_backend { void (*remove)(u_int64_t); }; + +#define STAT_KEY_SIZE 1024 +struct stat_kv { + void *iter; + char key[STAT_KEY_SIZE]; + size_t val; +}; + +struct stat_backend { + void (*init)(void); + void (*close)(void); + void (*increment)(const char *); + void (*decrement)(const char *); + void (*set)(const char *, size_t); + int (*iter)(void **, char **, size_t *); +}; + + extern struct smtpd *env; extern void (*imsg_callback)(struct imsgev *, struct imsg *); @@ -1118,7 +1078,7 @@ time_t scheduler_compute_schedule(struct scheduler_info *); /* smtp.c */ pid_t smtp(void); void smtp_resume(void); - +void smtp_destroy(struct session *); /* smtp_session.c */ void session_init(struct listener *, struct session *); @@ -1159,11 +1119,12 @@ SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp); int ssl_ctx_use_private_key(void *, char *, off_t); int ssl_ctx_use_certificate_chain(void *, char *, off_t); -/* stats.c */ -void stat_init(struct stat_counter *, int); -size_t stat_get(int, int); -size_t stat_increment(int); -size_t stat_decrement(int); + +/* stat_backend.c */ +struct stat_backend *stat_backend_lookup(const char *); +void stat_increment(const char *); +void stat_decrement(const char *); +void stat_set(const char *, size_t); /* tree.c */ diff --git a/usr.sbin/smtpd/smtpd/Makefile b/usr.sbin/smtpd/smtpd/Makefile index 3d9467405e9..44fcb194fb5 100644 --- a/usr.sbin/smtpd/smtpd/Makefile +++ b/usr.sbin/smtpd/smtpd/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.46 2012/08/07 21:47:58 eric Exp $ +# $OpenBSD: Makefile,v 1.47 2012/08/18 18:18:23 gilles Exp $ .PATH: ${.CURDIR}/.. ${.CURDIR}/../../../lib/libc/asr @@ -10,7 +10,8 @@ SRCS= aliases.c auth.c bounce.c config.c control.c \ mfa.c mfa_session.c mta.c mta_session.c parse.y \ queue.c queue_backend.c ruleset.c \ scheduler.c scheduler_backend.c smtp.c smtp_session.c \ - smtpd.c ssl.c ssl_privsep.c stats.c tree.c user.c util.c + smtpd.c ssl.c ssl_privsep.c stat_backend.c tree.c \ + user.c util.c # backends SRCS+= auth_bsd.c @@ -24,6 +25,8 @@ SRCS+= map_static.c SRCS+= map_stdio.c SRCS+= queue_fsqueue.c SRCS+= scheduler_ramqueue.c +SRCS+= stat_ramstat.c +#SRCS+= stat_sqlite.c SRCS+= user_pwd.c # resolver diff --git a/usr.sbin/smtpd/stat_backend.c b/usr.sbin/smtpd/stat_backend.c new file mode 100644 index 00000000000..b77ce3abc83 --- /dev/null +++ b/usr.sbin/smtpd/stat_backend.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2012 Gilles Chehade <gilles@openbsd.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 <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <sys/tree.h> +#include <sys/param.h> + +#include <event.h> +#include <imsg.h> +#include <stdio.h> +#include <string.h> + +#include "log.h" +#include "smtpd.h" + +struct stat_backend stat_backend_ramstat; +struct stat_backend stat_backend_sqlite; + +struct stat_backend * +stat_backend_lookup(const char *name) +{ + if (!strcmp(name, "ram")) + return &stat_backend_ramstat; + + if (!strcmp(name, "sqlite")) + return &stat_backend_sqlite; + + return (NULL); +} + +void +stat_increment(const char *name) +{ + char key[STAT_KEY_SIZE]; + + if (strlcpy(key, name, sizeof key) >= sizeof key) + log_warn("stat_increment: truncated key '%s', ignored", name); + + imsg_compose_event(env->sc_ievs[PROC_CONTROL], + IMSG_STAT_INCREMENT, 0, 0, -1, key, sizeof key); +} + +void +stat_decrement(const char *name) +{ + char key[STAT_KEY_SIZE]; + + if (strlcpy(key, name, sizeof key) >= sizeof key) + log_warn("stat_increment: truncated key '%s', ignored", name); + + imsg_compose_event(env->sc_ievs[PROC_CONTROL], + IMSG_STAT_DECREMENT, 0, 0, -1, key, sizeof key); +} + +void +stat_set(const char *name, size_t value) +{ + struct stat_kv kv; + + bzero(&kv, sizeof kv); + if (strlcpy(kv.key, name, sizeof kv.key) >= sizeof kv.key) + log_warn("stat_increment: truncated key '%s', ignored", name); + kv.val = value; + + imsg_compose_event(env->sc_ievs[PROC_CONTROL], + IMSG_STAT_SET, 0, 0, -1, &kv, sizeof kv); +} diff --git a/usr.sbin/smtpd/stat_ramstat.c b/usr.sbin/smtpd/stat_ramstat.c new file mode 100644 index 00000000000..996f8ff8a24 --- /dev/null +++ b/usr.sbin/smtpd/stat_ramstat.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2012 Gilles Chehade <gilles@openbsd.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 <sys/types.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <sys/tree.h> +#include <sys/param.h> + +#include <event.h> +#include <imsg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "smtpd.h" +#include "log.h" + + +static void ramstat_init(void); +static void ramstat_close(void); +static void ramstat_increment(const char *); +static void ramstat_decrement(const char *); +static void ramstat_set(const char *, size_t); +static int ramstat_iter(void **, char **, size_t *); + +struct ramstat_entry { + RB_ENTRY(ramstat_entry) entry; + + char key[STAT_KEY_SIZE]; + size_t 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", env->sc_uptime); +} + +static void +ramstat_close(void) +{ + log_trace(TRACE_STAT, "ramstat: close"); +} + +static void +ramstat_increment(const char *name) +{ + struct ramstat_entry *np, lk; + + log_trace(TRACE_STAT, "ramstat: increment: %s", name); + strlcpy(lk.key, name, sizeof (lk.key)); + np = RB_FIND(stats_tree, &stats, &lk); + if (np == NULL) { + np = calloc(1, sizeof *np); + if (np == NULL) + fatal("calloc"); + strlcpy(np->key, name, sizeof (np->key)); + RB_INSERT(stats_tree, &stats, np); + } + log_trace(TRACE_STAT, "ramstat: %s (%p): %d -> %d", + name, name, (int)np->value, (int)np->value + 1); + np->value++; +} + +static void +ramstat_decrement(const char *name) +{ + struct ramstat_entry *np, lk; + + log_trace(TRACE_STAT, "ramstat: decrement: %s", name); + strlcpy(lk.key, name, sizeof (lk.key)); + np = RB_FIND(stats_tree, &stats, &lk); + if (np == NULL) { + np = calloc(1, sizeof *np); + if (np == NULL) + fatal("calloc"); + strlcpy(np->key, name, sizeof (np->key)); + RB_INSERT(stats_tree, &stats, np); + } + log_trace(TRACE_STAT, "ramstat: %s (%p): %d -> %d", + name, name, (int)np->value, (int)np->value - 1); + np->value--; +} + +static void +ramstat_set(const char *name, size_t val) +{ + struct ramstat_entry *np, lk; + + log_trace(TRACE_STAT, "ramstat: set"); + strlcpy(lk.key, name, sizeof (lk.key)); + np = RB_FIND(stats_tree, &stats, &lk); + if (np == NULL) { + np = calloc(1, sizeof *np); + if (np == NULL) + fatal("calloc"); + strlcpy(np->key, name, sizeof (np->key)); + RB_INSERT(stats_tree, &stats, np); + } + log_trace(TRACE_STAT, "ramstat: %s: %d -> %d", + name, (int)np->value, (int)val); + np->value = val; +} + +static int +ramstat_iter(void **iter, char **name, size_t *val) +{ + struct ramstat_entry *np; + + log_trace(TRACE_STAT, "ramstat: iter"); + if (RB_EMPTY(&stats)) + return 0; + + if (*iter == NULL) + np = RB_ROOT(&stats); + else + np = RB_NEXT(stats_tree, &stats, *iter); + + if (np) { + *name = np->key; + *val = np->value; + } + *iter = np; + 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); diff --git a/usr.sbin/smtpd/stats.c b/usr.sbin/smtpd/stats.c index fb9715d2ddb..e69de29bb2d 100644 --- a/usr.sbin/smtpd/stats.c +++ b/usr.sbin/smtpd/stats.c @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2011 Eric Faurot <eric@openbsd.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 <sys/types.h> -#include <sys/socket.h> -#include <sys/queue.h> -#include <sys/tree.h> -#include <sys/param.h> - -#include <event.h> -#include <imsg.h> -#include <stdio.h> - -#include "smtpd.h" - -static struct stat_counter *counters = NULL; -static int ncounter = 0; - -void -stat_init(struct stat_counter *c, int n) -{ - counters = c; - ncounter = n; -} - -size_t -stat_increment(int stat) -{ - if (stat < 0 || stat >= ncounter) - return (-1); - - counters[stat].count++; - if (++counters[stat].active > counters[stat].maxactive) - counters[stat].maxactive = counters[stat].active; - - return (counters[stat].active); -} - -size_t -stat_decrement(int stat) -{ - if (stat < 0 || stat >= ncounter) - return (-1); - - counters[stat].active--; - - return (counters[stat].active); -} - -size_t -stat_get(int stat, int what) -{ - if (stat < 0 || stat >= ncounter) - return (-1); - - switch (what) { - case STAT_COUNT: - return counters[stat].count; - case STAT_ACTIVE: - return counters[stat].active; - case STAT_MAXACTIVE: - return counters[stat].maxactive; - default: - return (-1); - } -} |