s3/utils: Detect (and report) failure to parse sddl
[samba.git] / source3 / utils / status_profile.c
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 static void profile_separator(const char * title,
29                               struct traverse_state *state)
30 {
31         char line[79 + 1];
32         char * end;
33
34         if (state->json_output) {
35                 return;
36         }
37
38         snprintf(line, sizeof(line), "**** %s ", title);
39
40         for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
41                 *end = '*';
42         }
43
44         line[sizeof(line) - 1] = '\0';
45         d_printf("%s\n", line);
46 }
47
48 /*******************************************************************
49  dump the elements of the profile structure
50   ******************************************************************/
51 bool status_profile_dump(bool verbose,
52                          struct traverse_state *state)
53 {
54         struct profile_stats stats = {};
55         const char* latest_section = NULL;
56
57         if (!profile_setup(NULL, True)) {
58                 fprintf(stderr,"Failed to initialise profile memory\n");
59                 return False;
60         }
61
62         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         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         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 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         uint64_t step = current->count - last->count;
138         uint64_t count = 0;
139
140         if (step != 0) {
141                 uint64_t delta_sec = usec_to_sec(delta_usec);
142
143                 count++;
144
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';
153                 }
154         }
155
156         return count;
157 }
158
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)
165 {
166         uint64_t step = current->count - last->count;
167         uint64_t spent = current->time - last->time;
168         uint64_t count = 0;
169
170         if (step != 0) {
171                 uint64_t delta_sec = usec_to_sec(delta_usec);
172
173                 count++;
174
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';
185                 }
186         }
187
188         return count;
189 }
190
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)
197 {
198         uint64_t step = current->count - last->count;
199         uint64_t spent = current->time - last->time;
200         uint64_t count = 0;
201
202         if (step != 0) {
203                 uint64_t delta_sec = usec_to_sec(delta_usec);
204
205                 count++;
206
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';
217                 }
218         }
219
220         return count;
221 }
222
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)
229 {
230         uint64_t step = current->count - last->count;
231         uint64_t spent = current->time - last->time;
232         uint64_t count = 0;
233
234         if (step != 0) {
235                 uint64_t delta_sec = usec_to_sec(delta_usec);
236
237                 count++;
238
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';
249                 }
250         }
251
252         return count;
253 }
254
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)
259 {
260         uint64_t count = 0;
261         char buf[60] = { '\0', };
262
263         if (delta_usec == 0) {
264                 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                                            &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
311
312         if (buf[0] != '\0') {
313                 printf("%-40s\n", buf);
314                 buf[0] = '\0';
315         }
316
317         return count;
318 }
319
320 static struct profile_stats     sample_data[2];
321 static uint64_t         sample_time[2];
322
323 bool status_profile_rates(bool verbose)
324 {
325         uint64_t remain_usec;
326         uint64_t next_usec;
327         uint64_t delta_usec;
328
329         int last = 0;
330         int current = 1;
331         int tmp;
332
333         if (verbose) {
334             fprintf(stderr, "Sampling stats at %d sec intervals\n",
335                     usec_to_sec(sample_interval_usec));
336         }
337
338         if (!profile_setup(NULL, True)) {
339                 fprintf(stderr,"Failed to initialise profile memory\n");
340                 return False;
341         }
342
343         smbprofile_collect(&sample_data[last]);
344         for (;;) {
345                 sample_time[current] = profile_timestamp();
346                 next_usec = sample_time[current] + sample_interval_usec;
347
348                 /* Take a sample. */
349                 smbprofile_collect(&sample_data[current]);
350
351                 /* Rate convert some values and print results. */
352                 delta_usec = sample_time[current] - sample_time[last];
353
354                 if (print_count_samples(&sample_data[current],
355                         &sample_data[last], delta_usec)) {
356                         printf("\n");
357                 }
358
359                 /* Swap sampling buffers. */
360                 tmp = last;
361                 last = current;
362                 current = tmp;
363
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));
373                         }
374
375                         usleep(remain_usec);
376                 }
377
378         }
379
380         return True;
381 }