]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add statsmulti
authorAlessio Podda <alessio@isc.org>
Fri, 5 Sep 2025 13:39:48 +0000 (15:39 +0200)
committerAlessio Podda <alessio@isc.org>
Wed, 24 Sep 2025 15:01:48 +0000 (17:01 +0200)
lib/isc/include/isc/statsmulti.h [new file with mode: 0644]
lib/isc/statsmulti.c [new file with mode: 0644]

diff --git a/lib/isc/include/isc/statsmulti.h b/lib/isc/include/isc/statsmulti.h
new file mode 100644 (file)
index 0000000..272f463
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#pragma once
+
+/*! \file isc/statsmulti.h */
+
+#include <inttypes.h>
+
+#include <isc/types.h>
+
+typedef struct isc_statsmulti isc_statsmulti_t; /*%< Statistics Multi */
+
+/*%<
+ * Flag(s) for isc_statsmulti_dump().
+ */
+#define ISC_STATSMULTIDUMP_VERBOSE 0x00000001 /*%< dump 0-value counters */
+
+/*%<
+ * Dump callback type.
+ */
+typedef void (*isc_statsmulti_dumper_t)(isc_statscounter_t, uint64_t, void *);
+
+void
+isc_statsmulti_create(isc_mem_t *mctx, isc_statsmulti_t **statsp, int ncounters);
+/*%<
+ * Create a statistics counter structure of general type.  It counts a general
+ * set of counters indexed by an ID between 0 and ncounters -1.
+ *
+ * Requires:
+ *\li  'mctx' must be a valid memory context.
+ *
+ *\li  'statsp' != NULL && '*statsp' == NULL.
+ */
+
+void
+isc_statsmulti_attach(isc_statsmulti_t *stats, isc_statsmulti_t **statsp);
+/*%<
+ * Attach to a statistics set.
+ *
+ * Requires:
+ *\li  'stats' is a valid isc_statsmulti_t.
+ *
+ *\li  'statsp' != NULL && '*statsp' == NULL
+ */
+
+void
+isc_statsmulti_detach(isc_statsmulti_t **statsp);
+/*%<
+ * Detaches from the statistics set.
+ *
+ * Requires:
+ *\li  'statsp' != NULL and '*statsp' is a valid isc_statsmulti_t.
+ */
+
+isc_statscounter_t
+isc_statsmulti_increment(isc_statsmulti_t *stats, isc_statscounter_t counter);
+/*%<
+ * Increment the counter-th counter of stats and return the old value.
+ *
+ * Requires:
+ *\li  'stats' is a valid isc_statsmulti_t.
+ *
+ *\li  counter is less than the maximum available ID for the stats specified
+ *     on creation.
+ */
+
+void
+isc_statsmulti_decrement(isc_statsmulti_t *stats, isc_statscounter_t counter);
+/*%<
+ * Decrement the counter-th counter of stats.
+ *
+ * Requires:
+ *\li  'stats' is a valid isc_statsmulti_t.
+ */
+
+void
+isc_statsmulti_dump(isc_statsmulti_t *stats, isc_statsmulti_dumper_t dump_fn, void *arg,
+                   unsigned int options);
+/*%<
+ * Dump the current statistics counters in a specified way.  For each counter
+ * in stats, dump_fn is called with its current value and the given argument
+ * arg.  By default counters that have a value of 0 is skipped; if options has
+ * the ISC_STATSMULTIDUMP_VERBOSE flag, even such counters are dumped.
+ *
+ * Requires:
+ *\li  'stats' is a valid isc_statsmulti_t.
+ */
+
+isc_statscounter_t
+isc_statsmulti_get_counter(isc_statsmulti_t *stats, isc_statscounter_t counter);
+/*%<
+ * Returns value currently stored in counter.
+ *
+ * Requires:
+ *\li  'stats' is a valid isc_statsmulti_t.
+ *
+ *\li  counter is less than the maximum available ID for the stats specified
+ *     on creation.
+ */
\ No newline at end of file
diff --git a/lib/isc/statsmulti.c b/lib/isc/statsmulti.c
new file mode 100644 (file)
index 0000000..c37ed69
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <isc/atomic.h>
+#include <isc/buffer.h>
+#include <isc/magic.h>
+#include <isc/mem.h>
+#include <isc/refcount.h>
+#include <isc/stats.h>
+#include <isc/statsmulti.h>
+#include <isc/util.h>
+
+#define ISC_STATSMULTI_MAGIC      ISC_MAGIC('S', 'M', 'u', 'l')
+#define ISC_STATSMULTI_VALID(x) ISC_MAGIC_VALID(x, ISC_STATSMULTI_MAGIC)
+
+/*
+ * Same constraint as stats.c
+ */
+STATIC_ASSERT(sizeof(isc_statscounter_t) <= sizeof(uint64_t),
+             "Exported statistics must fit into the statistic counter size");
+
+struct isc_statsmulti {
+       unsigned int magic;
+       isc_mem_t *mctx;
+       isc_refcount_t references;
+       int ncounters;
+       isc_atomic_statscounter_t *counters;
+};
+
+void
+isc_statsmulti_create(isc_mem_t *mctx, isc_statsmulti_t **statsp, int ncounters) {
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       isc_statsmulti_t *stats = isc_mem_get(mctx, sizeof(*stats));
+       size_t counters_alloc_size = sizeof(isc_atomic_statscounter_t) *
+                                    ncounters;
+       stats->counters = isc_mem_get(mctx, counters_alloc_size);
+       isc_refcount_init(&stats->references, 1);
+       for (int i = 0; i < ncounters; i++) {
+               atomic_init(&stats->counters[i], 0);
+       }
+       stats->mctx = NULL;
+       isc_mem_attach(mctx, &stats->mctx);
+       stats->ncounters = ncounters;
+       stats->magic = ISC_STATSMULTI_MAGIC;
+       *statsp = stats;
+}
+
+void
+isc_statsmulti_attach(isc_statsmulti_t *stats, isc_statsmulti_t **statsp) {
+       REQUIRE(ISC_STATSMULTI_VALID(stats));
+       REQUIRE(statsp != NULL && *statsp == NULL);
+
+       isc_refcount_increment(&stats->references);
+       *statsp = stats;
+}
+
+void
+isc_statsmulti_detach(isc_statsmulti_t **statsp) {
+       isc_statsmulti_t *stats;
+
+       REQUIRE(statsp != NULL && ISC_STATSMULTI_VALID(*statsp));
+
+       stats = *statsp;
+       *statsp = NULL;
+
+       if (isc_refcount_decrement(&stats->references) == 1) {
+               isc_refcount_destroy(&stats->references);
+               isc_mem_cput(stats->mctx, stats->counters, stats->ncounters,
+                            sizeof(isc_atomic_statscounter_t));
+               isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
+       }
+}
+
+isc_statscounter_t
+isc_statsmulti_increment(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+       REQUIRE(ISC_STATSMULTI_VALID(stats));
+       REQUIRE(counter < stats->ncounters);
+
+       return atomic_fetch_add_relaxed(&stats->counters[counter], 1);
+}
+
+void
+isc_statsmulti_decrement(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+       REQUIRE(ISC_STATSMULTI_VALID(stats));
+       REQUIRE(counter < stats->ncounters);
+#if ISC_STATS_CHECKUNDERFLOW
+       REQUIRE(atomic_fetch_sub_release(&stats->counters[counter], 1) > 0);
+#else
+       atomic_fetch_sub_release(&stats->counters[counter], 1);
+#endif
+}
+
+void
+isc_statsmulti_dump(isc_statsmulti_t *stats, isc_statsmulti_dumper_t dump_fn, void *arg,
+                   unsigned int options) {
+       int i;
+
+       REQUIRE(ISC_STATSMULTI_VALID(stats));
+
+       for (i = 0; i < stats->ncounters; i++) {
+               isc_statscounter_t counter =
+                       atomic_load_acquire(&stats->counters[i]);
+               if ((options & ISC_STATSMULTIDUMP_VERBOSE) == 0 && counter == 0) {
+                       continue;
+               }
+               dump_fn((isc_statscounter_t)i, counter, arg);
+       }
+}
+
+isc_statscounter_t
+isc_statsmulti_get_counter(isc_statsmulti_t *stats, isc_statscounter_t counter) {
+       REQUIRE(ISC_STATSMULTI_VALID(stats));
+       REQUIRE(counter < stats->ncounters);
+
+       return atomic_load_acquire(&stats->counters[counter]);
+}