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

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: 
                     31: static struct unit *byte_unit, *bit_unit, *number_unit;
                     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: 
                    127:        xfree(f->f_name);
                    128:        xfree(f);
                    129: }
                    130: 
                    131: void unit_add_div(struct unit *unit, int type, const char *txt, float div)
                    132: {
                    133:        struct fraction *f;
                    134: 
                    135:        if (!unit)
                    136:                BUG();
                    137: 
                    138:        f = xcalloc(1, sizeof(*f));
                    139: 
                    140:        init_list_head(&f->f_list);
                    141: 
                    142:        f->f_divisor = div;
                    143:        f->f_name = strdup(txt);
                    144: 
                    145:        list_add_tail(&f->f_list, &unit->u_div[type]);
                    146: }
                    147: 
                    148: struct unit *unit_add(const char *name)
                    149: {
                    150:        struct unit *unit;
                    151:        int i;
                    152: 
                    153:        if (!(unit = unit_lookup(name))) {
                    154:                unit = xcalloc(1, sizeof(*unit));
                    155:                unit->u_name = strdup(name);
                    156: 
                    157:                for (i = 0; i < __UNIT_MAX; i++)
                    158:                        init_list_head(&unit->u_div[i]);
                    159: 
                    160:                list_add_tail(&unit->u_list, &units);
                    161:        }
                    162: 
                    163:        return unit;
                    164: }
                    165: 
                    166: static void unit_free(struct unit *u)
                    167: {
                    168:        struct fraction *f, *n;
                    169: 
                    170:        if (!u)
                    171:                return;
                    172: 
                    173:        list_for_each_entry_safe(f, n, &u->u_div[UNIT_DEFAULT], f_list)
                    174:                fraction_free(f);
                    175: 
                    176:        list_for_each_entry_safe(f, n, &u->u_div[UNIT_SI], f_list)
                    177:                fraction_free(f);
                    178: 
                    179:        xfree(u->u_name);
                    180:        xfree(u);
                    181: }
                    182: 
                    183: char *unit_bytes2str(uint64_t bytes, char *buf, size_t len)
                    184: {
                    185:        char *ustr;
                    186:        int prec;
                    187:        double v;
                    188: 
                    189:        if (byte_unit) {
                    190:                v = unit_value2str(bytes, byte_unit, &ustr, &prec);
                    191:                snprintf(buf, len, "%'.*f%3s", prec, v, ustr);
                    192:        } else
                    193:                snprintf(buf, len, "%llu", (unsigned long long) bytes);
                    194: 
                    195:        return buf;
                    196: }
                    197: 
                    198: char *unit_bit2str(uint64_t bits, char *buf, size_t len)
                    199: {
                    200:        char *ustr;
                    201:        int prec;
                    202:        double v;
                    203: 
                    204:        if (bit_unit) {
                    205:                v = unit_value2str(bits, bit_unit, &ustr, &prec);
                    206:                snprintf(buf, len, "%'.*f%3s", prec, v, ustr);
                    207:        } else
                    208:                snprintf(buf, len, "%llu", (unsigned long long) bits);
                    209: 
                    210:        return buf;
                    211: }
                    212: 
                    213: static void __exit unit_exit(void)
                    214: {
                    215:        struct unit *u, *n;
                    216: 
                    217:        list_for_each_entry_safe(u, n, &units, u_list)
                    218:                unit_free(u);
                    219: }

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