From 9acce8a82abec4b88630c1d05a18a44ebb051ecb Mon Sep 17 00:00:00 2001 From: Matthijs Mekking Date: Thu, 19 Aug 2021 13:38:51 +0200 Subject: [PATCH] Add a function isc_stats_resize Add a new function to resize the number of counters in a statistics counter structure. This will be needed when we keep track of DNSSEC sign statistics and new keys are introduced due to a rollover. --- lib/isc/include/isc/stats.h | 11 +++++++++++ lib/isc/stats.c | 32 ++++++++++++++++++++++++++++++++ lib/isc/tests/stats_test.c | 17 +++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/lib/isc/include/isc/stats.h b/lib/isc/include/isc/stats.h index c2ab4e6c03..f57aa1a96f 100644 --- a/lib/isc/include/isc/stats.h +++ b/lib/isc/include/isc/stats.h @@ -238,6 +238,17 @@ isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter); * on creation. */ +void +isc_stats_resize(isc_stats_t **stats, int ncounters); +/*%< + * Resize a statistics counter structure of general type. The new set of + * counters are indexed by an ID between 0 and ncounters -1. + * + * Requires: + *\li 'stats' is a valid isc_stats_t. + *\li 'ncounters' is a non-zero positive number. + */ + ISC_LANG_ENDDECLS #endif /* ISC_STATS_H */ diff --git a/lib/isc/stats.c b/lib/isc/stats.c index ab599b18af..6297946cb2 100644 --- a/lib/isc/stats.c +++ b/lib/isc/stats.c @@ -162,3 +162,35 @@ isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter) { return (atomic_load_acquire(&stats->counters[counter])); } + +void +isc_stats_resize(isc_stats_t **statsp, int ncounters) { + isc_stats_t *stats; + size_t counters_alloc_size; + isc__atomic_statcounter_t *newcounters; + + REQUIRE(statsp != NULL && *statsp != NULL); + REQUIRE(ISC_STATS_VALID(*statsp)); + REQUIRE(ncounters > 0); + + stats = *statsp; + if (stats->ncounters >= ncounters) { + /* We already have enough counters. */ + return; + } + + /* Grow number of counters. */ + counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters; + newcounters = isc_mem_get(stats->mctx, counters_alloc_size); + for (int i = 0; i < ncounters; i++) { + atomic_init(&newcounters[i], 0); + } + for (int i = 0; i < stats->ncounters; i++) { + uint32_t counter = atomic_load_acquire(&stats->counters[i]); + atomic_store_release(&newcounters[i], counter); + } + isc_mem_put(stats->mctx, stats->counters, + sizeof(isc__atomic_statcounter_t) * stats->ncounters); + stats->counters = newcounters; + stats->ncounters = ncounters; +} diff --git a/lib/isc/tests/stats_test.c b/lib/isc/tests/stats_test.c index a212613143..7b7476d3ad 100644 --- a/lib/isc/tests/stats_test.c +++ b/lib/isc/tests/stats_test.c @@ -96,6 +96,23 @@ isc_stats_basic_test(void **state) { assert_int_equal(isc_stats_get_counter(stats, i), i + 1); } + /* Test resize. */ + isc_stats_resize(&stats, 3); + assert_int_equal(isc_stats_ncounters(stats), 4); + isc_stats_resize(&stats, 4); + assert_int_equal(isc_stats_ncounters(stats), 4); + isc_stats_resize(&stats, 5); + assert_int_equal(isc_stats_ncounters(stats), 5); + + /* Existing counters are retained */ + for (int i = 0; i < isc_stats_ncounters(stats); i++) { + uint32_t expect = i + 1; + if (i == 4) { + expect = 0; + } + assert_int_equal(isc_stats_get_counter(stats, i), expect); + } + isc_stats_detach(&stats); }