--- embedaddon/bmon/src/utils.c 2012/02/21 22:19:56 1.1 +++ embedaddon/bmon/src/utils.c 2019/10/21 14:58:35 1.1.1.3 @@ -1,7 +1,8 @@ /* * utils.c General purpose utilities * - * Copyright (c) 2001-2005 Thomas Graf + * Copyright (c) 2001-2013 Thomas Graf + * Copyright (c) 2013 Red Hat, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -26,7 +27,12 @@ #include #include -void * xcalloc(size_t n, size_t s) +#ifdef __MACH__ +#include +#include +#endif + +void *xcalloc(size_t n, size_t s) { void *d = calloc(n, s); @@ -38,7 +44,7 @@ void * xcalloc(size_t n, size_t s) return d; } -void * xrealloc(void *p, size_t s) +void *xrealloc(void *p, size_t s) { void *d = realloc(p, s); @@ -56,18 +62,23 @@ void xfree(void *d) free(d); } -inline float ts_to_float(timestamp_t *src) +float timestamp_to_float(timestamp_t *src) { return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f); } -inline void float_to_ts(timestamp_t *dst, float src) +int64_t timestamp_to_int(timestamp_t *src) { + return (src->tv_sec * 1000000ULL) + src->tv_usec; +} + +void float_to_timestamp(timestamp_t *dst, float src) +{ dst->tv_sec = (time_t) src; dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f; } -inline void ts_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2) +void timestamp_add(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2) { dst->tv_sec = src1->tv_sec + src2->tv_sec; dst->tv_usec = src1->tv_usec + src2->tv_usec; @@ -78,17 +89,17 @@ inline void ts_add(timestamp_t *dst, timestamp_t *src1 } } -inline void ts_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2) +void timestamp_sub(timestamp_t *dst, timestamp_t *src1, timestamp_t *src2) { dst->tv_sec = src1->tv_sec - src2->tv_sec; dst->tv_usec = src1->tv_usec - src2->tv_usec; - if (dst->tv_usec <= -1000000) { + if (dst->tv_usec < 0) { dst->tv_sec--; dst->tv_usec += 1000000; } } -inline int ts_le(timestamp_t *a, timestamp_t *b) +int timestamp_le(timestamp_t *a, timestamp_t *b) { if (a->tv_sec > b->tv_sec) return 0; @@ -99,102 +110,57 @@ inline int ts_le(timestamp_t *a, timestamp_t *b) return 0; } -inline void update_ts(timestamp_t *dst) +int timestamp_is_negative(timestamp_t *ts) { - struct timeval tv; - - gettimeofday(&tv, NULL); - - dst->tv_sec = tv.tv_sec; - dst->tv_usec = tv.tv_usec; + return (ts->tv_sec < 0 || ts->tv_usec < 0); } - -float time_diff(timestamp_t *t1, timestamp_t *t2) +void update_timestamp(timestamp_t *dst) { - timestamp_t ts; - ts_sub(&ts, t2, t1); - return ts_to_float(&ts); -} +#ifdef __MACH__ + clock_serv_t cclock; + mach_timespec_t tp; -float diff_now(timestamp_t *t1) -{ - timestamp_t now; - update_ts(&now); - return time_diff(t1, &now); -} + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &tp); + mach_port_deallocate(mach_task_self(), cclock); +#else + struct timespec tp; -static inline b_cnt_t __divisor(int type, int exp) -{ - static b_cnt_t cache[2][32]; + clock_gettime(CLOCK_MONOTONIC, &tp); +#endif - if (exp) { - if (!cache[get_use_si()][exp]) { - cache[get_use_si()][exp] = - (b_cnt_t) pow(get_use_si() || - type == U_NUMBER ? 1000.0f : 1024.0f, exp); - } - return cache[get_use_si()][exp]; - } else - return 1; + dst->tv_sec = tp.tv_sec; + dst->tv_usec = tp.tv_nsec / 1000; } -static inline char * __unit(int type, int exp) +void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2) { - static char *u[2][3][32] = { - [0] = { /* IEC */ - [U_BITS] = { " b ", "Kib", "Mib", "Gib", "Tib" }, - [U_BYTES] = { " B ", "KiB", "MiB", "GiB", "TiB" }, - [U_NUMBER] = { " ", "K", "M", "G", "T" }, - }, - [1] = { /* SI */ - [U_BITS] = { " b", "Kb ", "Mb ", "Gb ", "Tb " }, - [U_BYTES] = { " B ", "KB ", "MB ", "GB ", "TB " }, - [U_NUMBER] = { " ", "K", "M", "G", "T" }, - } - }; - - return u[get_use_si()][type][exp]; - + ts1->tv_sec = ts2->tv_sec; + ts1->tv_usec = ts2->tv_usec; } -b_cnt_t get_divisor(b_cnt_t hint, int unit, char **dst_unit, int *prec) +float timestamp_diff(timestamp_t *t1, timestamp_t *t2) { - int yunit = get_y_unit(); + float diff; - if (prec) - *prec = 2; + diff = t2->tv_sec - t1->tv_sec; + diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f); - if (yunit == Y_DYNAMIC) { - if (hint >= __divisor(unit, 3)) { - *dst_unit = __unit(unit, 3); - return __divisor(unit, 3); - } else if (hint >= __divisor(unit, 2)) { - *dst_unit = __unit(unit, 2); - return __divisor(unit, 2); - } else if (hint >= __divisor(unit, 1)) { - *dst_unit = __unit(unit, 1); - return __divisor(unit, 1); - } else { - *dst_unit = __unit(unit, 0); - if (prec) - *prec = 0; - return 1; - } - } else { - *dst_unit = __unit(unit, yunit); - return __divisor(unit, yunit); - } - - return 1; + return diff; } -double cancel_down(b_cnt_t l, int unit, char **dst_unit, int *prec) +#if 0 + + +float diff_now(timestamp_t *t1) { - return ((double) l / (double) get_divisor(l, unit, dst_unit, prec)); + timestamp_t now; + update_ts(&now); + return time_diff(t1, &now); } -const char * xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt) +const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt) { void *s; int family; @@ -211,10 +177,10 @@ const char * xinet_ntop(struct sockaddr *src, char *ds return inet_ntop(family, s, dst, cnt); } -b_cnt_t parse_size(const char *str) +uint64_t parse_size(const char *str) { char *p; - b_cnt_t l = strtol(str, &p, 0); + uint64_t l = strtol(str, &p, 0); if (p == str) return -1; @@ -244,5 +210,226 @@ char *strdup(const char *s) char *t = xcalloc(1, strlen(s) + 1); memcpy(t, s, strlen(s)); return s; +} +#endif + +char *timestamp2str(timestamp_t *ts, char *buf, size_t len) +{ + int i, split[5]; + char *units[] = {"d", "h", "m", "s", "usec"}; + time_t sec = ts->tv_sec; + +#define _SPLIT(idx, unit) if ((split[idx] = sec / unit) > 0) sec %= unit + _SPLIT(0, 86400); /* days */ + _SPLIT(1, 3600); /* hours */ + _SPLIT(2, 60); /* minutes */ + _SPLIT(3, 1); /* seconds */ +#undef _SPLIT + split[4] = ts->tv_usec; + + memset(buf, 0, len); + + for (i = 0; i < ARRAY_SIZE(split); i++) { + if (split[i] > 0) { + char t[64]; + snprintf(t, sizeof(t), "%s%d%s", + strlen(buf) ? " " : "", split[i], units[i]); + strncat(buf, t, len - strlen(buf) - 1); + } + } + + return buf; +} + +int parse_date(const char *str, xdate_t *dst) +{ + time_t now = time(NULL); + struct tm *now_tm = localtime(&now); + const char *next; + char *p; + struct tm backup; + + memset(dst, 0, sizeof(*dst)); + + if (strchr(str, '-')) { + next = strptime(str, "%Y-%m-%d", &dst->d_tm); + if (next == NULL || + (*next != '\0' && *next != ' ')) + goto invalid_date; + } else { + dst->d_tm.tm_mday = now_tm->tm_mday; + dst->d_tm.tm_mon = now_tm->tm_mon; + dst->d_tm.tm_year = now_tm->tm_year; + dst->d_tm.tm_wday = now_tm->tm_wday; + dst->d_tm.tm_yday = now_tm->tm_yday; + dst->d_tm.tm_isdst = now_tm->tm_isdst; + next = str; + } + + if (*next == '\0') + return 0; + + while (*next == ' ') + next++; + + if (*next == '.') + goto read_us; + + /* Make a backup, we can't rely on strptime to not screw + * up what we've got so far. */ + memset(&backup, 0, sizeof(backup)); + memcpy(&backup, &dst->d_tm, sizeof(backup)); + + next = strptime(next, "%H:%M:%S", &dst->d_tm); + if (next == NULL || + (*next != '\0' && *next != '.')) + goto invalid_date; + + dst->d_tm.tm_mday = backup.tm_mday; + dst->d_tm.tm_mon = backup.tm_mon; + dst->d_tm.tm_year = backup.tm_year; + dst->d_tm.tm_wday = backup.tm_wday; + dst->d_tm.tm_yday = backup.tm_yday; + dst->d_tm.tm_isdst = backup.tm_isdst; + + if (*next == '\0') + return 0; +read_us: + if (*next == '.') + next++; + else + BUG(); + + dst->d_usec = strtoul(next, &p, 10); + + if (*p != '\0') + goto invalid_date; + + return 0; + +invalid_date: + fprintf(stderr, "Invalid date \"%s\"\n", str); + return -1; +} + +static inline void print_token(FILE *fd, struct db_token *tok) +{ + fprintf(fd, "%s", tok->t_name); + + if (tok->t_flags & DB_T_ATTR) + fprintf(fd, ""); +} + +void db_print_filter(FILE *fd, struct db_filter *filter) +{ + if (filter->f_node) + print_token(fd, filter->f_node); + + if (filter->f_group) { + fprintf(fd, "."); + print_token(fd, filter->f_group); + } + + if (filter->f_item) { + fprintf(fd, "."); + print_token(fd, filter->f_item); + } + + if (filter->f_attr) { + fprintf(fd, "."); + print_token(fd, filter->f_attr); + } + + if (filter->f_field) + fprintf(fd, "@%s", filter->f_field); +} + +void *db_filter__scan_string(const char *); +void db_filter__switch_to_buffer(void *); +int db_filter_parse(void); + +struct db_filter * parse_db_filter(const char *buf) +{ + struct db_filter *f; + struct db_token *tok, *t; + + void *state = db_filter__scan_string(buf); + db_filter__switch_to_buffer(state); + + if (db_filter_parse()) { + fprintf(stderr, "Failed to parse filter \"%s\"\n", buf); + return NULL; + } + + tok = db_filter_out; /* generated by yacc */ + if (tok == NULL) + return NULL; + + f = xcalloc(1, sizeof(*f)); + + f->f_node = tok; + + if (!tok->t_next) + goto out; + tok = tok->t_next; + + if (tok->t_flags & DB_T_ATTR) { + fprintf(stderr, "Node may not contain an attribute field\n"); + goto errout; + } + + f->f_group = tok; + if (!tok->t_next) + goto out; + tok = tok->t_next; + + if (tok->t_flags & DB_T_ATTR) { + fprintf(stderr, "Group may not contain an attribute field\n"); + goto errout; + } + + f->f_item = tok; + + if (!tok->t_next) + goto out; + tok = tok->t_next; + + if (tok->t_flags & DB_T_ATTR) { + if (!tok->t_name) + BUG(); + f->f_field = tok->t_name; + goto out; + } else + f->f_attr = tok; + + if (!tok->t_next) + goto out; + tok = tok->t_next; + + if (tok->t_flags & DB_T_ATTR) { + if (!tok->t_name) + BUG(); + f->f_field = tok->t_name; + } else { + fprintf(stderr, "Unexpected additional token after attribute\n"); + goto errout; + } + +out: + /* free unused tokens */ + for (tok = tok->t_next ; tok; tok = t) { + t = tok->t_next; + if (tok->t_name) + free(tok->t_name); + free(tok); + } + + return f; + +errout: + free(f); + f = NULL; + tok = db_filter_out; + goto out; } #endif