From: Shachar Sharon Date: Mon, 28 Apr 2025 18:30:22 +0000 (+0300) Subject: status: dump per-share profile counters X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cfadbb73f35b0a46fe02c74b9a228bea3812ba51;p=thirdparty%2Fsamba.git status: dump per-share profile counters When dumping profile information, try to iterate also on per-share profile entries and emit (json format). Signed-off-by: Shachar Sharon Reviewed-by: Volker Lendecke Reviewed-by: Anoop C S --- diff --git a/source3/utils/status_json.c b/source3/utils/status_json.c index f7727b4c39d..22606439b78 100644 --- a/source3/utils/status_json.c +++ b/source3/utils/status_json.c @@ -184,50 +184,76 @@ static const struct mask2txt lease_mask[] = { {0, NULL} }; -int add_profile_item_to_json(struct traverse_state *state, - const char *section, - const char *subsection, - const char *key, - uintmax_t value) +/* Add nested json key:value entry, up to 4 levels deep */ +static int add_nested_item_to_json(struct json_object *root_json, + const char **subs, + size_t nsubs, + const char *key, + uintmax_t value) { - struct json_object section_json = { - .valid = false, - }; - struct json_object subsection_json = { - .valid = false, - }; + struct json_object jobj_sub[4] = {0}; + struct json_object *jo[5] = {root_json, + &jobj_sub[0], + &jobj_sub[1], + &jobj_sub[2], + &jobj_sub[3]}; + size_t i = 0; int result = 0; - section_json = json_get_object(&state->root_json, section); - if (json_is_invalid(§ion_json)) { - goto failure; - } - subsection_json = json_get_object(§ion_json, subsection); - if (json_is_invalid(&subsection_json)) { - goto failure; + if (nsubs > ARRAY_SIZE(jobj_sub)) { + return -1; } - result = json_add_int(&subsection_json, key, value); - if (result < 0) { - goto failure; + for (i = 0; i < nsubs; ++i) { + *(jo[i + 1]) = json_get_object(jo[i], subs[i]); + if (json_is_invalid(jo[i + 1])) { + goto failure; + } } - result = json_update_object(§ion_json, subsection, &subsection_json); + result = json_add_int(jo[nsubs], key, value); if (result < 0) { goto failure; } - result = json_update_object(&state->root_json, section, §ion_json); - if (result < 0) { - goto failure; + + for (i = nsubs; i > 0; --i) { + result = json_update_object(jo[i - 1], subs[i - 1], jo[i]); + if (result < 0) { + goto failure; + } } return 0; failure: - json_free(§ion_json); - json_free(&subsection_json); + for (i = 0; i < nsubs; ++i) { + json_free(&jobj_sub[i]); + } return -1; } +int add_profile_item_to_json(struct traverse_state *state, + const char *section, + const char *subsection, + const char *key, + uintmax_t value) +{ + const char *subs[] = {section, subsection}; + + return add_nested_item_to_json(&state->root_json, subs, 2, key, value); +} + +int add_profile_persvc_item_to_json(struct traverse_state *state, + const char *section1, + const char *section2, + const char *section3, + const char *key, + uintmax_t value) +{ + const char *subs[] = {"Extended Profile", section1, section2, section3}; + + return add_nested_item_to_json(&state->root_json, subs, 4, key, value); +} + int add_section_to_json(struct traverse_state *state, const char *key) { diff --git a/source3/utils/status_json.h b/source3/utils/status_json.h index ef5d18139be..70cd00992ac 100644 --- a/source3/utils/status_json.h +++ b/source3/utils/status_json.h @@ -34,6 +34,13 @@ int add_profile_item_to_json(struct traverse_state *state, const char *key, uintmax_t value); +int add_profile_persvc_item_to_json(struct traverse_state *state, + const char *section1, + const char *section2, + const char *section3, + const char *key, + uintmax_t value); + int traverse_connections_json(struct traverse_state *state, const struct connections_data *crec, const char *encryption_cipher, diff --git a/source3/utils/status_json_dummy.c b/source3/utils/status_json_dummy.c index 3cd8531c2de..262b3c28054 100644 --- a/source3/utils/status_json_dummy.c +++ b/source3/utils/status_json_dummy.c @@ -44,6 +44,16 @@ int add_profile_item_to_json(struct traverse_state *state, return 0; } +int add_profile_persvc_item_to_json(struct traverse_state *state, + const char *section1, + const char *section2, + const char *section3, + const char *key, + uintmax_t value) +{ + return 0; +} + int traverse_connections_json(struct traverse_state *state, const struct connections_data *crec, const char *encryption_cipher, diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c index 299731b4813..32b9ada598f 100644 --- a/source3/utils/status_profile.c +++ b/source3/utils/status_profile.c @@ -76,6 +76,102 @@ static void print_buckets(struct traverse_state *state, s->buckets[9]); } +/******************************************************************* + dump the elements of the persvc profile structure + ******************************************************************/ + +static void status_profile_dump_persvc_stats(struct traverse_state *state, + const char *secname, + const struct profile_stats *pstats) +{ + const char *latest_section = NULL; + +#define __PRINT_FIELD_LINE(name, _stats, field) \ + do { \ + uintmax_t val = (uintmax_t)(*pstats).values._stats.field; \ + if (!state->json_output) { \ + d_printf("%s %-59s%20ju\n", \ + secname, \ + name "_" #field ":", \ + val); \ + } else { \ + add_profile_persvc_item_to_json(state, \ + secname, \ + latest_section, \ + name, \ + #field, \ + val); \ + } \ + } while (0); +#define SMBPROFILE_STATS_START +#define SMBPROFILE_STATS_SECTION_START(name, display) \ + do { \ + latest_section = display; \ + profile_separator(display, state); \ + } while (0); +#define SMBPROFILE_STATS_COUNT(name) \ + do { \ + __PRINT_FIELD_LINE(#name, name##_stats, count); \ + } while (0); +#define SMBPROFILE_STATS_TIME(name) \ + do { \ + __PRINT_FIELD_LINE(#name, name##_stats, time); \ + } while (0); +#define SMBPROFILE_STATS_BASIC(name) \ + do { \ + __PRINT_FIELD_LINE(#name, name##_stats, count); \ + __PRINT_FIELD_LINE(#name, name##_stats, time); \ + } while (0); +#define SMBPROFILE_STATS_BYTES(name) \ + do { \ + __PRINT_FIELD_LINE(#name, name##_stats, count); \ + __PRINT_FIELD_LINE(#name, name##_stats, time); \ + __PRINT_FIELD_LINE(#name, name##_stats, idle); \ + __PRINT_FIELD_LINE(#name, name##_stats, bytes); \ + } while (0); +#define SMBPROFILE_STATS_IOBYTES(name) \ + do { \ + __PRINT_FIELD_LINE(#name, name##_stats, count); \ + __PRINT_FIELD_LINE(#name, name##_stats, failed_count); \ + __PRINT_FIELD_LINE(#name, name##_stats, time); \ + print_buckets(state, #name, &(*pstats).values.name##_stats); \ + __PRINT_FIELD_LINE(#name, name##_stats, idle); \ + __PRINT_FIELD_LINE(#name, name##_stats, inbytes); \ + __PRINT_FIELD_LINE(#name, name##_stats, outbytes); \ + } while (0); +#define SMBPROFILE_STATS_SECTION_END +#define SMBPROFILE_STATS_END + SMBPROFILE_STATS_ALL_SECTIONS +#undef __PRINT_FIELD_LINE +#undef SMBPROFILE_STATS_START +#undef SMBPROFILE_STATS_SECTION_START +#undef SMBPROFILE_STATS_COUNT +#undef SMBPROFILE_STATS_TIME +#undef SMBPROFILE_STATS_BASIC +#undef SMBPROFILE_STATS_BYTES +#undef SMBPROFILE_STATS_IOBYTES +#undef SMBPROFILE_STATS_SECTION_END +#undef SMBPROFILE_STATS_END +} + +static int status_profile_dump_persvc_cb(const char *key, + const struct profile_stats *stats, + void *private_data) +{ + struct traverse_state *state = private_data; + + status_profile_dump_persvc_stats(state, key, stats); + return 0; +} + +static void status_profile_dump_persvc(struct traverse_state *state) +{ + if (!state->json_output) { + return; + } + smbprofile_persvc_collect(status_profile_dump_persvc_cb, state); +} + /******************************************************************* dump the elements of the profile structure ******************************************************************/ @@ -146,6 +242,7 @@ bool status_profile_dump(bool verbose, #undef SMBPROFILE_STATS_SECTION_END #undef SMBPROFILE_STATS_END + status_profile_dump_persvc(state); return True; }