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>