Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * status reporting
4 : * Copyright (C) Andrew Tridgell 1994-1998
5 : * Copyright (C) James Peach 2005-2006
6 : *
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.
11 : *
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.
16 : *
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/>.
19 : */
20 :
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"
27 :
28 16 : static void profile_separator(const char * title,
29 : struct traverse_state *state)
30 : {
31 : char line[79 + 1];
32 : char * end;
33 :
34 16 : if (state->json_output) {
35 16 : return;
36 : }
37 :
38 0 : snprintf(line, sizeof(line), "**** %s ", title);
39 :
40 0 : for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
41 0 : *end = '*';
42 : }
43 :
44 0 : line[sizeof(line) - 1] = '\0';
45 0 : d_printf("%s\n", line);
46 : }
47 :
48 : /*******************************************************************
49 : dump the elements of the profile structure
50 : ******************************************************************/
51 2 : bool status_profile_dump(bool verbose,
52 : struct traverse_state *state)
53 : {
54 2 : struct profile_stats stats = {};
55 2 : const char* latest_section = NULL;
56 :
57 2 : if (!profile_setup(NULL, True)) {
58 0 : fprintf(stderr,"Failed to initialise profile memory\n");
59 0 : return False;
60 : }
61 :
62 2 : smbprofile_collect(&stats);
63 :
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 2 : 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
115 :
116 2 : return True;
117 : }
118 :
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)
125 :
126 : #define sample_interval_usec one_second_usec
127 :
128 : #define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 )
129 :
130 0 : 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)
136 : {
137 0 : uint64_t step = current->count - last->count;
138 0 : uint64_t count = 0;
139 :
140 0 : if (step != 0) {
141 0 : uint64_t delta_sec = usec_to_sec(delta_usec);
142 :
143 0 : count++;
144 :
145 0 : if (buf[0] == '\0') {
146 0 : snprintf(buf, buflen,
147 : "%-40s %ju/sec",
148 0 : name, (uintmax_t)(step / delta_sec));
149 : } else {
150 0 : printf("%-40s %s %ju/sec\n",
151 0 : buf, name, (uintmax_t)(step / delta_sec));
152 0 : buf[0] = '\0';
153 : }
154 : }
155 :
156 0 : return count;
157 : }
158 :
159 0 : 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)
165 : {
166 0 : uint64_t step = current->count - last->count;
167 0 : uint64_t spent = current->time - last->time;
168 0 : uint64_t count = 0;
169 :
170 0 : if (step != 0) {
171 0 : uint64_t delta_sec = usec_to_sec(delta_usec);
172 :
173 0 : count++;
174 :
175 0 : if (buf[0] == '\0') {
176 0 : snprintf(buf, buflen,
177 : "%s %ju/sec (%.2f%%)",
178 0 : name, (uintmax_t)(step / delta_sec),
179 0 : percent_time(spent, delta_usec));
180 : } else {
181 0 : printf("%-40s %s %ju/sec (%.2f%%)\n",
182 0 : buf, name, (uintmax_t)(step / delta_sec),
183 0 : percent_time(spent, delta_usec));
184 0 : buf[0] = '\0';
185 : }
186 : }
187 :
188 0 : return count;
189 : }
190 :
191 0 : 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)
197 : {
198 0 : uint64_t step = current->count - last->count;
199 0 : uint64_t spent = current->time - last->time;
200 0 : uint64_t count = 0;
201 :
202 0 : if (step != 0) {
203 0 : uint64_t delta_sec = usec_to_sec(delta_usec);
204 :
205 0 : count++;
206 :
207 0 : if (buf[0] == '\0') {
208 0 : snprintf(buf, buflen,
209 : "%s %ju/sec (%.2f%%)",
210 0 : name, (uintmax_t)(step / delta_sec),
211 0 : percent_time(spent, delta_usec));
212 : } else {
213 0 : printf("%-40s %s %ju/sec (%.2f%%)\n",
214 0 : buf, name, (uintmax_t)(step / delta_sec),
215 0 : percent_time(spent, delta_usec));
216 0 : buf[0] = '\0';
217 : }
218 : }
219 :
220 0 : return count;
221 : }
222 :
223 0 : 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)
229 : {
230 0 : uint64_t step = current->count - last->count;
231 0 : uint64_t spent = current->time - last->time;
232 0 : uint64_t count = 0;
233 :
234 0 : if (step != 0) {
235 0 : uint64_t delta_sec = usec_to_sec(delta_usec);
236 :
237 0 : count++;
238 :
239 0 : if (buf[0] == '\0') {
240 0 : snprintf(buf, buflen,
241 : "%s %ju/sec (%.2f%%)",
242 0 : name, (uintmax_t)(step / delta_sec),
243 0 : percent_time(spent, delta_usec));
244 : } else {
245 0 : printf("%-40s %s %ju/sec (%.2f%%)\n",
246 0 : buf, name, (uintmax_t)(step / delta_sec),
247 0 : percent_time(spent, delta_usec));
248 0 : buf[0] = '\0';
249 : }
250 : }
251 :
252 0 : return count;
253 : }
254 :
255 0 : 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)
259 : {
260 0 : uint64_t count = 0;
261 0 : char buf[60] = { '\0', };
262 :
263 0 : if (delta_usec == 0) {
264 0 : return 0;
265 : }
266 :
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 : ¤t->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 : ¤t->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 : ¤t->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 : ¤t->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 0 : 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
311 :
312 0 : if (buf[0] != '\0') {
313 0 : printf("%-40s\n", buf);
314 0 : buf[0] = '\0';
315 : }
316 :
317 0 : return count;
318 : }
319 :
320 : static struct profile_stats sample_data[2];
321 : static uint64_t sample_time[2];
322 :
323 0 : bool status_profile_rates(bool verbose)
324 : {
325 : uint64_t remain_usec;
326 : uint64_t next_usec;
327 : uint64_t delta_usec;
328 :
329 0 : int last = 0;
330 0 : int current = 1;
331 : int tmp;
332 :
333 0 : if (verbose) {
334 0 : fprintf(stderr, "Sampling stats at %d sec intervals\n",
335 : usec_to_sec(sample_interval_usec));
336 : }
337 :
338 0 : if (!profile_setup(NULL, True)) {
339 0 : fprintf(stderr,"Failed to initialise profile memory\n");
340 0 : return False;
341 : }
342 :
343 0 : smbprofile_collect(&sample_data[last]);
344 : for (;;) {
345 0 : sample_time[current] = profile_timestamp();
346 0 : next_usec = sample_time[current] + sample_interval_usec;
347 :
348 : /* Take a sample. */
349 0 : smbprofile_collect(&sample_data[current]);
350 :
351 : /* Rate convert some values and print results. */
352 0 : delta_usec = sample_time[current] - sample_time[last];
353 :
354 0 : if (print_count_samples(&sample_data[current],
355 0 : &sample_data[last], delta_usec)) {
356 0 : printf("\n");
357 : }
358 :
359 : /* Swap sampling buffers. */
360 0 : tmp = last;
361 0 : last = current;
362 0 : current = tmp;
363 :
364 : /* Delay until next sample time. */
365 0 : remain_usec = next_usec - profile_timestamp();
366 0 : if (remain_usec > sample_interval_usec) {
367 0 : fprintf(stderr, "eek! falling behind sampling rate!\n");
368 : } else {
369 0 : if (verbose) {
370 0 : fprintf(stderr,
371 : "delaying for %lu msec\n",
372 0 : (unsigned long )usec_to_msec(remain_usec));
373 : }
374 :
375 0 : usleep(remain_usec);
376 : }
377 :
378 : }
379 :
380 : return True;
381 : }
|