Annotation of embedaddon/bmon/src/unit.c, revision 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>