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 |