2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Andrew Tridgell 1994-1998
5 * Copyright (C) James Peach 2005-2006
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "smbprofile.h"
23 #include "status_profile.h"
25 #include "librpc/gen_ndr/open_files.h"
26 #include "status_json.h"
28 static void profile_separator(const char * title
,
29 struct traverse_state
*state
)
34 if (state
->json_output
) {
38 snprintf(line
, sizeof(line
), "**** %s ", title
);
40 for (end
= line
+ strlen(line
); end
< &line
[sizeof(line
) -1]; ++end
) {
44 line
[sizeof(line
) - 1] = '\0';
45 d_printf("%s\n", line
);
48 /*******************************************************************
49 dump the elements of the profile structure
50 ******************************************************************/
51 bool status_profile_dump(bool verbose
,
52 struct traverse_state
*state
)
54 struct profile_stats stats
= {};
55 const char* latest_section
= NULL
;
57 if (!profile_setup(NULL
, True
)) {
58 fprintf(stderr
,"Failed to initialise profile memory\n");
62 smbprofile_collect(&stats
);
64 #define __PRINT_FIELD_LINE(name, _stats, field) do { \
65 uintmax_t val = (uintmax_t)stats.values._stats.field; \
66 if (!state->json_output) { \
67 d_printf("%-59s%20ju\n", \
68 name "_" #field ":", \
71 add_profile_item_to_json(state, latest_section, name, #field, val); \
74 #define SMBPROFILE_STATS_START
75 #define SMBPROFILE_STATS_SECTION_START(name, display) do { \
76 latest_section = display; \
77 profile_separator(display, state);\
79 #define SMBPROFILE_STATS_COUNT(name) do { \
80 __PRINT_FIELD_LINE(#name, name##_stats, count); \
82 #define SMBPROFILE_STATS_TIME(name) do { \
83 __PRINT_FIELD_LINE(#name, name##_stats, time); \
85 #define SMBPROFILE_STATS_BASIC(name) do { \
86 __PRINT_FIELD_LINE(#name, name##_stats, count); \
87 __PRINT_FIELD_LINE(#name, name##_stats, time); \
89 #define SMBPROFILE_STATS_BYTES(name) do { \
90 __PRINT_FIELD_LINE(#name, name##_stats, count); \
91 __PRINT_FIELD_LINE(#name, name##_stats, time); \
92 __PRINT_FIELD_LINE(#name, name##_stats, idle); \
93 __PRINT_FIELD_LINE(#name, name##_stats, bytes); \
95 #define SMBPROFILE_STATS_IOBYTES(name) do { \
96 __PRINT_FIELD_LINE(#name, name##_stats, count); \
97 __PRINT_FIELD_LINE(#name, name##_stats, time); \
98 __PRINT_FIELD_LINE(#name, name##_stats, idle); \
99 __PRINT_FIELD_LINE(#name, name##_stats, inbytes); \
100 __PRINT_FIELD_LINE(#name, name##_stats, outbytes); \
102 #define SMBPROFILE_STATS_SECTION_END
103 #define SMBPROFILE_STATS_END
104 SMBPROFILE_STATS_ALL_SECTIONS
105 #undef __PRINT_FIELD_LINE
106 #undef SMBPROFILE_STATS_START
107 #undef SMBPROFILE_STATS_SECTION_START
108 #undef SMBPROFILE_STATS_COUNT
109 #undef SMBPROFILE_STATS_TIME
110 #undef SMBPROFILE_STATS_BASIC
111 #undef SMBPROFILE_STATS_BYTES
112 #undef SMBPROFILE_STATS_IOBYTES
113 #undef SMBPROFILE_STATS_SECTION_END
114 #undef SMBPROFILE_STATS_END
119 /* Convert microseconds to milliseconds. */
120 #define usec_to_msec(s) ((s) / 1000)
121 /* Convert microseconds to seconds. */
122 #define usec_to_sec(s) ((s) / 1000000)
123 /* One second in microseconds. */
124 #define one_second_usec (1000000)
126 #define sample_interval_usec one_second_usec
128 #define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 )
130 static uint64_t print_count_count_samples(
131 char *buf
, const size_t buflen
,
133 const struct smbprofile_stats_count
* const current
,
134 const struct smbprofile_stats_count
* const last
,
137 uint64_t step
= current
->count
- last
->count
;
141 uint64_t delta_sec
= usec_to_sec(delta_usec
);
145 if (buf
[0] == '\0') {
146 snprintf(buf
, buflen
,
148 name
, (uintmax_t)(step
/ delta_sec
));
150 printf("%-40s %s %ju/sec\n",
151 buf
, name
, (uintmax_t)(step
/ delta_sec
));
159 static uint64_t print_basic_count_samples(
160 char *buf
, const size_t buflen
,
162 const struct smbprofile_stats_basic
* const current
,
163 const struct smbprofile_stats_basic
* const last
,
166 uint64_t step
= current
->count
- last
->count
;
167 uint64_t spent
= current
->time
- last
->time
;
171 uint64_t delta_sec
= usec_to_sec(delta_usec
);
175 if (buf
[0] == '\0') {
176 snprintf(buf
, buflen
,
177 "%s %ju/sec (%.2f%%)",
178 name
, (uintmax_t)(step
/ delta_sec
),
179 percent_time(spent
, delta_usec
));
181 printf("%-40s %s %ju/sec (%.2f%%)\n",
182 buf
, name
, (uintmax_t)(step
/ delta_sec
),
183 percent_time(spent
, delta_usec
));
191 static uint64_t print_bytes_count_samples(
192 char *buf
, const size_t buflen
,
194 const struct smbprofile_stats_bytes
* const current
,
195 const struct smbprofile_stats_bytes
* const last
,
198 uint64_t step
= current
->count
- last
->count
;
199 uint64_t spent
= current
->time
- last
->time
;
203 uint64_t delta_sec
= usec_to_sec(delta_usec
);
207 if (buf
[0] == '\0') {
208 snprintf(buf
, buflen
,
209 "%s %ju/sec (%.2f%%)",
210 name
, (uintmax_t)(step
/ delta_sec
),
211 percent_time(spent
, delta_usec
));
213 printf("%-40s %s %ju/sec (%.2f%%)\n",
214 buf
, name
, (uintmax_t)(step
/ delta_sec
),
215 percent_time(spent
, delta_usec
));
223 static uint64_t print_iobytes_count_samples(
224 char *buf
, const size_t buflen
,
226 const struct smbprofile_stats_iobytes
* const current
,
227 const struct smbprofile_stats_iobytes
* const last
,
230 uint64_t step
= current
->count
- last
->count
;
231 uint64_t spent
= current
->time
- last
->time
;
235 uint64_t delta_sec
= usec_to_sec(delta_usec
);
239 if (buf
[0] == '\0') {
240 snprintf(buf
, buflen
,
241 "%s %ju/sec (%.2f%%)",
242 name
, (uintmax_t)(step
/ delta_sec
),
243 percent_time(spent
, delta_usec
));
245 printf("%-40s %s %ju/sec (%.2f%%)\n",
246 buf
, name
, (uintmax_t)(step
/ delta_sec
),
247 percent_time(spent
, delta_usec
));
255 static uint64_t print_count_samples(
256 const struct profile_stats
* const current
,
257 const struct profile_stats
* const last
,
261 char buf
[60] = { '\0', };
263 if (delta_usec
== 0) {
267 #define SMBPROFILE_STATS_START
268 #define SMBPROFILE_STATS_SECTION_START(name, display)
269 #define SMBPROFILE_STATS_COUNT(name) do { \
270 count += print_count_count_samples(buf, sizeof(buf), \
272 ¤t->values.name##_stats, \
273 &last->values.name##_stats, \
276 #define SMBPROFILE_STATS_TIME(name) do { \
278 #define SMBPROFILE_STATS_BASIC(name) do { \
279 count += print_basic_count_samples(buf, sizeof(buf), \
281 ¤t->values.name##_stats, \
282 &last->values.name##_stats, \
285 #define SMBPROFILE_STATS_BYTES(name) do { \
286 count += print_bytes_count_samples(buf, sizeof(buf), \
288 ¤t->values.name##_stats, \
289 &last->values.name##_stats, \
292 #define SMBPROFILE_STATS_IOBYTES(name) do { \
293 count += print_iobytes_count_samples(buf, sizeof(buf), \
295 ¤t->values.name##_stats, \
296 &last->values.name##_stats, \
299 #define SMBPROFILE_STATS_SECTION_END
300 #define SMBPROFILE_STATS_END
301 SMBPROFILE_STATS_ALL_SECTIONS
302 #undef SMBPROFILE_STATS_START
303 #undef SMBPROFILE_STATS_SECTION_START
304 #undef SMBPROFILE_STATS_COUNT
305 #undef SMBPROFILE_STATS_TIME
306 #undef SMBPROFILE_STATS_BASIC
307 #undef SMBPROFILE_STATS_BYTES
308 #undef SMBPROFILE_STATS_IOBYTES
309 #undef SMBPROFILE_STATS_SECTION_END
310 #undef SMBPROFILE_STATS_END
312 if (buf
[0] != '\0') {
313 printf("%-40s\n", buf
);
320 static struct profile_stats sample_data
[2];
321 static uint64_t sample_time
[2];
323 bool status_profile_rates(bool verbose
)
325 uint64_t remain_usec
;
334 fprintf(stderr
, "Sampling stats at %d sec intervals\n",
335 usec_to_sec(sample_interval_usec
));
338 if (!profile_setup(NULL
, True
)) {
339 fprintf(stderr
,"Failed to initialise profile memory\n");
343 smbprofile_collect(&sample_data
[last
]);
345 sample_time
[current
] = profile_timestamp();
346 next_usec
= sample_time
[current
] + sample_interval_usec
;
349 smbprofile_collect(&sample_data
[current
]);
351 /* Rate convert some values and print results. */
352 delta_usec
= sample_time
[current
] - sample_time
[last
];
354 if (print_count_samples(&sample_data
[current
],
355 &sample_data
[last
], delta_usec
)) {
359 /* Swap sampling buffers. */
364 /* Delay until next sample time. */
365 remain_usec
= next_usec
- profile_timestamp();
366 if (remain_usec
> sample_interval_usec
) {
367 fprintf(stderr
, "eek! falling behind sampling rate!\n");
371 "delaying for %lu msec\n",
372 (unsigned long )usec_to_msec(remain_usec
));