<p>neels has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmocore/+/25464">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">refactor stat_item: get rid of FIFO and "skipped" error<br><br>Intead of attempting to store all distinct values of a reporting period,<br>just store min, max, last as well as a sum and N of each reporting<br>period.<br><br>This gets rid of error messages like<br><br>  DLSTATS ERROR stat_item.c:285 num_bts:oml_connected: 44 stats values skipped<br><br>while at the same time more accurately reporting the max value for each<br>reporting period. (So far stats_item only reports the max value; keep<br>that part unchanged, as shown in stats_test.c.)<br><br>With the other so far unused values (min, sum), we are ready to also<br>report the minimum value as well as an average value per reporting<br>period in the future, if/when our stats reporter allows for it.<br><br>Store the complete record of the previous reporting period. So far we<br>only compare the 'max' value, but like this we are ready to also see<br>changes in min, last and average value between reporting periods.<br><br>Related: SYS#5542<br>Change-Id: I137992a5479fc39bbceb6c6c2af9c227bd33b39b<br>---<br>M TODO-RELEASE<br>M include/osmocom/core/stat_item.h<br>M src/stat_item.c<br>M src/stats.c<br>M tests/stats/stats_test.c<br>M tests/stats/stats_test.err<br>6 files changed, 318 insertions(+), 272 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/64/25464/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/TODO-RELEASE b/TODO-RELEASE</span><br><span>index c8966cd..855ceaa 100644</span><br><span>--- a/TODO-RELEASE</span><br><span>+++ b/TODO-RELEASE</span><br><span>@@ -15,4 +15,5 @@</span><br><span> libosmosim      osim_card_{reset,close} New API</span><br><span> libosmocore     struct rate_ctr_group, osmo_stat_item_group_desc ABI breakage due to new struct members</span><br><span> libosmgsm      kdf functions   New API</span><br><span style="color: hsl(0, 100%, 40%);">-libosmocore osmo_stat_item          ABI + API breakage due to new struct members</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore       osmo_stat_item          API change and ABI breakage due to new struct members; some osmo_stat_item API deprecated.</span><br><span style="color: hsl(120, 100%, 40%);">+libosmocore osmo_stat_item          No FIFO buffer of values used anymore, the "skipped values" error is no longer possible.</span><br><span>diff --git a/include/osmocom/core/stat_item.h b/include/osmocom/core/stat_item.h</span><br><span>index c4e8332..717cfe9 100644</span><br><span>--- a/include/osmocom/core/stat_item.h</span><br><span>+++ b/include/osmocom/core/stat_item.h</span><br><span>@@ -14,28 +14,43 @@</span><br><span> #define OSMO_STAT_ITEM_NOVALUE_ID 0</span><br><span> #define OSMO_STAT_ITEM_NO_UNIT NULL</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Individual entry in value FIFO */</span><br><span style="color: hsl(120, 100%, 40%);">+/*! DEPRECATED, kept only for backwards API compatibility. */</span><br><span> struct osmo_stat_item_value {</span><br><span>         int32_t id;             /*!< identifier of value */</span><br><span>       int32_t value;          /*!< actual value */</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct osmo_stat_item_period {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Number of osmo_stat_item_set() that occured during the reporting period, zero if none. */</span><br><span style="color: hsl(120, 100%, 40%);">+  uint32_t n;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Smallest value seen in a reporting period. */</span><br><span style="color: hsl(120, 100%, 40%);">+      int32_t min;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Most recent value passed to osmo_stat_item_set(), or the item->desc->default_value if none. */</span><br><span style="color: hsl(120, 100%, 40%);">+       int32_t last;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Largest value seen in a reporting period. */</span><br><span style="color: hsl(120, 100%, 40%);">+       int32_t max;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Sum of all values passed to osmo_stat_item_set() in the reporting period. */</span><br><span style="color: hsl(120, 100%, 40%);">+       int64_t sum;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! data we keep for each actual item */</span><br><span> struct osmo_stat_item {</span><br><span>    /*! back-reference to the item description */</span><br><span>        const struct osmo_stat_item_desc *desc;</span><br><span style="color: hsl(0, 100%, 40%);">- /* internal use by stats API (stats.c): the id of the next value to</span><br><span style="color: hsl(0, 100%, 40%);">-      * be read from the FIFO. If accessing osmo_stat_item directly, without</span><br><span style="color: hsl(0, 100%, 40%);">-  * the stats API, store this value elsewhere. */</span><br><span style="color: hsl(0, 100%, 40%);">-        int32_t stats_next_id;</span><br><span style="color: hsl(0, 100%, 40%);">-  /* internal use by stats API: indicate if the last value sent to</span><br><span style="color: hsl(0, 100%, 40%);">-         * reporters was actually the last value in the FIFO. This may not be</span><br><span style="color: hsl(0, 100%, 40%);">-    * the case, as always a max of 1 or more values gets sent (OS#5215) */</span><br><span style="color: hsl(0, 100%, 40%);">- bool stats_last_sent_was_max;</span><br><span style="color: hsl(0, 100%, 40%);">-   /*! the index of the last value written to the FIFO */</span><br><span style="color: hsl(0, 100%, 40%);">-  int16_t last_offs;</span><br><span style="color: hsl(0, 100%, 40%);">-      /*! value FIFO */</span><br><span style="color: hsl(0, 100%, 40%);">-       struct osmo_stat_item_value values[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! DEPRECATED, kept only for backwards API compatibility. */</span><br><span style="color: hsl(120, 100%, 40%);">+ int32_t not_stats_next_id;</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! DEPRECATED, kept only for backwards API compatibility. */</span><br><span style="color: hsl(120, 100%, 40%);">+ int16_t not_last_offs;</span><br><span style="color: hsl(120, 100%, 40%);">+        /*! DEPRECATED, kept only for backwards API compatibility. */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct osmo_stat_item_value not_values[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Current reporting period / current value. */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct osmo_stat_item_period value;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The results of the previous reporting period. According to these, the stats reporter decides whether to</span><br><span style="color: hsl(120, 100%, 40%);">+     * re-send values or omit an unchanged value from a report. */</span><br><span style="color: hsl(120, 100%, 40%);">+        struct osmo_stat_item_period reported;</span><br><span> };</span><br><span> </span><br><span> /*! Statistics item description */</span><br><span>@@ -43,7 +58,7 @@</span><br><span>   const char *name;       /*!< name of the item */</span><br><span>  const char *description;/*!< description of the item */</span><br><span>   const char *unit;       /*!< unit of a value */</span><br><span style="color: hsl(0, 100%, 40%);">-      unsigned int num_values;/*!< number of values to store in FIFO */</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int num_values;/*!< DEPRECATED, this value is ignored after libosmocore version 1.5.1 */</span><br><span>         int32_t default_value;  /*!< default value */</span><br><span> };</span><br><span> </span><br><span>@@ -106,12 +121,13 @@</span><br><span> const struct osmo_stat_item *osmo_stat_item_get_by_name(</span><br><span>       const struct osmo_stat_item_group *statg, const char *name);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int osmo_stat_item_get_next(const struct osmo_stat_item *item, int32_t *next_id, int32_t *value);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_stat_item_get_next(const struct osmo_stat_item *item, int32_t *next_id, int32_t *value)</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_DEPRECATED("Access item->value.last, item->value.min, item->value.max or osmo_stat_item_get_avg() instead");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Get the last (freshest) value */</span><br><span style="color: hsl(0, 100%, 40%);">-static int32_t osmo_stat_item_get_last(const struct osmo_stat_item *item);</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_stat_item_flush(struct osmo_stat_item *item);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-int osmo_stat_item_discard(const struct osmo_stat_item *item, int32_t *next_id);</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_stat_item_discard(const struct osmo_stat_item *item, int32_t *next_id)</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_DEPRECATED("Use osmo_stat_item_flush() instead");</span><br><span> </span><br><span> int osmo_stat_item_discard_all(int32_t *next_id)</span><br><span>     OSMO_DEPRECATED("Use osmo_stat_item_discard with item-specific next_id instead");</span><br><span>@@ -126,9 +142,10 @@</span><br><span> </span><br><span> int osmo_stat_item_for_each_group(osmo_stat_item_group_handler_t handle_group, void *data);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! Get the last (freshest) value. Simply returns item->value.last. */</span><br><span> static inline int32_t osmo_stat_item_get_last(const struct osmo_stat_item *item)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   return item->values[item->last_offs].value;</span><br><span style="color: hsl(120, 100%, 40%);">+     return item->value.last;</span><br><span> }</span><br><span> </span><br><span> void osmo_stat_item_reset(struct osmo_stat_item *item);</span><br><span>diff --git a/src/stat_item.c b/src/stat_item.c</span><br><span>index aca8ba6..6014411 100644</span><br><span>--- a/src/stat_item.c</span><br><span>+++ b/src/stat_item.c</span><br><span>@@ -54,20 +54,105 @@</span><br><span>  */</span><br><span> </span><br><span> /* Struct overview:</span><br><span style="color: hsl(0, 100%, 40%);">- * Each osmo_stat_item is attached to an osmo_stat_item_group, which is</span><br><span style="color: hsl(0, 100%, 40%);">- * attached to the global osmo_stat_item_groups list.</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- *                       osmo_stat_item_groups</span><br><span style="color: hsl(0, 100%, 40%);">- *                           /           \</span><br><span style="color: hsl(0, 100%, 40%);">- *                        group1        group2</span><br><span style="color: hsl(0, 100%, 40%);">- *                       /      \</span><br><span style="color: hsl(0, 100%, 40%);">- *                    item1    item2</span><br><span style="color: hsl(0, 100%, 40%);">- *                      |</span><br><span style="color: hsl(0, 100%, 40%);">- *                   values</span><br><span style="color: hsl(0, 100%, 40%);">- *                  /      \</span><br><span style="color: hsl(0, 100%, 40%);">- *                 1        2</span><br><span style="color: hsl(0, 100%, 40%);">- *                 |-id     |-id</span><br><span style="color: hsl(0, 100%, 40%);">- *                 '-value  '-value</span><br><span style="color: hsl(120, 100%, 40%);">+ * Group and item descriptions:</span><br><span style="color: hsl(120, 100%, 40%);">+ * Each group description exists once as osmo_stat_item_group_desc,</span><br><span style="color: hsl(120, 100%, 40%);">+ * each such group description lists N osmo_stat_item_desc, i.e. describes N stat items.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Actual stats:</span><br><span style="color: hsl(120, 100%, 40%);">+ * The global osmo_stat_item_groups llist contains all group instances, each points at a group description.</span><br><span style="color: hsl(120, 100%, 40%);">+ * This list mixes all types of groups in a single llist, where each instance points at its group desc and has an index.</span><br><span style="color: hsl(120, 100%, 40%);">+ * There are one or more instances of each group, each storing stats for a distinct object (for example, one description</span><br><span style="color: hsl(120, 100%, 40%);">+ * for a BTS group, and any number of BTS instances with independent stats). A group is identified by a group index nr</span><br><span style="color: hsl(120, 100%, 40%);">+ * and possibly also a given name for that particular index (e.g. in osmo-mgw, a group instance is named</span><br><span style="color: hsl(120, 100%, 40%);">+ * "virtual-trunk-0" and can be looked up by that name instead of its more or less arbitrary group index number).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Each group instance contains one osmo_stat_item instance per global stat item description.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Each osmo_stat_item keeps track of the values for the current reporting period (min, last, max, sum, n),</span><br><span style="color: hsl(120, 100%, 40%);">+ * and also stores the set of values reported at the end of the previous reporting period.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  const osmo_stat_item_group_desc foo</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                   +-- group_name_prefix = "foo"</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                   +-- item_desc[] (array of osmo_stat_item_desc)</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        +-- osmo_stat_item_desc bar</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- name = "bar"</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- description</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- unit</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- default_value</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        +-- osmo_stat_item_desc: baz</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                             +-- ...</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  const osmo_stat_item_group_desc moo</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                   +-- group_name_prefix = "moo"</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                   +-- item_desc[]</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        +-- osmo_stat_item_desc goo</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- name = "goo"</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- description</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- unit</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |    +-- default_value</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        |</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                        +-- osmo_stat_item_desc: loo</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                             +-- ...</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  osmo_stat_item_groups (llist of osmo_stat_item_group)</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   +-- group: foo[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- desc --> osmo_stat_item_group_desc foo</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- idx = 0</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- name = NULL (no given name for this group instance)</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- items[]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |        [0] --> osmo_stat_item instance for "bar"</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- desc --> osmo_stat_item_desc bar (see above)</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- value.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- reported.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |        [1] --> osmo_stat_item instance for "baz"</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- desc --> osmo_stat_item_desc baz</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- value.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- reported.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         .</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         :</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   +-- group: foo[1]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- desc --> osmo_stat_item_group_desc foo</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- idx = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- name = "special-foo" (instance can be looked up by this index-name)</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- items[]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |        [0] --> osmo_stat_item instance for "bar"</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- desc --> osmo_stat_item_desc bar</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- value.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- reported.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |        [1] --> osmo_stat_item instance for "baz"</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- desc --> osmo_stat_item_desc baz</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- value.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- reported.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         .</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         :</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   +-- group: moo[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- desc --> osmo_stat_item_group_desc moo</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- idx = 0</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- name = NULL</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |    +-- items[]</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |        [0] --> osmo_stat_item instance for "goo"</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- desc --> osmo_stat_item_desc goo</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- value.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- reported.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |        [1] --> osmo_stat_item instance for "loo"</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- desc --> osmo_stat_item_desc loo</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- value.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         |       +-- reported.{min, last, max, n, sum}</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         .</span><br><span style="color: hsl(120, 100%, 40%);">+ *   |         :</span><br><span style="color: hsl(120, 100%, 40%);">+ *   .</span><br><span style="color: hsl(120, 100%, 40%);">+ *   :</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span>  */</span><br><span> </span><br><span> #include <stdint.h></span><br><span>@@ -98,9 +183,8 @@</span><br><span>                                      unsigned int idx)</span><br><span> {</span><br><span>   unsigned int group_size;</span><br><span style="color: hsl(0, 100%, 40%);">-        unsigned long items_size = 0;</span><br><span>        unsigned int item_idx;</span><br><span style="color: hsl(0, 100%, 40%);">-  void *items;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct osmo_stat_item *items;</span><br><span> </span><br><span>    struct osmo_stat_item_group *group;</span><br><span> </span><br><span>@@ -117,46 +201,25 @@</span><br><span>      group->desc = group_desc;</span><br><span>         group->idx = idx;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* Get combined size of all items */</span><br><span style="color: hsl(120, 100%, 40%);">+  items = talloc_array(group, struct osmo_stat_item, group_desc->num_items);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(items);</span><br><span>  for (item_idx = 0; item_idx < group_desc->num_items; item_idx++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                unsigned int size;</span><br><span style="color: hsl(0, 100%, 40%);">-              size = sizeof(struct osmo_stat_item) +</span><br><span style="color: hsl(0, 100%, 40%);">-                  sizeof(struct osmo_stat_item_value) *</span><br><span style="color: hsl(0, 100%, 40%);">-                   group_desc->item_desc[item_idx].num_values;</span><br><span style="color: hsl(0, 100%, 40%);">-          /* Align to pointer size */</span><br><span style="color: hsl(0, 100%, 40%);">-             size = (size + sizeof(void *) - 1) & ~(sizeof(void *) - 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         /* Store offsets into the item array */</span><br><span style="color: hsl(0, 100%, 40%);">-         group->items[item_idx] = (void *)items_size;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-         items_size += size;</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       items = talloc_zero_size(group, items_size);</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!items) {</span><br><span style="color: hsl(0, 100%, 40%);">-           talloc_free(group);</span><br><span style="color: hsl(0, 100%, 40%);">-             return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Update item pointers */</span><br><span style="color: hsl(0, 100%, 40%);">-      for (item_idx = 0; item_idx < group_desc->num_items; item_idx++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                struct osmo_stat_item *item = (struct osmo_stat_item *)</span><br><span style="color: hsl(0, 100%, 40%);">-                 ((uint8_t *)items + (unsigned long)group->items[item_idx]);</span><br><span style="color: hsl(0, 100%, 40%);">-          unsigned int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+               struct osmo_stat_item *item = &items[item_idx];</span><br><span style="color: hsl(120, 100%, 40%);">+           const struct osmo_stat_item_desc *item_desc = &group_desc->item_desc[item_idx];</span><br><span>               group->items[item_idx] = item;</span><br><span style="color: hsl(0, 100%, 40%);">-               item->last_offs = group_desc->item_desc[item_idx].num_values - 1;</span><br><span style="color: hsl(0, 100%, 40%);">-         item->stats_next_id = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-             item->desc = &group_desc->item_desc[item_idx];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                for (i = 0; i <= item->last_offs; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  item->values[i].value = group_desc->item_desc[item_idx].default_value;</span><br><span style="color: hsl(0, 100%, 40%);">-                    item->values[i].id = OSMO_STAT_ITEM_NOVALUE_ID;</span><br><span style="color: hsl(0, 100%, 40%);">-              }</span><br><span style="color: hsl(120, 100%, 40%);">+             *item = (struct osmo_stat_item){</span><br><span style="color: hsl(120, 100%, 40%);">+                      .desc = item_desc,</span><br><span style="color: hsl(120, 100%, 40%);">+                    .value = {</span><br><span style="color: hsl(120, 100%, 40%);">+                            .n = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                               .last = item_desc->default_value,</span><br><span style="color: hsl(120, 100%, 40%);">+                          .min = item_desc->default_value,</span><br><span style="color: hsl(120, 100%, 40%);">+                           .max = item_desc->default_value,</span><br><span style="color: hsl(120, 100%, 40%);">+                           .sum = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                     },</span><br><span style="color: hsl(120, 100%, 40%);">+            };</span><br><span>   }</span><br><span> </span><br><span>        llist_add(&group->list, &osmo_stat_item_groups);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>  return group;</span><br><span> }</span><br><span> </span><br><span>@@ -195,8 +258,7 @@</span><br><span>  */</span><br><span> void osmo_stat_item_inc(struct osmo_stat_item *item, int32_t value)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- int32_t oldvalue = item->values[item->last_offs].value;</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_stat_item_set(item, oldvalue + value);</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_stat_item_set(item, item->value.last + value);</span><br><span> }</span><br><span> </span><br><span> /*! Descrease the stat_item to the given value.</span><br><span>@@ -207,8 +269,7 @@</span><br><span>  */</span><br><span> void osmo_stat_item_dec(struct osmo_stat_item *item, int32_t value)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     int32_t oldvalue = item->values[item->last_offs].value;</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_stat_item_set(item, oldvalue - value);</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_stat_item_set(item, item->value.last - value);</span><br><span> }</span><br><span> </span><br><span> /*! Set the a given stat_item to the given value.</span><br><span>@@ -219,16 +280,19 @@</span><br><span>  */</span><br><span> void osmo_stat_item_set(struct osmo_stat_item *item, int32_t value)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- int32_t id = item->values[item->last_offs].id + 1;</span><br><span style="color: hsl(0, 100%, 40%);">-        if (id == OSMO_STAT_ITEM_NOVALUE_ID)</span><br><span style="color: hsl(0, 100%, 40%);">-            id++;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   item->last_offs += 1;</span><br><span style="color: hsl(0, 100%, 40%);">-        if (item->last_offs >= item->desc->num_values)</span><br><span style="color: hsl(0, 100%, 40%);">-              item->last_offs = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- item->values[item->last_offs].value = value;</span><br><span style="color: hsl(0, 100%, 40%);">-      item->values[item->last_offs].id    = id;</span><br><span style="color: hsl(120, 100%, 40%);">+       item->value.last = value;</span><br><span style="color: hsl(120, 100%, 40%);">+  if (item->value.n == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No values recorded yet, clamp min and max to this first value. */</span><br><span style="color: hsl(120, 100%, 40%);">+          item->value.min = item->value.max = value;</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Overwrite any cruft remaining in value.sum */</span><br><span style="color: hsl(120, 100%, 40%);">+              item->value.sum = value;</span><br><span style="color: hsl(120, 100%, 40%);">+           item->value.n = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              item->value.min = OSMO_MIN(item->value.min, value);</span><br><span style="color: hsl(120, 100%, 40%);">+             item->value.max = OSMO_MAX(item->value.max, value);</span><br><span style="color: hsl(120, 100%, 40%);">+             item->value.sum += value;</span><br><span style="color: hsl(120, 100%, 40%);">+          item->value.n++;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span> }</span><br><span> </span><br><span> /*! Retrieve a stat item struct.</span><br><span>@@ -282,51 +346,34 @@</span><br><span> int osmo_stat_item_get_next(const struct osmo_stat_item *item, int32_t *next_id,</span><br><span>   int32_t *value)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    const struct osmo_stat_item_value *next_value;</span><br><span style="color: hsl(0, 100%, 40%);">-  const struct osmo_stat_item_value *item_value = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-   int id_delta;</span><br><span style="color: hsl(0, 100%, 40%);">-   int next_offs;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (value)</span><br><span style="color: hsl(120, 100%, 40%);">+            *value = item->value.last;</span><br><span style="color: hsl(120, 100%, 40%);">+ return item->value.n;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- next_offs = item->last_offs;</span><br><span style="color: hsl(0, 100%, 40%);">- next_value = &item->values[next_offs];</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Indicate that a reporting period has elapsed, and prepare the stat item for a new period of collecting min/max/avg.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param item  Stat item to flush.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_stat_item_flush(struct osmo_stat_item *item)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   item->reported = item->value;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- while (next_value->id - *next_id >= 0 &&</span><br><span style="color: hsl(0, 100%, 40%);">-          next_value->id != OSMO_STAT_ITEM_NOVALUE_ID)</span><br><span style="color: hsl(0, 100%, 40%);">- {</span><br><span style="color: hsl(0, 100%, 40%);">-               item_value = next_value;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Indicate a new reporting period: no values have been received, but the previous value.last remains unchanged</span><br><span style="color: hsl(120, 100%, 40%);">+        * for the case that an entire period elapses without a new value appearing. */</span><br><span style="color: hsl(120, 100%, 40%);">+       item->value.n = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ item->value.sum = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-             next_offs -= 1;</span><br><span style="color: hsl(0, 100%, 40%);">-         if (next_offs < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                   next_offs = item->desc->num_values - 1;</span><br><span style="color: hsl(0, 100%, 40%);">-           if (next_offs == item->last_offs)</span><br><span style="color: hsl(0, 100%, 40%);">-                    break;</span><br><span style="color: hsl(0, 100%, 40%);">-          next_value = &item->values[next_offs];</span><br><span style="color: hsl(0, 100%, 40%);">-   }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (!item_value)</span><br><span style="color: hsl(0, 100%, 40%);">-                /* All items have been read */</span><br><span style="color: hsl(0, 100%, 40%);">-          return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       *value = item_value->value;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  id_delta = item_value->id + 1 - *next_id;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    *next_id = item_value->id + 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       if (id_delta > 1) {</span><br><span style="color: hsl(0, 100%, 40%);">-          LOGP(DLSTATS, LOGL_ERROR, "%s: %d stats values skipped\n", item->desc->name, id_delta - 1);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return id_delta;</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Also for the case that an entire period elapses without any osmo_stat_item_set(), put the min and max to the</span><br><span style="color: hsl(120, 100%, 40%);">+        * last value. As soon as one osmo_stat_item_set() occurs, these are both set to the new value (when n is still</span><br><span style="color: hsl(120, 100%, 40%);">+        * zero from above). */</span><br><span style="color: hsl(120, 100%, 40%);">+       item->value.min = item->value.max = item->value.last;</span><br><span> }</span><br><span> </span><br><span> /*! Skip/discard all values of this item and update \a next_id accordingly */</span><br><span> int osmo_stat_item_discard(const struct osmo_stat_item *item, int32_t *next_id)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        int discarded = item->values[item->last_offs].id + 1 - *next_id;</span><br><span style="color: hsl(0, 100%, 40%);">-  *next_id = item->values[item->last_offs].id + 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  return discarded;</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DLSTATS, LOGL_ERROR, "osmo_stat_item_discard is deprecated (no-op)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+        return 0;</span><br><span> }</span><br><span> </span><br><span> /*! Skip all values of all items and update \a next_id accordingly */</span><br><span>@@ -453,15 +500,9 @@</span><br><span>  */</span><br><span> void osmo_stat_item_reset(struct osmo_stat_item *item)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        unsigned int i;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- item->last_offs = item->desc->num_values - 1;</span><br><span style="color: hsl(0, 100%, 40%);">-  item->stats_next_id = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-     for (i = 0; i <= item->last_offs; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-          item->values[i].value = item->desc->default_value;</span><br><span style="color: hsl(0, 100%, 40%);">-             item->values[i].id = OSMO_STAT_ITEM_NOVALUE_ID;</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(120, 100%, 40%);">+     item->value.sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       item->value.n = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ item->value.last = item->value.min = item->value.max = item->desc->default_value;</span><br><span> }</span><br><span> </span><br><span> /*! Reset all osmo stat items in a group</span><br><span>diff --git a/src/stats.c b/src/stats.c</span><br><span>index f06515d..f9a3bbc 100644</span><br><span>--- a/src/stats.c</span><br><span>+++ b/src/stats.c</span><br><span>@@ -235,28 +235,11 @@</span><br><span>       talloc_free(srep);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int osmo_stats_discard_item(struct osmo_stat_item_group *statg, struct osmo_stat_item *item, void *sctx_)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    return osmo_stat_item_discard(item, &item->stats_next_id);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int osmo_stats_discard_group(struct osmo_stat_item_group *statg, void *sctx_)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return osmo_stat_item_for_each_item(statg, &osmo_stats_discard_item, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int osmo_stats_discard_all()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    return osmo_stat_item_for_each_group(&osmo_stats_discard_group, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! Initilize the stats reporting module; call this once in your program</span><br><span style="color: hsl(120, 100%, 40%);">+/*! Initialize the stats reporting module; call this once in your program.</span><br><span>  *  \param[in] ctx Talloc context from which stats related memory is allocated */</span><br><span> void osmo_stats_init(void *ctx)</span><br><span> {</span><br><span>         osmo_stats_ctx = ctx;</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_stats_discard_all();</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>    is_initialised = 1;</span><br><span>  start_timer();</span><br><span> }</span><br><span>@@ -708,43 +691,33 @@</span><br><span>  struct osmo_stat_item_group *statg, struct osmo_stat_item *item, void *sctx_)</span><br><span> {</span><br><span>   struct osmo_stats_reporter *srep;</span><br><span style="color: hsl(0, 100%, 40%);">-       int32_t value;</span><br><span style="color: hsl(0, 100%, 40%);">-  bool have_value;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        have_value = osmo_stat_item_get_next(item, &item->stats_next_id, &value) > 0;</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!have_value) {</span><br><span style="color: hsl(0, 100%, 40%);">-              /* Send the last value in case a flush is requested */</span><br><span style="color: hsl(0, 100%, 40%);">-          value = osmo_stat_item_get_last(item);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-          /* Also send it in case a different max value was sent</span><br><span style="color: hsl(0, 100%, 40%);">-           * previously (OS#5215) */</span><br><span style="color: hsl(0, 100%, 40%);">-              if (!item->stats_last_sent_was_max)</span><br><span style="color: hsl(0, 100%, 40%);">-                  have_value = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                int32_t next_val;</span><br><span style="color: hsl(0, 100%, 40%);">-               /* If we have multiple values only send the max */</span><br><span style="color: hsl(0, 100%, 40%);">-              while (osmo_stat_item_get_next(item, &item->stats_next_id, &next_val) > 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                        value = OSMO_MAX(value, next_val);</span><br><span style="color: hsl(0, 100%, 40%);">-      }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       item->stats_last_sent_was_max = (osmo_stat_item_get_last(item) == value);</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t prev_reported_value = item->reported.max;</span><br><span style="color: hsl(120, 100%, 40%);">+  int32_t new_value = item->value.max;</span><br><span> </span><br><span>  llist_for_each_entry(srep, &osmo_stats_reporter_list, list) {</span><br><span>            if (!srep->running)</span><br><span>                       continue;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (!have_value && !srep->force_single_flush)</span><br><span style="color: hsl(120, 100%, 40%);">+              /* If no new stat values have been set in the current reporting period, skip resending the value.</span><br><span style="color: hsl(120, 100%, 40%);">+              * However, if the previously sent value is not the same as the current value, then do send the changed</span><br><span style="color: hsl(120, 100%, 40%);">+                * value (while n == 0, the last value from the previous reporting period is in item->value.max == .last</span><br><span style="color: hsl(120, 100%, 40%);">+            * == .min, which was put in new_value above).</span><br><span style="color: hsl(120, 100%, 40%);">+                 * Also if the stats reporter is set to resend all values, also do resend the current value regardless</span><br><span style="color: hsl(120, 100%, 40%);">+                 * of repetitions.</span><br><span style="color: hsl(120, 100%, 40%);">+             */</span><br><span style="color: hsl(120, 100%, 40%);">+           if ((!item->value.n && new_value == prev_reported_value)</span><br><span style="color: hsl(120, 100%, 40%);">+               && !srep->force_single_flush)</span><br><span>                         continue;</span><br><span> </span><br><span>                if (!osmo_stats_reporter_check_config(srep,</span><br><span>                          statg->idx, statg->desc->class_id))</span><br><span>                         continue;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           osmo_stats_reporter_send_item(srep, statg,</span><br><span style="color: hsl(0, 100%, 40%);">-                      item->desc, value);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_stats_reporter_send_item(srep, statg, item->desc, new_value);</span><br><span>        }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stat_item_flush(item);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        return 0;</span><br><span> }</span><br><span> </span><br><span>@@ -818,7 +791,6 @@</span><br><span>     osmo_stat_item_for_each_group(osmo_stat_item_group_handler, NULL);</span><br><span> </span><br><span>       /* global actions */</span><br><span style="color: hsl(0, 100%, 40%);">-    osmo_stats_discard_all();</span><br><span>    flush_all_reporters();</span><br><span>       TRACE(LIBOSMOCORE_STATS_DONE());</span><br><span> </span><br><span>diff --git a/tests/stats/stats_test.c b/tests/stats/stats_test.c</span><br><span>index ccb3f91..23025d1 100644</span><br><span>--- a/tests/stats/stats_test.c</span><br><span>+++ b/tests/stats/stats_test.c</span><br><span>@@ -88,11 +88,10 @@</span><br><span> </span><br><span>  struct osmo_stat_item_group *sgrp2;</span><br><span>  const struct osmo_stat_item *sitem1, *sitem2;</span><br><span style="color: hsl(0, 100%, 40%);">-   int rc;</span><br><span>      int32_t value;</span><br><span style="color: hsl(0, 100%, 40%);">-  int32_t next_id_a = 1;</span><br><span style="color: hsl(0, 100%, 40%);">-  int32_t next_id_b = 1;</span><br><span>       int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        int64_t sum1;</span><br><span style="color: hsl(120, 100%, 40%);">+ int64_t sum2;</span><br><span> </span><br><span>    OSMO_ASSERT(statg != NULL);</span><br><span> </span><br><span>@@ -125,124 +124,144 @@</span><br><span>    OSMO_ASSERT(osmo_stat_item_get("test.one", 0, "item.b") == sitem2);</span><br><span>      OSMO_ASSERT(osmo_stat_item_get_using_idxname("test.one", "name-for-idx-0", "item.b") == sitem2);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    /* No value set yet, expecting default value from osmo_stat_item_desc definition above. */</span><br><span>   value = osmo_stat_item_get_last(osmo_stat_item_group_get_item(statg, TEST_A_ITEM));</span><br><span>  OSMO_ASSERT(value == -1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ /* No value set yet, expecting new value in all fields */</span><br><span>    osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+     sum1 = 1;</span><br><span>    value = osmo_stat_item_get_last(osmo_stat_item_group_get_item(statg, TEST_A_ITEM));</span><br><span>  OSMO_ASSERT(value == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.n == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sitem1->value.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->value.last == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.max == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->value.sum == 1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+ sum2 = 0;</span><br><span>    for (i = 2; i <= 32; i++) {</span><br><span>               osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), i);</span><br><span style="color: hsl(120, 100%, 40%);">+             sum1 += i;</span><br><span>           osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), 1000 + i);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-            OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           OSMO_ASSERT(value == i);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), &next_id_b, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-            OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           OSMO_ASSERT(value == 1000 + i);</span><br><span style="color: hsl(120, 100%, 40%);">+               sum2 += 1000 + i;</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(sitem1->value.n == 32);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->value.last == 32);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(sitem1->value.max == 32);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == sum1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem2->value.n == 31);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem2->value.min == 1002);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(sitem2->value.last == 1032);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem2->value.max == 1032);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(sitem2->value.sum == sum2);</span><br><span> </span><br><span>       /* check if dec & inc is working */</span><br><span>      osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 42);</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+     sum1 += 42;</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->value.n == 33);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->value.last == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == sum1);</span><br><span> </span><br><span>       osmo_stat_item_dec(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 21);</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 21);</span><br><span style="color: hsl(120, 100%, 40%);">+     sum1 += 42 - 21;</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.n == 34);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->value.last == 21);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 21);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == sum1);</span><br><span> </span><br><span>       osmo_stat_item_inc(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 21);</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+     sum1 += 42;</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->value.n == 35);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->value.last == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == sum1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Keep 2 in FIFO */</span><br><span style="color: hsl(0, 100%, 40%);">-    osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 33);</span><br><span style="color: hsl(0, 100%, 40%);">-      osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), 1000 + 33);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Test item flush, reporting period elapsing */</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_stat_item_flush(osmo_stat_item_get("test.one", 0, "item.a"));</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sitem1->value.min == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.last == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     for (i = 34; i <= 64; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-         osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), i);</span><br><span style="color: hsl(0, 100%, 40%);">-               osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), 1000 + i);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Still see the previous reporting period in reported.* */</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.n == 35);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(sitem1->reported.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(sitem1->reported.last == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->reported.max == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.sum == sum1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-               rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-            OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           OSMO_ASSERT(value == i-1);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* After a flush, the first item replaces the last, min and max */</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_stat_item_set(osmo_stat_item_get("test.one", 0, "item.a"), 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.n == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sitem1->value.min == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.last == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == 97);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-            rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), &next_id_b, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-            OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           OSMO_ASSERT(value == 1000 + i-1);</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* ...and still see the previous reporting period in reported.* */</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(sitem1->reported.n == 35);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(sitem1->reported.min == 1);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(sitem1->reported.last == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->reported.max == 42);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.sum == sum1);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 64);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* If an entire reporting period elapses without a new value, the last seen value remains. */</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stat_item_flush(osmo_stat_item_get("test.one", 0, "item.a"));</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_stat_item_flush(osmo_stat_item_get("test.one", 0, "item.a"));</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sitem1->value.min == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.last == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), &next_id_b, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 1000 + 64);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* now the previous reporting period got turned around */</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(sitem1->reported.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->reported.min == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.last == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->reported.max == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.sum == 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Overrun FIFOs */</span><br><span style="color: hsl(0, 100%, 40%);">-     for (i = 65; i <= 96; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-         osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), i);</span><br><span style="color: hsl(0, 100%, 40%);">-               osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), 1000 + i);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Another empty reporting period, everything remained the same. */</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_stat_item_flush(osmo_stat_item_get("test.one", 0, "item.a"));</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sitem1->value.min == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.last == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->reported.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->reported.min == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.last == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->reported.max == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.sum == 0);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  fprintf(stderr, "Skipping %d values\n", 93 - 65);</span><br><span style="color: hsl(0, 100%, 40%);">-     rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 93 - 65 + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(value == 93);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       for (i = 94; i <= 96; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-         rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-            OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           OSMO_ASSERT(value == i);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       fprintf(stderr, "Skipping %d values\n", 90 - 65);</span><br><span style="color: hsl(0, 100%, 40%);">-     rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), &next_id_b, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 90 - 65 + 1);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(value == 1000 + 90);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        for (i = 91; i <= 96; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-         rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_B_ITEM), &next_id_b, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-            OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-           OSMO_ASSERT(value == 1000 + i);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Test Discard (single item) */</span><br><span style="color: hsl(0, 100%, 40%);">-        osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 97);</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = osmo_stat_item_discard(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   rc = osmo_stat_item_discard(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_stat_item_set(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), 98);</span><br><span style="color: hsl(0, 100%, 40%);">-      rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 1);</span><br><span style="color: hsl(0, 100%, 40%);">-   OSMO_ASSERT(value == 98);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       rc = osmo_stat_item_get_next(osmo_stat_item_group_get_item(statg, TEST_A_ITEM), &next_id_a, &value);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(rc == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Test Reset, place back to default value. The previously reported value remains the same. */</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_stat_item_reset(osmo_stat_item_get("test.one", 0, "item.a"));</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(sitem1->value.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(sitem1->value.min == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.last == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(osmo_stat_item_get_last(osmo_stat_item_get("test.one", 0, "item.a")) == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->value.max == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->value.sum == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(sitem1->reported.n == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(sitem1->reported.min == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.last == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(sitem1->reported.max == 97);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(sitem1->reported.sum == 0);</span><br><span> </span><br><span>       osmo_stat_item_group_free(statg);</span><br><span> </span><br><span>diff --git a/tests/stats/stats_test.err b/tests/stats/stats_test.err</span><br><span>index 92d6ce1..a890e0f 100644</span><br><span>--- a/tests/stats/stats_test.err</span><br><span>+++ b/tests/stats/stats_test.err</span><br><span>@@ -1,7 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-Skipping 28 values</span><br><span style="color: hsl(0, 100%, 40%);">-DLSTATS ERROR item.a: 28 stats values skipped</span><br><span style="color: hsl(0, 100%, 40%);">-Skipping 25 values</span><br><span style="color: hsl(0, 100%, 40%);">-DLSTATS ERROR item.b: 25 stats values skipped</span><br><span> Start test: test_reporting</span><br><span> DLGLOBAL ERROR counter group 'ctr-test:one' already exists for index 2, instead using index 3. This is a software bug that needs fixing.</span><br><span> DLGLOBAL ERROR 'ctr-test.one_dot' is not a valid counter group identifier</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmocore/+/25464">change 25464</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/libosmocore/+/25464"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I137992a5479fc39bbceb6c6c2af9c227bd33b39b </div>
<div style="display:none"> Gerrit-Change-Number: 25464 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>