Annotation of embedaddon/bmon/src/element.c, revision 1.1
1.1 ! misho 1: /*
! 2: * src/element.c Elements
! 3: *
! 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
! 5: * Copyright (c) 2013 Red Hat, Inc.
! 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>
! 28: #include <bmon/element.h>
! 29: #include <bmon/element_cfg.h>
! 30: #include <bmon/group.h>
! 31: #include <bmon/input.h>
! 32: #include <bmon/utils.h>
! 33:
! 34: static LIST_HEAD(allowed);
! 35: static LIST_HEAD(denied);
! 36:
! 37: static int match_mask(const struct policy *p, const char *str)
! 38: {
! 39: int i, n;
! 40: char c;
! 41:
! 42: if (!p || !str)
! 43: return 0;
! 44:
! 45: for (i = 0, n = 0; p->p_rule[i] != '\0'; i++) {
! 46: if (p->p_rule[i] == '*') {
! 47: c = tolower(p->p_rule[i + 1]);
! 48:
! 49: if (c == '\0')
! 50: return 1;
! 51:
! 52: while (tolower(str[n]) != c)
! 53: if (str[n++] == '\0')
! 54: return 0;
! 55: } else if (tolower(p->p_rule[i]) != tolower(str[n++]))
! 56: return 0;
! 57: }
! 58:
! 59: return str[n] == '\0' ? 1 : 0;
! 60: }
! 61:
! 62: int element_allowed(const char *name, struct element_cfg *cfg)
! 63: {
! 64: struct policy *p;
! 65:
! 66: if (cfg) {
! 67: if (cfg->ec_flags & ELEMENT_CFG_HIDE)
! 68: return 0;
! 69: else if (cfg->ec_flags & ELEMENT_CFG_SHOW)
! 70: return 1;
! 71: }
! 72:
! 73: list_for_each_entry(p, &denied, p_list)
! 74: if (match_mask(p, name))
! 75: return 0;
! 76:
! 77: if (!list_empty(&allowed)) {
! 78: list_for_each_entry(p, &allowed, p_list)
! 79: if (match_mask(p, name))
! 80: return 1;
! 81:
! 82: return 0;
! 83: }
! 84:
! 85: return 1;
! 86: }
! 87:
! 88: void element_parse_policy(const char *policy)
! 89: {
! 90: char *start, *copy, *save = NULL, *tok;
! 91: struct policy *p;
! 92:
! 93: if (!policy)
! 94: return;
! 95:
! 96: copy = strdup(policy);
! 97: start = copy;
! 98:
! 99: while ((tok = strtok_r(start, ",", &save)) != NULL) {
! 100: start = NULL;
! 101:
! 102: p = xcalloc(1, sizeof(*p));
! 103:
! 104: if (*tok == '!') {
! 105: p->p_rule = strdup(++tok);
! 106: list_add_tail(&p->p_list, &denied);
! 107: } else {
! 108: p->p_rule = strdup(tok);
! 109: list_add_tail(&p->p_list, &allowed);
! 110: }
! 111: }
! 112:
! 113: xfree(copy);
! 114: }
! 115:
! 116: struct element *__lookup_element(struct element_group *group, const char *name,
! 117: uint32_t id, struct element *parent)
! 118: {
! 119: struct list_head *list;
! 120: struct element *e;
! 121:
! 122: if (parent)
! 123: list = &parent->e_childs;
! 124: else
! 125: list = &group->g_elements;
! 126:
! 127: list_for_each_entry(e, list, e_list)
! 128: if (!strcmp(name, e->e_name) && e->e_id == id)
! 129: return e;
! 130:
! 131: return NULL;
! 132: }
! 133:
! 134: struct element *element_lookup(struct element_group *group, const char *name,
! 135: uint32_t id, struct element *parent, int flags)
! 136: {
! 137: struct element_cfg *cfg;
! 138: struct element *e;
! 139: int i;
! 140:
! 141: if (!group)
! 142: BUG();
! 143:
! 144: if ((e = __lookup_element(group, name, id, parent)))
! 145: return e;
! 146:
! 147: if (!(flags & ELEMENT_CREAT))
! 148: return NULL;
! 149:
! 150: cfg = element_cfg_lookup(name);
! 151: if (!element_allowed(name, cfg))
! 152: return NULL;
! 153:
! 154: DBG("Creating element %d \"%s\"", id, name);
! 155:
! 156: e = xcalloc(1, sizeof(*e));
! 157:
! 158: init_list_head(&e->e_list);
! 159: init_list_head(&e->e_childs);
! 160: init_list_head(&e->e_info_list);
! 161: init_list_head(&e->e_attr_sorted);
! 162:
! 163: for (i = 0; i < ATTR_HASH_SIZE; i++)
! 164: init_list_head(&e->e_attrhash[i]);
! 165:
! 166: e->e_name = strdup(name);
! 167: e->e_id = id;
! 168: e->e_parent = parent;
! 169: e->e_group = group;
! 170: e->e_lifecycles = get_lifecycles();
! 171: e->e_flags = ELEMENT_FLAG_CREATED;
! 172: e->e_cfg = cfg;
! 173:
! 174: if (e->e_cfg) {
! 175: if (e->e_cfg->ec_description)
! 176: element_update_info(e, "Description",
! 177: e->e_cfg->ec_description);
! 178:
! 179: element_set_rxmax(e, e->e_cfg->ec_rxmax);
! 180: element_set_txmax(e, e->e_cfg->ec_txmax);
! 181: }
! 182:
! 183: if (parent) {
! 184: DBG("Attached to parent %d \"%s\"", parent->e_id, parent->e_name);
! 185: list_add_tail(&e->e_list, &parent->e_childs);
! 186: } else {
! 187: DBG("Attached to group %s", group->g_name);
! 188: list_add_tail(&e->e_list, &group->g_elements);
! 189: }
! 190:
! 191: group->g_nelements++;
! 192:
! 193: return e;
! 194: }
! 195:
! 196: void element_free(struct element *e)
! 197: {
! 198: struct info *info, *ninfo;
! 199: struct element *c, *cnext;
! 200: struct attr *a, *an;
! 201: int i;
! 202:
! 203: if (e->e_group->g_current == e) {
! 204: element_select_prev();
! 205: if (e->e_group->g_current == e)
! 206: e->e_group->g_current = NULL;
! 207: }
! 208:
! 209: list_for_each_entry_safe(c, cnext, &e->e_childs, e_list)
! 210: element_free(c);
! 211:
! 212: list_for_each_entry_safe(info, ninfo, &e->e_info_list, i_list) {
! 213: xfree(info->i_name);
! 214: xfree(info->i_value);
! 215: list_del(&info->i_list);
! 216: xfree(info);
! 217: }
! 218:
! 219: for (i = 0; i < ATTR_HASH_SIZE; i++)
! 220: list_for_each_entry_safe(a, an, &e->e_attrhash[i], a_list)
! 221: attr_free(a);
! 222:
! 223: if (e->e_group) {
! 224: list_del(&e->e_list);
! 225: e->e_group->g_nelements--;
! 226: }
! 227:
! 228: xfree(e->e_name);
! 229: xfree(e);
! 230: }
! 231:
! 232: #if 0
! 233: if (item->i_group->g_selected == item) {
! 234: if (item_select_prev() == END_OF_LIST) {
! 235: if (group_select_prev() == END_OF_LIST) {
! 236: if (node_select_prev() != END_OF_LIST)
! 237: item_select_last();
! 238: } else
! 239: item_select_last();
! 240: }
! 241: }
! 242: #endif
! 243:
! 244: #if 0
! 245:
! 246: void item_delete(struct item *item)
! 247: {
! 248: int m;
! 249: struct item *child;
! 250:
! 251: for (m = 0; m < ATTR_HASH_MAX; m++) {
! 252: struct attr *a, *next;
! 253: for (a = item->i_attrs[m]; a; a = next) {
! 254: next = a->a_next;
! 255: xfree(a);
! 256: }
! 257: }
! 258:
! 259: if (item->i_group->g_selected == item) {
! 260: if (item_select_prev() == END_OF_LIST) {
! 261: if (group_select_prev() == END_OF_LIST) {
! 262: if (node_select_prev() != END_OF_LIST)
! 263: item_select_last();
! 264: } else
! 265: item_select_last();
! 266: }
! 267: }
! 268:
! 269: unlink_item(item);
! 270: item->i_group->g_nitems--;
! 271:
! 272: for (child = item->i_childs; child; child = child->i_next)
! 273: item_delete(child);
! 274:
! 275: if (item->i_path)
! 276: xfree(item->i_path);
! 277:
! 278: xfree(item);
! 279: }
! 280:
! 281: #endif
! 282:
! 283: void element_reset_update_flag(struct element_group *g,
! 284: struct element *e, void *arg)
! 285: {
! 286: DBG("Reseting update flag of %s", e->e_name);
! 287: e->e_flags &= ~ELEMENT_FLAG_UPDATED;
! 288: }
! 289:
! 290: /**
! 291: * Needs to be called after updating all attributes of an element
! 292: */
! 293: void element_notify_update(struct element *e, timestamp_t *ts)
! 294: {
! 295: struct attr *a;
! 296: int i;
! 297:
! 298: e->e_flags |= ELEMENT_FLAG_UPDATED;
! 299:
! 300: if (ts == NULL)
! 301: ts = &rtiming.rt_last_read;
! 302:
! 303: for (i = 0; i < ATTR_HASH_SIZE; i++)
! 304: list_for_each_entry(a, &e->e_attrhash[i], a_list)
! 305: attr_notify_update(a, ts);
! 306:
! 307: if (e->e_usage_attr && e->e_cfg &&
! 308: (a = attr_lookup(e, e->e_usage_attr->ad_id))) {
! 309: attr_calc_usage(a, &e->e_rx_usage, &e->e_tx_usage,
! 310: e->e_cfg->ec_rxmax, e->e_cfg->ec_txmax);
! 311: } else {
! 312: e->e_rx_usage = FLT_MAX;
! 313: e->e_tx_usage = FLT_MAX;
! 314: }
! 315: }
! 316:
! 317: void element_lifesign(struct element *e, int n)
! 318: {
! 319: e->e_lifecycles = n * get_lifecycles();
! 320: }
! 321:
! 322: void element_check_if_dead(struct element_group *g,
! 323: struct element *e, void *arg)
! 324: {
! 325: if (--(e->e_lifecycles) <= 0) {
! 326: element_free(e);
! 327: DBG("Deleting dead element %s", e->e_name);
! 328: }
! 329: }
! 330:
! 331: void element_foreach_attr(struct element *e,
! 332: void (*cb)(struct element *e,
! 333: struct attr *, void *),
! 334: void *arg)
! 335: {
! 336: struct attr *a;
! 337:
! 338: list_for_each_entry(a, &e->e_attr_sorted, a_sort_list)
! 339: cb(e, a, arg);
! 340: }
! 341:
! 342: int element_set_key_attr(struct element *e, const char *major,
! 343: const char * minor)
! 344: {
! 345: if (!(e->e_key_attr[GT_MAJOR] = attr_def_lookup(major)))
! 346: return -ENOENT;
! 347:
! 348: if (!(e->e_key_attr[GT_MINOR] = attr_def_lookup(minor)))
! 349: return -ENOENT;
! 350:
! 351: return 0;
! 352: }
! 353:
! 354: int element_set_usage_attr(struct element *e, const char *usage)
! 355: {
! 356: if (!(e->e_usage_attr = attr_def_lookup(usage)))
! 357: return -ENOENT;
! 358:
! 359: return 0;
! 360: }
! 361:
! 362: struct element *element_current(void)
! 363: {
! 364: struct element_group *g;
! 365:
! 366: if (!(g = group_current()))
! 367: return NULL;
! 368:
! 369: if (!g->g_current)
! 370: element_select_first();
! 371:
! 372: return g->g_current;
! 373: }
! 374:
! 375: struct element *element_select_first(void)
! 376: {
! 377: struct element_group *g;
! 378:
! 379: if (!(g = group_current()))
! 380: return NULL;
! 381:
! 382: if (list_empty(&g->g_elements))
! 383: g->g_current = NULL;
! 384: else
! 385: g->g_current = list_first_entry(&g->g_elements,
! 386: struct element, e_list);
! 387:
! 388: return g->g_current;
! 389: }
! 390:
! 391: struct element *element_select_last(void)
! 392: {
! 393: struct element_group *g;
! 394:
! 395: if (!(g = group_current()))
! 396: return NULL;
! 397:
! 398: if (list_empty(&g->g_elements))
! 399: g->g_current = NULL;
! 400: else {
! 401: struct element *e;
! 402:
! 403: e = list_entry(g->g_elements.prev, struct element, e_list);
! 404:
! 405: while (!list_empty(&e->e_childs))
! 406: e = list_entry(e->e_childs.prev, struct element,
! 407: e_list);
! 408:
! 409: g->g_current = e;
! 410: }
! 411:
! 412: return g->g_current;
! 413: }
! 414:
! 415: struct element *element_select_next(void)
! 416: {
! 417: struct element_group *g;
! 418: struct element *e;
! 419:
! 420: if (!(g = group_current()))
! 421: return NULL;
! 422:
! 423: if (!(e = g->g_current))
! 424: return element_select_first();
! 425:
! 426: if (!list_empty(&e->e_childs))
! 427: e = list_first_entry(&e->e_childs, struct element, e_list);
! 428: else {
! 429: /*
! 430: * move upwards until we have no parent or there is a next
! 431: * entry in the list
! 432: */
! 433: while (e->e_parent && e->e_list.next == &e->e_parent->e_childs)
! 434: e = e->e_parent;
! 435:
! 436: if (!e->e_parent && e->e_list.next == &g->g_elements) {
! 437: group_select_next();
! 438: return element_select_first();
! 439: } else
! 440: e = list_entry(e->e_list.next, struct element, e_list);
! 441: }
! 442:
! 443: g->g_current = e;
! 444:
! 445: return e;
! 446: }
! 447:
! 448: struct element *element_select_prev(void)
! 449: {
! 450: struct element_group *g;
! 451: struct element *e;
! 452:
! 453: if (!(g = group_current()))
! 454: return NULL;
! 455:
! 456: if (!(e = g->g_current))
! 457: return element_select_last();
! 458:
! 459: if (!e->e_parent && e->e_list.prev == &g->g_elements) {
! 460: group_select_prev();
! 461: return element_select_last();
! 462: }
! 463:
! 464: if (e->e_parent && e->e_list.prev == &e->e_parent->e_childs)
! 465: e = e->e_parent;
! 466: else {
! 467: e = list_entry(e->e_list.prev, struct element, e_list);
! 468:
! 469: while (!list_empty(&e->e_childs))
! 470: e = list_entry(e->e_childs.prev, struct element,
! 471: e_list);
! 472: }
! 473:
! 474: g->g_current = e;
! 475:
! 476: return e;
! 477: }
! 478:
! 479: static struct info *element_info_lookup(struct element *e, const char *name)
! 480: {
! 481: struct info *i;
! 482:
! 483: list_for_each_entry(i, &e->e_info_list, i_list)
! 484: if (!strcmp(i->i_name, name))
! 485: return i;
! 486:
! 487: return NULL;
! 488: }
! 489:
! 490: void element_update_info(struct element *e, const char *name, const char *value)
! 491: {
! 492: struct info *i;
! 493:
! 494: if ((i = element_info_lookup(e, name))) {
! 495: xfree(i->i_value);
! 496: i->i_value = strdup(value);
! 497: return;
! 498: }
! 499:
! 500: DBG("Created element info %s (\"%s\")", name, value);
! 501:
! 502: i = xcalloc(1, sizeof(*i));
! 503: i->i_name = strdup(name);
! 504: i->i_value = strdup(value);
! 505:
! 506: e->e_ninfo++;
! 507:
! 508: list_add_tail(&i->i_list, &e->e_info_list);
! 509: }
! 510:
! 511: void element_set_txmax(struct element *e, uint64_t max)
! 512: {
! 513: char buf[32];
! 514:
! 515: if (!e->e_cfg)
! 516: e->e_cfg = element_cfg_create(e->e_name);
! 517:
! 518: if (e->e_cfg->ec_txmax != max)
! 519: e->e_cfg->ec_txmax = max;
! 520:
! 521: unit_bit2str(e->e_cfg->ec_txmax * 8, buf, sizeof(buf));
! 522: element_update_info(e, "TxMax", buf);
! 523: }
! 524:
! 525: void element_set_rxmax(struct element *e, uint64_t max)
! 526: {
! 527: char buf[32];
! 528:
! 529: if (!e->e_cfg)
! 530: e->e_cfg = element_cfg_create(e->e_name);
! 531:
! 532: if (e->e_cfg->ec_rxmax != max)
! 533: e->e_cfg->ec_rxmax = max;
! 534:
! 535: unit_bit2str(e->e_cfg->ec_rxmax * 8, buf, sizeof(buf));
! 536: element_update_info(e, "RxMax", buf);
! 537: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>