diff options
Diffstat (limited to 'src/utils.c')
-rw-r--r-- | src/utils.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..bf49d9f --- /dev/null +++ b/src/utils.c @@ -0,0 +1,421 @@ +/* + * utils.c General purpose utilities + * + * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch> + * 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"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <bmon/bmon.h> +#include <bmon/conf.h> +#include <bmon/utils.h> + +void *xcalloc(size_t n, size_t s) +{ + void *d = calloc(n, s); + + if (NULL == d) { + fprintf(stderr, "xalloc: Out of memory\n"); + exit(ENOMEM); + } + + return d; +} + +void *xrealloc(void *p, size_t s) +{ + void *d = realloc(p, s); + + if (NULL == d) { + fprintf(stderr, "xrealloc: Out of memory!\n"); + exit(ENOMEM); + } + + return d; +} + +void xfree(void *d) +{ + if (d) + free(d); +} + +float timestamp_to_float(timestamp_t *src) +{ + return (float) src->tv_sec + ((float) src->tv_usec / 1000000.0f); +} + +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; +} + +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; + + if (dst->tv_usec >= 1000000) { + dst->tv_sec++; + dst->tv_usec -= 1000000; + } +} + +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 < 0) { + dst->tv_sec--; + dst->tv_usec += 1000000; + } +} + +int timestamp_le(timestamp_t *a, timestamp_t *b) +{ + if (a->tv_sec > b->tv_sec) + return 0; + + if (a->tv_sec < b->tv_sec || a->tv_usec <= b->tv_usec) + return 1; + + return 0; +} + +int timestamp_is_negative(timestamp_t *ts) +{ + return (ts->tv_sec < 0 || ts->tv_usec < 0); +} + +void update_timestamp(timestamp_t *dst) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + dst->tv_sec = tv.tv_sec; + dst->tv_usec = tv.tv_usec; +} + +void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2) +{ + ts1->tv_sec = ts2->tv_sec; + ts2->tv_usec = ts2->tv_usec; +} + +float timestamp_diff(timestamp_t *t1, timestamp_t *t2) +{ + float diff; + + diff = t2->tv_sec - t1->tv_sec; + diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f); + + return diff; +} + +#if 0 + + +float diff_now(timestamp_t *t1) +{ + timestamp_t now; + update_ts(&now); + return time_diff(t1, &now); +} + +const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt) +{ + void *s; + int family; + + if (src->sa_family == AF_INET6) { + s = &((struct sockaddr_in6 *) src)->sin6_addr; + family = AF_INET6; + } else if (src->sa_family == AF_INET) { + s = &((struct sockaddr_in *) src)->sin_addr; + family = AF_INET; + } else + return NULL; + + return inet_ntop(family, s, dst, cnt); +} + +uint64_t parse_size(const char *str) +{ + char *p; + uint64_t l = strtol(str, &p, 0); + if (p == str) + return -1; + + if (*p) { + if (!strcasecmp(p, "kb") || !strcasecmp(p, "k")) + l *= 1024; + else if (!strcasecmp(p, "gb") || !strcasecmp(p, "g")) + l *= 1024*1024*1024; + else if (!strcasecmp(p, "gbit")) + l *= 1024*1024*1024/8; + else if (!strcasecmp(p, "mb") || !strcasecmp(p, "m")) + l *= 1024*1024; + else if (!strcasecmp(p, "mbit")) + l *= 1024*1024/8; + else if (!strcasecmp(p, "kbit")) + l *= 1024/8; + else if (strcasecmp(p, "b") != 0) + return -1; + } + + return l; +} + +#ifndef HAVE_STRDUP +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, "<attr>"); +} + +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 |