]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Add functions for collecting high-water counters
authorDiego Fronza <diego@isc.org>
Tue, 5 Nov 2019 20:48:47 +0000 (17:48 -0300)
committerOndřej Surý <ondrej@sury.org>
Wed, 6 Nov 2019 11:35:33 +0000 (12:35 +0100)
Add {isc,ns}_stats_{update_if_greater,get_counter}() functions that
are used to set and collect high-water type of statistics.

(cherry picked from commit a544e2e3006cf426b4125a892ae828137d692e6b)

lib/isc/include/isc/stats.h
lib/isc/stats.c
lib/isc/win32/libisc.def.in

index 8f41bb95aa867b4c6a0af4b2c188c6d7a748ba8a..d127dbdf95f3740dfd3f26c2d5dbebe02a0c339e 100644 (file)
@@ -132,6 +132,31 @@ isc_stats_set(isc_stats_t *stats, uint64_t val,
  *\li  'stats' is a valid isc_stats_t.
  */
 
+void isc_stats_update_if_greater(isc_stats_t *stats,
+                                isc_statscounter_t counter,
+                                uint64_t value);
+/*%<
+* Atomically assigns 'value' to 'counter' if value > counter.
+*
+* Requires:
+*\li   'stats' is a valid isc_stats_t.
+*
+*\li   counter is less than the maximum available ID for the stats specified
+*      on creation.
+*/
+
+uint64_t
+isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter);
+/*%<
+ * Returns value currently stored in counter.
+ *
+ * Requires:
+ *\li  'stats' is a valid isc_stats_t.
+ *
+ *\li  counter is less than the maximum available ID for the stats specified
+ *     on creation.
+ */
+
 ISC_LANG_ENDDECLS
 
 #endif /* ISC_STATS_H */
index 5b8c9580a13aef687b3aeb3d668e09663e1d479d..72ee5028ab31cdd6328e2738d0ccf607ae89ea88 100644 (file)
@@ -461,3 +461,85 @@ isc_stats_set(isc_stats_t *stats, uint64_t val,
        isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
 #endif
 }
+
+void isc_stats_update_if_greater(isc_stats_t *stats,
+                                isc_statscounter_t counter,
+                                uint64_t value)
+{
+       REQUIRE(ISC_STATS_VALID(stats));
+       REQUIRE(counter < stats->ncounters);
+
+#if ISC_STATS_LOCKCOUNTERS
+       isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+
+#if ISC_STATS_USEMULTIFIELDS
+       uint64_t curr_value = (stats->counters[counter].hi << 32) &&
+               stats->counters[counter].lo;
+
+       if (curr_value < value) {
+               stats->counters[counter].hi =
+                       (uint32_t)((value >> 32) & 0xffffffff);
+               stats->counters[counter].lo =
+                       (uint32_t)(value & 0xffffffff);
+       }
+#elif ISC_STATS_HAVEATOMICQ
+#if defined(ISC_STATS_HAVESTDATOMICQ)
+       isc_statscounter_t curr_value;
+
+       do {
+               curr_value = atomic_load_explicit(&stats->counters[counter],
+                                                 memory_order_relaxed);
+               if (curr_value >= value) {
+                       break;
+               }
+
+       } while (!atomic_compare_exchange_strong(&stats->counters[counter],
+                                                (int64_t *)&curr_value,
+                                                value));
+#else
+       isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
+       if (stats->counters[counter] < value) {
+               stats->counters[counter] = value;
+       }
+       isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+
+#if ISC_STATS_LOCKCOUNTERS
+       isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+}
+
+uint64_t
+isc_stats_get_counter(isc_stats_t *stats, isc_statscounter_t counter)
+{
+       REQUIRE(ISC_STATS_VALID(stats));
+       REQUIRE(counter < stats->ncounters);
+
+       uint64_t curr_value;
+
+#if ISC_STATS_LOCKCOUNTERS
+       isc_rwlock_lock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+
+#if ISC_STATS_USEMULTIFIELDS
+       curr_value = (stats->counters[counter].hi << 32) &&
+               stats->counters[counter].lo;
+#elif ISC_STATS_HAVEATOMICQ
+#if defined(ISC_STATS_HAVESTDATOMICQ)
+       curr_value = atomic_load_explicit(&stats->counters[counter],
+                                         memory_order_relaxed);
+#else
+#else
+       /* use xaddq(..., 0) as an atomic load */
+       curr_value =
+               (uint64_t)isc_atomic_xaddq((int64_t *)&stats->counters[counter],
+                                          0);
+#endif
+
+#if ISC_STATS_LOCKCOUNTERS
+       isc_rwlock_unlock(&stats->counterlock, isc_rwlocktype_write);
+#endif
+
+       return (curr_value);
+}
index fb48fbfadf822ad5242302d96ab1d9a9c83d83e3..bf3a10ca81ac7bb8b6f4af0c6a380a25b65b0333 100644 (file)
@@ -642,9 +642,11 @@ isc_stats_create
 isc_stats_decrement
 isc_stats_detach
 isc_stats_dump
+isc_stats_get_counter
 isc_stats_increment
 isc_stats_ncounters
 isc_stats_set
+isc_stats_update_if_greater
 isc_stdio_close
 isc_stdio_flush
 isc_stdio_open