}
if (recursive_high_water) {
- isc_stats_set(ns_stats_get(server->sctx->nsstats), 0,
- ns_statscounter_recurshighwater);
+ ns_stats_reset_highwater(server->sctx->nsstats,
+ ns_statscounter_recurshighwater);
}
if (tcp_high_water) {
- isc_stats_set(ns_stats_get(server->sctx->nsstats), 0,
- ns_statscounter_tcphighwater);
+ ns_stats_reset_highwater(server->sctx->nsstats,
+ ns_statscounter_tcphighwater);
}
return ISC_R_SUCCESS;
values, options);
}
+static isc_result_t
+dump_statsmulti(isc_statsmulti_t *stats, isc_statsformat_t type, void *arg,
+ const char *category, const char **desc, int ncounters,
+ int *indices, uint64_t *values, int options) {
+ stats_dumparg_t dumparg;
+ unsigned int multioptions = 0;
+
+ dumparg.type = type;
+ dumparg.ncounters = ncounters;
+ dumparg.counterindices = indices;
+ dumparg.countervalues = values;
+
+ /* Convert ISC_STATSDUMP_VERBOSE to ISC_STATSMULTIDUMP_VERBOSE */
+ if ((options & ISC_STATSDUMP_VERBOSE) != 0) {
+ multioptions |= ISC_STATSMULTIDUMP_VERBOSE;
+ }
+
+ memset(values, 0, sizeof(values[0]) * ncounters);
+ isc_statsmulti_dump(stats, generalstat_dump, &dumparg, multioptions);
+
+ return dump_counters(type, arg, category, desc, ncounters, indices,
+ values, options);
+}
+
#if defined(EXTENDED_STATS)
static isc_result_t
dump_histo(isc_histomulti_t *hm, isc_statsformat_t type, void *arg,
TRY0(xmlTextWriterWriteAttribute(writer, ISC_XMLCHAR "type",
ISC_XMLCHAR "nsstat"));
- CHECK(dump_stats(ns_stats_get(server->sctx->nsstats),
- isc_statsformat_xml, writer, NULL,
- nsstats_xmldesc, ns_statscounter_max,
- nsstats_index, nsstat_values,
- ISC_STATSDUMP_VERBOSE));
+ CHECK(dump_statsmulti(server->sctx->nsstats,
+ isc_statsformat_xml, writer, NULL,
+ nsstats_xmldesc, ns_statscounter_max,
+ nsstats_index, nsstat_values,
+ ISC_STATSDUMP_VERBOSE));
TRY0(xmlTextWriterEndElement(writer)); /* /nsstat */
dumparg.result = ISC_R_SUCCESS;
dumparg.arg = counters;
- result = dump_stats(ns_stats_get(server->sctx->nsstats),
- isc_statsformat_json, counters, NULL,
- nsstats_xmldesc, ns_statscounter_max,
- nsstats_index, nsstat_values, 0);
+ result = dump_statsmulti(server->sctx->nsstats,
+ isc_statsformat_json, counters, NULL,
+ nsstats_xmldesc, ns_statscounter_max,
+ nsstats_index, nsstat_values, 0);
if (result != ISC_R_SUCCESS) {
json_object_put(counters);
goto cleanup;
}
fprintf(fp, "++ Name Server Statistics ++\n");
- (void)dump_stats(ns_stats_get(server->sctx->nsstats),
- isc_statsformat_file, fp, NULL, nsstats_desc,
- ns_statscounter_max, nsstats_index, nsstat_values, 0);
+ (void)dump_statsmulti(server->sctx->nsstats,
+ isc_statsformat_file, fp, NULL, nsstats_desc,
+ ns_statscounter_max, nsstats_index,
+ nsstat_values, 0);
fprintf(fp, "++ Zone Maintenance Statistics ++\n");
(void)dump_stats(server->zonestats, isc_statsformat_file, fp, NULL,
* Create rdtype statistics using statsmulti for better multithreading performance.
* We need RDTYPECOUNTER_MAXVAL + 1 counters (0x0602 + 1 = 1539 counters).
*/
+ // XXX(ap): Fix this, this is wrong!
isc_statsmulti_create(mctx, statsp, RDTYPECOUNTER_MAXVAL + 1, 0);
}
*\li 'stats' is a valid isc_statsmulti_t.
*
*\li counter is less than n_max specified on creation.
+ */
+
+void
+isc_statsmulti_reset_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter);
+/*%<
+ * Reset a highwater counter to zero across all threads.
+ * Takes counter values from 0 to n_max-1 and internally maps to the highwater range.
+ *
+ * Requires:
+ *\li 'stats' is a valid isc_statsmulti_t.
+ *
+ *\li counter is less than n_max specified on creation.
*/
\ No newline at end of file
void
isc_statsmulti_update_if_greater(isc_statsmulti_t *stats, isc_statscounter_t counter, isc_statscounter_t value) {
REQUIRE(ISC_STATSMULTI_VALID(stats));
- REQUIRE(counter < stats->n_max);
+ REQUIRE(counter >= stats->n_additive);
+ REQUIRE(counter < stats->ncounters);
/* Map counter to internal highwater position */
isc_statscounter_t internal_counter = stats->n_additive + counter;
isc_statscounter_t
isc_statsmulti_get_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter) {
REQUIRE(ISC_STATSMULTI_VALID(stats));
- REQUIRE(counter < stats->n_max);
+ REQUIRE(counter >= stats->n_additive);
+ REQUIRE(counter < stats->ncounters);
/* Map counter to internal highwater position */
isc_statscounter_t internal_counter = stats->n_additive + counter;
}
return max_value;
}
+
+void
+isc_statsmulti_reset_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+ REQUIRE(ISC_STATSMULTI_VALID(stats));
+ REQUIRE(counter >= stats->n_additive);
+ REQUIRE(counter < stats->ncounters);
+
+ /* Map counter to internal highwater position */
+ isc_statscounter_t internal_counter = stats->n_additive + counter;
+
+ /* Reset highwater counter to 0 across all threads */
+ for (int thread = 0; thread < stats->num_threads; thread++) {
+ int index = thread * stats->per_thread_capacity + internal_counter;
+ atomic_store_relaxed(&stats->counters[index], 0);
+ }
+}
ns_matchview_t matchingview;
/*% Stats counters */
- ns_stats_t *nsstats;
+ isc_statsmulti_t *nsstats;
isc_statsmulti_t *rcvquerystats;
dns_stats_t *opcodestats;
dns_stats_t *rcodestats;
#include <isc/mem.h>
#include <isc/stats.h>
+#include <isc/statsmulti.h>
#include <ns/types.h>
+// XXX(ap): additive counters
/*%
* Server statistics counters. Used as isc_statscounter_t values.
*/
ns_statscounter_prefetch = 64,
ns_statscounter_keytagopt = 65,
- ns_statscounter_tcphighwater = 66,
+ ns_statscounter_reclimitdropped = 66,
- ns_statscounter_reclimitdropped = 67,
+ ns_statscounter_updatequota = 67,
+ ns_statscounter_dot = 68,
+ ns_statscounter_doh = 69,
+ ns_statscounter_dohplain = 70,
- ns_statscounter_updatequota = 68,
-
- ns_statscounter_recurshighwater = 69,
-
- ns_statscounter_dot = 70,
- ns_statscounter_doh = 71,
- ns_statscounter_dohplain = 72,
-
- ns_statscounter_proxyudp = 73,
- ns_statscounter_proxytcp = 74,
- ns_statscounter_proxydot = 75,
- ns_statscounter_proxydoh = 76,
- ns_statscounter_proxydohplain = 77,
- ns_statscounter_encryptedproxydot = 78,
- ns_statscounter_encryptedproxydoh = 79,
+ ns_statscounter_proxyudp = 71,
+ ns_statscounter_proxytcp = 72,
+ ns_statscounter_proxydot = 73,
+ ns_statscounter_proxydoh = 74,
+ ns_statscounter_proxydohplain = 75,
+ ns_statscounter_encryptedproxydot = 76,
+ ns_statscounter_encryptedproxydoh = 77,
ns_statscounter_max = 80,
};
-void
-ns_stats_attach(ns_stats_t *stats, ns_stats_t **statsp);
+// XXX(ap): highwater counters
+enum {
+ ns_statscounter_tcphighwater = 78,
+ ns_statscounter_recurshighwater = 79,
-void
-ns_stats_detach(ns_stats_t **statsp);
+ ns_highwater_max = ns_statscounter_max,
+};
+
+enum {
+ ns_statscounter_total = ns_statscounter_max + ns_highwater_max,
+};
void
-ns_stats_create(isc_mem_t *mctx, int ncounters, ns_stats_t **statsp);
+ns_stats_create(isc_mem_t *mctx, isc_statsmulti_t **statsp);
isc_statscounter_t
-ns_stats_increment(ns_stats_t *stats, isc_statscounter_t counter);
+ns_stats_increment(isc_statsmulti_t *stats, isc_statscounter_t counter);
void
-ns_stats_decrement(ns_stats_t *stats, isc_statscounter_t counter);
-
-isc_stats_t *
-ns_stats_get(ns_stats_t *stats);
+ns_stats_decrement(isc_statsmulti_t *stats, isc_statscounter_t counter);
void
-ns_stats_update_if_greater(ns_stats_t *stats, isc_statscounter_t counter,
+ns_stats_update_if_greater(isc_statsmulti_t *stats, isc_statscounter_t counter,
isc_statscounter_t value);
isc_statscounter_t
-ns_stats_get_counter(ns_stats_t *stats, isc_statscounter_t counter);
+ns_stats_get_counter(isc_statsmulti_t *stats, isc_statscounter_t counter);
+
+isc_statscounter_t
+ns_stats_get_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter);
+
+void
+ns_stats_reset_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter);
ISC_LIST_INIT(sctx->http_quotas);
isc_mutex_init(&sctx->http_quotas_lock);
- ns_stats_create(mctx, ns_statscounter_max, &sctx->nsstats);
+ ns_stats_create(mctx, &sctx->nsstats);
dns_rdatatypestats_create(mctx, &sctx->rcvquerystats);
}
if (sctx->nsstats != NULL) {
- ns_stats_detach(&sctx->nsstats);
+ isc_statsmulti_detach(&sctx->nsstats);
}
if (sctx->rcvquerystats != NULL) {
/*! \file */
-#include <isc/magic.h>
#include <isc/mem.h>
-#include <isc/refcount.h>
-#include <isc/stats.h>
+#include <isc/statsmulti.h>
#include <isc/util.h>
#include <ns/stats.h>
-#define NS_STATS_MAGIC ISC_MAGIC('N', 's', 't', 't')
-#define NS_STATS_VALID(x) ISC_MAGIC_VALID(x, NS_STATS_MAGIC)
-
-struct ns_stats {
- /*% Unlocked */
- unsigned int magic;
- isc_mem_t *mctx;
- isc_stats_t *counters;
- isc_refcount_t references;
-};
-
void
-ns_stats_attach(ns_stats_t *stats, ns_stats_t **statsp) {
- REQUIRE(NS_STATS_VALID(stats));
+ns_stats_create(isc_mem_t *mctx, isc_statsmulti_t **statsp) {
REQUIRE(statsp != NULL && *statsp == NULL);
- isc_refcount_increment(&stats->references);
-
- *statsp = stats;
-}
-
-void
-ns_stats_detach(ns_stats_t **statsp) {
- ns_stats_t *stats;
-
- REQUIRE(statsp != NULL && NS_STATS_VALID(*statsp));
-
- stats = *statsp;
- *statsp = NULL;
-
- if (isc_refcount_decrement(&stats->references) == 1) {
- isc_stats_detach(&stats->counters);
- isc_refcount_destroy(&stats->references);
- isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
- }
-}
-
-void
-ns_stats_create(isc_mem_t *mctx, int ncounters, ns_stats_t **statsp) {
- REQUIRE(statsp != NULL && *statsp == NULL);
-
- ns_stats_t *stats = isc_mem_get(mctx, sizeof(*stats));
- stats->counters = NULL;
-
- isc_refcount_init(&stats->references, 1);
-
- isc_stats_create(mctx, &stats->counters, ncounters);
-
- stats->magic = NS_STATS_MAGIC;
- stats->mctx = NULL;
- isc_mem_attach(mctx, &stats->mctx);
- *statsp = stats;
+ /*
+ * Create ns statistics using statsmulti for better multithreading performance.
+ * We have 78 additive counters and ns_highwater_max highwater counters.
+ */
+ isc_statsmulti_create(mctx, statsp, 78, 2);
}
/*%
* Increment/Decrement methods
*/
isc_statscounter_t
-ns_stats_increment(ns_stats_t *stats, isc_statscounter_t counter) {
- REQUIRE(NS_STATS_VALID(stats));
+ns_stats_increment(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+ REQUIRE(stats != NULL);
- return isc_stats_increment(stats->counters, counter);
+ return isc_statsmulti_increment(stats, counter);
}
void
-ns_stats_decrement(ns_stats_t *stats, isc_statscounter_t counter) {
- REQUIRE(NS_STATS_VALID(stats));
+ns_stats_decrement(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+ REQUIRE(stats != NULL);
- isc_stats_decrement(stats->counters, counter);
+ isc_statsmulti_decrement(stats, counter);
}
-isc_stats_t *
-ns_stats_get(ns_stats_t *stats) {
- REQUIRE(NS_STATS_VALID(stats));
+void
+ns_stats_update_if_greater(isc_statsmulti_t *stats, isc_statscounter_t counter,
+ isc_statscounter_t value) {
+ REQUIRE(stats != NULL);
- return stats->counters;
+ isc_statsmulti_update_if_greater(stats, counter, value);
}
-void
-ns_stats_update_if_greater(ns_stats_t *stats, isc_statscounter_t counter,
- isc_statscounter_t value) {
- REQUIRE(NS_STATS_VALID(stats));
+isc_statscounter_t
+ns_stats_get_counter(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+ REQUIRE(stats != NULL);
+
+ /* Check if this is a highwater counter */
+ if (counter == ns_statscounter_tcphighwater || counter == ns_statscounter_recurshighwater) {
+ return ns_stats_get_highwater(stats, counter);
+ }
- isc_stats_update_if_greater(stats->counters, counter, value);
+ return isc_statsmulti_get_counter(stats, counter);
}
isc_statscounter_t
-ns_stats_get_counter(ns_stats_t *stats, isc_statscounter_t counter) {
- REQUIRE(NS_STATS_VALID(stats));
+ns_stats_get_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+ REQUIRE(stats != NULL);
+
+ return isc_statsmulti_get_highwater(stats, counter);
+}
+
+void
+ns_stats_reset_highwater(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+ REQUIRE(stats != NULL);
- return isc_stats_get_counter(stats->counters, counter);
+ isc_statsmulti_reset_highwater(stats, counter);
}