File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bmon / src / element.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 14:58:35 2019 UTC (4 years, 8 months ago) by misho
Branches: bmon, MAIN
CVS tags: v4_0p0, HEAD
bmon ver 4.0

    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: static struct element *__lookup_element(struct element_group *group,
  117: 					const char *name, uint32_t id,
  118: 					struct element *parent)
  119: {
  120: 	struct list_head *list;
  121: 	struct element *e;
  122: 
  123: 	if (parent)
  124: 		list = &parent->e_childs;
  125: 	else
  126: 		list = &group->g_elements;
  127: 
  128: 	list_for_each_entry(e, list, e_list)
  129: 		if (!strcmp(name, e->e_name) && e->e_id == id)
  130: 			return e;
  131: 
  132: 	return NULL;
  133: }
  134: 
  135: struct element *element_lookup(struct element_group *group, const char *name,
  136: 			       uint32_t id, struct element *parent, int flags)
  137: {
  138: 	struct element_cfg *cfg;
  139: 	struct element *e;
  140: 	int i;
  141: 
  142: 	if (!group)
  143: 		BUG();
  144: 
  145: 	if ((e = __lookup_element(group, name, id, parent)))
  146: 		return e;
  147: 
  148: 	if (!(flags & ELEMENT_CREAT))
  149: 		return NULL;
  150: 
  151: 	cfg = element_cfg_lookup(name);
  152: 	if (!element_allowed(name, cfg))
  153: 		return NULL;
  154: 
  155: 	DBG("Creating element %d \"%s\"", id, name);
  156: 
  157: 	e = xcalloc(1, sizeof(*e));
  158: 
  159: 	init_list_head(&e->e_list);
  160: 	init_list_head(&e->e_childs);
  161: 	init_list_head(&e->e_info_list);
  162: 	init_list_head(&e->e_attr_sorted);
  163: 
  164: 	for (i = 0; i < ATTR_HASH_SIZE; i++)
  165: 		init_list_head(&e->e_attrhash[i]);
  166: 
  167: 	e->e_name = strdup(name);
  168: 	e->e_id = id;
  169: 	e->e_parent = parent;
  170: 	e->e_group = group;
  171: 	e->e_lifecycles = get_lifecycles();
  172: 	e->e_flags = ELEMENT_FLAG_CREATED;
  173: 	e->e_cfg = cfg;
  174: 
  175: 	if (e->e_cfg) {
  176: 		if (e->e_cfg->ec_description)
  177: 			element_update_info(e, "Description",
  178: 					    e->e_cfg->ec_description);
  179: 	
  180: 		element_set_rxmax(e, e->e_cfg->ec_rxmax);
  181: 		element_set_txmax(e, e->e_cfg->ec_txmax);
  182: 	}
  183: 
  184: 	if (parent) {
  185: 		DBG("Attached to parent %d \"%s\"", parent->e_id, parent->e_name);
  186: 		list_add_tail(&e->e_list, &parent->e_childs);
  187: 	} else {
  188: 		DBG("Attached to group %s", group->g_name);
  189: 		list_add_tail(&e->e_list, &group->g_elements);
  190: 	}
  191: 
  192: 	group->g_nelements++;
  193: 
  194: 	return e;
  195: }
  196: 
  197: void element_free(struct element *e)
  198: {
  199: 	struct info *info, *ninfo;
  200: 	struct element *c, *cnext;
  201: 	struct attr *a, *an;
  202: 	int i;
  203: 
  204: 	list_for_each_entry_safe(c, cnext, &e->e_childs, e_list)
  205: 		element_free(c);
  206: 
  207: 	list_for_each_entry_safe(info, ninfo, &e->e_info_list, i_list) {
  208: 		xfree(info->i_name);
  209: 		xfree(info->i_value);
  210: 		list_del(&info->i_list);
  211: 		xfree(info);
  212: 	}
  213: 
  214: 	for (i = 0; i < ATTR_HASH_SIZE; i++)
  215: 		list_for_each_entry_safe(a, an, &e->e_attrhash[i], a_list)
  216: 			attr_free(a);
  217: 
  218: 	if (e->e_group->g_current == e) {
  219: 		element_select_prev();
  220: 		if (e->e_group->g_current == e)
  221: 			e->e_group->g_current = NULL;
  222: 	}
  223: 
  224: 	list_del(&e->e_list);
  225: 	e->e_group->g_nelements--;
  226: 
  227: 	xfree(e->e_name);
  228: 	xfree(e);
  229: }
  230: 
  231: #if 0
  232: 	if (item->i_group->g_selected == item) {
  233: 		if (item_select_prev() == END_OF_LIST) {
  234: 			if (group_select_prev() == END_OF_LIST) {
  235: 				if (node_select_prev() != END_OF_LIST)
  236: 					item_select_last();
  237: 			} else
  238: 				item_select_last();
  239: 		}
  240: 	}
  241: #endif
  242: 
  243: #if 0
  244: 
  245: void item_delete(struct item *item)
  246: {
  247: 	int m;
  248: 	struct item *child;
  249: 
  250: 	for (m = 0; m < ATTR_HASH_MAX; m++) {
  251: 		struct attr *a, *next;
  252: 		for (a = item->i_attrs[m]; a; a = next) {
  253: 			next = a->a_next;
  254: 			xfree(a);
  255: 		}
  256: 	}
  257: 
  258: 	if (item->i_group->g_selected == item) {
  259: 		if (item_select_prev() == END_OF_LIST) {
  260: 			if (group_select_prev() == END_OF_LIST) {
  261: 				if (node_select_prev() != END_OF_LIST)
  262: 					item_select_last();
  263: 			} else
  264: 				item_select_last();
  265: 		}
  266: 	}
  267: 
  268: 	unlink_item(item);
  269: 	item->i_group->g_nitems--;
  270: 
  271: 	for (child = item->i_childs; child; child = child->i_next)
  272: 		item_delete(child);
  273: 
  274: 	if (item->i_path)
  275: 		xfree(item->i_path);
  276: 	
  277: 	xfree(item);
  278: }
  279: 
  280: #endif
  281: 
  282: void element_reset_update_flag(struct element_group *g,
  283: 			       struct element *e, void *arg)
  284: {
  285: 	DBG("Reseting update flag of %s", e->e_name);
  286: 	e->e_flags &= ~ELEMENT_FLAG_UPDATED;
  287: }
  288: 
  289: /**
  290:  * Needs to be called after updating all attributes of an element
  291:  */
  292: void element_notify_update(struct element *e, timestamp_t *ts)
  293: {
  294: 	struct attr *a;
  295: 	int i;
  296: 
  297: 	e->e_flags |= ELEMENT_FLAG_UPDATED;
  298: 
  299: 	if (ts == NULL)
  300: 		ts = &rtiming.rt_last_read;
  301: 
  302: 	for (i = 0; i < ATTR_HASH_SIZE; i++)
  303: 		list_for_each_entry(a, &e->e_attrhash[i], a_list)
  304: 			attr_notify_update(a, ts);
  305: 
  306: 	if (e->e_usage_attr && e->e_cfg &&
  307: 	    (a = attr_lookup(e, e->e_usage_attr->ad_id))) {
  308: 		attr_calc_usage(a, &e->e_rx_usage, &e->e_tx_usage,
  309: 				e->e_cfg->ec_rxmax, e->e_cfg->ec_txmax);
  310: 	} else {
  311: 		e->e_rx_usage = FLT_MAX;
  312: 		e->e_tx_usage = FLT_MAX;
  313: 	}
  314: }
  315: 
  316: void element_lifesign(struct element *e, int n)
  317: {
  318: 	e->e_lifecycles = n * get_lifecycles();
  319: }
  320: 
  321: void element_check_if_dead(struct element_group *g,
  322: 			   struct element *e, void *arg)
  323: {
  324: 	if (--(e->e_lifecycles) <= 0) {
  325: 		element_free(e);
  326: 		DBG("Deleting dead element %s", e->e_name);
  327: 	}
  328: }
  329: 
  330: void element_foreach_attr(struct element *e,
  331: 			  void (*cb)(struct element *e,
  332: 			  	     struct attr *, void *),
  333: 			  void *arg)
  334: {
  335: 	struct attr *a;
  336: 
  337: 	list_for_each_entry(a, &e->e_attr_sorted, a_sort_list)
  338: 		cb(e, a, arg);
  339: }
  340: 
  341: int element_set_key_attr(struct element *e, const char *major,
  342: 			  const char * minor)
  343: {
  344: 	if (!(e->e_key_attr[GT_MAJOR] = attr_def_lookup(major)))
  345: 		return -ENOENT;
  346: 
  347: 	if (!(e->e_key_attr[GT_MINOR] = attr_def_lookup(minor)))
  348: 		return -ENOENT;
  349: 
  350: 	return 0;
  351: }
  352: 
  353: int element_set_usage_attr(struct element *e, const char *usage)
  354: {
  355: 	if (!(e->e_usage_attr = attr_def_lookup(usage)))
  356: 		return -ENOENT;
  357: 
  358: 	return 0;
  359: }
  360: 
  361: void element_pick_from_policy(struct element_group *g)
  362: {
  363: 	if (!list_empty(&allowed)) {
  364: 		struct policy *p;
  365: 
  366: 		list_for_each_entry(p, &allowed, p_list) {
  367: 			struct element *e;
  368: 
  369: 			list_for_each_entry(e, &g->g_elements, e_list) {
  370: 				if (match_mask(p, e->e_name)) {
  371: 					g->g_current = e;
  372: 					return;
  373: 				}
  374: 			}
  375: 		}
  376: 	}
  377: 
  378: 	element_select_first();
  379: }
  380: 
  381: struct element *element_current(void)
  382: {
  383: 	struct element_group *g;
  384: 
  385: 	if (!(g = group_current()))
  386: 		return NULL;
  387: 
  388: 	/*
  389: 	 * If no element is picked yet, pick a default interface according to
  390: 	 * the selection policy.
  391: 	 */
  392: 	if (!g->g_current)
  393: 		element_pick_from_policy(g);
  394: 
  395: 	return g->g_current;
  396: }
  397: 
  398: struct element *element_select_first(void)
  399: {
  400: 	struct element_group *g;
  401: 
  402: 	if (!(g = group_current()))
  403: 		return NULL;
  404: 
  405: 	if (list_empty(&g->g_elements))
  406: 		g->g_current = NULL;
  407: 	else
  408: 		g->g_current = list_first_entry(&g->g_elements,
  409: 						struct element, e_list);
  410: 
  411: 	return g->g_current;
  412: }
  413: 
  414: struct element *element_select_last(void)
  415: {
  416: 	struct element_group *g;
  417: 
  418: 	if (!(g = group_current()))
  419: 		return NULL;
  420: 
  421: 	if (list_empty(&g->g_elements))
  422: 		g->g_current = NULL;
  423: 	else {
  424: 		struct element *e;
  425: 
  426: 		e = list_entry(g->g_elements.prev, struct element, e_list);
  427: 
  428: 		while (!list_empty(&e->e_childs))
  429: 			e = list_entry(e->e_childs.prev, struct element,
  430: 				       e_list);
  431: 
  432: 		g->g_current = e;
  433: 	}
  434: 
  435: 	return g->g_current;
  436: }
  437: 
  438: struct element *element_select_next(void)
  439: {
  440: 	struct element_group *g;
  441: 	struct element *e;
  442: 
  443: 	if (!(g = group_current()))
  444: 		return NULL;
  445: 
  446: 	if (!(e = g->g_current))
  447: 		return element_select_first();
  448: 
  449: 	if (!list_empty(&e->e_childs))
  450: 		e = list_first_entry(&e->e_childs, struct element, e_list);
  451: 	else {
  452: 		/*
  453: 		 * move upwards until we have no parent or there is a next
  454: 		 * entry in the list
  455: 		 */
  456: 		while (e->e_parent && e->e_list.next == &e->e_parent->e_childs)
  457: 			e = e->e_parent;
  458: 
  459: 		if (!e->e_parent && e->e_list.next == &g->g_elements) {
  460: 			group_select_next();
  461: 			return element_select_first();
  462: 		} else
  463: 			e = list_entry(e->e_list.next, struct element, e_list);
  464: 	}
  465: 
  466: 	g->g_current = e;
  467: 
  468: 	return e;
  469: }
  470: 
  471: struct element *element_select_prev(void)
  472: {
  473: 	struct element_group *g;
  474: 	struct element *e;
  475: 
  476: 	if (!(g = group_current()))
  477: 		return NULL;
  478: 
  479: 	if (!(e = g->g_current))
  480: 		return element_select_last();
  481: 
  482: 	if (!e->e_parent && e->e_list.prev == &g->g_elements) {
  483: 		group_select_prev();
  484: 		return element_select_last();
  485: 	}
  486: 
  487: 	if (e->e_parent && e->e_list.prev == &e->e_parent->e_childs)
  488: 		e = e->e_parent;
  489: 	else {
  490: 		e = list_entry(e->e_list.prev, struct element, e_list);
  491: 
  492: 		while (!list_empty(&e->e_childs))
  493: 			e = list_entry(e->e_childs.prev, struct element,
  494: 				       e_list);
  495: 	}
  496: 
  497: 	g->g_current = e;
  498: 
  499: 	return e;
  500: }
  501: 
  502: static struct info *element_info_lookup(struct element *e, const char *name)
  503: {
  504: 	struct info *i;
  505: 
  506: 	list_for_each_entry(i, &e->e_info_list, i_list)
  507: 		if (!strcmp(i->i_name, name))
  508: 			return i;
  509: 
  510: 	return NULL;
  511: }
  512: 
  513: void element_update_info(struct element *e, const char *name, const char *value)
  514: {
  515: 	struct info *i;
  516: 
  517: 	if ((i = element_info_lookup(e, name))) {
  518: 		xfree(i->i_value);
  519: 		i->i_value = strdup(value);
  520: 		return;
  521: 	}
  522: 
  523: 	DBG("Created element info %s (\"%s\")", name, value);
  524: 
  525: 	i = xcalloc(1, sizeof(*i));
  526: 	i->i_name = strdup(name);
  527: 	i->i_value = strdup(value);
  528: 
  529: 	e->e_ninfo++;
  530: 
  531: 	list_add_tail(&i->i_list, &e->e_info_list);
  532: }
  533: 
  534: void element_set_txmax(struct element *e, uint64_t max)
  535: {
  536: 	char buf[32];
  537: 
  538: 	if (!e->e_cfg)
  539: 		e->e_cfg = element_cfg_create(e->e_name);
  540: 
  541: 	if (e->e_cfg->ec_txmax != max)
  542: 		e->e_cfg->ec_txmax = max;
  543: 
  544: 	unit_bit2str(e->e_cfg->ec_txmax * 8, buf, sizeof(buf));
  545: 	element_update_info(e, "TxMax", buf);
  546: }
  547: 
  548: void element_set_rxmax(struct element *e, uint64_t max)
  549: {
  550: 	char buf[32];
  551: 
  552: 	if (!e->e_cfg)
  553: 		e->e_cfg = element_cfg_create(e->e_name);
  554: 
  555: 	if (e->e_cfg->ec_rxmax != max)
  556: 		e->e_cfg->ec_rxmax = max;
  557: 
  558: 	unit_bit2str(e->e_cfg->ec_rxmax * 8, buf, sizeof(buf));
  559: 	element_update_info(e, "RxMax", buf);
  560: }

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