Annotation of embedaddon/bmon/src/in_sysfs.c, revision 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>