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