mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
803899fdc3
Signed-off-by: Jule Anger <janger@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
382 lines
9.8 KiB
C
382 lines
9.8 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#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;
|
|
}
|