stats.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004, 2005, 2007-2009, 2012  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 2000, 2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id: stats.c,v 1.18 2009/01/27 23:47:54 tbox Exp $ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/magic.h>
00025 #include <isc/mem.h>
00026 #include <isc/stats.h>
00027 #include <isc/util.h>
00028 
00029 #include <dns/opcode.h>
00030 #include <dns/rdatatype.h>
00031 #include <dns/stats.h>
00032 
00033 #define DNS_STATS_MAGIC                 ISC_MAGIC('D', 's', 't', 't')
00034 #define DNS_STATS_VALID(x)              ISC_MAGIC_VALID(x, DNS_STATS_MAGIC)
00035 
00036 /*%
00037  * Statistics types.
00038  */
00039 typedef enum {
00040         dns_statstype_general = 0,
00041         dns_statstype_rdtype = 1,
00042         dns_statstype_rdataset = 2,
00043         dns_statstype_opcode = 3
00044 } dns_statstype_t;
00045 
00046 /*%
00047  * It doesn't make sense to have 2^16 counters for all possible types since
00048  * most of them won't be used.  We have counters for the first 256 types and
00049  * those explicitly supported in the rdata implementation.
00050  * XXXJT: this introduces tight coupling with the rdata implementation.
00051  * Ideally, we should have rdata handle this type of details.
00052  */
00053 /*
00054  * types, !types, nxdomain, stale types, stale !types, stale nxdomain
00055  */
00056 enum {
00057         /* For 0-255, we use the rdtype value as counter indices */
00058         rdtypecounter_dlv = 256,        /* for dns_rdatatype_dlv */
00059         rdtypecounter_others = 257,     /* anything else */
00060         rdtypecounter_max = 258,
00061         /* The following are used for rdataset */
00062         rdtypenxcounter_max = rdtypecounter_max * 2,
00063         rdtypecounter_nxdomain = rdtypenxcounter_max,
00064         /* stale counters offset */
00065         rdtypecounter_stale = rdtypecounter_nxdomain + 1,
00066         rdatasettypecounter_max = rdtypecounter_stale * 2
00067 };
00068 
00069 struct dns_stats {
00070         /*% Unlocked */
00071         unsigned int    magic;
00072         dns_statstype_t type;
00073         isc_mem_t       *mctx;
00074         isc_mutex_t     lock;
00075         isc_stats_t     *counters;
00076 
00077         /*%  Locked by lock */
00078         unsigned int    references;
00079 };
00080 
00081 typedef struct rdatadumparg {
00082         dns_rdatatypestats_dumper_t     fn;
00083         void                            *arg;
00084 } rdatadumparg_t;
00085 
00086 typedef struct opcodedumparg {
00087         dns_opcodestats_dumper_t        fn;
00088         void                            *arg;
00089 } opcodedumparg_t;
00090 
00091 void
00092 dns_stats_attach(dns_stats_t *stats, dns_stats_t **statsp) {
00093         REQUIRE(DNS_STATS_VALID(stats));
00094         REQUIRE(statsp != NULL && *statsp == NULL);
00095 
00096         LOCK(&stats->lock);
00097         stats->references++;
00098         UNLOCK(&stats->lock);
00099 
00100         *statsp = stats;
00101 }
00102 
00103 void
00104 dns_stats_detach(dns_stats_t **statsp) {
00105         dns_stats_t *stats;
00106 
00107         REQUIRE(statsp != NULL && DNS_STATS_VALID(*statsp));
00108 
00109         stats = *statsp;
00110         *statsp = NULL;
00111 
00112         LOCK(&stats->lock);
00113         stats->references--;
00114         UNLOCK(&stats->lock);
00115 
00116         if (stats->references == 0) {
00117                 isc_stats_detach(&stats->counters);
00118                 DESTROYLOCK(&stats->lock);
00119                 isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
00120         }
00121 }
00122 
00123 /*%
00124  * Create methods
00125  */
00126 static isc_result_t
00127 create_stats(isc_mem_t *mctx, dns_statstype_t type, int ncounters,
00128              dns_stats_t **statsp)
00129 {
00130         dns_stats_t *stats;
00131         isc_result_t result;
00132 
00133         stats = isc_mem_get(mctx, sizeof(*stats));
00134         if (stats == NULL)
00135                 return (ISC_R_NOMEMORY);
00136 
00137         stats->counters = NULL;
00138         stats->references = 1;
00139 
00140         result = isc_mutex_init(&stats->lock);
00141         if (result != ISC_R_SUCCESS)
00142                 goto clean_stats;
00143 
00144         result = isc_stats_create(mctx, &stats->counters, ncounters);
00145         if (result != ISC_R_SUCCESS)
00146                 goto clean_mutex;
00147 
00148         stats->magic = DNS_STATS_MAGIC;
00149         stats->type = type;
00150         stats->mctx = NULL;
00151         isc_mem_attach(mctx, &stats->mctx);
00152         *statsp = stats;
00153 
00154         return (ISC_R_SUCCESS);
00155 
00156   clean_mutex:
00157         DESTROYLOCK(&stats->lock);
00158   clean_stats:
00159         isc_mem_put(mctx, stats, sizeof(*stats));
00160 
00161         return (result);
00162 }
00163 
00164 isc_result_t
00165 dns_generalstats_create(isc_mem_t *mctx, dns_stats_t **statsp, int ncounters) {
00166         REQUIRE(statsp != NULL && *statsp == NULL);
00167 
00168         return (create_stats(mctx, dns_statstype_general, ncounters, statsp));
00169 }
00170 
00171 isc_result_t
00172 dns_rdatatypestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
00173         REQUIRE(statsp != NULL && *statsp == NULL);
00174 
00175         return (create_stats(mctx, dns_statstype_rdtype, rdtypecounter_max,
00176                              statsp));
00177 }
00178 
00179 isc_result_t
00180 dns_rdatasetstats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
00181         REQUIRE(statsp != NULL && *statsp == NULL);
00182 
00183         return (create_stats(mctx, dns_statstype_rdataset,
00184                              rdatasettypecounter_max, statsp));
00185 }
00186 
00187 isc_result_t
00188 dns_opcodestats_create(isc_mem_t *mctx, dns_stats_t **statsp) {
00189         REQUIRE(statsp != NULL && *statsp == NULL);
00190 
00191         return (create_stats(mctx, dns_statstype_opcode, 16, statsp));
00192 }
00193 
00194 /*%
00195  * Increment/Decrement methods
00196  */
00197 void
00198 dns_generalstats_increment(dns_stats_t *stats, isc_statscounter_t counter) {
00199         REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
00200 
00201         isc_stats_increment(stats->counters, counter);
00202 }
00203 
00204 void
00205 dns_rdatatypestats_increment(dns_stats_t *stats, dns_rdatatype_t type) {
00206         int counter;
00207 
00208         REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
00209 
00210         if (type == dns_rdatatype_dlv)
00211                 counter = rdtypecounter_dlv;
00212         else if (type > dns_rdatatype_any)
00213                 counter = rdtypecounter_others;
00214         else
00215                 counter = (int)type;
00216 
00217         isc_stats_increment(stats->counters, (isc_statscounter_t)counter);
00218 }
00219 
00220 static inline void
00221 update_rdatasetstats(dns_stats_t *stats, dns_rdatastatstype_t rrsettype,
00222                      isc_boolean_t increment)
00223 {
00224         int counter;
00225         dns_rdatatype_t rdtype;
00226 
00227         if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
00228              DNS_RDATASTATSTYPE_ATTR_NXDOMAIN) != 0) {
00229                 counter = rdtypecounter_nxdomain;
00230         } else {
00231                 rdtype = DNS_RDATASTATSTYPE_BASE(rrsettype);
00232                 if (rdtype == dns_rdatatype_dlv)
00233                         counter = (int)rdtypecounter_dlv;
00234                 else if (rdtype > dns_rdatatype_any)
00235                         counter = (int)rdtypecounter_others;
00236                 else
00237                         counter = (int)rdtype;
00238 
00239                 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
00240                      DNS_RDATASTATSTYPE_ATTR_NXRRSET) != 0)
00241                         counter += rdtypecounter_max;
00242         }
00243 
00244         if (increment) {
00245                 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
00246                      DNS_RDATASTATSTYPE_ATTR_STALE) != 0) {
00247                         isc_stats_decrement(stats->counters, counter);
00248                         counter += rdtypecounter_stale;
00249                 }
00250                 isc_stats_increment(stats->counters, counter);
00251         } else {
00252                 if ((DNS_RDATASTATSTYPE_ATTR(rrsettype) &
00253                      DNS_RDATASTATSTYPE_ATTR_STALE) != 0)
00254                         counter += rdtypecounter_stale;
00255                 isc_stats_decrement(stats->counters, counter);
00256         }
00257 }
00258 
00259 void
00260 dns_rdatasetstats_increment(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
00261 {
00262         REQUIRE(DNS_STATS_VALID(stats) &&
00263                 stats->type == dns_statstype_rdataset);
00264 
00265         update_rdatasetstats(stats, rrsettype, ISC_TRUE);
00266 }
00267 
00268 void
00269 dns_rdatasetstats_decrement(dns_stats_t *stats, dns_rdatastatstype_t rrsettype)
00270 {
00271         REQUIRE(DNS_STATS_VALID(stats) &&
00272                 stats->type == dns_statstype_rdataset);
00273 
00274         update_rdatasetstats(stats, rrsettype, ISC_FALSE);
00275 }
00276 
00277 void
00278 dns_opcodestats_increment(dns_stats_t *stats, dns_opcode_t code) {
00279         REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
00280 
00281         isc_stats_increment(stats->counters, (isc_statscounter_t)code);
00282 }
00283 
00284 /*%
00285  * Dump methods
00286  */
00287 void
00288 dns_generalstats_dump(dns_stats_t *stats, dns_generalstats_dumper_t dump_fn,
00289                       void *arg, unsigned int options)
00290 {
00291         REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_general);
00292 
00293         isc_stats_dump(stats->counters, (isc_stats_dumper_t)dump_fn,
00294                        arg, options);
00295 }
00296 
00297 static void
00298 dump_rdentry(int rdcounter, isc_uint64_t value, dns_rdatastatstype_t attributes,
00299              dns_rdatatypestats_dumper_t dump_fn, void * arg)
00300 {
00301         dns_rdatatype_t rdtype = dns_rdatatype_none; /* sentinel */
00302         dns_rdatastatstype_t type;
00303 
00304         if (rdcounter == rdtypecounter_others)
00305                 attributes |= DNS_RDATASTATSTYPE_ATTR_OTHERTYPE;
00306         else {
00307                 if (rdcounter == rdtypecounter_dlv)
00308                         rdtype = dns_rdatatype_dlv;
00309                 else
00310                         rdtype = (dns_rdatatype_t)rdcounter;
00311         }
00312         type = DNS_RDATASTATSTYPE_VALUE((dns_rdatastatstype_t)rdtype,
00313                                         attributes);
00314         dump_fn(type, value, arg);
00315 }
00316 
00317 static void
00318 rdatatype_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
00319         rdatadumparg_t *rdatadumparg = arg;
00320 
00321         dump_rdentry(counter, value, 0, rdatadumparg->fn, rdatadumparg->arg);
00322 }
00323 
00324 void
00325 dns_rdatatypestats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
00326                         void *arg0, unsigned int options)
00327 {
00328         rdatadumparg_t arg;
00329         REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_rdtype);
00330 
00331         arg.fn = dump_fn;
00332         arg.arg = arg0;
00333         isc_stats_dump(stats->counters, rdatatype_dumpcb, &arg, options);
00334 }
00335 
00336 static void
00337 rdataset_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
00338         rdatadumparg_t *rdatadumparg = arg;
00339         unsigned int attributes;
00340 
00341         if (counter < rdtypecounter_max) {
00342                 dump_rdentry(counter, value, 0, rdatadumparg->fn,
00343                              rdatadumparg->arg);
00344         } else if (counter < rdtypecounter_nxdomain) {
00345                 counter -= rdtypecounter_max;
00346                 attributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET;
00347                 dump_rdentry(counter, value, attributes, rdatadumparg->fn,
00348                              rdatadumparg->arg);
00349         } else if (counter == rdtypecounter_nxdomain) {
00350                 dump_rdentry(0, value, DNS_RDATASTATSTYPE_ATTR_NXDOMAIN,
00351                              rdatadumparg->fn, rdatadumparg->arg);
00352         } else if (counter < rdtypecounter_stale + rdtypecounter_max) {
00353                 counter -= rdtypecounter_stale;
00354                 attributes = DNS_RDATASTATSTYPE_ATTR_STALE;
00355                 dump_rdentry(counter, value, attributes, rdatadumparg->fn,
00356                              rdatadumparg->arg);
00357         } else if (counter < rdtypecounter_stale + rdtypecounter_nxdomain) {
00358                 counter -= rdtypecounter_stale + rdtypecounter_max;
00359                 attributes = DNS_RDATASTATSTYPE_ATTR_NXRRSET |
00360                              DNS_RDATASTATSTYPE_ATTR_STALE;
00361                 dump_rdentry(counter, value, attributes, rdatadumparg->fn,
00362                              rdatadumparg->arg);
00363         } else {
00364                 attributes = DNS_RDATASTATSTYPE_ATTR_NXDOMAIN |
00365                              DNS_RDATASTATSTYPE_ATTR_STALE;
00366                 dump_rdentry(0, value, attributes, rdatadumparg->fn,
00367                              rdatadumparg->arg);
00368         }
00369 }
00370 
00371 void
00372 dns_rdatasetstats_dump(dns_stats_t *stats, dns_rdatatypestats_dumper_t dump_fn,
00373                        void *arg0, unsigned int options)
00374 {
00375         rdatadumparg_t arg;
00376 
00377         REQUIRE(DNS_STATS_VALID(stats) &&
00378                 stats->type == dns_statstype_rdataset);
00379 
00380         arg.fn = dump_fn;
00381         arg.arg = arg0;
00382         isc_stats_dump(stats->counters, rdataset_dumpcb, &arg, options);
00383 }
00384 
00385 static void
00386 opcode_dumpcb(isc_statscounter_t counter, isc_uint64_t value, void *arg) {
00387         opcodedumparg_t *opcodearg = arg;
00388 
00389         opcodearg->fn((dns_opcode_t)counter, value, opcodearg->arg);
00390 }
00391 
00392 void
00393 dns_opcodestats_dump(dns_stats_t *stats, dns_opcodestats_dumper_t dump_fn,
00394                      void *arg0, unsigned int options)
00395 {
00396         opcodedumparg_t arg;
00397 
00398         REQUIRE(DNS_STATS_VALID(stats) && stats->type == dns_statstype_opcode);
00399 
00400         arg.fn = dump_fn;
00401         arg.arg = arg0;
00402         isc_stats_dump(stats->counters, opcode_dumpcb, &arg, options);
00403 }
00404 
00405 /***
00406  *** Obsolete variables and functions follow:
00407  ***/
00408 LIBDNS_EXTERNAL_DATA const char *dns_statscounter_names[DNS_STATS_NCOUNTERS] =
00409         {
00410         "success",
00411         "referral",
00412         "nxrrset",
00413         "nxdomain",
00414         "recursion",
00415         "failure",
00416         "duplicate",
00417         "dropped"
00418         };
00419 
00420 isc_result_t
00421 dns_stats_alloccounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
00422         int i;
00423         isc_uint64_t *p =
00424                 isc_mem_get(mctx, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
00425         if (p == NULL)
00426                 return (ISC_R_NOMEMORY);
00427         for (i = 0; i < DNS_STATS_NCOUNTERS; i++)
00428                 p[i] = 0;
00429         *ctrp = p;
00430         return (ISC_R_SUCCESS);
00431 }
00432 
00433 void
00434 dns_stats_freecounters(isc_mem_t *mctx, isc_uint64_t **ctrp) {
00435         isc_mem_put(mctx, *ctrp, DNS_STATS_NCOUNTERS * sizeof(isc_uint64_t));
00436         *ctrp = NULL;
00437 }

Generated on Tue Apr 28 17:41:05 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha