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>