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