Annotation of embedaddon/bmon/src/bmon.c, revision 1.1.1.3
1.1 misho 1: /*
2: * src/bmon.c Bandwidth Monitor
3: *
1.1.1.2 misho 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
5: * Copyright (c) 2013 Red Hat, Inc.
1.1 misho 6: *
7: * Permission is hereby granted, free of charge, to any person obtaining a
8: * copy of this software and associated documentation files (the "Software"),
9: * to deal in the Software without restriction, including without limitation
10: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11: * and/or sell copies of the Software, and to permit persons to whom the
12: * Software is furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included
15: * in all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23: * DEALINGS IN THE SOFTWARE.
24: */
25:
26: #include <bmon/bmon.h>
27: #include <bmon/conf.h>
1.1.1.2 misho 28: #include <bmon/attr.h>
29: #include <bmon/utils.h>
1.1 misho 30: #include <bmon/input.h>
31: #include <bmon/output.h>
1.1.1.2 misho 32: #include <bmon/module.h>
33: #include <bmon/group.h>
1.1 misho 34:
35: int start_time;
36:
37: struct reader_timing rtiming;
1.1.1.2 misho 38:
1.1 misho 39: static char *usage_text =
40: "Usage: bmon [OPTION]...\n" \
41: "\n" \
42: "Options:\n" \
1.1.1.2 misho 43: "Startup:\n" \
44: " -i, --input=MODPARM Input module(s)\n" \
45: " -o, --output=MODPARM Output module(s)\n" \
46: " -f, --configfile=PATH Alternative path to configuration file\n" \
47: " -h, --help Show this help text\n" \
48: " -V, --version Show version\n" \
49: "\n" \
50: "Input:\n" \
51: " -p, --policy=POLICY Element display policy (see below)\n" \
52: " -a, --show-all Show all elements (even disabled elements)\n" \
53: " -r, --read-interval=FLOAT Read interval in seconds (float)\n" \
54: " -R, --rate-interval=FLOAT Rate interval in seconds (float)\n" \
55: " -s, --sleep-interval=FLOAT Sleep time in seconds (float)\n" \
56: " -L, --lifetime=LIFETIME Lifetime of an element in seconds (float)\n" \
57: "\n" \
58: "Output:\n" \
59: " -U, --use-si Use SI units\n" \
60: " -b, --use-bit Display in bits instead of bytes\n" \
1.1 misho 61: "\n" \
62: "Module configuration:\n" \
63: " modparm := MODULE:optlist,MODULE:optlist,...\n" \
64: " optlist := option;option;...\n" \
65: " option := TYPE[=VALUE]\n" \
66: "\n" \
67: " Examples:\n" \
1.1.1.2 misho 68: " -o curses:ngraph=2\n" \
69: " -o list # Shows a list of available modules\n" \
70: " -o curses:help # Shows a help text for html module\n" \
1.1 misho 71: "\n" \
72: "Interface selection:\n" \
73: " policy := [!]simple_regexp,[!]simple_regexp,...\n" \
74: "\n" \
75: " Example: -p 'eth*,lo*,!eth1'\n" \
76: "\n" \
77: "Please see the bmon(1) man pages for full documentation.\n";
78:
79: static void do_shutdown(void)
80: {
81: static int done;
82:
83: if (!done) {
84: done = 1;
1.1.1.2 misho 85: module_shutdown();
1.1 misho 86: }
87: }
88:
1.1.1.3 ! misho 89: static void sig_exit(void)
1.1 misho 90: {
91: do_shutdown();
92: }
93:
94: void quit(const char *fmt, ...)
95: {
96: static int done;
97: va_list args;
98:
1.1.1.2 misho 99: va_start(args, fmt);
100: vfprintf(stderr, fmt, args);
101: va_end(args);
102:
1.1 misho 103: if (!done) {
104: done = 1;
105: do_shutdown();
106: }
107:
108: exit(1);
109: }
110:
1.1.1.2 misho 111: static inline void print_version(void)
1.1 misho 112: {
113: printf("bmon %s\n", PACKAGE_VERSION);
1.1.1.3 ! misho 114: printf("Copyright (C) 2001-2015 by Thomas Graf <tgraf@suug.ch>\n");
1.1.1.2 misho 115: printf("Copyright (C) 2013 Red Hat, Inc.\n");
116: printf("bmon comes with ABSOLUTELY NO WARRANTY. This is free " \
117: "software, and you\nare welcome to redistribute it under " \
118: "certain conditions. See the source\ncode for details.\n");
1.1 misho 119: }
120:
1.1.1.2 misho 121: static void parse_args_pre(int argc, char *argv[])
1.1 misho 122: {
1.1.1.2 misho 123: DBG("Parsing arguments pre state");
124:
1.1 misho 125: for (;;)
126: {
1.1.1.2 misho 127: char *gostr = "+:hvVf:";
1.1 misho 128:
1.1.1.2 misho 129: struct option long_opts[] = {
1.1.1.3 ! misho 130: {"help", 0, NULL, 'h'},
! 131: {"version", 0, NULL, 'v'},
! 132: {"configfile", 1, NULL, 'f'},
! 133: {NULL, 0, NULL, 0},
1.1.1.2 misho 134: };
135: int c = getopt_long(argc, argv, gostr, long_opts, NULL);
1.1 misho 136: if (c == -1)
137: break;
138:
139: switch (c)
140: {
1.1.1.2 misho 141: case 'f':
142: set_configfile(optarg);
1.1 misho 143: break;
144:
1.1.1.2 misho 145: case 'h':
146: print_version();
147: printf("\n%s", usage_text);
148: exit(1);
149: case 'V':
150: case 'v':
151: print_version();
152: exit(0);
153: }
154: }
155: }
1.1 misho 156:
1.1.1.2 misho 157: static int parse_args_post(int argc, char *argv[])
158: {
159: DBG("Parsing arguments post state");
1.1 misho 160:
1.1.1.2 misho 161: optind = 1;
162:
163: for (;;)
164: {
165: char *gostr = "i:o:p:r:R:s:aUb" \
166: "L:hvVf:";
167:
168: struct option long_opts[] = {
1.1.1.3 ! misho 169: {"input", 1, NULL, 'i'},
! 170: {"output", 1, NULL, 'o'},
! 171: {"policy", 1, NULL, 'p'},
! 172: {"read-interval", 1, NULL, 'r'},
! 173: {"rate-interval", 1, NULL, 'R'},
! 174: {"sleep-interval", 1, NULL, 's'},
! 175: {"show-all", 0, NULL, 'a'},
! 176: {"use-si", 0, NULL, 'U'},
! 177: {"use-bit", 0, NULL, 'b'},
! 178: {"lifetime", 1, NULL, 'L'},
! 179: {NULL, 0, NULL, 0},
1.1.1.2 misho 180: };
181: int c = getopt_long(argc, argv, gostr, long_opts, NULL);
182: if (c == -1)
183: break;
184:
185: switch (c)
186: {
187: case 'i':
188: if (input_set(optarg))
189: return 1;
1.1 misho 190: break;
191:
1.1.1.2 misho 192: case 'o':
193: if (output_set(optarg))
194: return 1;
1.1 misho 195: break;
196:
1.1.1.2 misho 197: case 'p':
198: cfg_setstr(cfg, "policy", optarg);
1.1 misho 199: break;
200:
201: case 'r':
1.1.1.2 misho 202: cfg_setfloat(cfg, "read_interval", strtod(optarg, NULL));
1.1 misho 203: break;
204:
205: case 'R':
1.1.1.2 misho 206: cfg_setfloat(cfg, "rate_interval", strtod(optarg, NULL));
1.1 misho 207: break;
208:
209: case 's':
1.1.1.2 misho 210: cfg_setint(cfg, "sleep_time", strtoul(optarg, NULL, 0));
1.1 misho 211: break;
212:
213: case 'a':
1.1.1.3 ! misho 214: cfg_setbool(cfg, "show_all", cfg_true);
1.1 misho 215: break;
216:
1.1.1.2 misho 217: case 'U':
218: cfg_setbool(cfg, "use_si", cfg_true);
1.1 misho 219: break;
220:
1.1.1.2 misho 221: case 'b':
222: cfg_setbool(cfg, "use_bit", cfg_true);
1.1 misho 223: break;
224:
1.1.1.2 misho 225: case 'L':
226: cfg_setint(cfg, "lifetime", strtoul(optarg, NULL, 0));
1.1 misho 227: break;
228:
1.1.1.2 misho 229: case 'f':
230: /* Already handled in pre getopt loop */
1.1 misho 231: break;
232:
233: default:
234: quit("Aborting...\n");
1.1.1.2 misho 235: break;
236:
1.1 misho 237: }
238: }
1.1.1.2 misho 239:
240: return 0;
1.1 misho 241: }
242:
1.1.1.2 misho 243: #if 0
1.1 misho 244: static void calc_variance(timestamp_t *c, timestamp_t *ri)
245: {
246: float v = (ts_to_float(c) / ts_to_float(ri)) * 100.0f;
247:
248: rtiming.rt_variance.v_error = v;
249: rtiming.rt_variance.v_total += v;
250:
251: if (v > rtiming.rt_variance.v_max)
252: rtiming.rt_variance.v_max = v;
253:
254: if (v < rtiming.rt_variance.v_min)
255: rtiming.rt_variance.v_min = v;
256: }
1.1.1.2 misho 257: #endif
1.1 misho 258:
259: int main(int argc, char *argv[])
260: {
1.1.1.2 misho 261: unsigned long sleep_time;
262: double read_interval;
263:
1.1.1.3 ! misho 264: start_time = time(NULL);
1.1.1.2 misho 265: memset(&rtiming, 0, sizeof(rtiming));
266: rtiming.rt_variance.v_min = FLT_MAX;
1.1 misho 267:
1.1.1.2 misho 268: /*
269: * Early initialization before reading config
270: */
271: conf_init_pre();
272: parse_args_pre(argc, argv);
1.1 misho 273:
1.1.1.2 misho 274: /*
275: * Reading the configuration file */
276: configfile_read();
1.1 misho 277:
1.1.1.2 misho 278: /*
279: * Late initialization after reading config
280: */
281: if (parse_args_post(argc, argv))
282: return 1;
283: conf_init_post();
1.1 misho 284:
1.1.1.2 misho 285: module_init();
1.1 misho 286:
1.1.1.2 misho 287: read_interval = cfg_read_interval;
288: sleep_time = cfg_getint(cfg, "sleep_time");
1.1 misho 289:
1.1.1.2 misho 290: if (((double) sleep_time / 1000000.0f) > read_interval)
291: sleep_time = (unsigned long) (read_interval * 1000000.0f);
292:
293: DBG("Entering mainloop...");
294:
295: do {
1.1 misho 296: /*
297: * E := Elapsed time
298: * NR := Next Read
299: * LR := Last Read
300: * RI := Read Interval
301: * ST := Sleep Time
302: * C := Correction
303: */
304: timestamp_t e, ri, tmp;
305: unsigned long st;
306:
1.1.1.2 misho 307: float_to_timestamp(&ri, read_interval);
1.1 misho 308:
309: /*
1.1.1.2 misho 310: * NR := NOW
1.1 misho 311: */
1.1.1.2 misho 312: update_timestamp(&rtiming.rt_next_read);
1.1 misho 313:
314: for (;;) {
315: output_pre();
316:
317: /*
1.1.1.2 misho 318: * E := NOW
1.1 misho 319: */
1.1.1.2 misho 320: update_timestamp(&e);
1.1 misho 321:
322: /*
323: * IF NR <= E THEN
324: */
1.1.1.2 misho 325: if (timestamp_le(&rtiming.rt_next_read, &e)) {
1.1 misho 326: timestamp_t c;
327:
328: /*
329: * C := (NR - E)
330: */
1.1.1.2 misho 331: timestamp_sub(&c, &rtiming.rt_next_read, &e);
1.1 misho 332:
1.1.1.2 misho 333: //calc_variance(&c, &ri);
1.1 misho 334:
335: /*
336: * LR := E
337: */
1.1.1.2 misho 338: copy_timestamp(&rtiming.rt_last_read, &e);
1.1 misho 339:
340: /*
341: * NR := E + RI + C
342: */
1.1.1.2 misho 343: timestamp_add(&rtiming.rt_next_read, &e, &ri);
344: timestamp_add(&rtiming.rt_next_read,
345: &rtiming.rt_next_read, &c);
346:
1.1 misho 347:
1.1.1.2 misho 348: reset_update_flags();
1.1 misho 349: input_read();
1.1.1.2 misho 350: free_unused_elements();
1.1 misho 351: output_draw();
352: output_post();
353: }
354:
355: /*
356: * ST := Configured ST
357: */
1.1.1.2 misho 358: st = sleep_time;
1.1 misho 359:
360: /*
361: * IF (NR - E) < ST THEN
362: */
1.1.1.2 misho 363: timestamp_sub(&tmp, &rtiming.rt_next_read, &e);
1.1 misho 364:
365: if (tmp.tv_sec < 0)
366: continue;
367:
368: if (tmp.tv_sec == 0 && tmp.tv_usec < st) {
369: if (tmp.tv_usec < 0)
370: continue;
371: /*
372: * ST := (NR - E)
373: */
374: st = tmp.tv_usec;
375: }
376:
377: /*
378: * SLEEP(ST)
379: */
380: usleep(st);
381: }
1.1.1.2 misho 382: } while (0);
383:
1.1 misho 384: return 0; /* buddha says i'll never be reached */
385: }
386:
387: static void __init bmon_init(void)
388: {
389: atexit(&sig_exit);
390: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>