Annotation of embedaddon/bmon/src/bmon.c, revision 1.1.1.2

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>