|
version 1.1.1.1, 2012/02/21 22:19:56
|
version 1.1.1.2, 2014/07/30 07:55:27
|
|
Line 1
|
Line 1
|
| /* |
/* |
| * utils.c General purpose utilities |
* utils.c General purpose utilities |
| * |
* |
| * Copyright (c) 2001-2005 Thomas Graf <tgraf@suug.ch> | * 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 |
* Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
* copy of this software and associated documentation files (the "Software"), |
|
Line 26
|
Line 27
|
| #include <bmon/conf.h> |
#include <bmon/conf.h> |
| #include <bmon/utils.h> |
#include <bmon/utils.h> |
| |
|
| void * xcalloc(size_t n, size_t s) | void *xcalloc(size_t n, size_t s) |
| { |
{ |
| void *d = calloc(n, s); |
void *d = calloc(n, s); |
| |
|
|
Line 38 void * xcalloc(size_t n, size_t s)
|
Line 39 void * xcalloc(size_t n, size_t s)
|
| return d; |
return d; |
| } |
} |
| |
|
| void * xrealloc(void *p, size_t s) | void *xrealloc(void *p, size_t s) |
| { |
{ |
| void *d = realloc(p, s); |
void *d = realloc(p, s); |
| |
|
|
Line 56 void xfree(void *d)
|
Line 57 void xfree(void *d)
|
| free(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); |
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_sec = (time_t) src; |
| dst->tv_usec = (src - ((float) ((time_t) src))) * 1000000.0f; |
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_sec = src1->tv_sec + src2->tv_sec; |
| dst->tv_usec = src1->tv_usec + src2->tv_usec; |
dst->tv_usec = src1->tv_usec + src2->tv_usec; |
|
Line 78 inline void ts_add(timestamp_t *dst, timestamp_t *src1
|
Line 84 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_sec = src1->tv_sec - src2->tv_sec; |
| dst->tv_usec = src1->tv_usec - src2->tv_usec; |
dst->tv_usec = src1->tv_usec - src2->tv_usec; |
| if (dst->tv_usec <= -1000000) { | if (dst->tv_usec < 0) { |
| dst->tv_sec--; |
dst->tv_sec--; |
| dst->tv_usec += 1000000; |
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) |
if (a->tv_sec > b->tv_sec) |
| return 0; |
return 0; |
|
Line 99 inline int ts_le(timestamp_t *a, timestamp_t *b)
|
Line 105 inline int ts_le(timestamp_t *a, timestamp_t *b)
|
| return 0; |
return 0; |
| } |
} |
| |
|
| inline void update_ts(timestamp_t *dst) | 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; |
struct timeval tv; |
| |
|
| gettimeofday(&tv, NULL); |
gettimeofday(&tv, NULL); |
|
Line 108 inline void update_ts(timestamp_t *dst)
|
Line 119 inline void update_ts(timestamp_t *dst)
|
| dst->tv_sec = tv.tv_sec; |
dst->tv_sec = tv.tv_sec; |
| dst->tv_usec = tv.tv_usec; |
dst->tv_usec = tv.tv_usec; |
| } |
} |
| |
|
| |
|
| float time_diff(timestamp_t *t1, timestamp_t *t2) | void copy_timestamp(timestamp_t *ts1, timestamp_t *ts2) |
| { |
{ |
| timestamp_t ts; | ts1->tv_sec = ts2->tv_sec; |
| ts_sub(&ts, t2, t1); | ts2->tv_usec = ts2->tv_usec; |
| return ts_to_float(&ts); | |
| } |
} |
| |
|
| float diff_now(timestamp_t *t1) | float timestamp_diff(timestamp_t *t1, timestamp_t *t2) |
| { |
{ |
| timestamp_t now; | float diff; |
| update_ts(&now); | |
| return time_diff(t1, &now); | |
| } | |
| |
|
| static inline b_cnt_t __divisor(int type, int exp) | diff = t2->tv_sec - t1->tv_sec; |
| { | diff += (((float) t2->tv_usec - (float) t1->tv_usec) / 1000000.0f); |
| static b_cnt_t cache[2][32]; | |
| |
|
| if (exp) { | return diff; |
| 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; | |
| } |
} |
| |
|
| static inline char * __unit(int type, int exp) | #if 0 |
| { | |
| 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]; |
|
| |
|
| } |
|
| |
|
| b_cnt_t get_divisor(b_cnt_t hint, int unit, char **dst_unit, int *prec) | float diff_now(timestamp_t *t1) |
| { |
{ |
| int yunit = get_y_unit(); | timestamp_t now; |
| update_ts(&now); |
| if (prec) | return time_diff(t1, &now); |
| *prec = 2; | |
| |
| 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; | |
| } |
} |
| |
|
| double cancel_down(b_cnt_t l, int unit, char **dst_unit, int *prec) | const char *xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt) |
| { |
{ |
| return ((double) l / (double) get_divisor(l, unit, dst_unit, prec)); |
|
| } |
|
| |
|
| const char * xinet_ntop(struct sockaddr *src, char *dst, socklen_t cnt) |
|
| { |
|
| void *s; |
void *s; |
| int family; |
int family; |
| |
|
|
Line 211 const char * xinet_ntop(struct sockaddr *src, char *ds
|
Line 163 const char * xinet_ntop(struct sockaddr *src, char *ds
|
| return inet_ntop(family, s, dst, cnt); |
return inet_ntop(family, s, dst, cnt); |
| } |
} |
| |
|
| b_cnt_t parse_size(const char *str) | uint64_t parse_size(const char *str) |
| { |
{ |
| char *p; |
char *p; |
| b_cnt_t l = strtol(str, &p, 0); | uint64_t l = strtol(str, &p, 0); |
| if (p == str) |
if (p == str) |
| return -1; |
return -1; |
| |
|
|
Line 244 char *strdup(const char *s)
|
Line 196 char *strdup(const char *s)
|
| char *t = xcalloc(1, strlen(s) + 1); |
char *t = xcalloc(1, strlen(s) + 1); |
| memcpy(t, s, strlen(s)); |
memcpy(t, s, strlen(s)); |
| return 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 |
#endif |