Annotation of embedaddon/bmon/src/utils.c, revision 1.1.1.3
1.1 misho 1: /*
2: * utils.c General purpose utilities
3: *
1.1.1.2 misho 4: * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
5: * Copyright (c) 2013 Red Hat, Inc.
1.1 misho 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/utils.h>
29:
1.1.1.3 ! misho 30: #ifdef __MACH__
! 31: #include <mach/clock.h>
! 32: #include <mach/mach.h>
! 33: #endif
! 34:
1.1.1.2 misho 35: void *xcalloc(size_t n, size_t s)
1.1 misho 36: {
37: void *d = calloc(n, s);
38:
39: if (NULL == d) {
40: fprintf(stderr, "xalloc: Out of memory\n");
41: exit(ENOMEM);
42: }
43:
44: return d;
45: }
46:
1.1.1.2 misho 47: void *xrealloc(void *p, size_t s)
1.1 misho 48: {
49: void *d = realloc(p, s);
50:
51: if (NULL == d) {
52: fprintf(stderr, "xrealloc: Out of memory!\n");
53: exit(ENOMEM);
54: }
55:
56: return d;
57: }
58:
59: void xfree(void *d)
60: {
61: if (d)
62: free(d);
63: }
64:
1.1.1.2 misho 65: float timestamp_to_float(timestamp_t *src)
1.1 misho 66: {
67: return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f);
68: }
69:
1.1.1.2 misho 70: int64_t timestamp_to_int(timestamp_t *src)
71: {
72: return (src->tv_sec * 1000000ULL) + src->tv_usec;
73: }
74:
75: void float_to_timestamp(timestamp_t *dst, float src)
1.1 misho 76: {
77: dst->tv_sec = (time_t) src;
78: dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f;
79: }
80:
1.1.1.2 misho 81: void timestamp_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
1.1 misho 82: {
83: dst->tv_sec = src1->tv_sec + src2->tv_sec;
84: dst->tv_usec = src1->tv_usec + src2->tv_usec;
85:
86: if (dst->tv_usec >= 1000000) {
87: dst->tv_sec++;
88: dst->tv_usec -= 1000000;
89: }
90: }
91:
1.1.1.2 misho 92: void timestamp_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2)
1.1 misho 93: {
94: dst->tv_sec = src1->tv_sec - src2->tv_sec;
95: dst->tv_usec = src1->tv_usec - src2->tv_usec;
1.1.1.2 misho 96: if (dst->tv_usec < 0) {
1.1 misho 97: dst->tv_sec--;
98: dst->tv_usec += 1000000;
99: }
100: }
101:
1.1.1.2 misho 102: int timestamp_le(timestamp_t *a, timestamp_t *b)
1.1 misho 103: {
104: if (a->tv_sec > b->tv_sec)
105: return 0;
106:
107: if (a->tv_sec < b->tv_sec || a->tv_usec <= b->tv_usec)
108: return 1;
109:
110: return 0;
111: }
112:
1.1.1.2 misho 113: int timestamp_is_negative(timestamp_t *ts)
114: {
115: return (ts->tv_sec < 0 || ts->tv_usec < 0);
116: }
117:
118: void update_timestamp(timestamp_t *dst)
1.1 misho 119: {
1.1.1.3 ! misho 120: #ifdef __MACH__
! 121: clock_serv_t cclock;
! 122: mach_timespec_t tp;
! 123:
! 124: host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock);
! 125: clock_get_time(cclock, &tp);
! 126: mach_port_deallocate(mach_task_self(), cclock);
! 127: #else
! 128: struct timespec tp;
1.1 misho 129:
1.1.1.3 ! misho 130: clock_gettime(CLOCK_MONOTONIC, &tp);
! 131: #endif
1.1 misho 132:
1.1.1.3 ! misho 133: dst->tv_sec = tp.tv_sec;
! 134: dst->tv_usec = tp.tv_nsec / 1000;
1.1 misho 135: }
136:
1.1.1.2 misho 137: void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2)
1.1 misho 138: {
1.1.1.2 misho 139: ts1->tv_sec = ts2->tv_sec;
1.1.1.3 ! misho 140: ts1->tv_usec = ts2->tv_usec;
1.1 misho 141: }
142:
1.1.1.2 misho 143: float timestamp_diff(timestamp_t *t1, timestamp_t *t2)
1.1 misho 144: {
1.1.1.2 misho 145: float diff;
1.1 misho 146:
1.1.1.2 misho 147: diff = t2->tv_sec - t1->tv_sec;
148: diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f);
1.1 misho 149:
1.1.1.2 misho 150: return diff;
1.1 misho 151: }
152:
1.1.1.2 misho 153: #if 0
1.1 misho 154:
155:
1.1.1.2 misho 156: float diff_now(timestamp_t *t1)
1.1 misho 157: {
1.1.1.2 misho 158: timestamp_t now;
159: update_ts(&now);
160: return time_diff(t1, &now);
1.1 misho 161: }
162:
1.1.1.2 misho 163: const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt)
1.1 misho 164: {
165: void *s;
166: int family;
167:
168: if (src->sa_family == AF_INET6) {
169: s = &((struct sockaddr_in6 *) src)->sin6_addr;
170: family = AF_INET6;
171: } else if (src->sa_family == AF_INET) {
172: s = &((struct sockaddr_in *) src)->sin_addr;
173: family = AF_INET;
174: } else
175: return NULL;
176:
177: return inet_ntop(family, s, dst, cnt);
178: }
179:
1.1.1.2 misho 180: uint64_t parse_size(const char *str)
1.1 misho 181: {
182: char *p;
1.1.1.2 misho 183: uint64_t l = strtol(str, &p, 0);
1.1 misho 184: if (p == str)
185: return -1;
186:
187: if (*p) {
188: if (!strcasecmp(p, "kb") || !strcasecmp(p, "k"))
189: l *= 1024;
190: else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g"))
191: l *= 1024*1024*1024;
192: else if (!strcasecmp(p, "gbit"))
193: l *= 1024*1024*1024/8;
194: else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m"))
195: l *= 1024*1024;
196: else if (!strcasecmp(p, "mbit"))
197: l *= 1024*1024/8;
198: else if (!strcasecmp(p, "kbit"))
199: l *= 1024/8;
200: else if (strcasecmp(p, "b") != 0)
201: return -1;
202: }
203:
204: return l;
205: }
206:
207: #ifndef HAVE_STRDUP
208: char *strdup(const char *s)
209: {
210: char *t = xcalloc(1, strlen(s) + 1);
211: memcpy(t, s, strlen(s));
212: return s;
213: }
214: #endif
1.1.1.2 misho 215:
216: char *timestamp2str(timestamp_t *ts, char *buf, size_t len)
217: {
218: int i, split[5];
219: char *units[] = {"d", "h", "m", "s", "usec"};
220: time_t sec = ts->tv_sec;
221:
222: #define _SPLIT(idx, unit) if ((split[idx] = sec / unit) > 0) sec %= unit
223: _SPLIT(0, 86400); /* days */
224: _SPLIT(1, 3600); /* hours */
225: _SPLIT(2, 60); /* minutes */
226: _SPLIT(3, 1); /* seconds */
227: #undef _SPLIT
228: split[4] = ts->tv_usec;
229:
230: memset(buf, 0, len);
231:
232: for (i = 0; i < ARRAY_SIZE(split); i++) {
233: if (split[i] > 0) {
234: char t[64];
235: snprintf(t, sizeof(t), "%s%d%s",
236: strlen(buf) ? " " : "", split[i], units[i]);
237: strncat(buf, t, len - strlen(buf) - 1);
238: }
239: }
240:
241: return buf;
242: }
243:
244: int parse_date(const char *str, xdate_t *dst)
245: {
246: time_t now = time(NULL);
247: struct tm *now_tm = localtime(&now);
248: const char *next;
249: char *p;
250: struct tm backup;
251:
252: memset(dst, 0, sizeof(*dst));
253:
254: if (strchr(str, '-')) {
255: next = strptime(str, "%Y-%m-%d", &dst->d_tm);
256: if (next == NULL ||
257: (*next != '\0' && *next != ' '))
258: goto invalid_date;
259: } else {
260: dst->d_tm.tm_mday = now_tm->tm_mday;
261: dst->d_tm.tm_mon = now_tm->tm_mon;
262: dst->d_tm.tm_year = now_tm->tm_year;
263: dst->d_tm.tm_wday = now_tm->tm_wday;
264: dst->d_tm.tm_yday = now_tm->tm_yday;
265: dst->d_tm.tm_isdst = now_tm->tm_isdst;
266: next = str;
267: }
268:
269: if (*next == '\0')
270: return 0;
271:
272: while (*next == ' ')
273: next++;
274:
275: if (*next == '.')
276: goto read_us;
277:
278: /* Make a backup, we can't rely on strptime to not screw
279: * up what we've got so far. */
280: memset(&backup, 0, sizeof(backup));
281: memcpy(&backup, &dst->d_tm, sizeof(backup));
282:
283: next = strptime(next, "%H:%M:%S", &dst->d_tm);
284: if (next == NULL ||
285: (*next != '\0' && *next != '.'))
286: goto invalid_date;
287:
288: dst->d_tm.tm_mday = backup.tm_mday;
289: dst->d_tm.tm_mon = backup.tm_mon;
290: dst->d_tm.tm_year = backup.tm_year;
291: dst->d_tm.tm_wday = backup.tm_wday;
292: dst->d_tm.tm_yday = backup.tm_yday;
293: dst->d_tm.tm_isdst = backup.tm_isdst;
294:
295: if (*next == '\0')
296: return 0;
297: read_us:
298: if (*next == '.')
299: next++;
300: else
301: BUG();
302:
303: dst->d_usec = strtoul(next, &p, 10);
304:
305: if (*p != '\0')
306: goto invalid_date;
307:
308: return 0;
309:
310: invalid_date:
311: fprintf(stderr, "Invalid date \"%s\"\n", str);
312: return -1;
313: }
314:
315: static inline void print_token(FILE *fd, struct db_token *tok)
316: {
317: fprintf(fd, "%s", tok->t_name);
318:
319: if (tok->t_flags & DB_T_ATTR)
320: fprintf(fd, "<attr>");
321: }
322:
323: void db_print_filter(FILE *fd, struct db_filter *filter)
324: {
325: if (filter->f_node)
326: print_token(fd, filter->f_node);
327:
328: if (filter->f_group) {
329: fprintf(fd, ".");
330: print_token(fd, filter->f_group);
331: }
332:
333: if (filter->f_item) {
334: fprintf(fd, ".");
335: print_token(fd, filter->f_item);
336: }
337:
338: if (filter->f_attr) {
339: fprintf(fd, ".");
340: print_token(fd, filter->f_attr);
341: }
342:
343: if (filter->f_field)
344: fprintf(fd, "@%s", filter->f_field);
345: }
346:
347: void *db_filter__scan_string(const char *);
348: void db_filter__switch_to_buffer(void *);
349: int db_filter_parse(void);
350:
351: struct db_filter * parse_db_filter(const char *buf)
352: {
353: struct db_filter *f;
354: struct db_token *tok, *t;
355:
356: void *state = db_filter__scan_string(buf);
357: db_filter__switch_to_buffer(state);
358:
359: if (db_filter_parse()) {
360: fprintf(stderr, "Failed to parse filter \"%s\"\n", buf);
361: return NULL;
362: }
363:
364: tok = db_filter_out; /* generated by yacc */
365: if (tok == NULL)
366: return NULL;
367:
368: f = xcalloc(1, sizeof(*f));
369:
370: f->f_node = tok;
371:
372: if (!tok->t_next)
373: goto out;
374: tok = tok->t_next;
375:
376: if (tok->t_flags & DB_T_ATTR) {
377: fprintf(stderr, "Node may not contain an attribute field\n");
378: goto errout;
379: }
380:
381: f->f_group = tok;
382: if (!tok->t_next)
383: goto out;
384: tok = tok->t_next;
385:
386: if (tok->t_flags & DB_T_ATTR) {
387: fprintf(stderr, "Group may not contain an attribute field\n");
388: goto errout;
389: }
390:
391: f->f_item = tok;
392:
393: if (!tok->t_next)
394: goto out;
395: tok = tok->t_next;
396:
397: if (tok->t_flags & DB_T_ATTR) {
398: if (!tok->t_name)
399: BUG();
400: f->f_field = tok->t_name;
401: goto out;
402: } else
403: f->f_attr = tok;
404:
405: if (!tok->t_next)
406: goto out;
407: tok = tok->t_next;
408:
409: if (tok->t_flags & DB_T_ATTR) {
410: if (!tok->t_name)
411: BUG();
412: f->f_field = tok->t_name;
413: } else {
414: fprintf(stderr, "Unexpected additional token after attribute\n");
415: goto errout;
416: }
417:
418: out:
419: /* free unused tokens */
420: for (tok = tok->t_next ; tok; tok = t) {
421: t = tok->t_next;
422: if (tok->t_name)
423: free(tok->t_name);
424: free(tok);
425: }
426:
427: return f;
428:
429: errout:
430: free(f);
431: f = NULL;
432: tok = db_filter_out;
433: goto out;
434: }
435: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>