Annotation of embedaddon/bmon/src/unit.c, revision 1.1.1.2

1.1       misho       1: /*
                      2:  * unit.c              Unit Definitions
                      3:  *
                      4:  * Copyright (c) 2001-2013 Thomas Graf <tgraf@suug.ch>
                      5:  * Copyright (c) 2013 Red Hat, Inc.
                      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: #include <bmon/unit.h>
                     30: 
1.1.1.2 ! misho      31: static struct unit *byte_unit, *bit_unit;
1.1       misho      32: 
                     33: static LIST_HEAD(units);
                     34: 
                     35: static struct list_head *get_flist(struct unit *unit)
                     36: {
                     37:        int div = UNIT_DEFAULT;
                     38: 
                     39:        if (cfg_getbool(cfg, "use_bit"))
                     40:                div = UNIT_BIT;
                     41:        else if (cfg_getbool(cfg, "use_si"))
                     42:                div = UNIT_SI;
                     43:        
                     44:        if (!list_empty(&unit->u_div[div]))
                     45:                return &unit->u_div[div];
                     46:        else
                     47:                return &unit->u_div[UNIT_DEFAULT];
                     48: }
                     49: 
                     50: struct unit *unit_lookup(const char *name)
                     51: {
                     52:        struct unit *unit;
                     53: 
                     54:        list_for_each_entry(unit, &units, u_list)
                     55:                if (!strcmp(name, unit->u_name))
                     56:                        return unit;
                     57: 
                     58:        return NULL;
                     59: }
                     60: 
                     61: /**
                     62:  * Lookup best divisor to use for a certain situation
                     63:  * @hint               Value in question (for DYNAMIC_EXP)
                     64:  * @unit               Unit of value
                     65:  * @name               Place to store name of divisor used
                     66:  * @prec               Place to store suggested precision
                     67:  *
                     68:  * Searches for the best divisor to be used depending on the unit
                     69:  * exponent configured by the user. If a dynamic exponent is
                     70:  * configured, the divisor is selected based on the value of hint
                     71:  * so that hint is dividied into a small float >= 1.0. The name
                     72:  * of the divisor used is stored in *name.
                     73:  *
                     74:  * If prec points to a vaild integer, a number of precision digits
                     75:  * is suggested to avoid n.00 to make pretty printing easier.
                     76:  */
                     77: double unit_divisor(uint64_t hint, struct unit *unit, char **name,
                     78:                    int *prec)
                     79: {
                     80:        struct list_head *flist = get_flist(unit);
                     81:        struct fraction *f;
                     82: 
                     83:        if (prec)
                     84:                *prec = 2;
                     85: 
                     86:        if (cfg_unit_exp == DYNAMIC_EXP) {
                     87:                list_for_each_entry_reverse(f, flist, f_list) {
                     88:                        if (hint >= f->f_divisor)
                     89:                                goto found_it;
                     90:                }
                     91:        } else {
                     92:                int n = cfg_unit_exp;
                     93:                list_for_each_entry(f, flist, f_list) {
                     94:                        if (--n == 0)
                     95:                                goto found_it;
                     96:                }
                     97:        }
                     98: 
                     99:        *name = "";
                    100:        return 1;
                    101: 
                    102: found_it:
                    103:        if (f->f_divisor == 1.0f && prec)
                    104:                *prec = 0;
                    105: 
                    106:        *name = f->f_name;
                    107:        return f->f_divisor;
                    108: }
                    109: 
                    110: double unit_value2str(uint64_t value, struct unit *unit,
                    111:                      char **name, int *prec)
                    112: {
                    113:        double div = unit_divisor(value, unit, name, prec);
                    114:        double v = (double) value;
                    115: 
                    116:        if (fmod(v, div) == 0.0f && prec)
                    117:                *prec = 0;
                    118: 
                    119:        return v / div;
                    120: }
                    121: 
                    122: void fraction_free(struct fraction *f)
                    123: {
                    124:        if (!f)
                    125:                return;
                    126: 
1.1.1.2 ! misho     127:        list_del(&f->f_list);
1.1       misho     128:        xfree(f->f_name);
                    129:        xfree(f);
                    130: }
                    131: 
                    132: void unit_add_div(struct unit *unit, int type, const char *txt, float div)
                    133: {
                    134:        struct fraction *f;
                    135: 
                    136:        if (!unit)
                    137:                BUG();
                    138: 
                    139:        f = xcalloc(1, sizeof(*f));
                    140: 
                    141:        init_list_head(&f->f_list);
                    142: 
                    143:        f->f_divisor = div;
                    144:        f->f_name = strdup(txt);
                    145: 
                    146:        list_add_tail(&f->f_list, &unit->u_div[type]);
                    147: }
                    148: 
                    149: struct unit *unit_add(const char *name)
                    150: {
                    151:        struct unit *unit;
                    152:        int i;
                    153: 
                    154:        if (!(unit = unit_lookup(name))) {
                    155:                unit = xcalloc(1, sizeof(*unit));
                    156:                unit->u_name = strdup(name);
                    157: 
                    158:                for (i = 0; i < __UNIT_MAX; i++)
                    159:                        init_list_head(&unit->u_div[i]);
                    160: 
                    161:                list_add_tail(&unit->u_list, &units);
                    162:        }
                    163: 
                    164:        return unit;
                    165: }
                    166: 
                    167: static void unit_free(struct unit *u)
                    168: {
                    169:        struct fraction *f, *n;
                    170: 
                    171:        if (!u)
                    172:                return;
                    173: 
                    174:        list_for_each_entry_safe(f, n, &u->u_div[UNIT_DEFAULT], f_list)
                    175:                fraction_free(f);
                    176: 
                    177:        list_for_each_entry_safe(f, n, &u->u_div[UNIT_SI], f_list)
                    178:                fraction_free(f);
                    179: 
                    180:        xfree(u->u_name);
                    181:        xfree(u);
                    182: }
                    183: 
                    184: char *unit_bytes2str(uint64_t bytes, char *buf, size_t len)
                    185: {
                    186:        char *ustr;
                    187:        int prec;
                    188:        double v;
                    189: 
                    190:        if (byte_unit) {
                    191:                v = unit_value2str(bytes, byte_unit, &ustr, &prec);
                    192:                snprintf(buf, len, "%'.*f%3s", prec, v, ustr);
                    193:        } else
1.1.1.2 ! misho     194:                snprintf(buf, len, "%" PRIu64, bytes);
1.1       misho     195: 
                    196:        return buf;
                    197: }
                    198: 
                    199: char *unit_bit2str(uint64_t bits, char *buf, size_t len)
                    200: {
                    201:        char *ustr;
                    202:        int prec;
                    203:        double v;
                    204: 
                    205:        if (bit_unit) {
                    206:                v = unit_value2str(bits, bit_unit, &ustr, &prec);
                    207:                snprintf(buf, len, "%'.*f%3s", prec, v, ustr);
                    208:        } else
1.1.1.2 ! misho     209:                snprintf(buf, len, "%" PRIu64, bits);
1.1       misho     210: 
                    211:        return buf;
                    212: }
                    213: 
                    214: static void __exit unit_exit(void)
                    215: {
                    216:        struct unit *u, *n;
                    217: 
                    218:        list_for_each_entry_safe(u, n, &units, u_list)
                    219:                unit_free(u);
                    220: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>