Annotation of embedaddon/bmon/src/in_sysfs.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * in_sysfs.c           /sys input (Linux)
                      3:  *
                      4:  * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch>
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a
                      7:  * copy of this software and associated documentation files (the "Software"),
                      8:  * to deal in the Software without restriction, including without limitation
                      9:  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
                     10:  * and/or sell copies of the Software, and to permit persons to whom the
                     11:  * Software is furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included
                     14:  * in all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
                     17:  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
                     21:  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
                     22:  * DEALINGS IN THE SOFTWARE.
                     23:  *
                     24:  * TODO: Give cached FD's some timer to they can be closed if unused
                     25:  */
                     26: 
                     27: #include <bmon/bmon.h>
                     28: #include <bmon/input.h>
                     29: #include <bmon/item.h>
                     30: #include <bmon/node.h>
                     31: #include <bmon/utils.h>
                     32: #include <inttypes.h>
                     33: 
                     34: #if defined SYS_LINUX
                     35: 
                     36: #if HAVE_DIRENT_H
                     37: # include <dirent.h>
                     38: # define NAMLEN(dirent) strlen((dirent)->d_name)
                     39: #else
                     40: # define dirent direct
                     41: # define NAMLEN(dirent) (dirent)->d_namlen
                     42: # if HAVE_SYS_NDIR_H
                     43: #  include <sys/ndir.h>
                     44: # endif
                     45: # if HAVE_SYS_DIR_H
                     46: #  include <sys/dir.h>
                     47: # endif
                     48: # if HAVE_NDIR_H
                     49: #  include <ndir.h>
                     50: # endif
                     51: #endif
                     52: 
                     53: static char * c_dir = "/sys";
                     54: static int    c_cache = 1;
                     55: 
                     56: struct sysfs_fd_cache
                     57: {
                     58:        char *filename;
                     59:        FILE *fd;
                     60:        struct sysfs_fd_cache *next;
                     61: };
                     62: 
                     63: #define FD_HTSIZE 2048
                     64: 
                     65: struct sysfs_fd_cache * fd_ht[FD_HTSIZE];
                     66: 
                     67: static uint32_t hash(register const char *s)
                     68: {
                     69: #define ROTATE_RIGHT(x, n) (x = (x >> (n & 0x1f)) | (x << (32 - (n & 0x1f))))
                     70: 
                     71:     uint32_t ret = 0xcafebabe;
                     72:     uint8_t  temp;
                     73: 
                     74:     do {
                     75:         temp = *s++;
                     76:         ret ^= temp ^ ((ret >> 8) & 0xff);
                     77:         ROTATE_RIGHT(ret, ret);
                     78:     } while(temp);
                     79: 
                     80: #undef ROTATE_RIGHT
                     81: 
                     82:     return ret % FD_HTSIZE;
                     83: }
                     84: 
                     85: static struct sysfs_fd_cache * cache_get(const char *filename)
                     86: {
                     87:        struct sysfs_fd_cache *f;
                     88:        uint32_t h = hash(filename);
                     89: 
                     90:        for (f = fd_ht[h]; f; f = f->next)
                     91:                if (!strcmp(f->filename, filename))
                     92:                        return f;
                     93: 
                     94:        return NULL;
                     95: }
                     96: 
                     97: static struct sysfs_fd_cache * cache_put(struct sysfs_fd_cache *f)
                     98: {
                     99:        uint32_t h = hash(f->filename);
                    100: 
                    101:        f->next = fd_ht[h];
                    102:        fd_ht[h] = f;
                    103: 
                    104:        return f;
                    105: }
                    106: 
                    107: static FILE * get_cached_fd(const char *filename)
                    108: {
                    109:        struct sysfs_fd_cache *f = cache_get(filename);
                    110: 
                    111:        if (NULL == f) {
                    112:                f = xcalloc(1, sizeof(*f));
                    113:                f->filename = strdup(filename);
                    114:                f->fd = fopen(filename, "r");
                    115: 
                    116:                if (NULL == f->fd)
                    117:                        quit("Cannot open file %s: %s\n", filename, strerror(errno));
                    118: 
                    119:                return cache_put(f)->fd;
                    120:        }
                    121: 
                    122:        fseek(f->fd, 0, SEEK_SET);
                    123:        return f->fd;
                    124: }
                    125: 
                    126: static b_cnt_t read_int(const char *prefix, const char *file)
                    127: {
                    128:        FILE *f;
                    129:        b_cnt_t r;
                    130:        char p[FILENAME_MAX];
                    131: 
                    132:        snprintf(p, sizeof(p), "%s/%s", prefix, file);
                    133: 
                    134:        if (c_cache)
                    135:                f = get_cached_fd(p);
                    136:        else {
                    137:                f = fopen(p, "r");
                    138:                if (NULL == f)
                    139:                        quit("Cannot open file %s: %s\n", p, strerror(errno));
                    140:        }
                    141:                        
                    142: 
                    143:        if (fscanf(f, "%" SCNu64 "\n", &r) != 1)
                    144:                quit("fscanf failed: format error\n");
                    145: 
                    146:        if (!c_cache)
                    147:                fclose(f);
                    148: 
                    149:        return r;
                    150: }
                    151: 
                    152: static void sysfs_read(void)
                    153: {
                    154:        item_t *n;
                    155:        DIR *d;
                    156:        struct dirent *de;
                    157:        char topdir[FILENAME_MAX];
                    158: 
                    159:        snprintf(topdir, sizeof(topdir), "%s/class/net", c_dir);
                    160: 
                    161:        d = opendir(topdir);
                    162: 
                    163:        if (!d)
                    164:                quit("Failed to open directory %s: %s\n", topdir, strerror(errno));
                    165: 
                    166:        while ((de = readdir(d))) {
                    167:                if (de->d_type == DT_DIR && de->d_name[0] != '.') {
                    168:                        char p[FILENAME_MAX];
                    169: 
                    170:                        snprintf(p, sizeof(p), "%s/%s/statistics",
                    171:                                topdir, de->d_name);
                    172: 
                    173:                        n = lookup_item(get_local_node(), de->d_name, 0, 0);
                    174: 
                    175:                        if (NULL == n)
                    176:                                continue;
                    177: 
                    178:                        n->i_major_attr = BYTES;
                    179:                        n->i_minor_attr = PACKETS;
                    180:                        
                    181:                        update_attr(n, BYTES, read_int(p, "rx_bytes"),
                    182:                                    read_int(p, "tx_bytes"), RX_PROVIDED|TX_PROVIDED);
                    183:                        update_attr(n, PACKETS, read_int(p, "rx_packets"),
                    184:                                    read_int(p, "tx_packets"), RX_PROVIDED|TX_PROVIDED);
                    185:                        update_attr(n, ERRORS, read_int(p, "rx_errors"),
                    186:                                read_int(p, "tx_errors"), RX_PROVIDED|TX_PROVIDED);
                    187:                        update_attr(n, DROP, read_int(p, "rx_dropped"),
                    188:                                read_int(p, "tx_dropped"), RX_PROVIDED|TX_PROVIDED);
                    189:                        update_attr(n, FIFO, read_int(p, "rx_fifo_errors"),
                    190:                                read_int(p, "tx_fifo_errors"), RX_PROVIDED|TX_PROVIDED);
                    191:                        update_attr(n, FRAME, read_int(p, "rx_frame_errors"),
                    192:                                0, RX_PROVIDED);
                    193:                        update_attr(n, COMPRESSED, read_int(p, "rx_compressed"),
                    194:                                read_int(p, "tx_compressed"), RX_PROVIDED|TX_PROVIDED);
                    195:                        update_attr(n, MULTICAST, read_int(p, "multicast"),
                    196:                                0, RX_PROVIDED);
                    197:                        update_attr(n, COLLISIONS, 0,
                    198:                                read_int(p, "collisions"), TX_PROVIDED);
                    199:                        update_attr(n, CRC_ERRORS, read_int(p, "rx_crc_errors"),
                    200:                                0, RX_PROVIDED);
                    201:                        update_attr(n, LENGTH_ERRORS, read_int(p, "rx_length_errors"),
                    202:                                0, RX_PROVIDED);
                    203:                        update_attr(n, MISSED_ERRORS, read_int(p, "rx_missed_errors"),
                    204:                                0, RX_PROVIDED);
                    205:                        update_attr(n, OVER_ERRORS, read_int(p, "rx_over_errors"),
                    206:                                0, RX_PROVIDED);
                    207:                        update_attr(n, ABORTED_ERRORS, 0,
                    208:                                read_int(p, "tx_aborted_errors"), TX_PROVIDED);
                    209:                        update_attr(n, CARRIER_ERRORS, 0,
                    210:                                read_int(p, "tx_carrier_errors"), TX_PROVIDED);
                    211:                        update_attr(n, HEARTBEAT_ERRORS, 0,
                    212:                                read_int(p, "tx_heartbeat_errors"), TX_PROVIDED);
                    213:                        update_attr(n, WINDOW_ERRORS, 0,
                    214:                                read_int(p, "tx_window_errors"), TX_PROVIDED);
                    215: 
                    216:                        notify_update(n, NULL);
                    217:                        increase_lifetime(n, 1);
                    218:                }
                    219:        }
                    220: 
                    221:        closedir(d);
                    222: }
                    223: 
                    224: static void print_help(void)
                    225: {
                    226:        printf(
                    227:        "sysfs - sysfs statistic collector for Linux" \
                    228:        "\n" \
                    229:        "  Reads statistics from sysfs (/sys/class/net). File descriptors are\n" \
                    230:        "  cached and not closed to minimize I/O operations. This might cause\n" \
                    231:        "  problems due to the huge amount of open file descriptors.\n" \
                    232:        "  Author: Thomas Graf <tgraf@suug.ch>\n" \
                    233:        "\n" \
                    234:        "  Options:\n" \
                    235:        "    dir=DIR        Sysfs directory (default: /sys)\n" \
                    236:        "    nocache        Don't cache file descriptors.\n");
                    237: }
                    238: 
                    239: static void sysfs_set_opts(tv_t *attrs)
                    240: {
                    241:        while (attrs) {
                    242:                if (!strcasecmp(attrs->type, "dir") && attrs->value)
                    243:                        c_dir = attrs->value;
                    244:                else if (!strcasecmp(attrs->type, "nocache"))
                    245:                        c_cache = 0;
                    246:                else if (!strcasecmp(attrs->type, "help")) {
                    247:                        print_help();
                    248:                        exit(0);
                    249:                }
                    250:                attrs = attrs->next;
                    251:        }
                    252: }
                    253: 
                    254: static int sysfs_probe(void)
                    255: {
                    256:        DIR *d;
                    257:        char topdir[FILENAME_MAX];
                    258: 
                    259:        snprintf(topdir, sizeof(topdir), "%s/class/net", c_dir);
                    260:        d = opendir(topdir);
                    261: 
                    262:        if (d) {
                    263:                closedir(d);
                    264:                return 1;
                    265:        }
                    266:        return 0;
                    267: }
                    268: 
                    269: static struct input_module sysfs_ops = {
                    270:        .im_name = "sysfs",
                    271:        .im_read = sysfs_read,
                    272:        .im_set_opts = sysfs_set_opts,
                    273:        .im_probe = sysfs_probe,
                    274: };
                    275: 
                    276: static void __init proc_init(void)
                    277: {
                    278:        register_input_module(&sysfs_ops);
                    279: }
                    280: 
                    281: #endif

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