00001 #ifndef _MAP_C_
00002 #define _MAP_C_
00003
00004
00005
00006
00007
00008 #include "map.h"
00009 #include "alloc.c"
00010 #include "string.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
00542 void _stp_map_set_int64(MAP map, int64_t val)
00543 {
00544 __stp_map_set_int64 (map, val, 0);
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 void _stp_map_add_int64(MAP map, int64_t val)
00560 {
00561 __stp_map_set_int64 (map, val, 1);
00562 }
00563
00564
00565
00566
00567
00568
00569 int64_t _stp_map_get_int64(MAP map)
00570 {
00571 struct map_node_int64 *m;
00572 if (map == NULL || map->create || map->key == NULL)
00573 return 0;
00574 dbug ("%lx\n", (long)map->key);
00575 m = (struct map_node_int64 *)map->key;
00576 return m->val;
00577 }
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 void _stp_map_set_str(MAP map, char *val)
00591 {
00592 struct map_node_str *m;
00593
00594 if (map == NULL)
00595 return;
00596
00597 if (map->create) {
00598 if (val == NULL)
00599 return;
00600
00601 if (map->maxnum) {
00602 if (list_empty(&map->pool)) {
00603 if (map->no_wrap) {
00604
00605 return;
00606 }
00607 m = (struct map_node_str *)map->head.next;
00608 hlist_del_init(&m->n.hnode);
00609 map_free_strings(map, (struct map_node *)m);
00610 dbug ("got %lx off head\n", (long)m);
00611 } else {
00612 m = (struct map_node_str *)map->pool.next;
00613 dbug ("got %lx off pool\n", (long)m);
00614 }
00615 list_move_tail(&m->n.lnode, &map->head);
00616 } else {
00617 m = (struct map_node_str *)
00618 _stp_calloc(sizeof(struct map_node_str));
00619
00620 list_add_tail(&m->n.lnode, &map->head);
00621 }
00622
00623
00624 map_copy_keys(map, &m->n);
00625
00626
00627 m->str = _stp_alloc(strlen(val) + 1);
00628 strcpy(m->str, val);
00629 } else {
00630 if (map->key == NULL)
00631 return;
00632
00633 if (val) {
00634 m = (struct map_node_str *)map->key;
00635 if (m->str)
00636 _stp_free(m->str);
00637 m->str = _stp_alloc(strlen(val) + 1);
00638 strcpy(m->str, val);
00639 } else {
00640
00641 _stp_map_key_del(map);
00642 }
00643 }
00644 }
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657 void _stp_map_set_string (MAP map, String str)
00658 {
00659 _stp_map_set_str (map, str->buf);
00660 }
00661
00662
00663
00664
00665
00666
00667 char *_stp_map_get_str(MAP map)
00668 {
00669 struct map_node_str *m;
00670 if (map == NULL || map->create || map->key == NULL)
00671 return NULL;
00672 dbug ("%lx\n", (long)map->key);
00673 m = (struct map_node_str *)map->key;
00674 return m->str;
00675 }
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 void _stp_map_set_stat(MAP map, stat * stats)
00692 {
00693 struct map_node_stat *m;
00694
00695 if (map == NULL)
00696 return;
00697 dbug ("set_stat %lx\n", (long)map->key);
00698
00699 if (map->create) {
00700 if (stats == NULL)
00701 return;
00702
00703 if (map->maxnum) {
00704 if (list_empty(&map->pool)) {
00705 if (map->no_wrap) {
00706
00707 return;
00708 }
00709 m = (struct map_node_stat *)map->head.next;
00710 hlist_del_init(&m->n.hnode);
00711 map_free_strings(map, (struct map_node *)m);
00712 dbug ("got %lx off head\n", (long)m);
00713 } else {
00714 m = (struct map_node_stat *)map->pool.next;
00715 dbug ("got %lx off pool\n", (long)m);
00716 }
00717 list_move_tail(&m->n.lnode, &map->head);
00718 } else {
00719 m = (struct map_node_stat *)
00720 _stp_calloc(sizeof(struct map_node_stat));
00721
00722 list_add_tail(&m->n.lnode, &map->head);
00723 }
00724
00725
00726 map_copy_keys(map, &m->n);
00727
00728
00729 memcpy(&m->stats, stats, sizeof(stat));
00730 } else {
00731 if (map->key == NULL)
00732 return;
00733
00734 if (stats) {
00735 m = (struct map_node_stat *)map->key;
00736 memcpy(&m->stats, stats, sizeof(stat));
00737 } else {
00738
00739 _stp_map_key_del(map);
00740 }
00741 }
00742 }
00743
00744
00745
00746
00747
00748
00749
00750 stat *_stp_map_get_stat(MAP map)
00751 {
00752 struct map_node_stat *m;
00753 if (map == NULL || map->create || map->key == NULL)
00754 return NULL;
00755 dbug ("%lx\n", (long)map->key);
00756 m = (struct map_node_stat *)map->key;
00757 return &m->stats;
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 void _stp_map_stat_add(MAP map, int64_t val)
00772 {
00773 struct map_node_stat *m;
00774 if (map == NULL)
00775 return;
00776
00777 if (map->create) {
00778 stat st = { 1, val, val, val };
00779
00780 _stp_map_set_stat(map, &st);
00781 return;
00782 }
00783
00784 if (map->key == NULL)
00785 return;
00786
00787 dbug ("add_stat %lx\n", (long)map->key);
00788 m = (struct map_node_stat *)map->key;
00789 m->stats.count++;
00790 m->stats.sum += val;
00791 if (val > m->stats.max)
00792 m->stats.max = val;
00793 if (val < m->stats.min)
00794 m->stats.min = val;
00795
00796 }
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 MAP _stp_list_new(unsigned max_entries, enum valtype type)
00820 {
00821 MAP map = _stp_map_new (max_entries, type);
00822 map->no_wrap = 1;
00823 return map;
00824 }
00825
00826
00827
00828
00829
00830
00831 void _stp_list_clear(MAP map)
00832 {
00833 if (map == NULL)
00834 return;
00835
00836 if (!list_empty(&map->head)) {
00837 struct map_node *ptr = (struct map_node *)map->head.next;
00838
00839 while (ptr && ptr != (struct map_node *)&map->head) {
00840 struct map_node *next = (struct map_node *)ptr->lnode.next;
00841
00842
00843 hlist_del_init(&ptr->hnode);
00844
00845
00846 list_del(&ptr->lnode);
00847
00848
00849 map_free_strings(map, ptr);
00850
00851 if (map->maxnum)
00852 list_add(&ptr->lnode, &map->pool);
00853 else
00854 _stp_free(ptr);
00855
00856 map->num--;
00857 ptr = next;
00858 }
00859 }
00860
00861 if (map->num != 0) {
00862 _stp_log ("ERROR: list is supposed to be empty (has %d)\n", map->num);
00863 }
00864 }
00865
00866
00867
00868
00869
00870
00871
00872 inline void _stp_list_add_str(MAP map, char *str)
00873 {
00874 _stp_map_key_long(map, map->num);
00875 _stp_map_set_str(map, str);
00876 }
00877
00878
00879
00880
00881
00882
00883
00884 inline void _stp_list_add_string (MAP map, String str)
00885 {
00886 _stp_map_key_long(map, map->num);
00887 _stp_map_set_str(map, str->buf);
00888 }
00889
00890
00891
00892
00893
00894
00895
00896 inline void _stp_list_add_int64(MAP map, int64_t val)
00897 {
00898 _stp_map_key_long(map, map->num);
00899 _stp_map_set_int64(map, val);
00900 }
00901
00902
00903
00904
00905
00906
00907 inline int _stp_list_size(MAP map)
00908 {
00909 return map->num;
00910 }
00911
00912 #endif