summaryrefslogtreecommitdiffstats
path: root/runtime/map.c
diff options
context:
space:
mode:
authorhunt <hunt>2005-05-17 08:02:30 +0000
committerhunt <hunt>2005-05-17 08:02:30 +0000
commit43614f5d7e0d18f553c0ee2a4e195d7b8f63be1f (patch)
tree89edd85aa491b4f9632d10705fcd68c04fc98db3 /runtime/map.c
parent30add090cbcbb6367c06c8bcc3c270e60c2f928e (diff)
downloadsystemtap-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.c1093
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_ */