1: /*
2: * node.c node handling
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:
25: #include <bmon/bmon.h>
26: #include <bmon/node.h>
27: #include <bmon/item.h>
28: #include <bmon/utils.h>
29:
30: static node_t *nodes;
31: static size_t nodes_size;
32: static size_t nnodes;
33: static const char * node_name;
34: static node_t *local_node;
35: static node_t *current_node;
36:
37:
38: node_t * lookup_node(const char *name, int creat)
39: {
40: int i;
41:
42: if (NULL == nodes) {
43: nodes_size = 32;
44: nodes = xcalloc(nodes_size, sizeof(node_t));
45: }
46:
47: for (i = 0; i < nodes_size; i++)
48: if (nodes[i].n_name && !strcmp(name, nodes[i].n_name))
49: return &nodes[i];
50:
51: if (creat) {
52: for (i = 0; i < nodes_size; i++)
53: if (NULL == nodes[i].n_name)
54: break;
55:
56: while (i >= nodes_size) {
57: int oldsize = nodes_size;
58: nodes_size += 32;
59: nodes = xrealloc(nodes, nodes_size * sizeof(node_t));
60: memset((uint8_t *) nodes + oldsize, 0, (nodes_size - oldsize) * sizeof(node_t));
61: }
62:
63: nodes[i].n_name = strdup(name);
64: nodes[i].n_index = i;
65: nnodes++;
66: return &nodes[i];
67: }
68:
69: return NULL;
70: }
71:
72: void foreach_node(void (*cb)(node_t *, void *), void *arg)
73: {
74: int i;
75:
76: for (i = 0; i < nnodes; i++)
77: cb(&nodes[i], arg);
78: }
79:
80: void foreach_item(node_t *n, void (*cb)(item_t *, void *), void *arg)
81: {
82: int i;
83:
84: for (i = 0; i < n->n_nitems; i++)
85: if (n->n_items[i].i_name[0])
86: cb(&n->n_items[i], arg);
87: }
88:
89:
90: void foreach_node_item(void (*cb)(node_t *, item_t *, void *), void *arg)
91: {
92: int i, m;
93:
94: for (i = 0; i < nnodes; i++) {
95: node_t *n = &nodes[i];
96:
97: for (m = 0; m < n->n_nitems; m++)
98: if (n->n_items[m].i_name[0])
99: cb(n, &n->n_items[m], arg);
100: }
101: }
102:
103:
104: static void __reset_item(node_t *n, item_t *i, void *arg)
105: {
106: reset_item(i);
107: }
108:
109: void reset_nodes(void)
110: {
111: foreach_node_item(__reset_item, NULL);
112: }
113:
114: static void __remove_unused_item(node_t *n, item_t *i, void *arg)
115: {
116: remove_unused_items(i);
117: }
118:
119: void remove_unused_node_items(void)
120: {
121: foreach_node_item(__remove_unused_item, NULL);
122: }
123:
124:
125:
126: node_t * get_local_node(void)
127: {
128: if (NULL == local_node)
129: local_node = lookup_node(node_name, 1);
130:
131: return local_node;
132: }
133:
134: int get_nnodes(void)
135: {
136: return nnodes;
137: }
138:
139: static void get_node_info(void)
140: {
141: struct utsname uts;
142:
143: if (uname(&uts) < 0)
144: quit("utsname failed: %s\n", strerror(errno));
145:
146: node_name = strdup(uts.nodename);
147: }
148:
149: void calc_node_rate(node_t *node)
150: {
151: int i;
152:
153: node->n_rx_maj_total = 0;
154: node->n_tx_maj_total = 0;
155: node->n_rx_min_total = 0;
156: node->n_tx_min_total = 0;
157:
158: for (i = 0; i < node->n_nitems; i++) {
159: item_t *it = &node->n_items[i];
160: if (it->i_name[0] &&
161: it->i_level == 0 &&
162: !(it->i_flags & ITEM_FLAG_EXCLUDE)) {
163: stat_attr_t *maj = lookup_attr(it, it->i_major_attr);
164: stat_attr_t *min = lookup_attr(it, it->i_minor_attr);
165:
166: if (maj) {
167: node->n_rx_maj_total += attr_get_rx_rate(maj);
168: node->n_tx_maj_total += attr_get_tx_rate(maj);
169: }
170:
171: if (min) {
172: node->n_rx_min_total += attr_get_rx_rate(min);
173: node->n_tx_min_total += attr_get_tx_rate(min);
174: }
175:
176: }
177: }
178: }
179:
180: void calc_node_rates(void)
181: {
182: int i;
183:
184: for (i = 0; i < nnodes; i++)
185: calc_node_rate(&nodes[i]);
186: }
187:
188: node_t * get_current_node(void)
189: {
190: return current_node;
191: }
192:
193: int first_node(void)
194: {
195: int i;
196:
197: if (nnodes <= 0)
198: return EMPTY_LIST;
199:
200: for (i = 0; i < nnodes; i++) {
201: if (nodes[i].n_name) {
202: current_node = &nodes[i];
203: return 0;
204: }
205: }
206:
207: return EMPTY_LIST;
208: }
209:
210: int last_node(void)
211: {
212: int i;
213:
214: if (nnodes <= 0)
215: return EMPTY_LIST;
216:
217: for (i = (nnodes - 1); i >= 0; i--) {
218: if (nodes[i].n_name) {
219: current_node = &nodes[i];
220: return 0;
221: }
222: }
223:
224: return EMPTY_LIST;
225: }
226:
227:
228: int prev_node(void)
229: {
230: if (nnodes <= 0)
231: return EMPTY_LIST;
232:
233: if (current_node == NULL)
234: return first_node();
235: else {
236: int i;
237: for (i = (current_node->n_index - 1); i >= 0; i--) {
238: if (nodes[i].n_name) {
239: current_node = &nodes[i];
240: return 0;
241: }
242: }
243: return END_OF_LIST;
244: }
245:
246: return EMPTY_LIST;
247: }
248:
249: int next_node(void)
250: {
251: if (nnodes <= 0)
252: return EMPTY_LIST;
253:
254: if (current_node == NULL)
255: return first_node();
256: else {
257: int i;
258: for (i = (current_node->n_index + 1); i < nnodes; i++) {
259: if (nodes[i].n_name) {
260: current_node = &nodes[i];
261: return 0;
262: }
263: }
264: return END_OF_LIST;
265: }
266:
267: return EMPTY_LIST;
268: }
269:
270: item_t * get_current_item(void)
271: {
272: if (current_node) {
273: if (current_node->n_selected < current_node->n_nitems &&
274: current_node->n_selected >= 0) {
275: item_t *i = &(current_node->n_items[current_node->n_selected]);
276:
277: if (i->i_name[0])
278: return i;
279: }
280: }
281: return NULL;
282: }
283:
284: int first_item(void)
285: {
286: int i;
287:
288: if (current_node == NULL)
289: return EMPTY_LIST;
290:
291: if (current_node->n_nitems <= 0)
292: return EMPTY_LIST;
293:
294: for (i = 0; i < current_node->n_nitems; i++) {
295: if (current_node->n_items[i].i_name[0]) {
296: current_node->n_selected = i;
297: return 0;
298: }
299: }
300:
301: return EMPTY_LIST;
302: }
303:
304: int last_item(void)
305: {
306: int i;
307:
308: if (current_node == NULL)
309: return EMPTY_LIST;
310:
311: if (current_node->n_nitems <= 0)
312: return EMPTY_LIST;
313:
314: for (i = (current_node->n_nitems - 1); i >= 0; i--) {
315: if (current_node->n_items[i].i_name[0]) {
316: current_node->n_selected = i;
317: return 0;
318: }
319: }
320:
321: return EMPTY_LIST;
322: }
323:
324: int goto_item(int num)
325: {
326: if (current_node == NULL)
327: return EMPTY_LIST;
328:
329: if (current_node->n_nitems <= 0)
330: return EMPTY_LIST;
331:
332: if (num < current_node->n_nitems && num >= 0)
333: if (current_node->n_items[num].i_name[0])
334: current_node->n_selected = num;
335:
336: return 0;
337: }
338:
339: int next_item(void)
340: {
341: if (current_node == NULL)
342: return EMPTY_LIST;
343:
344: if (current_node->n_nitems <= 0)
345: return EMPTY_LIST;
346:
347: if (current_node->n_selected < 0 ||
348: current_node->n_selected >= current_node->n_nitems)
349: return last_item();
350: else {
351: int i;
352: node_t *cn = current_node;
353:
354: for (i = (cn->n_selected + 1); i < cn->n_nitems; i++) {
355: if (!cn->n_items[i].i_name[0])
356: continue;
357:
358: if (cn->n_items[i].i_flags & ITEM_FLAG_IS_CHILD) {
359: item_t *fi = get_item(cn, cn->n_items[i].i_link);
360:
361: if (fi->i_flags & ITEM_FLAG_FOLDED)
362: continue;
363: }
364:
365: cn->n_selected = i;
366: return 0;
367: }
368:
369: return END_OF_LIST;
370: }
371:
372: return EMPTY_LIST;
373: }
374:
375: int prev_item(void)
376: {
377: if (current_node == NULL)
378: return EMPTY_LIST;
379:
380: if (current_node->n_nitems <= 0)
381: return EMPTY_LIST;
382:
383: if (current_node->n_selected < 0 ||
384: current_node->n_selected >= current_node->n_nitems)
385: return first_item();
386: else {
387: int i;
388: node_t *cn = current_node;
389:
390: for (i = (cn->n_selected - 1); i >= 0; i--) {
391: if (!cn->n_items[i].i_name[0])
392: continue;
393:
394: if (cn->n_items[i].i_flags & ITEM_FLAG_IS_CHILD) {
395: item_t *fi = get_item(cn, cn->n_items[i].i_link);
396:
397: if (fi->i_flags & ITEM_FLAG_FOLDED)
398: continue;
399: }
400:
401: cn->n_selected = i;
402: return 0;
403: }
404:
405: return END_OF_LIST;
406: }
407:
408: return EMPTY_LIST;
409: }
410:
411: static void __init node_init(void)
412: {
413: get_node_info();
414: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>