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.
This commit is contained in:
Matthijs Mekking 2021-08-19 13:38:51 +02:00
parent 0bac9c7c5c
commit 9acce8a82a
3 changed files with 60 additions and 0 deletions

View file

@ -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 */

View file

@ -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;
}

View file

@ -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);
}