From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- source3/utils/status_profile.c | 381 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 381 insertions(+) create mode 100644 source3/utils/status_profile.c (limited to 'source3/utils/status_profile.c') diff --git a/source3/utils/status_profile.c b/source3/utils/status_profile.c new file mode 100644 index 0000000..6e0916e --- /dev/null +++ b/source3/utils/status_profile.c @@ -0,0 +1,381 @@ +/* + * Unix SMB/CIFS implementation. + * status reporting + * Copyright (C) Andrew Tridgell 1994-1998 + * Copyright (C) James Peach 2005-2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "includes.h" +#include "smbprofile.h" +#include "status_profile.h" +#include "conn_tdb.h" +#include "librpc/gen_ndr/open_files.h" +#include "status_json.h" + +static void profile_separator(const char * title, + struct traverse_state *state) +{ + char line[79 + 1]; + char * end; + + if (state->json_output) { + return; + } + + snprintf(line, sizeof(line), "**** %s ", title); + + for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) { + *end = '*'; + } + + line[sizeof(line) - 1] = '\0'; + d_printf("%s\n", line); +} + +/******************************************************************* + dump the elements of the profile structure + ******************************************************************/ +bool status_profile_dump(bool verbose, + struct traverse_state *state) +{ + struct profile_stats stats = {}; + const char* latest_section = NULL; + + if (!profile_setup(NULL, True)) { + fprintf(stderr,"Failed to initialise profile memory\n"); + return False; + } + + smbprofile_collect(&stats); + +#define __PRINT_FIELD_LINE(name, _stats, field) do { \ + uintmax_t val = (uintmax_t)stats.values._stats.field; \ + if (!state->json_output) { \ + d_printf("%-59s%20ju\n", \ + name "_" #field ":", \ + val); \ + } else { \ + add_profile_item_to_json(state, 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, time); \ + __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 + + return True; +} + +/* Convert microseconds to milliseconds. */ +#define usec_to_msec(s) ((s) / 1000) +/* Convert microseconds to seconds. */ +#define usec_to_sec(s) ((s) / 1000000) +/* One second in microseconds. */ +#define one_second_usec (1000000) + +#define sample_interval_usec one_second_usec + +#define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 ) + +static uint64_t print_count_count_samples( + char *buf, const size_t buflen, + const char *name, + const struct smbprofile_stats_count * const current, + const struct smbprofile_stats_count * const last, + uint64_t delta_usec) +{ + uint64_t step = current->count - last->count; + uint64_t count = 0; + + if (step != 0) { + uint64_t delta_sec = usec_to_sec(delta_usec); + + count++; + + if (buf[0] == '\0') { + snprintf(buf, buflen, + "%-40s %ju/sec", + name, (uintmax_t)(step / delta_sec)); + } else { + printf("%-40s %s %ju/sec\n", + buf, name, (uintmax_t)(step / delta_sec)); + buf[0] = '\0'; + } + } + + return count; +} + +static uint64_t print_basic_count_samples( + char *buf, const size_t buflen, + const char *name, + const struct smbprofile_stats_basic * const current, + const struct smbprofile_stats_basic * const last, + uint64_t delta_usec) +{ + uint64_t step = current->count - last->count; + uint64_t spent = current->time - last->time; + uint64_t count = 0; + + if (step != 0) { + uint64_t delta_sec = usec_to_sec(delta_usec); + + count++; + + if (buf[0] == '\0') { + snprintf(buf, buflen, + "%s %ju/sec (%.2f%%)", + name, (uintmax_t)(step / delta_sec), + percent_time(spent, delta_usec)); + } else { + printf("%-40s %s %ju/sec (%.2f%%)\n", + buf, name, (uintmax_t)(step / delta_sec), + percent_time(spent, delta_usec)); + buf[0] = '\0'; + } + } + + return count; +} + +static uint64_t print_bytes_count_samples( + char *buf, const size_t buflen, + const char *name, + const struct smbprofile_stats_bytes * const current, + const struct smbprofile_stats_bytes * const last, + uint64_t delta_usec) +{ + uint64_t step = current->count - last->count; + uint64_t spent = current->time - last->time; + uint64_t count = 0; + + if (step != 0) { + uint64_t delta_sec = usec_to_sec(delta_usec); + + count++; + + if (buf[0] == '\0') { + snprintf(buf, buflen, + "%s %ju/sec (%.2f%%)", + name, (uintmax_t)(step / delta_sec), + percent_time(spent, delta_usec)); + } else { + printf("%-40s %s %ju/sec (%.2f%%)\n", + buf, name, (uintmax_t)(step / delta_sec), + percent_time(spent, delta_usec)); + buf[0] = '\0'; + } + } + + return count; +} + +static uint64_t print_iobytes_count_samples( + char *buf, const size_t buflen, + const char *name, + const struct smbprofile_stats_iobytes * const current, + const struct smbprofile_stats_iobytes * const last, + uint64_t delta_usec) +{ + uint64_t step = current->count - last->count; + uint64_t spent = current->time - last->time; + uint64_t count = 0; + + if (step != 0) { + uint64_t delta_sec = usec_to_sec(delta_usec); + + count++; + + if (buf[0] == '\0') { + snprintf(buf, buflen, + "%s %ju/sec (%.2f%%)", + name, (uintmax_t)(step / delta_sec), + percent_time(spent, delta_usec)); + } else { + printf("%-40s %s %ju/sec (%.2f%%)\n", + buf, name, (uintmax_t)(step / delta_sec), + percent_time(spent, delta_usec)); + buf[0] = '\0'; + } + } + + return count; +} + +static uint64_t print_count_samples( + const struct profile_stats * const current, + const struct profile_stats * const last, + uint64_t delta_usec) +{ + uint64_t count = 0; + char buf[60] = { '\0', }; + + if (delta_usec == 0) { + return 0; + } + +#define SMBPROFILE_STATS_START +#define SMBPROFILE_STATS_SECTION_START(name, display) +#define SMBPROFILE_STATS_COUNT(name) do { \ + count += print_count_count_samples(buf, sizeof(buf), \ + #name, \ + ¤t->values.name##_stats, \ + &last->values.name##_stats, \ + delta_usec); \ +} while(0); +#define SMBPROFILE_STATS_TIME(name) do { \ +} while(0); +#define SMBPROFILE_STATS_BASIC(name) do { \ + count += print_basic_count_samples(buf, sizeof(buf), \ + #name, \ + ¤t->values.name##_stats, \ + &last->values.name##_stats, \ + delta_usec); \ +} while(0); +#define SMBPROFILE_STATS_BYTES(name) do { \ + count += print_bytes_count_samples(buf, sizeof(buf), \ + #name, \ + ¤t->values.name##_stats, \ + &last->values.name##_stats, \ + delta_usec); \ +} while(0); +#define SMBPROFILE_STATS_IOBYTES(name) do { \ + count += print_iobytes_count_samples(buf, sizeof(buf), \ + #name, \ + ¤t->values.name##_stats, \ + &last->values.name##_stats, \ + delta_usec); \ +} while(0); +#define SMBPROFILE_STATS_SECTION_END +#define SMBPROFILE_STATS_END + SMBPROFILE_STATS_ALL_SECTIONS +#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 + + if (buf[0] != '\0') { + printf("%-40s\n", buf); + buf[0] = '\0'; + } + + return count; +} + +static struct profile_stats sample_data[2]; +static uint64_t sample_time[2]; + +bool status_profile_rates(bool verbose) +{ + uint64_t remain_usec; + uint64_t next_usec; + uint64_t delta_usec; + + int last = 0; + int current = 1; + int tmp; + + if (verbose) { + fprintf(stderr, "Sampling stats at %d sec intervals\n", + usec_to_sec(sample_interval_usec)); + } + + if (!profile_setup(NULL, True)) { + fprintf(stderr,"Failed to initialise profile memory\n"); + return False; + } + + smbprofile_collect(&sample_data[last]); + for (;;) { + sample_time[current] = profile_timestamp(); + next_usec = sample_time[current] + sample_interval_usec; + + /* Take a sample. */ + smbprofile_collect(&sample_data[current]); + + /* Rate convert some values and print results. */ + delta_usec = sample_time[current] - sample_time[last]; + + if (print_count_samples(&sample_data[current], + &sample_data[last], delta_usec)) { + printf("\n"); + } + + /* Swap sampling buffers. */ + tmp = last; + last = current; + current = tmp; + + /* Delay until next sample time. */ + remain_usec = next_usec - profile_timestamp(); + if (remain_usec > sample_interval_usec) { + fprintf(stderr, "eek! falling behind sampling rate!\n"); + } else { + if (verbose) { + fprintf(stderr, + "delaying for %lu msec\n", + (unsigned long )usec_to_msec(remain_usec)); + } + + usleep(remain_usec); + } + + } + + return True; +} -- cgit v1.2.3