GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/smtpd/smtpd/../stat_ramstat.c Lines: 0 50 0.0 %
Date: 2017-11-07 Branches: 0 192 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: stat_ramstat.c,v 1.10 2015/01/20 17:37:54 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
19
#include <sys/types.h>
20
#include <sys/socket.h>
21
#include <sys/queue.h>
22
#include <sys/tree.h>
23
24
#include <event.h>
25
#include <imsg.h>
26
#include <stdio.h>
27
#include <stdlib.h>
28
#include <string.h>
29
#include <limits.h>
30
31
#include "smtpd.h"
32
#include "log.h"
33
34
35
static void	ramstat_init(void);
36
static void	ramstat_close(void);
37
static void	ramstat_increment(const char *, size_t);
38
static void	ramstat_decrement(const char *, size_t);
39
static void	ramstat_set(const char *, const struct stat_value *);
40
static int	ramstat_iter(void **, char **, struct stat_value *);
41
42
struct ramstat_entry {
43
	RB_ENTRY(ramstat_entry)	entry;
44
	char			key[STAT_KEY_SIZE];
45
	struct stat_value	value;
46
};
47
RB_HEAD(stats_tree, ramstat_entry)	stats;
48
RB_PROTOTYPE(stats_tree, ramstat_entry, entry, ramstat_entry_cmp);
49
50
struct stat_backend	stat_backend_ramstat = {
51
	ramstat_init,
52
	ramstat_close,
53
	ramstat_increment,
54
	ramstat_decrement,
55
	ramstat_set,
56
	ramstat_iter
57
};
58
59
static void
60
ramstat_init(void)
61
{
62
	log_trace(TRACE_STAT, "ramstat: init");
63
64
	RB_INIT(&stats);
65
66
	/* ramstat_set() should be called for each key we want
67
	 * to have displayed by smtpctl show stats at startup.
68
	 */
69
	ramstat_set("uptime", stat_timestamp(env->sc_uptime));
70
}
71
72
static void
73
ramstat_close(void)
74
{
75
	log_trace(TRACE_STAT, "ramstat: close");
76
}
77
78
static void
79
ramstat_increment(const char *name, size_t val)
80
{
81
	struct ramstat_entry	*np, lk;
82
83
	log_trace(TRACE_STAT, "ramstat: increment: %s", name);
84
	(void)strlcpy(lk.key, name, sizeof (lk.key));
85
	np = RB_FIND(stats_tree, &stats, &lk);
86
	if (np == NULL) {
87
		np = xcalloc(1, sizeof *np, "ramstat_increment");
88
		(void)strlcpy(np->key, name, sizeof (np->key));
89
		RB_INSERT(stats_tree, &stats, np);
90
	}
91
	log_trace(TRACE_STAT, "ramstat: %s (%p): %zd -> %zd",
92
	    name, name, np->value.u.counter, np->value.u.counter + val);
93
	np->value.u.counter += val;
94
}
95
96
static void
97
ramstat_decrement(const char *name, size_t val)
98
{
99
	struct ramstat_entry	*np, lk;
100
101
	log_trace(TRACE_STAT, "ramstat: decrement: %s", name);
102
	(void)strlcpy(lk.key, name, sizeof (lk.key));
103
	np = RB_FIND(stats_tree, &stats, &lk);
104
	if (np == NULL) {
105
		np = xcalloc(1, sizeof *np, "ramstat_decrement");
106
		(void)strlcpy(np->key, name, sizeof (np->key));
107
		RB_INSERT(stats_tree, &stats, np);
108
	}
109
	log_trace(TRACE_STAT, "ramstat: %s (%p): %zd -> %zd",
110
	    name, name, np->value.u.counter, np->value.u.counter - val);
111
	np->value.u.counter -= val;
112
}
113
114
static void
115
ramstat_set(const char *name, const struct stat_value *val)
116
{
117
	struct ramstat_entry	*np, lk;
118
119
	log_trace(TRACE_STAT, "ramstat: set: %s", name);
120
	(void)strlcpy(lk.key, name, sizeof (lk.key));
121
	np = RB_FIND(stats_tree, &stats, &lk);
122
	if (np == NULL) {
123
		np = xcalloc(1, sizeof *np, "ramstat_set");
124
		(void)strlcpy(np->key, name, sizeof (np->key));
125
		RB_INSERT(stats_tree, &stats, np);
126
	}
127
	log_trace(TRACE_STAT, "ramstat: %s: n/a -> n/a", name);
128
	np->value = *val;
129
}
130
131
static int
132
ramstat_iter(void **iter, char **name, struct stat_value *val)
133
{
134
	struct ramstat_entry *np;
135
136
	log_trace(TRACE_STAT, "ramstat: iter");
137
	if (RB_EMPTY(&stats))
138
		return 0;
139
140
	if (*iter == NULL)
141
		np = RB_MIN(stats_tree, &stats);
142
	else
143
		np = RB_NEXT(stats_tree, &stats, *iter);
144
145
	*iter = np;
146
	if (np == NULL)
147
		return 0;
148
149
	*name = np->key;
150
	*val  = np->value;
151
	return 1;
152
}
153
154
155
static int
156
ramstat_entry_cmp(struct ramstat_entry *e1, struct ramstat_entry *e2)
157
{
158
	return strcmp(e1->key, e2->key);
159
}
160
161
RB_GENERATE(stats_tree, ramstat_entry, entry, ramstat_entry_cmp);