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>