ctdb: make use of ctdb_canonicalize_ip_inplace() in ctdb_control_tcp_client()
[Samba.git] / source3 / utils / status_profile.c
blob6e0916ed7e8cc6db53b4a61fa3a29d5132aa132d
1 /*
2 * Unix SMB/CIFS implementation.
3 * status reporting
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/>.
21 #include "includes.h"
22 #include "smbprofile.h"
23 #include "status_profile.h"
24 #include "conn_tdb.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)
31 char line[79 + 1];
32 char * end;
34 if (state->json_output) {
35 return;
38 snprintf(line, sizeof(line), "**** %s ", title);
40 for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
41 *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");
59 return False;
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 ":", \
69 val); \
70 } else { \
71 add_profile_item_to_json(state, latest_section, name, #field, val); \
72 } \
73 } while(0);
74 #define SMBPROFILE_STATS_START
75 #define SMBPROFILE_STATS_SECTION_START(name, display) do { \
76 latest_section = display; \
77 profile_separator(display, state);\
78 } while(0);
79 #define SMBPROFILE_STATS_COUNT(name) do { \
80 __PRINT_FIELD_LINE(#name, name##_stats, count); \
81 } while(0);
82 #define SMBPROFILE_STATS_TIME(name) do { \
83 __PRINT_FIELD_LINE(#name, name##_stats, time); \
84 } while(0);
85 #define SMBPROFILE_STATS_BASIC(name) do { \
86 __PRINT_FIELD_LINE(#name, name##_stats, count); \
87 __PRINT_FIELD_LINE(#name, name##_stats, time); \
88 } while(0);
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); \
94 } while(0);
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); \
101 } while(0);
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
116 return True;
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,
132 const char *name,
133 const struct smbprofile_stats_count * const current,
134 const struct smbprofile_stats_count * const last,
135 uint64_t delta_usec)
137 uint64_t step = current->count - last->count;
138 uint64_t count = 0;
140 if (step != 0) {
141 uint64_t delta_sec = usec_to_sec(delta_usec);
143 count++;
145 if (buf[0] == '\0') {
146 snprintf(buf, buflen,
147 "%-40s %ju/sec",
148 name, (uintmax_t)(step / delta_sec));
149 } else {
150 printf("%-40s %s %ju/sec\n",
151 buf, name, (uintmax_t)(step / delta_sec));
152 buf[0] = '\0';
156 return count;
159 static uint64_t print_basic_count_samples(
160 char *buf, const size_t buflen,
161 const char *name,
162 const struct smbprofile_stats_basic * const current,
163 const struct smbprofile_stats_basic * const last,
164 uint64_t delta_usec)
166 uint64_t step = current->count - last->count;
167 uint64_t spent = current->time - last->time;
168 uint64_t count = 0;
170 if (step != 0) {
171 uint64_t delta_sec = usec_to_sec(delta_usec);
173 count++;
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));
180 } else {
181 printf("%-40s %s %ju/sec (%.2f%%)\n",
182 buf, name, (uintmax_t)(step / delta_sec),
183 percent_time(spent, delta_usec));
184 buf[0] = '\0';
188 return count;
191 static uint64_t print_bytes_count_samples(
192 char *buf, const size_t buflen,
193 const char *name,
194 const struct smbprofile_stats_bytes * const current,
195 const struct smbprofile_stats_bytes * const last,
196 uint64_t delta_usec)
198 uint64_t step = current->count - last->count;
199 uint64_t spent = current->time - last->time;
200 uint64_t count = 0;
202 if (step != 0) {
203 uint64_t delta_sec = usec_to_sec(delta_usec);
205 count++;
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));
212 } else {
213 printf("%-40s %s %ju/sec (%.2f%%)\n",
214 buf, name, (uintmax_t)(step / delta_sec),
215 percent_time(spent, delta_usec));
216 buf[0] = '\0';
220 return count;
223 static uint64_t print_iobytes_count_samples(
224 char *buf, const size_t buflen,
225 const char *name,
226 const struct smbprofile_stats_iobytes * const current,
227 const struct smbprofile_stats_iobytes * const last,
228 uint64_t delta_usec)
230 uint64_t step = current->count - last->count;
231 uint64_t spent = current->time - last->time;
232 uint64_t count = 0;
234 if (step != 0) {
235 uint64_t delta_sec = usec_to_sec(delta_usec);
237 count++;
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));
244 } else {
245 printf("%-40s %s %ju/sec (%.2f%%)\n",
246 buf, name, (uintmax_t)(step / delta_sec),
247 percent_time(spent, delta_usec));
248 buf[0] = '\0';
252 return count;
255 static uint64_t print_count_samples(
256 const struct profile_stats * const current,
257 const struct profile_stats * const last,
258 uint64_t delta_usec)
260 uint64_t count = 0;
261 char buf[60] = { '\0', };
263 if (delta_usec == 0) {
264 return 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), \
271 #name, \
272 &current->values.name##_stats, \
273 &last->values.name##_stats, \
274 delta_usec); \
275 } while(0);
276 #define SMBPROFILE_STATS_TIME(name) do { \
277 } while(0);
278 #define SMBPROFILE_STATS_BASIC(name) do { \
279 count += print_basic_count_samples(buf, sizeof(buf), \
280 #name, \
281 &current->values.name##_stats, \
282 &last->values.name##_stats, \
283 delta_usec); \
284 } while(0);
285 #define SMBPROFILE_STATS_BYTES(name) do { \
286 count += print_bytes_count_samples(buf, sizeof(buf), \
287 #name, \
288 &current->values.name##_stats, \
289 &last->values.name##_stats, \
290 delta_usec); \
291 } while(0);
292 #define SMBPROFILE_STATS_IOBYTES(name) do { \
293 count += print_iobytes_count_samples(buf, sizeof(buf), \
294 #name, \
295 &current->values.name##_stats, \
296 &last->values.name##_stats, \
297 delta_usec); \
298 } while(0);
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);
314 buf[0] = '\0';
317 return count;
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;
326 uint64_t next_usec;
327 uint64_t delta_usec;
329 int last = 0;
330 int current = 1;
331 int tmp;
333 if (verbose) {
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");
340 return False;
343 smbprofile_collect(&sample_data[last]);
344 for (;;) {
345 sample_time[current] = profile_timestamp();
346 next_usec = sample_time[current] + sample_interval_usec;
348 /* Take a sample. */
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)) {
356 printf("\n");
359 /* Swap sampling buffers. */
360 tmp = last;
361 last = current;
362 current = tmp;
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");
368 } else {
369 if (verbose) {
370 fprintf(stderr,
371 "delaying for %lu msec\n",
372 (unsigned long )usec_to_msec(remain_usec));
375 usleep(remain_usec);
380 return True;