Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / stats.c
blob076b60bb87d5af23a190efba40ed138a25b8e3a4
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004, 2005, 2007-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: stats.c,v 1.18 2009/01/27 23:47:54 tbox Exp */
22 /*! \file */
24 #include <config.h>
26 #include <isc/magic.h>
27 #include <isc/mem.h>
28 #include <isc/stats.h>
29 #include <isc/util.h>
31 #include <dns/opcode.h>
32 #include <dns/rdatatype.h>
33 #include <dns/stats.h>
35 #define DNS_STATS_MAGIC ISC_MAGIC('D', 's', 't', 't')
36 #define DNS_STATS_VALID(x) ISC_MAGIC_VALID(x, DNS_STATS_MAGIC)
38 /*%
39 * Statistics types.
41 typedef enum {
42 dns_statstype_general = 0,
43 dns_statstype_rdtype = 1,
44 dns_statstype_rdataset = 2,
45 dns_statstype_opcode = 3
46 } dns_statstype_t;
48 /*%
49 * It doesn't make sense to have 2^16 counters for all possible types since
50 * most of them won't be used. We have counters for the first 256 types and
51 * those explicitly supported in the rdata implementation.
52 * XXXJT: this introduces tight coupling with the rdata implementation.
53 * Ideally, we should have rdata handle this type of details.
55 enum {
56 /* For 0-255, we use the rdtype value as counter indices */
57 rdtypecounter_dlv = 256, /* for dns_rdatatype_dlv */
58 rdtypecounter_others = 257, /* anything else */
59 rdtypecounter_max = 258,
60 /* The following are used for rdataset */
61 rdtypenxcounter_max = rdtypecounter_max * 2,
62 rdtypecounter_nxdomain = rdtypenxcounter_max,
63 rdatasettypecounter_max = rdtypecounter_nxdomain + 1
66 struct dns_stats {
67 /*% Unlocked */
68 unsigned int magic;
69 dns_statstype_t type;
70 isc_mem_t *mctx;
71 isc_mutex_t lock;
72 isc_stats_t *counters;
74 /*% Locked by lock */
75 unsigned int references;
78 typedef struct rdatadumparg {
79 dns_rdatatypestats_dumper_t fn;
80 void *arg;
81 } rdatadumparg_t;
83 typedef struct opcodedumparg {
84 dns_opcodestats_dumper_t fn;
85 void *arg;
86 } opcodedumparg_t;
88 void
89 dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
90 REQUIRE(DNS_STATS_VALID(stats));
91 REQUIRE(statsp != NULL && *statsp == NULL);
93 LOCK(&stats->lock);
94 stats->references++;
95 UNLOCK(&stats->lock);
97 *statsp = stats;
100 void
101 dns_stats_detach(dns_stats_t **statsp) {
102 dns_stats_t *stats;
104 REQUIRE(statsp != NULL && DNS_STATS_VALID(*statsp));
106 stats = *statsp;
107 *statsp = NULL;
109 LOCK(&stats->lock);
110 stats->references--;
111 UNLOCK(&stats->lock);
113 if (stats->references == 0) {
114 isc_stats_detach(&stats->counters);
115 DESTROYLOCK(&stats->lock);
116 isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
121 * Create methods
123 static isc_result_t
124 create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
125 dns_stats_t **statsp)
127 dns_stats_t *stats;
128 isc_result_t result;
130 stats = isc_mem_get(mctx, sizeof(*stats));
131 if (stats == NULL)
132 return (ISC_R_NOMEMORY);
134 stats->counters = NULL;
135 stats->references = 1;
137 result = isc_mutex_init(&stats->lock);
138 if (result != ISC_R_SUCCESS)
139 goto clean_stats;
141 result = isc_stats_create(mctx, &stats->counters, ncounters);
142 if (result != ISC_R_SUCCESS)
143 goto clean_mutex;
145 stats->magic = DNS_STATS_MAGIC;
146 stats->type = type;
147 stats->mctx = NULL;
148 isc_mem_attach(mctx, &stats->mctx);
149 *statsp = stats;
151 return (ISC_R_SUCCESS);
153 clean_mutex:
154 DESTROYLOCK(&stats->lock);
155 clean_stats:
156 isc_mem_put(mctx, stats, sizeof(*stats));
158 return (result);
161 isc_result_t
162 dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters) {
163 REQUIRE(statsp != NULL && *statsp == NULL);
165 return (create_stats(mctx, dns_statstype_general, ncounters, statsp));
168 isc_result_t
169 dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
170 REQUIRE(statsp != NULL && *statsp == NULL);
172 return (create_stats(mctx, dns_statstype_rdtype, rdtypecounter_max,
173 statsp));
176 isc_result_t
177 dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
178 REQUIRE(statsp != NULL && *statsp == NULL);
180 return (create_stats(mctx, dns_statstype_rdataset,
181 (rdtypecounter_max * 2) + 1, statsp));
184 isc_result_t
185 dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
186 REQUIRE(statsp != NULL && *statsp == NULL);
188 return (create_stats(mctx, dns_statstype_opcode, 16, statsp));
192 * Increment/Decrement methods
194 void
195 dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter) {
196 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
198 isc_stats_increment(stats->counters, counter);
201 void
202 dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
203 int counter;
205 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
207 if (type == dns_rdatatype_dlv)
208 counter = rdtypecounter_dlv;
209 else if (type > dns_rdatatype_any)
210 counter = rdtypecounter_others;
211 else
212 counter = (int)type;
214 isc_stats_increment(stats->counters, (isc_statscounter_t)counter);
217 static inline void
218 update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
219 isc_boolean_t increment)
221 int counter;
222 dns_rdatatype_t rdtype;
224 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
225 DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) {
226 counter = rdtypecounter_nxdomain;
227 } else {
228 rdtype = DNS_RDATASTATSTYPE_BASE(rrsettype);
229 if (rdtype == dns_rdatatype_dlv)
230 counter = (int)rdtypecounter_dlv;
231 else if (rdtype > dns_rdatatype_any)
232 counter = (int)rdtypecounter_others;
233 else
234 counter = (int)rdtype;
236 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
237 DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0)
238 counter += rdtypecounter_max;
241 if (increment)
242 isc_stats_increment(stats->counters, counter);
243 else
244 isc_stats_decrement(stats->counters, counter);
247 void
248 dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
250 REQUIRE(DNS_STATS_VALID(stats) &&
251 stats->type == dns_statstype_rdataset);
253 update_rdatasetstats(stats, rrsettype, ISC_TRUE);
256 void
257 dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
259 REQUIRE(DNS_STATS_VALID(stats) &&
260 stats->type == dns_statstype_rdataset);
262 update_rdatasetstats(stats, rrsettype, ISC_FALSE);
264 void
265 dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
266 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
268 isc_stats_increment(stats->counters, (isc_statscounter_t)code);
272 * Dump methods
274 void
275 dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
276 void *arg, unsigned int options)
278 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
280 isc_stats_dump(stats->counters, (isc_stats_dumper_t)dump_fn,
281 arg, options);
284 static void
285 dump_rdentry(int rdcounter, isc_uint64_t value, dns_rdatastatstype_t attributes,
286 dns_rdatatypestats_dumper_t dump_fn, void * arg)
288 dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
289 dns_rdatastatstype_t type;
291 if (rdcounter == rdtypecounter_others)
292 attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
293 else {
294 if (rdcounter == rdtypecounter_dlv)
295 rdtype = dns_rdatatype_dlv;
296 else
297 rdtype = (dns_rdatatype_t)rdcounter;
299 type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
300 attributes);
301 dump_fn(type, value, arg);
304 static void
305 rdatatype_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
306 rdatadumparg_t *rdatadumparg = arg;
308 dump_rdentry(counter, value, 0, rdatadumparg->fn, rdatadumparg->arg);
311 void
312 dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
313 void *arg0, unsigned int options)
315 rdatadumparg_t arg;
316 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
318 arg.fn = dump_fn;
319 arg.arg = arg0;
320 isc_stats_dump(stats->counters, rdatatype_dumpcb, &arg, options);
323 static void
324 rdataset_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
325 rdatadumparg_t *rdatadumparg = arg;
327 if (counter < rdtypecounter_max) {
328 dump_rdentry(counter, value, 0, rdatadumparg->fn,
329 rdatadumparg->arg);
330 } else if (counter < rdtypenxcounter_max) {
331 dump_rdentry(counter - rdtypecounter_max, value,
332 DNS_RDATASTATSTYPE_ATTR_NXRRSET,
333 rdatadumparg->fn, rdatadumparg->arg);
334 } else {
335 dump_rdentry(0, value, DNS_RDATASTATSTYPE_ATTR_NXDOMAIN,
336 rdatadumparg->fn, rdatadumparg->arg);
340 void
341 dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
342 void *arg0, unsigned int options)
344 rdatadumparg_t arg;
346 REQUIRE(DNS_STATS_VALID(stats) &&
347 stats->type == dns_statstype_rdataset);
349 arg.fn = dump_fn;
350 arg.arg = arg0;
351 isc_stats_dump(stats->counters, rdataset_dumpcb, &arg, options);
354 static void
355 opcode_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
356 opcodedumparg_t *opcodearg = arg;
358 opcodearg->fn((dns_opcode_t)counter, value, opcodearg->arg);
361 void
362 dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
363 void *arg0, unsigned int options)
365 opcodedumparg_t arg;
367 REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
369 arg.fn = dump_fn;
370 arg.arg = arg0;
371 isc_stats_dump(stats->counters, opcode_dumpcb, &arg, options);
374 /***
375 *** Obsolete variables and functions follow:
376 ***/
377 LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
379 "success",
380 "referral",
381 "nxrrset",
382 "nxdomain",
383 "recursion",
384 "failure",
385 "duplicate",
386 "dropped"
389 isc_result_t
390 dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
391 int i;
392 isc_uint64_t *p =
393 isc_mem_get(mctx, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
394 if (p == NULL)
395 return (ISC_R_NOMEMORY);
396 for (i = 0; i < DNS_STATS_NCOUNTERS; i++)
397 p[i] = 0;
398 *ctrp = p;
399 return (ISC_R_SUCCESS);
402 void
403 dns_stats_freecounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
404 isc_mem_put(mctx, *ctrp, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
405 *ctrp = NULL;