Main Page | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

map.c

Go to the documentation of this file.
00001 /* -*- linux-c -*- */
00002 /** @file map.c
00003  * @brief Implements maps (associative arrays) and lists
00004  */
00005 
00006 
00007 static int map_sizes[] = {
00008         sizeof(struct map_node_int64),
00009         sizeof(struct map_node_stat),
00010         sizeof(struct map_node_str),
00011         0
00012 };
00013 
00014 static unsigned string_hash(const char *key1, const char *key2)
00015 {
00016         int hash = 0, count = 0;
00017         char *v1 = (char *)key1;
00018         char *v2 = (char *)key2;
00019         while (*v1 && count++ < 5) {
00020                 hash += *v1++;
00021         }
00022         while (v2 && *v2 && count++ < 5) {
00023                 hash += *v2++;
00024         }
00025         return hash_long((unsigned long)hash, HASH_TABLE_BITS);
00026 }
00027 
00028 static unsigned mixed_hash(const char *key1, long key2)
00029 {
00030         int hash = 0, count = 0;
00031         char *v = (char *)key1;
00032         while (v && *v && count++ < 5)
00033                 hash += *v++;
00034         return hash_long((unsigned long)(hash ^ key2), HASH_TABLE_BITS);
00035 }
00036 
00037 /** Create a new map.
00038  * Maps must be created at module initialization time.
00039  * @param max_entries The maximum number of entries allowed. Currently that number will
00040  * be preallocated.  If more entries are required, the oldest ones will be deleted. This makes
00041  * it effectively a circular buffer.  If max_entries is 0, there will be no maximum and entries
00042  * will be allocated dynamically.
00043  * @param type Type of values stored in this map. 
00044  * @return A MAP on success or NULL on failure.
00045  */
00046 
00047 MAP _stp_map_new(unsigned max_entries, enum valtype type)
00048 {
00049         size_t size;
00050         MAP m = (MAP) _stp_valloc(sizeof(struct map_root));
00051         if (m == NULL)
00052                 return NULL;
00053 
00054         INIT_LIST_HEAD(&m->head);
00055 
00056         m->maxnum = max_entries;
00057         m->type = type;
00058         if (type >= END) {
00059                 dbug ("map_new: unknown type %d\n", type);
00060                 return NULL;
00061         }
00062 
00063         if (max_entries) {
00064                 void *tmp;
00065                 int i;
00066                 struct list_head *e;
00067 
00068                 INIT_LIST_HEAD(&m->pool);
00069                 size = map_sizes[type];
00070                 tmp = _stp_valloc(max_entries * size);
00071 
00072                 for (i = max_entries - 1; i >= 0; i--) {
00073                         e = i * size + tmp;
00074                         dbug ("e=%lx\n", (long)e);
00075                         list_add(e, &m->pool);
00076                 }
00077                 m->membuf = tmp;
00078         }
00079         return m;
00080 }
00081 
00082 static void map_free_strings(MAP map, struct map_node *n)
00083 {
00084         struct map_node_str *m = (struct map_node_str *)n;
00085         dbug ("n = %lx\n", (long)n);
00086         if (map->type == STRING) {
00087                 dbug ("val STRING %lx\n", (long)m->str);
00088                 if (m->str)
00089                         _stp_free(m->str);
00090         }
00091         if (m->n.key1type == STR) {
00092                 dbug ("key1 STR %lx\n", (long)key1str(m));
00093                 if (key1str(m))
00094                         _stp_free(key1str(m));
00095         }
00096         if (m->n.key2type == STR) {
00097                 dbug ("key2 STR %lx\n", (long)key2str(m));
00098                 if (key2str(m))
00099                         _stp_free(key2str(m));
00100         }
00101 }
00102 
00103 /** Deletes the current element.
00104  * If no current element (key) for this map is set, this function does nothing.
00105  * @param map 
00106  */
00107 
00108 void _stp_map_key_del(MAP map)
00109 {
00110         struct map_node *m;
00111 
00112         dbug ("create=%d key=%lx\n", map->create, (long)map->key);
00113         if (map == NULL)
00114                 return;
00115 
00116         if (map->create) {
00117                 map->create = 0;
00118                 map->key = NULL;
00119                 return;
00120         }
00121 
00122         if (map->key == NULL)
00123                 return;
00124 
00125         m = (struct map_node *)map->key;
00126 
00127         /* remove node from old hash list */
00128         hlist_del_init(&m->hnode);
00129 
00130         /* remove from entry list */
00131         list_del(&m->lnode);
00132 
00133         /* remove any allocated string storage */
00134         map_free_strings(map, (struct map_node *)map->key);
00135 
00136         if (map->maxnum)
00137                 list_add(&m->lnode, &map->pool);
00138         else
00139                 _stp_free(m);
00140 
00141         map->key = NULL;
00142         map->num--;
00143 }
00144 
00145 /** Get the first element in a map.
00146  * @param map 
00147  * @returns a pointer to the first element.
00148  * This is typically used with _stp_map_iter().  See the foreach() macro
00149  * for typical usage.  It probably does what you want anyway.
00150  * @sa foreach
00151  */
00152 
00153 struct map_node *_stp_map_start(MAP map)
00154 {
00155         if (map == NULL)
00156                 return NULL;
00157 
00158         dbug ("%lx\n", (long)map->head.next);
00159 
00160         if (list_empty(&map->head))
00161                 return NULL;
00162 
00163         return (struct map_node *)map->head.next;
00164 }
00165 
00166 /** Get the next element in a map.
00167  * @param map 
00168  * @param m a pointer to the current element, returned from _stp_map_start()
00169  * or _stp_map_iter().
00170  * @returns a pointer to the next element.
00171  * This is typically used with _stp_map_start().  See the foreach() macro
00172  * for typical usage.  It probably does what you want anyway.
00173  * @sa foreach
00174  */
00175 
00176 struct map_node *_stp_map_iter(MAP map, struct map_node *m)
00177 {
00178         if (map == NULL)
00179                 return NULL;
00180 
00181         dbug ("%lx next=%lx  prev=%lx  map->head.next=%lx\n", (long)m, 
00182               (long)m->lnode.next, (long)m->lnode.prev, (long)map->head.next);
00183 
00184         if (m->lnode.next == &map->head)
00185                 return NULL;
00186 
00187         return (struct map_node *)m->lnode.next;
00188 }
00189 
00190 /** Deletes a map.
00191  * Deletes a map, freeing all memory in all elements.  Normally done only when the module exits.
00192  * @param map
00193  */
00194 
00195 void _stp_map_del(MAP map)
00196 {
00197         if (map == NULL)
00198                 return;
00199 
00200         if (!list_empty(&map->head)) {
00201                 struct map_node *ptr = (struct map_node *)map->head.next;
00202                 while (ptr && ptr != (struct map_node *)&map->head) {
00203                         map_free_strings(map, ptr);
00204                         ptr = (struct map_node *)ptr->lnode.next;
00205                 }
00206         }
00207         _stp_vfree(map->membuf);
00208         _stp_vfree(map);
00209 }
00210 
00211 /**********************  KEY FUNCTIONS *********************/
00212 
00213 
00214 /** Set the map's key to two longs.
00215  * This sets the current element based on a key of two strings. If the keys are
00216  * not found, a new element will not be created until a <i>_stp_map_set_xxx</i>
00217  * call.
00218  * @param map
00219  * @param key1 first key
00220  * @param key2 second key
00221  */
00222 
00223 void _stp_map_key_long_long(MAP map, long key1, long key2)
00224 {
00225         unsigned hv;
00226         struct hlist_head *head;
00227         struct hlist_node *e;
00228 
00229         if (map == NULL)
00230                 return;
00231 
00232         hv = hash_long(key1 ^ key2, HASH_TABLE_BITS);
00233         head = &map->hashes[hv];
00234 
00235         dbug ("hash for %ld,%ld is %d\n", key1, key2, hv);
00236 
00237         hlist_for_each(e, head) {
00238                 struct map_node *n =
00239                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00240                 dbug ("n =%lx  key=%ld,%ld\n", (long)n, n->key1.val, n->key2.val);
00241                 if (key1 == n->key1.val && key2 == n->key2.val) {
00242                         map->key = n;
00243                         dbug ("saving key %lx\n", (long)map->key);
00244                         map->create = 0;
00245                         return;
00246                 }
00247         }
00248 
00249         map->c_key1.val = key1;
00250         map->c_key2.val = key2;
00251         map->c_key1type = LONG;
00252         map->c_key2type = LONG;
00253         map->c_keyhead = head;
00254         map->create = 1;
00255 }
00256 
00257 /** Set the map's key to two strings.
00258  * This sets the current element based on a key of two strings. If the keys are
00259  * not found, a new element will not be created until a <i>_stp_map_set_xxx</i>
00260  * call.
00261  * @param map
00262  * @param key1 first key
00263  * @param key2 second key
00264  */
00265 
00266 void _stp_map_key_str_str(MAP map, char *key1, char *key2)
00267 {
00268         unsigned hv;
00269         struct hlist_head *head;
00270         struct hlist_node *e;
00271 
00272         if (map == NULL)
00273                 return;
00274 
00275         if (key1 == NULL) {
00276                 map->key = NULL;
00277                 return;
00278         }
00279 
00280         hv = string_hash(key1, key2);
00281         head = &map->hashes[hv];
00282 
00283         dbug ("hash for %s,%s is %d\n", key1, key2, hv);
00284 
00285         hlist_for_each(e, head) {
00286                 struct map_node *n =
00287                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00288                 dbug ("e =%lx  key=%s,%s\n", (long)e, n->key1.str,n->key2.str);
00289                 if (strcmp(key1, n->key1.str) == 0
00290                     && (key2 == NULL || strcmp(key2, n->key2.str) == 0)) {
00291                         map->key = n;
00292                         dbug ("saving key %lx\n", (long)map->key);
00293                         map->create = 0;
00294                         return;
00295                 }
00296         }
00297 
00298         map->c_key1.str = key1;
00299         map->c_key2.str = key2;
00300         map->c_key1type = STR;
00301         map->c_key2type = STR;
00302         map->c_keyhead = head;
00303         map->create = 1;
00304 }
00305 
00306 /** Set the map's key to a string and a long.
00307  * This sets the current element based on a key of a string and a long. If the keys are
00308  * not found, a new element will not be created until a <i>_stp_map_set_xxx</i>
00309  * call.
00310  * @param map
00311  * @param key1 first key
00312  * @param key2 second key
00313  */
00314 
00315 void _stp_map_key_str_long(MAP map, char *key1, long key2)
00316 {
00317         unsigned hv;
00318         struct hlist_head *head;
00319         struct hlist_node *e;
00320 
00321         if (map == NULL)
00322                 return;
00323 
00324         if (key1 == NULL) {
00325                 map->key = NULL;
00326                 return;
00327         }
00328 
00329         hv = mixed_hash(key1, key2);
00330         head = &map->hashes[hv];
00331 
00332         dbug ("hash for %s,%ld is %d\n", key1, key2, hv);
00333 
00334         hlist_for_each(e, head) {
00335                 struct map_node *n =
00336                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00337                 dbug ("e =%lx  key=%s,%ld\n", (long)e, n->key1.str,(long)n->key2.val);
00338                 if (strcmp(key1, n->key1.str) == 0 && key2 == n->key2.val) {
00339                         map->key = n;
00340                         dbug ("saving key %lx\n", (long)map->key);
00341                         map->create = 0;
00342                         return;
00343                 }
00344         }
00345 
00346         map->c_key1.str = key1;
00347         map->c_key2.val = key2;
00348         map->c_key1type = STR;
00349         map->c_key2type = LONG;
00350         map->c_keyhead = head;
00351         map->create = 1;
00352 }
00353 
00354 /** Set the map's key to a long and a string.
00355  * This sets the current element based on a key of a long and a string. If the keys are
00356  * not found, a new element will not be created until a <i>_stp_map_set_xxx</i>
00357  * call.
00358  * @param map
00359  * @param key1 first key
00360  * @param key2 second key
00361  */
00362 
00363 void _stp_map_key_long_str(MAP map, long key1, char *key2)
00364 {
00365         unsigned hv;
00366         struct hlist_head *head;
00367         struct hlist_node *e;
00368 
00369         if (map == NULL)
00370                 return;
00371 
00372         hv = mixed_hash(key2, key1);
00373         head = &map->hashes[hv];
00374         dbug ("hash for %ld,%s is %d\n", key1, key2, hv);
00375 
00376         hlist_for_each(e, head) {
00377                 struct map_node *n =
00378                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00379                 dbug ("e =%lx  key=%ld,%s\n", (long)e, n->key1.val,n->key2.str);
00380                 if (key1 == n->key1.val && strcmp(key2, n->key2.str) == 0) {
00381                         map->key = n;
00382                         dbug ("saving key %lx\n", (long)map->key);
00383                         map->create = 0;
00384                         return;
00385                 }
00386         }
00387 
00388         map->c_key1.val = key1;
00389         map->c_key2.str = key2;
00390         map->c_key1type = LONG;
00391         map->c_key2type = STR;
00392         map->c_keyhead = head;
00393         map->create = 1;
00394 }
00395 
00396 /** Set the map's key to a string.
00397  * This sets the current element based on a string key. If the key is
00398  * not found, a new element will not be created until a <i>_stp_map_set_xxx</i>
00399  * call.
00400  * @param map
00401  * @param key
00402  */
00403 
00404 void _stp_map_key_str(MAP map, char *key)
00405 {
00406         if (map == NULL)
00407                 return;
00408         _stp_map_key_str_str(map, key, NULL);
00409         map->c_key2type = NONE;
00410 }
00411 
00412 /** Set the map's key to a long.
00413  * This sets the current element based on a long key. If the key is
00414  * not found, a new element will not be created until a <i>_stp_map_set_xxx</i>
00415  * call.
00416  * @param map
00417  * @param key 
00418  */
00419 
00420 void _stp_map_key_long(MAP map, long key)
00421 {
00422         if (map == NULL)
00423                 return;
00424         _stp_map_key_long_long(map, key, 0);
00425         map->c_key2type = NONE;
00426 }
00427 
00428 /**********************  SET/GET VALUES *********************/
00429 
00430 static void map_copy_keys(MAP map, struct map_node *m)
00431 {
00432         m->key1type = map->c_key1type;
00433         m->key2type = map->c_key2type;
00434         switch (map->c_key1type) {
00435         case STR:
00436                 m->key1.str = _stp_alloc(strlen(map->c_key1.str) + 1);
00437                 strcpy(m->key1.str, map->c_key1.str);
00438                 break;
00439         case LONG:
00440                 m->key1.val = map->c_key1.val;
00441                 break;
00442         case NONE:
00443                 /* ERROR */
00444                 break;
00445         }
00446         switch (map->c_key2type) {
00447         case STR:
00448                 m->key2.str = _stp_alloc(strlen(map->c_key2.str) + 1);
00449                 strcpy(m->key2.str, map->c_key2.str);
00450                 break;
00451         case LONG:
00452                 m->key2.val = map->c_key2.val;
00453                 break;
00454         case NONE:
00455                 break;
00456         }
00457 
00458         /* add node to new hash list */
00459         hlist_add_head(&m->hnode, map->c_keyhead);
00460         
00461         map->key = m;
00462         map->create = 0;
00463         map->num++;
00464 }
00465 
00466 static void __stp_map_set_int64(MAP map, int64_t val, int add)
00467 {
00468         struct map_node_int64 *m;
00469 
00470         if (map == NULL)
00471                 return;
00472 
00473         if (map->create) {
00474                 if (val == 0)
00475                         return;
00476 
00477                 if (map->maxnum) {
00478                         if (list_empty(&map->pool)) {
00479                                 if (map->no_wrap) {
00480                                         /* ERROR. FIXME */
00481                                         return;
00482                                 }
00483                                 m = (struct map_node_int64 *)map->head.next;
00484                                 hlist_del_init(&m->n.hnode);
00485                                 map_free_strings(map, (struct map_node *)m);
00486                                 dbug ("got %lx off head\n", (long)m);
00487                         } else {
00488                                 m = (struct map_node_int64 *)map->pool.next;
00489                                 dbug ("got %lx off pool\n", (long)m);
00490                         }
00491                         list_move_tail(&m->n.lnode, &map->head);
00492                 } else {
00493                         m = (struct map_node_int64 *)
00494                             _stp_calloc(sizeof(struct map_node_int64));
00495                         /* add node to list */
00496                         list_add_tail(&m->n.lnode, &map->head);
00497                 }
00498 
00499                 /* copy the key(s) */
00500                 map_copy_keys(map, &m->n);
00501 
00502                 /* set the value */
00503                 m->val = val;
00504         } else {
00505                 if (map->key == NULL)
00506                         return;
00507 
00508                 if (val) {
00509                         m = (struct map_node_int64 *)map->key;
00510                         if (add)
00511                                 m->val += val;
00512                         else
00513                                 m->val = val;
00514                 } else if (!add) {
00515                         /* setting value to 0 is the same as deleting */
00516                         _stp_map_key_del(map);
00517                 }
00518         }
00519 }
00520 
00521 /** Set the current element's value to an int64.
00522  * This sets the current element's value to an int64. The map must have been created
00523  * to hold int64s using _stp_map_new()
00524  *
00525  * If the element doesn't exist, it is created.  If no current element (key)
00526  * is set for the map, this function does nothing.
00527  * @param map
00528  * @param val new value
00529  * @sa _stp_map_add_int64
00530  */
00531 void _stp_map_set_int64(MAP map, int64_t val)
00532 {
00533         __stp_map_set_int64 (map, val, 0);
00534 }
00535 
00536 
00537 /** Adds an int64 to the current element's value.
00538  * This adds an int64 to the current element's value. The map must have been created
00539  * to hold int64s using _stp_map_new()
00540  *
00541  * If the element doesn't exist, it is created.  If no current element (key)
00542  * is set for the map, this function does nothing.
00543  * @param map
00544  * @param val value
00545  * @sa _stp_map_set_int64
00546  */
00547 
00548 void _stp_map_add_int64(MAP map, int64_t val)
00549 {
00550         __stp_map_set_int64 (map, val, 1);
00551 }
00552 
00553 /** Gets the current element's value.
00554  * @param map
00555  * @returns The value. If the current element is not set or doesn't exist, returns 0.
00556  */
00557 
00558 int64_t _stp_map_get_int64(MAP map)
00559 {
00560         struct map_node_int64 *m;
00561         if (map == NULL || map->create || map->key == NULL)
00562                 return 0;
00563         dbug ("%lx\n", (long)map->key);
00564         m = (struct map_node_int64 *)map->key;
00565         return m->val;
00566 }
00567 
00568 /** Set the current element's value to a string.
00569  * This sets the current element's value to an string. The map must have been created
00570  * to hold int64s using <i>_stp_map_new(xxx, STRING)</i>
00571  *
00572  * If the element doesn't exist, it is created.  If no current element (key)
00573  * is set for the map, this function does nothing.
00574  * @param map
00575  * @param val new string
00576  */
00577 
00578 void _stp_map_set_str(MAP map, char *val)
00579 {
00580         struct map_node_str *m;
00581 
00582         if (map == NULL)
00583                 return;
00584 
00585         if (map->create) {
00586                 if (val == NULL)
00587                         return;
00588 
00589                 if (map->maxnum) {
00590                         if (list_empty(&map->pool)) {
00591                                 if (map->no_wrap) {
00592                                         /* ERROR. FIXME */
00593                                         return;
00594                                 }
00595                                 m = (struct map_node_str *)map->head.next;
00596                                 hlist_del_init(&m->n.hnode);
00597                                 map_free_strings(map, (struct map_node *)m);
00598                                 dbug ("got %lx off head\n", (long)m);
00599                         } else {
00600                                 m = (struct map_node_str *)map->pool.next;
00601                                 dbug ("got %lx off pool\n", (long)m);
00602                         }
00603                         list_move_tail(&m->n.lnode, &map->head);
00604                 } else {
00605                         m = (struct map_node_str *)
00606                             _stp_calloc(sizeof(struct map_node_str));
00607                         /* add node to list */
00608                         list_add_tail(&m->n.lnode, &map->head);
00609                 }
00610 
00611                 /* copy the key(s) */
00612                 map_copy_keys(map, &m->n);
00613 
00614                 /* set the value */
00615                 m->str = _stp_alloc(strlen(val) + 1);
00616                 strcpy(m->str, val);
00617         } else {
00618                 if (map->key == NULL)
00619                         return;
00620 
00621                 if (val) {
00622                         m = (struct map_node_str *)map->key;
00623                         if (m->str)
00624                                 _stp_free(m->str);
00625                         m->str = _stp_alloc(strlen(val) + 1);
00626                         strcpy(m->str, val);
00627                 } else {
00628                         /* setting value to 0 is the same as deleting */
00629                         _stp_map_key_del(map);
00630                 }
00631         }
00632 }
00633 
00634 /** Gets the current element's value.
00635  * @param map
00636  * @returns A string pointer. If the current element is not set or doesn't exist, returns NULL.
00637  */
00638 
00639 char *_stp_map_get_str(MAP map)
00640 {
00641         struct map_node_str *m;
00642         if (map == NULL || map->create || map->key == NULL)
00643                 return NULL;
00644         dbug ("%lx\n", (long)map->key);
00645         m = (struct map_node_str *)map->key;
00646         return m->str;
00647 }
00648 
00649 /** Set the current element's value to a stat.
00650  * This sets the current element's value to an stat struct. The map must have been created
00651  * to hold stats using <i>_stp_map_new(xxx, STAT)</i>.  This function would only be used
00652  * if we wanted to set stats to something other than the normal initial values (count = 0,
00653  * sum = 0, etc).  It may be deleted if it doesn't turn out to be useful.
00654  * @sa _stp_map_stat_add 
00655  *
00656  * If the element doesn't exist, it is created.  If no current element (key)
00657  * is set for the map, this function does nothing.
00658  * @param map
00659  * @param stats pointer to stats struct.
00660  * @todo Histograms don't work yet.
00661  */
00662 
00663 void _stp_map_set_stat(MAP map, stat * stats)
00664 {
00665         struct map_node_stat *m;
00666 
00667         if (map == NULL)
00668                 return;
00669         dbug ("set_stat %lx\n", (long)map->key);
00670 
00671         if (map->create) {
00672                 if (stats == NULL)
00673                         return;
00674 
00675                 if (map->maxnum) {
00676                         if (list_empty(&map->pool)) {
00677                                 if (map->no_wrap) {
00678                                         /* ERROR. FIXME */
00679                                         return;
00680                                 }
00681                                 m = (struct map_node_stat *)map->head.next;
00682                                 hlist_del_init(&m->n.hnode);
00683                                 map_free_strings(map, (struct map_node *)m);
00684                                 dbug ("got %lx off head\n", (long)m);
00685                         } else {
00686                                 m = (struct map_node_stat *)map->pool.next;
00687                                 dbug ("got %lx off pool\n", (long)m);
00688                         }
00689                         list_move_tail(&m->n.lnode, &map->head);
00690                 } else {
00691                         m = (struct map_node_stat *)
00692                             _stp_calloc(sizeof(struct map_node_stat));
00693                         /* add node to list */
00694                         list_add_tail(&m->n.lnode, &map->head);
00695                 }
00696 
00697                 /* copy the key(s) */
00698                 map_copy_keys(map, &m->n);
00699 
00700                 /* set the value */
00701                 memcpy(&m->stats, stats, sizeof(stat));
00702         } else {
00703                 if (map->key == NULL)
00704                         return;
00705 
00706                 if (stats) {
00707                         m = (struct map_node_stat *)map->key;
00708                         memcpy(&m->stats, stats, sizeof(stat));
00709                 } else {
00710                         /* setting value to NULL is the same as deleting */
00711                         _stp_map_key_del(map);
00712                 }
00713         }
00714 }
00715 
00716 /** Gets the current element's value.
00717  * @param map
00718  * @returns A pointer to the stats struct. If the current element is not set 
00719  * or doesn't exist, returns NULL.
00720  */
00721 
00722 stat *_stp_map_get_stat(MAP map)
00723 {
00724         struct map_node_stat *m;
00725         if (map == NULL || map->create || map->key == NULL)
00726                 return NULL;
00727         dbug ("%lx\n", (long)map->key);
00728         m = (struct map_node_stat *)map->key;
00729         return &m->stats;
00730 }
00731 
00732 /** Add to the current element's statistics.
00733  * Increments the statistics counter by one and the sum by <i>val</i>.
00734  * Adjusts minimum, maximum, and histogram.
00735  *
00736  * If the element doesn't exist, it is created.  If no current element (key)
00737  * is set for the map, this function does nothing.
00738  * @param map
00739  * @param val value to add to the statistics
00740  * @todo Histograms don't work yet.
00741  */
00742 
00743 void _stp_map_stat_add(MAP map, int64_t val)
00744 {
00745         struct map_node_stat *m;
00746         if (map == NULL)
00747                 return;
00748 
00749         if (map->create) {
00750                 stat st = { 1, val, val, val };
00751                 /* histogram */
00752                 _stp_map_set_stat(map, &st);
00753                 return;
00754         }
00755 
00756         if (map->key == NULL)
00757                 return;
00758 
00759         dbug ("add_stat %lx\n", (long)map->key);
00760         m = (struct map_node_stat *)map->key;
00761         m->stats.count++;
00762         m->stats.sum += val;
00763         if (val > m->stats.max)
00764                 m->stats.max = val;
00765         if (val < m->stats.min)
00766                 m->stats.min = val;
00767         /* histogram */
00768 }
00769 
00770 /**********************  List Functions *********************/
00771 
00772 /** Create a new list.
00773  * A list is a map that internally has an incrementing long key for each member.
00774  * Lists do not wrap if elements are added to exceed their maximum size.
00775  * @param max_entries The maximum number of entries allowed. Currently that number will
00776  * be preallocated.  If max_entries is 0, there will be no maximum and entries
00777  * will be allocated dynamically.
00778  * @param type Type of values stored in this list. 
00779  * @return A MAP on success or NULL on failure.
00780  * @sa foreach
00781  */
00782 
00783 MAP _stp_list_new(unsigned max_entries, enum valtype type)
00784 {
00785   MAP map = _stp_map_new (max_entries, type);
00786   map->no_wrap = 1;
00787   return map;
00788 }
00789 
00790 /** Clears a list.
00791  * All elements in the list are deleted.
00792  * @param map 
00793  */
00794 
00795 void _stp_list_clear(MAP map)
00796 {
00797         if (map == NULL)
00798                 return;
00799 
00800         if (!list_empty(&map->head)) {
00801                 struct map_node *ptr = (struct map_node *)map->head.next;
00802 
00803                 while (ptr && ptr != (struct map_node *)&map->head) {
00804                         struct map_node *next = (struct map_node *)ptr->lnode.next;
00805 
00806                         /* remove node from old hash list */
00807                         hlist_del_init(&ptr->hnode);
00808 
00809                         /* remove from entry list */
00810                         list_del(&ptr->lnode);
00811                         
00812                         /* remove any allocated string storage */
00813                         map_free_strings(map, ptr);
00814                         
00815                         if (map->maxnum)
00816                                 list_add(&ptr->lnode, &map->pool);
00817                         else
00818                                 _stp_free(ptr);
00819 
00820                         map->num--;
00821                         ptr = next;
00822                 }
00823         }
00824 
00825         if (map->num != 0) {
00826                 dlog ("ERROR: list is supposed to be empty (has %d)\n", map->num);
00827         }
00828 }
00829 
00830 /** Adds a string to a list.
00831  * @param map
00832  * @param str
00833  */
00834 
00835 inline void _stp_list_add_str(MAP map, char *str)
00836 {
00837         _stp_map_key_long(map, map->num);
00838         _stp_map_set_str(map, str);
00839 }
00840 
00841 /** Adds an int64 to a list.
00842  * @param map
00843  * @param val
00844  */
00845 
00846 inline void _stp_list_add_int64(MAP map, int64_t val)
00847 {
00848         _stp_map_key_long(map, map->num);
00849         _stp_map_set_int64(map, val);
00850 }
00851 
00852 /** Get the number of elements in a list.
00853  * @param map
00854  * @returns The number of elements in a list.
00855  */
00856 
00857 inline int _stp_list_size(MAP map)
00858 {
00859         return map->num;
00860 }

Generated on Tue Mar 22 00:32:02 2005 for SystemTap.