From: Alan T. DeKok Date: Wed, 14 Jan 2026 01:39:53 +0000 (-0500) Subject: add doxygen and more utility functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1f609fc44986f0f1e0f67622d7888ad4dcb686f7;p=thirdparty%2Ffreeradius-server.git add doxygen and more utility functions --- diff --git a/src/lib/util/stats.c b/src/lib/util/stats.c index 24afdd2b470..9aa3c64e83f 100644 --- a/src/lib/util/stats.c +++ b/src/lib/util/stats.c @@ -24,8 +24,6 @@ RCSID("$Id$") #include -// convert a set of pairs to a struct - /** Convert a statistics structure to #fr_pair_t * * @param[in] ctx talloc ctx @@ -106,14 +104,21 @@ int fr_stats_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_stats_instance_t return 0; } -int fr_stats_from_pairs(TALLOC_CTX *ctx, fr_stats_instance_t *inst, fr_pair_list_t *in) + +/** Convert a statistics structure to #fr_pair_t + * + * @param[in] ctx talloc ctx + * @param[out] inst where the output pairs will be stored + * @param[in] list pairs where we read the pairs from + */ +int fr_stats_from_pairs(TALLOC_CTX *ctx, fr_stats_instance_t *inst, fr_pair_list_t const *list) { size_t i; fr_stats_link_t const *def = inst->def; uint8_t *out = inst->stats; fr_pair_t const *parent, *vp; - parent = fr_pair_find_by_da(in, NULL, *(def->root_p)); + parent = fr_pair_find_by_da(list, NULL, *(def->root_p)); if (!parent) return -1; memset(out, 0, inst->def->size); @@ -227,8 +232,13 @@ static int stats_merge_internal(fr_stats_link_t const *def, void *out, void cons /** Public API for merging two statistics structures * + * @param[out] out where the merged stats are written to + * @param[in] in source stats to merge into out + * @return + * - 0 on success + * - <0 on the two instances are not compatible. */ -int fr_stats_merge(fr_stats_instance_t *out, fr_stats_instance_t const *in) +int fr_stats_merge_instance(fr_stats_instance_t *out, fr_stats_instance_t const *in) { if (out->def != in->def) { fr_strerror_printf("Cannot merge stats into structure %s from different structure %s", @@ -239,13 +249,76 @@ int fr_stats_merge(fr_stats_instance_t *out, fr_stats_instance_t const *in) return stats_merge_internal(out->def, out->stats, in->stats); } +/** Public API for merging two value-boxes based on their enums + * + * @param[in,out] dst where the merged stats are written to + * @param[in] src source stats to merge into dst + * @return + * - 0 on success + * - <0 on the two boxes are not compatible, or we cannot merge the given data type + */ +int fr_stats_merge_value_box(fr_value_box_t *dst, fr_value_box_t const *src) +{ + if (dst->type != src->type) { + fr_strerror_const("Cannot merge two different data types"); + return -1; + } + + if (dst->enumv != src->enumv) { + fr_strerror_const("Cannot merge two different fields"); + return -1; + } + + if (!dst->enumv) { + fr_strerror_const("Unable to determine how to merge the fields"); + return -1; + } + + /* + * @todo - distinguish counter from gauge. This also means that we will need to update the + * dictionary.stats to set the "counter" flag. + */ + + switch (dst->type) { + case FR_TYPE_UINT16: + dst->vb_uint16 += src->vb_uint16; + break; + + case FR_TYPE_UINT32: + dst->vb_uint32 += src->vb_uint32; + break; + + case FR_TYPE_UINT64: + dst->vb_uint64 += src->vb_uint64; + break; + + default: + fr_strerror_const("Cannot merge non-integer data types"); + return -1; + } -void fr_stats_iter_init(fr_stats_instance_t const *in, fr_stats_iter_t *iter) + return 0; +} + + +/** Initialize an iterator over a structure + * + * @param[in] inst data structure defining this instance of the statistics + * @param[out] iter the initialized iterator + */ +void fr_stats_iter_init(fr_stats_instance_t const *inst, fr_stats_iter_t *iter) { - iter->inst = in; + iter->inst = inst; iter->current = 0; } +/** Go to the next entry in a structure + * + * @param[in] iter the iterator + * @return + * - true for continue the iteration + * - false for the iteration is done + */ bool fr_stats_iter_next(fr_stats_iter_t *iter) { if (iter->current < iter->inst->def->num_elements) { @@ -256,6 +329,17 @@ bool fr_stats_iter_next(fr_stats_iter_t *iter) return false; } + +/** Convert the statistic at an index to a value-box + * + * @param[in] ctx the talloc context + * @param[out] out the value-box to return + * @param[in] inst data structure defining this instance of the statistics + * @param[in] index the field index of the structure to use + * @return + * - 0 for success, and *out is non-NULL + * - <0 for error (memory allocation failed, index is invalid, etc), and *out is NULL + */ int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_instance_t const *inst, unsigned int index) { size_t len; @@ -263,13 +347,17 @@ int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_ uint8_t const *field; fr_dict_attr_t const *da; - if (index >= inst->def->num_elements) return 0; + if (index >= inst->def->num_elements) { + fail: + *out = NULL; + return -1; + } da = *(inst->def->entry[index].da_p); fr_assert(da != NULL); box = fr_value_box_alloc(ctx, inst->def->entry[index].type, da); - if (!box) return -1; + if (!box) goto fail; field = ((uint8_t const *) inst->stats) + inst->def->entry[index].offset; @@ -302,12 +390,13 @@ int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_ default: fr_strerror_printf("Unsupported data type '%s'", fr_type_to_str(box->type)); - return -1; + goto fail_free; } if (fr_value_box_from_memory(box, box, box->type, da, field, len) < 0) { + fail_free: talloc_free(box); - return -1; + goto fail; } *out = box; @@ -315,6 +404,15 @@ int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_ } +/** Convert the statistic at the current iterator to a value-box + * + * @param[in] ctx the talloc context + * @param[out] out the value-box to return + * @param[in] iter the iterator, which points to the current entry. + * @return + * - 0 for success, and *out is non-NULL + * - <0 for error (memory allocation failed, index is invalid, etc), and *out is NULL + */ int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_iter_t *iter) { fr_assert(iter->inst); @@ -322,3 +420,24 @@ int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_i return fr_stats_index_to_value_box(ctx, out, iter->inst, iter->current); } + + +/** Convert the statistic of a given name to a value-box + * + * @param[in] ctx the talloc context + * @param[out] out the value-box to return + * @param[in] inst data structure defining this instance of the statistics + * @param[in] name the field name in the structure + * @return + * - 0 for success, and *out is non-NULL + * - <0 for error (memory allocation failed, name is invalid, etc), and *out is NULL + */ +int fr_stats_name_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_instance_t const *inst, char const *name) +{ + fr_dict_attr_t const *da; + + da = fr_dict_attr_by_name(NULL, *inst->def->root_p, name); + if (!da) return -1; + + return fr_stats_index_to_value_box(ctx, out, inst, da->attr); +} diff --git a/src/lib/util/stats.h b/src/lib/util/stats.h index 6ee2d7cdd20..c1e479c3834 100644 --- a/src/lib/util/stats.h +++ b/src/lib/util/stats.h @@ -140,13 +140,17 @@ typedef struct { #define FR_STATS_FIELD(_var, _field) (_var)->stats.(_field) int fr_stats_to_pairs(TALLOC_CTX *ctx, fr_pair_list_t *out, fr_stats_instance_t const *in) CC_HINT(nonnull); -int fr_stats_from_pairs(TALLOC_CTX *ctx, fr_stats_instance_t *out, fr_pair_list_t *in) CC_HINT(nonnull); -int fr_stats_merge(fr_stats_instance_t *out, fr_stats_instance_t const *in) CC_HINT(nonnull); +int fr_stats_from_pairs(TALLOC_CTX *ctx, fr_stats_instance_t *out, fr_pair_list_t const *list) CC_HINT(nonnull); +int fr_stats_merge_instance(fr_stats_instance_t *out, fr_stats_instance_t const *in) CC_HINT(nonnull); +int fr_stats_merge_value_box(fr_value_box_t *dst, fr_value_box_t const *src) CC_HINT(nonnull); void fr_stats_iter_init(fr_stats_instance_t const *in, fr_stats_iter_t *iter) CC_HINT(nonnull); bool fr_stats_iter_next(fr_stats_iter_t *iter) CC_HINT(nonnull); int fr_stats_iter_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_iter_t *iter) CC_HINT(nonnull); -int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, fr_stats_instance_t const *in, unsigned int index) CC_HINT(nonnull); +int fr_stats_index_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, + fr_stats_instance_t const *in, unsigned int index) CC_HINT(nonnull); +int fr_stats_name_to_value_box(TALLOC_CTX *ctx, fr_value_box_t **out, + fr_stats_instance_t const *inst, char const *name) CC_HINT(nonnull); #ifdef __cplusplus