diff options
author | hunt <hunt> | 2005-05-17 08:02:30 +0000 |
---|---|---|
committer | hunt <hunt> | 2005-05-17 08:02:30 +0000 |
commit | 43614f5d7e0d18f553c0ee2a4e195d7b8f63be1f (patch) | |
tree | 89edd85aa491b4f9632d10705fcd68c04fc98db3 /runtime/map.c | |
parent | 30add090cbcbb6367c06c8bcc3c270e60c2f928e (diff) | |
download | systemtap-steved-43614f5d7e0d18f553c0ee2a4e195d7b8f63be1f.tar.gz systemtap-steved-43614f5d7e0d18f553c0ee2a4e195d7b8f63be1f.tar.xz systemtap-steved-43614f5d7e0d18f553c0ee2a4e195d7b8f63be1f.zip |
Rewritten maps and other updated files.
Diffstat (limited to 'runtime/map.c')
-rw-r--r-- | runtime/map.c | 1093 |
1 files changed, 385 insertions, 708 deletions
diff --git a/runtime/map.c b/runtime/map.c index 25ad8620..6f6116f5 100644 --- a/runtime/map.c +++ b/runtime/map.c @@ -5,40 +5,222 @@ * @brief Implements maps (associative arrays) and lists */ -#include "map.h" #include "alloc.c" -#include "string.c" static int map_sizes[] = { - sizeof(struct map_node_int64), - sizeof(struct map_node_stat), - sizeof(struct map_node_str), - 0 + sizeof(int64_t), + MAP_STRING_LENGTH, + sizeof(stat), + 0 }; -static unsigned string_hash(const char *key1, const char *key2) +#ifdef NEED_INT64_KEYS +unsigned int int64_hash (const int64_t v) +{ + return (unsigned int)hash_long ((unsigned long)v, HASH_TABLE_BITS); +} + +int int64_eq_p (int64_t key1, int64_t key2) +{ + return key1 == key2; +} +#endif /* NEED_INT64_KEYS */ + + +#ifdef NEED_INT64_VALS +void int64_copy (void *dest, int64_t val) +{ + *(int64_t *)dest = val; +} + +void int64_add (void *dest, int64_t val) +{ + *(int64_t *)dest += val; +} + +int64_t int64_get (void *ptr) +{ + return *(int64_t *)ptr; +} +#endif /* NEED_INT64_VALS */ + + +#ifdef NEED_STAT_VALS +void stat_copy (void *dest, stat *src) +{ + memcpy (dest, src, sizeof(stat)); +} + +void stat_add (void *dest, stat *src) +{ + stat *d = (stat *)dest; + + d->count =+ src->count; + d->sum += src->sum; + if (src->max > d->max) + d->max = src->max; + if (src->min < d->min) + d->min = src->min; + /* FIXME: do histogram */ +} + +stat *stat_get(void *ptr) +{ + return (stat *)ptr; +} + +/* implements a log base 2 function, or Most Significant Bit */ +/* with bits from 1 (lsb) to 64 (msb) */ +/* msb64(0) = 0 */ +/* msb64(1) = 1 */ +/* msb64(8) = 4 */ +/* msb64(512) = 10 */ + +int msb64(int64_t val) +{ + int res = 64; + + if (val == 0) + return 0; + + /* shortcut. most values will be 16-bit */ + if (val & 0xffffffffffff0000ull) { + if (!(val & 0xffffffff00000000ull)) { + val <<= 32; + res -= 32; + } + + if (!(val & 0xffff000000000000ull)) { + val <<= 16; + res -= 16; + } + } else { + val <<= 48; + res -= 48; + } + + if (!(val & 0xff00000000000000ull)) { + val <<= 8; + res -= 8; + } + + if (!(val & 0xf000000000000000ull)) { + val <<= 4; + res -= 4; + } + + if (!(val & 0xc000000000000000ull)) { + val <<= 2; + res -= 2; + } + + if (!(val & 0x8000000000000000ull)) { + val <<= 1; + res -= 1; + } + + return res; +} + +#endif /* NEED_STAT_VALS */ + +int64_t _stp_key_get_int64 (struct map_node *mn, int n) +{ + if (mn) + return (*mn->map->get_key)(mn, n, NULL).val; + return 0; +} + +char *_stp_key_get_str (struct map_node *mn, int n) +{ + if (mn) + return (*mn->map->get_key)(mn, n, NULL).strp; + return ""; +} + + + +#if defined(NEED_STRING_VALS) || defined (NEED_STRING_KEYS) +void str_copy(char *dest, char *src) +{ + int len = strlen(src); + if (len > MAP_STRING_LENGTH - 1) + len = MAP_STRING_LENGTH - 1; + strncpy (dest, src, len); + dest[len] = 0; +} +#endif + +#ifdef NEED_STRING_VALS +void str_add(void *dest, char *val) +{ + char *dst = (char *)dest; + int len = strlen(val); + int len1 = strlen(dst); + int num = MAP_STRING_LENGTH - 1 - len1; + + if (len > num) + len = num; + strncpy (&dst[len1], val, len); + dst[len + len1] = 0; +} + +char *str_get (void *ptr) +{ + return ptr; +} + +/** Set the current element's value to String. + * This sets the current element's value to a String. The map must have been created + * to hold int64s using <i>_stp_map_new(xxx, STRING)</i> + * + * If the element doesn't exist, it is created. If no current element (key) + * is set for the map, this function does nothing. + * @param map + * @param str String containing new value. + * @sa _stp_map_set() + */ + +void _stp_map_set_string (MAP map, String str) +{ + _stp_map_set_str (map, str->buf); +} + +#endif /* NEED_STRING_VALS */ + +#ifdef NEED_STRING_KEYS +int str_eq_p (char *key1, char *key2) +{ + return strncmp(key1, key2, MAP_STRING_LENGTH - 1) == 0; +} + +unsigned int str_hash(const char *key1) { int hash = 0, count = 0; char *v1 = (char *)key1; - char *v2 = (char *)key2; while (*v1 && count++ < 5) { hash += *v1++; } - while (v2 && *v2 && count++ < 5) { - hash += *v2++; - } - return hash_long((unsigned long)hash, HASH_TABLE_BITS); + return (unsigned int)hash_long((unsigned long)hash, HASH_TABLE_BITS); } +#endif /* NEED_STRING_KEYS */ -static unsigned mixed_hash(const char *key1, long key2) +int64_t _stp_get_int64(struct map_node *m) { - int hash = 0, count = 0; - char *v = (char *)key1; - while (v && *v && count++ < 5) - hash += *v++; - return hash_long((unsigned long)(hash ^ key2), HASH_TABLE_BITS); + return *(int64_t *)((long)m + m->map->data_offset); } +char *_stp_get_str(struct map_node *m) +{ + return (char *)((long)m + m->map->data_offset); +} + +stat *_stp_get_stat(struct map_node *m) +{ + return (stat *)((long)m + m->map->data_offset); +} + + /** @addtogroup maps * Implements maps (associative arrays) and lists * @{ @@ -54,9 +236,9 @@ static unsigned mixed_hash(const char *key1, long key2) * @return A MAP on success or NULL on failure. */ -MAP _stp_map_new(unsigned max_entries, enum valtype type) +static MAP _stp_map_new(unsigned max_entries, int type, int key_size, int data_size) { - size_t size; + int size; MAP m = (MAP) _stp_valloc(sizeof(struct map_root)); if (m == NULL) return NULL; @@ -69,45 +251,79 @@ MAP _stp_map_new(unsigned max_entries, enum valtype type) dbug ("map_new: unknown type %d\n", type); return NULL; } - if (max_entries) { void *tmp; int i; struct list_head *e; INIT_LIST_HEAD(&m->pool); - size = map_sizes[type]; + + /* size is the size of the map_node. */ + /* add space for the value. */ + key_size = ALIGN(key_size,4); + m->data_offset = key_size; + if (data_size == 0) + data_size = map_sizes[type]; + data_size = ALIGN(data_size,4); + size = key_size + data_size; + tmp = _stp_valloc(max_entries * size); for (i = max_entries - 1; i >= 0; i--) { e = i * size + tmp; dbug ("e=%lx\n", (long)e); list_add(e, &m->pool); + ((struct map_node *)e)->map = m; } m->membuf = tmp; } + if (type == STAT) + m->hist_type = HIST_NONE; return m; } -static void map_free_strings(MAP map, struct map_node *n) +MAP _stp_map_new_hstat_log (unsigned max_entries, int key_size, int buckets) { - struct map_node_str *m = (struct map_node_str *)n; - dbug ("n = %lx\n", (long)n); - if (map->type == STRING) { - dbug ("val STRING %lx\n", (long)m->str); - if (m->str) - _stp_free(m->str); - } - if (m->n.key1type == STR) { - dbug ("key1 STR %lx\n", (long)key1str(m)); - if (key1str(m)) - _stp_free(key1str(m)); + /* add size for buckets */ + int size = buckets * sizeof(int64_t) + sizeof(stat); + MAP m = _stp_map_new (max_entries, STAT, key_size, size); + if (m) { + m->hist_type = HIST_LOG; + m->hist_buckets = buckets; + if (buckets < 1 || buckets > 64) { + dbug ("histogram: Bad number of buckets. Must be between 1 and 64\n"); + m->hist_type = HIST_NONE; + return m; + } } - if (m->n.key2type == STR) { - dbug ("key2 STR %lx\n", (long)key2str(m)); - if (key2str(m)) - _stp_free(key2str(m)); + return m; +} + +MAP _stp_map_new_hstat_linear (unsigned max_entries, int ksize, int start, int stop, int interval) +{ + MAP m; + int size; + int buckets = (stop - start) / interval; + if ((stop - start) % interval) buckets++; + + /* add size for buckets */ + size = buckets * sizeof(int64_t) + sizeof(stat); + + m = _stp_map_new (max_entries, STAT, ksize, size); + if (m) { + m->hist_type = HIST_LINEAR; + m->hist_start = start; + m->hist_stop = stop; + m->hist_int = interval; + m->hist_buckets = buckets; + if (m->hist_buckets <= 0) { + dbug ("histogram: bad stop, start and/or interval\n"); + m->hist_type = HIST_NONE; + return m; + } + } + return m; } /** Deletes the current element. @@ -140,13 +356,7 @@ void _stp_map_key_del(MAP map) /* remove from entry list */ list_del(&m->lnode); - /* remove any allocated string storage */ - map_free_strings(map, (struct map_node *)map->key); - - if (map->maxnum) - list_add(&m->lnode, &map->pool); - else - _stp_free(m); + list_add(&m->lnode, &map->pool); map->key = NULL; map->num--; @@ -206,707 +416,174 @@ void _stp_map_del(MAP map) { if (map == NULL) return; - - if (!list_empty(&map->head)) { - struct map_node *ptr = (struct map_node *)map->head.next; - while (ptr && ptr != (struct map_node *)&map->head) { - map_free_strings(map, ptr); - ptr = (struct map_node *)ptr->lnode.next; - } - } _stp_vfree(map->membuf); _stp_vfree(map); } -/********************** KEY FUNCTIONS *********************/ - - -/** Set the map's key to two longs. - * This sets the current element based on a key of two strings. If the keys are - * not found, a new element will not be created until a <i>_stp_map_set_xxx</i> - * call. - * @param map - * @param key1 first key - * @param key2 second key - */ +#ifdef NEED_STAT_VALS -void _stp_map_key_long_long(MAP map, long key1, long key2) +static int needed_space(int64_t v) { - unsigned hv; - struct hlist_head *head; - struct hlist_node *e; + int space = 0; - if (map == NULL) - return; - - hv = hash_long(key1 ^ key2, HASH_TABLE_BITS); - head = &map->hashes[hv]; + if (v == 0) + return 1; - dbug ("hash for %ld,%ld is %d\n", key1, key2, hv); - - hlist_for_each(e, head) { - struct map_node *n = - (struct map_node *)((long)e - sizeof(struct hlist_node)); - dbug ("n =%lx key=%ld,%ld\n", (long)n, n->key1.val, n->key2.val); - if (key1 == n->key1.val && key2 == n->key2.val) { - map->key = n; - dbug ("saving key %lx\n", (long)map->key); - map->create = 0; - return; - } + if (v < 0) { + space++; + v = -v; } - - map->c_key1.val = key1; - map->c_key2.val = key2; - map->c_key1type = LONG; - map->c_key2type = LONG; - map->c_keyhead = head; - map->create = 1; + while (v) { + v /= 10; + space++; + } + return space; } -/** Set the map's key to two strings. - * This sets the current element based on a key of two strings. If the keys are - * not found, a new element will not be created until a <i>_stp_map_set_xxx</i> - * call. - * @param map - * @param key1 first key - * @param key2 second key - */ - -void _stp_map_key_str_str(MAP map, char *key1, char *key2) +static void reprint (int num, char *s) { - unsigned hv; - struct hlist_head *head; - struct hlist_node *e; - - if (map == NULL) - return; - - if (key1 == NULL) { - map->key = NULL; - return; + while (num > 0) { + _stp_print_cstr (s); + num--; } - - hv = string_hash(key1, key2); - head = &map->hashes[hv]; - - dbug ("hash for %s,%s is %d\n", key1, key2, hv); - - hlist_for_each(e, head) { - struct map_node *n = - (struct map_node *)((long)e - sizeof(struct hlist_node)); - dbug ("e =%lx key=%s,%s\n", (long)e, n->key1.str,n->key2.str); - if (strcmp(key1, n->key1.str) == 0 - && (key2 == NULL || strcmp(key2, n->key2.str) == 0)) { - map->key = n; - dbug ("saving key %lx\n", (long)map->key); - map->create = 0; - return; - } - } - - map->c_key1.str = key1; - map->c_key2.str = key2; - map->c_key1type = STR; - map->c_key2type = STR; - map->c_keyhead = head; - map->create = 1; } -/** Set the map's key to a string and a long. - * This sets the current element based on a key of a string and a long. If the keys are - * not found, a new element will not be created until a <i>_stp_map_set_xxx</i> - * call. - * @param map - * @param key1 first key - * @param key2 second key - */ +#define HIST_WIDTH 50 -void _stp_map_key_str_long(MAP map, char *key1, long key2) +void _stp_map_print_histogram (MAP map, stat *s) { - unsigned hv; - struct hlist_head *head; - struct hlist_node *e; + int scale, i, j, val_space, cnt_space; + int64_t val, v, max = 0; - if (map == NULL) + if (map->hist_type != HIST_LOG && map->hist_type != HIST_LINEAR) return; + /* get the maximum value, for scaling */ - if (key1 == NULL) { - map->key = NULL; - return; + for (i = 0; i < map->hist_buckets; i++) + if (s->histogram[i] > max) + max = s->histogram[i]; + + if (max <= HIST_WIDTH) + scale = 1; + else { + scale = max / HIST_WIDTH; + if (max % HIST_WIDTH) scale++; } - hv = mixed_hash(key1, key2); - head = &map->hashes[hv]; - - dbug ("hash for %s,%ld is %d\n", key1, key2, hv); + cnt_space = needed_space (max); + if (map->hist_type == HIST_LINEAR) + val_space = needed_space (map->hist_start + map->hist_int * (map->hist_buckets - 1)); + else + val_space = needed_space (1 << (map->hist_buckets - 1)); + dbug ("max=%lld scale=%d val_space=%d\n", max, scale, val_space); - hlist_for_each(e, head) { - struct map_node *n = - (struct map_node *)((long)e - sizeof(struct hlist_node)); - dbug ("e =%lx key=%s,%ld\n", (long)e, n->key1.str,(long)n->key2.val); - if (strcmp(key1, n->key1.str) == 0 && key2 == n->key2.val) { - map->key = n; - dbug ("saving key %lx\n", (long)map->key); - map->create = 0; - return; - } + /* print header */ + j = 0; + if (val_space > 5) /* 5 = sizeof("value") */ + j = val_space - 5; + else + val_space = 5; + for ( i = 0; i < j; i++) + _stp_print_cstr (" "); + _stp_print_cstr("value |"); + reprint (HIST_WIDTH, "-"); + _stp_print_cstr (" count\n"); + _stp_print_flush(); + if (map->hist_type == HIST_LINEAR) + val = map->hist_start; + else + val = 0; + for (i = 0; i < map->hist_buckets; i++) { + reprint (val_space - needed_space(val), " "); + _stp_printf("%d", val); + _stp_print_cstr (" |"); + v = s->histogram[i] / scale; + reprint (v, "@"); + reprint (HIST_WIDTH - v + 1 + cnt_space - needed_space(s->histogram[i]), " "); + _stp_printf ("%lld\n", s->histogram[i]); + if (map->hist_type == HIST_LINEAR) + val += map->hist_int; + else if (val == 0) + val = 1; + else + val *= 2; + _stp_print_flush(); } - - map->c_key1.str = key1; - map->c_key2.val = key2; - map->c_key1type = STR; - map->c_key2type = LONG; - map->c_keyhead = head; - map->create = 1; } +#endif /* NEED_STAT_VALS */ -/** Set the map's key to a long and a string. - * This sets the current element based on a key of a long and a string. If the keys are - * not found, a new element will not be created until a <i>_stp_map_set_xxx</i> - * call. - * @param map - * @param key1 first key - * @param key2 second key - */ - -void _stp_map_key_long_str(MAP map, long key1, char *key2) +void _stp_map_print (MAP map, const char *name) { - unsigned hv; - struct hlist_head *head; - struct hlist_node *e; - - if (map == NULL) - return; - - hv = mixed_hash(key2, key1); - head = &map->hashes[hv]; - dbug ("hash for %ld,%s is %d\n", key1, key2, hv); - - hlist_for_each(e, head) { - struct map_node *n = - (struct map_node *)((long)e - sizeof(struct hlist_node)); - dbug ("e =%lx key=%ld,%s\n", (long)e, n->key1.val,n->key2.str); - if (key1 == n->key1.val && strcmp(key2, n->key2.str) == 0) { - map->key = n; - dbug ("saving key %lx\n", (long)map->key); - map->create = 0; - return; + struct map_node *ptr; + int type, n, first; + key_data kd; + + dbug ("print map %lx\n", (long)map); + for (ptr = _stp_map_start(map); ptr; ptr = _stp_map_iter (map, ptr)) { + n = 1; first = 1; + _stp_print_cstr (name); + _stp_print_cstr ("["); + do { + kd = (*map->get_key)(ptr, n, &type); + if (type == END) + break; + if (!first) + _stp_print_cstr (", "); + first = 0; + if (type == STRING) + _stp_print_cstr (kd.strp); + else + _stp_printf("%lld", kd.val); + n++; + } while (1); + _stp_print_cstr ("] = "); + if (map->type == STRING) + _stp_print_cstr(_stp_get_str(ptr)); + else if (map->type == INT64) + _stp_printf("%d", _stp_get_int64(ptr)); +#ifdef NEED_STAT_VALS + else { + stat *s = _stp_get_stat(ptr); + _stp_printf("count:%lld sum:%lld avg:%lld min:%lld max:%lld\n", + s->count, s->sum, s->sum/s->count, s->min, s->max); + _stp_print_flush(); + _stp_map_print_histogram (map, s); } +#endif + _stp_print_cstr ("\n"); + _stp_print_flush(); } - - map->c_key1.val = key1; - map->c_key2.str = key2; - map->c_key1type = LONG; - map->c_key2type = STR; - map->c_keyhead = head; - map->create = 1; + _stp_print_cstr ("\n"); + _stp_print_flush(); } -/** Set the map's key to a string. - * This sets the current element based on a string key. If the key is - * not found, a new element will not be created until a <i>_stp_map_set_xxx</i> - * call. - * @param map - * @param key - */ - -void _stp_map_key_str(MAP map, char *key) +static struct map_node *__stp_map_create (MAP map) { - if (map == NULL) - return; - _stp_map_key_str_str(map, key, NULL); - map->c_key2type = NONE; -} - -/** Set the map's key to a long. - * This sets the current element based on a long key. If the key is - * not found, a new element will not be created until a <i>_stp_map_set_xxx</i> - * call. - * @param map - * @param key - */ - -void _stp_map_key_long(MAP map, long key) -{ - if (map == NULL) - return; - _stp_map_key_long_long(map, key, 0); - map->c_key2type = NONE; -} - -/********************** SET/GET VALUES *********************/ - -static void map_copy_keys(MAP map, struct map_node *m) -{ - m->key1type = map->c_key1type; - m->key2type = map->c_key2type; - switch (map->c_key1type) { - case STR: - m->key1.str = _stp_alloc(strlen(map->c_key1.str) + 1); - strcpy(m->key1.str, map->c_key1.str); - break; - case LONG: - m->key1.val = map->c_key1.val; - break; - case NONE: - /* ERROR */ - break; - } - switch (map->c_key2type) { - case STR: - m->key2.str = _stp_alloc(strlen(map->c_key2.str) + 1); - strcpy(m->key2.str, map->c_key2.str); - break; - case LONG: - m->key2.val = map->c_key2.val; - break; - case NONE: - break; + struct map_node *m; + if (list_empty(&map->pool)) { + if (map->no_wrap) { + /* ERROR. FIXME */ + return NULL; + } + m = (struct map_node *)map->head.next; + hlist_del_init(&m->hnode); + dbug ("got %lx off head\n", (long)m); + } else { + m = (struct map_node *)map->pool.next; + dbug ("got %lx off pool\n", (long)m); } - + list_move_tail(&m->lnode, &map->head); + + /* copy the key(s) */ + (map->copy_keys)(map, m); + /* add node to new hash list */ hlist_add_head(&m->hnode, map->c_keyhead); map->key = m; map->create = 0; map->num++; + return m; } +#endif -static void __stp_map_set_int64(MAP map, int64_t val, int add) -{ - struct map_node_int64 *m; - - if (map == NULL) - return; - - if (map->create) { - if (val == 0) - return; - - if (map->maxnum) { - if (list_empty(&map->pool)) { - if (map->no_wrap) { - /* ERROR. FIXME */ - return; - } - m = (struct map_node_int64 *)map->head.next; - hlist_del_init(&m->n.hnode); - map_free_strings(map, (struct map_node *)m); - dbug ("got %lx off head\n", (long)m); - } else { - m = (struct map_node_int64 *)map->pool.next; - dbug ("got %lx off pool\n", (long)m); - } - list_move_tail(&m->n.lnode, &map->head); - } else { - m = (struct map_node_int64 *) - _stp_calloc(sizeof(struct map_node_int64)); - /* add node to list */ - list_add_tail(&m->n.lnode, &map->head); - } - - /* copy the key(s) */ - map_copy_keys(map, &m->n); - - /* set the value */ - m->val = val; - } else { - if (map->key == NULL) - return; - - if (val) { - m = (struct map_node_int64 *)map->key; - if (add) - m->val += val; - else - m->val = val; - } else if (!add) { - /* setting value to 0 is the same as deleting */ - _stp_map_key_del(map); - } - } -} - -/** Set the current element's value to an int64. - * This sets the current element's value to an int64. The map must have been created - * to hold int64s using _stp_map_new() - * - * If the element doesn't exist, it is created. If no current element (key) - * is set for the map, this function does nothing. - * @param map - * @param val new value - * @sa _stp_map_add_int64 - * @sa _stp_map_set() - */ -void _stp_map_set_int64(MAP map, int64_t val) -{ - __stp_map_set_int64 (map, val, 0); -} - - -/** Adds an int64 to the current element's value. - * This adds an int64 to the current element's value. The map must have been created - * to hold int64s using _stp_map_new() - * - * If the element doesn't exist, it is created. If no current element (key) - * is set for the map, this function does nothing. - * @param map - * @param val value - * @sa _stp_map_set_int64 - */ - -void _stp_map_add_int64(MAP map, int64_t val) -{ - __stp_map_set_int64 (map, val, 1); -} - -/** Gets the current element's value. - * @param map - * @returns The value. If the current element is not set or doesn't exist, returns 0. - */ - -int64_t _stp_map_get_int64(MAP map) -{ - struct map_node_int64 *m; - if (map == NULL || map->create || map->key == NULL) - return 0; - dbug ("%lx\n", (long)map->key); - m = (struct map_node_int64 *)map->key; - return m->val; -} - -/** Set the current element's value to a C string. - * This sets the current element's value to an C string. The map must have been created - * to hold int64s using <i>_stp_map_new(xxx, STRING)</i> - * - * If the element doesn't exist, it is created. If no current element (key) - * is set for the map, this function does nothing. - * @param map - * @param val new string - * @sa _stp_map_set() - */ - -void _stp_map_set_str(MAP map, char *val) -{ - struct map_node_str *m; - - if (map == NULL) - return; - - if (map->create) { - if (val == NULL) - return; - - if (map->maxnum) { - if (list_empty(&map->pool)) { - if (map->no_wrap) { - /* ERROR. FIXME */ - return; - } - m = (struct map_node_str *)map->head.next; - hlist_del_init(&m->n.hnode); - map_free_strings(map, (struct map_node *)m); - dbug ("got %lx off head\n", (long)m); - } else { - m = (struct map_node_str *)map->pool.next; - dbug ("got %lx off pool\n", (long)m); - } - list_move_tail(&m->n.lnode, &map->head); - } else { - m = (struct map_node_str *) - _stp_calloc(sizeof(struct map_node_str)); - /* add node to list */ - list_add_tail(&m->n.lnode, &map->head); - } - - /* copy the key(s) */ - map_copy_keys(map, &m->n); - - /* set the value */ - m->str = _stp_alloc(strlen(val) + 1); - strcpy(m->str, val); - } else { - if (map->key == NULL) - return; - - if (val) { - m = (struct map_node_str *)map->key; - if (m->str) - _stp_free(m->str); - m->str = _stp_alloc(strlen(val) + 1); - strcpy(m->str, val); - } else { - /* setting value to 0 is the same as deleting */ - _stp_map_key_del(map); - } - } -} - -/** Set the current element's value to String. - * This sets the current element's value to a String. The map must have been created - * to hold int64s using <i>_stp_map_new(xxx, STRING)</i> - * - * If the element doesn't exist, it is created. If no current element (key) - * is set for the map, this function does nothing. - * @param map - * @param str String containing new value. - * @sa _stp_map_set() - */ - -void _stp_map_set_string (MAP map, String str) -{ - _stp_map_set_str (map, str->buf); -} - -/** Gets the current element's value. - * @param map - * @returns A string pointer. If the current element is not set or doesn't exist, returns NULL. - */ - -char *_stp_map_get_str(MAP map) -{ - struct map_node_str *m; - if (map == NULL || map->create || map->key == NULL) - return NULL; - dbug ("%lx\n", (long)map->key); - m = (struct map_node_str *)map->key; - return m->str; -} - -/** Set the current element's value to a stat. - * This sets the current element's value to an stat struct. The map must have been created - * to hold stats using <i>_stp_map_new(xxx, STAT)</i>. This function would only be used - * if we wanted to set stats to something other than the normal initial values (count = 0, - * sum = 0, etc). It may be deleted if it doesn't turn out to be useful. - * @sa _stp_map_stat_add - * - * If the element doesn't exist, it is created. If no current element (key) - * is set for the map, this function does nothing. - * @param map - * @param stats pointer to stats struct. - * @todo Histograms don't work yet. - */ - -void _stp_map_set_stat(MAP map, stat * stats) -{ - struct map_node_stat *m; - - if (map == NULL) - return; - dbug ("set_stat %lx\n", (long)map->key); - - if (map->create) { - if (stats == NULL) - return; - - if (map->maxnum) { - if (list_empty(&map->pool)) { - if (map->no_wrap) { - /* ERROR. FIXME */ - return; - } - m = (struct map_node_stat *)map->head.next; - hlist_del_init(&m->n.hnode); - map_free_strings(map, (struct map_node *)m); - dbug ("got %lx off head\n", (long)m); - } else { - m = (struct map_node_stat *)map->pool.next; - dbug ("got %lx off pool\n", (long)m); - } - list_move_tail(&m->n.lnode, &map->head); - } else { - m = (struct map_node_stat *) - _stp_calloc(sizeof(struct map_node_stat)); - /* add node to list */ - list_add_tail(&m->n.lnode, &map->head); - } - - /* copy the key(s) */ - map_copy_keys(map, &m->n); - - /* set the value */ - memcpy(&m->stats, stats, sizeof(stat)); - } else { - if (map->key == NULL) - return; - - if (stats) { - m = (struct map_node_stat *)map->key; - memcpy(&m->stats, stats, sizeof(stat)); - } else { - /* setting value to NULL is the same as deleting */ - _stp_map_key_del(map); - } - } -} - -/** Gets the current element's value. - * @param map - * @returns A pointer to the stats struct. If the current element is not set - * or doesn't exist, returns NULL. - */ - -stat *_stp_map_get_stat(MAP map) -{ - struct map_node_stat *m; - if (map == NULL || map->create || map->key == NULL) - return NULL; - dbug ("%lx\n", (long)map->key); - m = (struct map_node_stat *)map->key; - return &m->stats; -} - -/** Add to the current element's statistics. - * Increments the statistics counter by one and the sum by <i>val</i>. - * Adjusts minimum, maximum, and histogram. - * - * If the element doesn't exist, it is created. If no current element (key) - * is set for the map, this function does nothing. - * @param map - * @param val value to add to the statistics - * @todo Histograms don't work yet. - */ - -void _stp_map_stat_add(MAP map, int64_t val) -{ - struct map_node_stat *m; - if (map == NULL) - return; - - if (map->create) { - stat st = { 1, val, val, val }; - /* histogram */ - _stp_map_set_stat(map, &st); - return; - } - - if (map->key == NULL) - return; - - dbug ("add_stat %lx\n", (long)map->key); - m = (struct map_node_stat *)map->key; - m->stats.count++; - m->stats.sum += val; - if (val > m->stats.max) - m->stats.max = val; - if (val < m->stats.min) - m->stats.min = val; - /* histogram */ -} - -/** @} */ - -/********************** List Functions *********************/ - -/** @addtogroup lists - * Lists are special cases of maps. - * @b Example: - * @include list.c - * @{ */ - -/** Create a new list. - * A list is a map that internally has an incrementing long key for each member. - * Lists do not wrap if elements are added to exceed their maximum size. - * @param max_entries The maximum number of entries allowed. Currently that number will - * be preallocated. If max_entries is 0, there will be no maximum and entries - * will be allocated dynamically. - * @param type Type of values stored in this list. - * @return A MAP on success or NULL on failure. - * @sa foreach - */ - -MAP _stp_list_new(unsigned max_entries, enum valtype type) -{ - MAP map = _stp_map_new (max_entries, type); - map->no_wrap = 1; - return map; -} - -/** Clears a list. - * All elements in the list are deleted. - * @param map - */ - -void _stp_list_clear(MAP map) -{ - if (map == NULL) - return; - - if (!list_empty(&map->head)) { - struct map_node *ptr = (struct map_node *)map->head.next; - - while (ptr && ptr != (struct map_node *)&map->head) { - struct map_node *next = (struct map_node *)ptr->lnode.next; - - /* remove node from old hash list */ - hlist_del_init(&ptr->hnode); - - /* remove from entry list */ - list_del(&ptr->lnode); - - /* remove any allocated string storage */ - map_free_strings(map, ptr); - - if (map->maxnum) - list_add(&ptr->lnode, &map->pool); - else - _stp_free(ptr); - - map->num--; - ptr = next; - } - } - - if (map->num != 0) { - _stp_log ("ERROR: list is supposed to be empty (has %d)\n", map->num); - } -} - -/** Adds a C string to a list. - * @param map - * @param str - * @sa _stp_list_add() - */ - -inline void _stp_list_add_str(MAP map, char *str) -{ - _stp_map_key_long(map, map->num); - _stp_map_set_str(map, str); -} - -/** Adds a String to a list. - * @param map - * @param str String to add. - * @sa _stp_list_add() - */ - -inline void _stp_list_add_string (MAP map, String str) -{ - _stp_map_key_long(map, map->num); - _stp_map_set_str(map, str->buf); -} - -/** Adds an int64 to a list. - * @param map - * @param val - * @sa _stp_list_add() - */ - -inline void _stp_list_add_int64(MAP map, int64_t val) -{ - _stp_map_key_long(map, map->num); - _stp_map_set_int64(map, val); -} - -/** Get the number of elements in a list. - * @param map - * @returns The number of elements in a list. - */ - -inline int _stp_list_size(MAP map) -{ - return map->num; -} -/** @} */ -#endif /* _MAP_C_ */ |