s3:smbprofile: Replace sysv shmem with tdb
[vlendec/samba-autobuild/.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
25 static void profile_separator(const char * title)
26 {
27     char line[79 + 1];
28     char * end;
29
30     snprintf(line, sizeof(line), "**** %s ", title);
31
32     for (end = line + strlen(line); end < &line[sizeof(line) -1]; ++end) {
33             *end = '*';
34     }
35
36     line[sizeof(line) - 1] = '\0';
37     d_printf("%s\n", line);
38 }
39
40 /*******************************************************************
41  dump the elements of the profile structure
42   ******************************************************************/
43 bool status_profile_dump(bool verbose)
44 {
45         struct profile_stats stats = {};
46
47         if (!profile_setup(NULL, True)) {
48                 fprintf(stderr,"Failed to initialise profile memory\n");
49                 return False;
50         }
51
52         smbprofile_collect(&stats);
53
54 #define __PRINT_FIELD_LINE(name, _stats, field) do { \
55         d_printf("%-59s%20ju\n", \
56                  name "_" #field ":", \
57                  (uintmax_t)stats.values._stats.field); \
58 } while(0);
59 #define SMBPROFILE_STATS_START
60 #define SMBPROFILE_STATS_SECTION_START(name, display) profile_separator(#display);
61 #define SMBPROFILE_STATS_COUNT(name) do { \
62         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
63 } while(0);
64 #define SMBPROFILE_STATS_TIME(name) do { \
65         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
66 } while(0);
67 #define SMBPROFILE_STATS_BASIC(name) do { \
68         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
69         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
70 } while(0);
71 #define SMBPROFILE_STATS_BYTES(name) do { \
72         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
73         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
74         __PRINT_FIELD_LINE(#name, name##_stats,  idle); \
75         __PRINT_FIELD_LINE(#name, name##_stats,  bytes); \
76 } while(0);
77 #define SMBPROFILE_STATS_IOBYTES(name) do { \
78         __PRINT_FIELD_LINE(#name, name##_stats,  count); \
79         __PRINT_FIELD_LINE(#name, name##_stats,  time); \
80         __PRINT_FIELD_LINE(#name, name##_stats,  idle); \
81         __PRINT_FIELD_LINE(#name, name##_stats,  inbytes); \
82         __PRINT_FIELD_LINE(#name, name##_stats,  outbytes); \
83 } while(0);
84 #define SMBPROFILE_STATS_SECTION_END
85 #define SMBPROFILE_STATS_END
86         SMBPROFILE_STATS_ALL_SECTIONS
87 #undef __PRINT_FIELD_LINE
88 #undef SMBPROFILE_STATS_START
89 #undef SMBPROFILE_STATS_SECTION_START
90 #undef SMBPROFILE_STATS_COUNT
91 #undef SMBPROFILE_STATS_TIME
92 #undef SMBPROFILE_STATS_BASIC
93 #undef SMBPROFILE_STATS_BYTES
94 #undef SMBPROFILE_STATS_IOBYTES
95 #undef SMBPROFILE_STATS_SECTION_END
96 #undef SMBPROFILE_STATS_END
97
98         return True;
99 }
100
101 /* Convert microseconds to milliseconds. */
102 #define usec_to_msec(s) ((s) / 1000)
103 /* Convert microseconds to seconds. */
104 #define usec_to_sec(s) ((s) / 1000000)
105 /* One second in microseconds. */
106 #define one_second_usec (1000000)
107
108 #define sample_interval_usec one_second_usec
109
110 #define percent_time(used, period) ((double)(used) / (double)(period) * 100.0 )
111
112 static uint64_t print_count_count_samples(
113         char *buf, const size_t buflen,
114         const char *name,
115         const struct smbprofile_stats_count * const current,
116         const struct smbprofile_stats_count * const last,
117         uint64_t delta_usec)
118 {
119         uint64_t step = current->count - last->count;
120         uint64_t count = 0;
121
122         if (step != 0) {
123                 uint64_t delta_sec = usec_to_sec(delta_usec);
124
125                 count++;
126
127                 if (buf[0] == '\0') {
128                         snprintf(buf, buflen,
129                                 "%s %ju/sec",
130                                 name, (uintmax_t)(step / delta_sec));
131                 } else {
132                         printf("%-40s %s %ju/sec\n",
133                                 buf, name, (uintmax_t)(step / delta_sec));
134                         buf[0] = '\0';
135                 }
136         }
137
138         return count;
139 }
140
141 static uint64_t print_basic_count_samples(
142         char *buf, const size_t buflen,
143         const char *name,
144         const struct smbprofile_stats_basic * const current,
145         const struct smbprofile_stats_basic * const last,
146         uint64_t delta_usec)
147 {
148         uint64_t step = current->count - last->count;
149         uint64_t spent = current->time - last->time;
150         uint64_t count = 0;
151
152         if (step != 0) {
153                 uint64_t delta_sec = usec_to_sec(delta_usec);
154
155                 count++;
156
157                 if (buf[0] == '\0') {
158                         snprintf(buf, buflen,
159                                 "%s %ju/sec (%.2f%%)",
160                                 name, (uintmax_t)(step / delta_sec),
161                                 percent_time(spent, delta_usec));
162                 } else {
163                         printf("%-40s %s %ju/sec (%.2f%%)\n",
164                                 buf, name, (uintmax_t)(step / delta_sec),
165                                 percent_time(spent, delta_usec));
166                         buf[0] = '\0';
167                 }
168         }
169
170         return count;
171 }
172
173 static uint64_t print_bytes_count_samples(
174         char *buf, const size_t buflen,
175         const char *name,
176         const struct smbprofile_stats_bytes * const current,
177         const struct smbprofile_stats_bytes * const last,
178         uint64_t delta_usec)
179 {
180         uint64_t step = current->count - last->count;
181         uint64_t spent = current->time - last->time;
182         uint64_t count = 0;
183
184         if (step != 0) {
185                 uint64_t delta_sec = usec_to_sec(delta_usec);
186
187                 count++;
188
189                 if (buf[0] == '\0') {
190                         snprintf(buf, buflen,
191                                 "%s %ju/sec (%.2f%%)",
192                                 name, (uintmax_t)(step / delta_sec),
193                                 percent_time(spent, delta_usec));
194                 } else {
195                         printf("%-40s %s %ju/sec (%.2f%%)\n",
196                                 buf, name, (uintmax_t)(step / delta_sec),
197                                 percent_time(spent, delta_usec));
198                         buf[0] = '\0';
199                 }
200         }
201
202         return count;
203 }
204
205 static uint64_t print_iobytes_count_samples(
206         char *buf, const size_t buflen,
207         const char *name,
208         const struct smbprofile_stats_iobytes * const current,
209         const struct smbprofile_stats_iobytes * const last,
210         uint64_t delta_usec)
211 {
212         uint64_t step = current->count - last->count;
213         uint64_t spent = current->time - last->time;
214         uint64_t count = 0;
215
216         if (step != 0) {
217                 uint64_t delta_sec = usec_to_sec(delta_usec);
218
219                 count++;
220
221                 if (buf[0] == '\0') {
222                         snprintf(buf, buflen,
223                                 "%s %ju/sec (%.2f%%)",
224                                 name, (uintmax_t)(step / delta_sec),
225                                 percent_time(spent, delta_usec));
226                 } else {
227                         printf("%-40s %s %ju/sec (%.2f%%)\n",
228                                 buf, name, (uintmax_t)(step / delta_sec),
229                                 percent_time(spent, delta_usec));
230                         buf[0] = '\0';
231                 }
232         }
233
234         return count;
235 }
236
237 static uint64_t print_count_samples(
238         const struct profile_stats * const current,
239         const struct profile_stats * const last,
240         uint64_t delta_usec)
241 {
242         uint64_t count = 0;
243         char buf[40] = { '\0', };
244
245         if (delta_usec == 0) {
246                 return 0;
247         }
248
249 #define SMBPROFILE_STATS_START
250 #define SMBPROFILE_STATS_SECTION_START(name, display)
251 #define SMBPROFILE_STATS_COUNT(name) do { \
252         count += print_count_count_samples(buf, sizeof(buf), \
253                                            #name, \
254                                            &current->values.name##_stats, \
255                                            &last->values.name##_stats, \
256                                            delta_usec); \
257 } while(0);
258 #define SMBPROFILE_STATS_TIME(name) do { \
259 } while(0);
260 #define SMBPROFILE_STATS_BASIC(name) do { \
261         count += print_basic_count_samples(buf, sizeof(buf), \
262                                            #name, \
263                                            &current->values.name##_stats, \
264                                            &last->values.name##_stats, \
265                                            delta_usec); \
266 } while(0);
267 #define SMBPROFILE_STATS_BYTES(name) do { \
268         count += print_bytes_count_samples(buf, sizeof(buf), \
269                                            #name, \
270                                            &current->values.name##_stats, \
271                                            &last->values.name##_stats, \
272                                            delta_usec); \
273 } while(0);
274 #define SMBPROFILE_STATS_IOBYTES(name) do { \
275         count += print_iobytes_count_samples(buf, sizeof(buf), \
276                                              #name, \
277                                              &current->values.name##_stats, \
278                                              &last->values.name##_stats, \
279                                              delta_usec); \
280 } while(0);
281 #define SMBPROFILE_STATS_SECTION_END
282 #define SMBPROFILE_STATS_END
283         SMBPROFILE_STATS_ALL_SECTIONS
284 #undef SMBPROFILE_STATS_START
285 #undef SMBPROFILE_STATS_SECTION_START
286 #undef SMBPROFILE_STATS_COUNT
287 #undef SMBPROFILE_STATS_TIME
288 #undef SMBPROFILE_STATS_BASIC
289 #undef SMBPROFILE_STATS_BYTES
290 #undef SMBPROFILE_STATS_IOBYTES
291 #undef SMBPROFILE_STATS_SECTION_END
292 #undef SMBPROFILE_STATS_END
293
294         if (buf[0] != '\0') {
295                 printf("%-40s\n", buf);
296                 buf[0] = '\0';
297         }
298
299         return count;
300 }
301
302 static struct profile_stats     sample_data[2];
303 static uint64_t         sample_time[2];
304
305 bool status_profile_rates(bool verbose)
306 {
307         uint64_t remain_usec;
308         uint64_t next_usec;
309         uint64_t delta_usec;
310
311         int last = 0;
312         int current = 1;
313         int tmp;
314
315         if (verbose) {
316             fprintf(stderr, "Sampling stats at %d sec intervals\n",
317                     usec_to_sec(sample_interval_usec));
318         }
319
320         if (!profile_setup(NULL, True)) {
321                 fprintf(stderr,"Failed to initialise profile memory\n");
322                 return False;
323         }
324
325         smbprofile_collect(&sample_data[last]);
326         for (;;) {
327                 sample_time[current] = profile_timestamp();
328                 next_usec = sample_time[current] + sample_interval_usec;
329
330                 /* Take a sample. */
331                 smbprofile_collect(&sample_data[current]);
332
333                 /* Rate convert some values and print results. */
334                 delta_usec = sample_time[current] - sample_time[last];
335
336                 if (print_count_samples(&sample_data[current],
337                         &sample_data[last], delta_usec)) {
338                         printf("\n");
339                 }
340
341                 /* Swap sampling buffers. */
342                 tmp = last;
343                 last = current;
344                 current = tmp;
345
346                 /* Delay until next sample time. */
347                 remain_usec = next_usec - profile_timestamp();
348                 if (remain_usec > sample_interval_usec) {
349                         fprintf(stderr, "eek! falling behind sampling rate!\n");
350                 } else {
351                         if (verbose) {
352                             fprintf(stderr,
353                                     "delaying for %lu msec\n",
354                                     (unsigned long )usec_to_msec(remain_usec));
355                         }
356
357                         usleep(remain_usec);
358                 }
359
360         }
361
362         return True;
363 }