Intro | Functions | Defines | Enumerations | Enumeration Values

map.c

Go to the documentation of this file.
00001 /* -*- linux-c -*- */
00002 
00003 static int map_sizes[] = {
00004         sizeof(struct map_node_int64),
00005         sizeof(struct map_node_stat),
00006         sizeof(struct map_node_str),
00007         0
00008 };
00009 
00010 static inline unsigned string_hash(const char *key1, const char *key2)
00011 {
00012         int hash = 0, count = 0;
00013         char *v1 = (char *)key1;
00014         char *v2 = (char *)key2;
00015         while (*v1 && count++ < 5) {
00016                 hash += *v1++;
00017         }
00018         while (v2 && *v2 && count++ < 5) {
00019                 hash += *v2++;
00020         }
00021         return hash_long((unsigned long)hash, HASH_TABLE_BITS);
00022 }
00023 
00024 static inline unsigned mixed_hash(const char *key1, long key2)
00025 {
00026         int hash = 0, count = 0;
00027         char *v = (char *)key1;
00028         while (v && *v && count++ < 5)
00029                 hash += *v++;
00030         return hash_long((unsigned long)(hash ^ key2), HASH_TABLE_BITS);
00031 }
00032 
00043 MAP _stp_map_new(unsigned max_entries, enum valtype type)
00044 {
00045         size_t size;
00046         MAP m = (MAP) _stp_valloc(sizeof(struct map_root));
00047         if (m == NULL)
00048                 return NULL;
00049 
00050         INIT_LIST_HEAD(&m->head);
00051 
00052         m->maxnum = max_entries;
00053         m->type = type;
00054         if (type >= END) {
00055                 dbug ("map_new: unknown type %d\n", type);
00056                 return NULL;
00057         }
00058 
00059         if (max_entries) {
00060                 void *tmp;
00061                 int i;
00062                 struct list_head *e;
00063 
00064                 INIT_LIST_HEAD(&m->pool);
00065                 size = map_sizes[type];
00066                 tmp = _stp_valloc(max_entries * size);
00067 
00068                 for (i = max_entries - 1; i >= 0; i--) {
00069                         e = i * size + tmp;
00070                         dbug ("e=%lx\n", (long)e);
00071                         list_add(e, &m->pool);
00072                 }
00073                 m->membuf = tmp;
00074         }
00075         return m;
00076 }
00077 
00078 static void map_free_strings(MAP map, struct map_node *n)
00079 {
00080         struct map_node_str *m = (struct map_node_str *)n;
00081         dbug ("n = %lx\n", (long)n);
00082         if (map->type == STRING) {
00083                 dbug ("val STRING %lx\n", (long)m->str);
00084                 if (m->str)
00085                         _stp_free(m->str);
00086         }
00087         if (m->n.key1type == STR) {
00088                 dbug ("key1 STR %lx\n", (long)key1str(m));
00089                 if (key1str(m))
00090                         _stp_free(key1str(m));
00091         }
00092         if (m->n.key2type == STR) {
00093                 dbug ("key2 STR %lx\n", (long)key2str(m));
00094                 if (key2str(m))
00095                         _stp_free(key2str(m));
00096         }
00097 }
00098 
00104 void _stp_map_key_del(MAP map)
00105 {
00106         struct map_node *m;
00107 
00108         dbug ("create=%d key=%lx\n", map->create, (long)map->key);
00109         if (map == NULL)
00110                 return;
00111 
00112         if (map->create) {
00113                 map->create = 0;
00114                 map->key = NULL;
00115                 return;
00116         }
00117 
00118         if (map->key == NULL)
00119                 return;
00120 
00121         m = (struct map_node *)map->key;
00122 
00123         /* remove node from old hash list */
00124         hlist_del_init(&m->hnode);
00125 
00126         /* remove from entry list */
00127         list_del(&m->lnode);
00128 
00129         /* remove any allocated string storage */
00130         map_free_strings(map, (struct map_node *)map->key);
00131 
00132         if (map->maxnum)
00133                 list_add(&m->lnode, &map->pool);
00134         else
00135                 _stp_free(m);
00136 
00137         map->key = NULL;
00138         map->num--;
00139 }
00140 
00149 struct map_node *_stp_map_start(MAP map)
00150 {
00151         if (map == NULL)
00152                 return NULL;
00153 
00154         dbug ("%lx\n", (long)map->head.next);
00155 
00156         if (list_empty(&map->head))
00157                 return NULL;
00158 
00159         return (struct map_node *)map->head.next;
00160 }
00161 
00172 struct map_node *_stp_map_iter(MAP map, struct map_node *m)
00173 {
00174         if (map == NULL)
00175                 return NULL;
00176 
00177         dbug ("%lx next=%lx  prev=%lx  map->head.next=%lx\n", (long)m, (long)m->lnode.next, (long)m->lnode.prev, (long)map->head.next);
00178 
00179         if (m->lnode.next == &map->head)
00180                 return NULL;
00181 
00182         return (struct map_node *)m->lnode.next;
00183 }
00184 
00190 void _stp_map_del(MAP map)
00191 {
00192         if (map == NULL)
00193                 return;
00194 
00195         if (!list_empty(&map->head)) {
00196                 struct map_node *ptr = (struct map_node *)map->head.next;
00197                 while (ptr && ptr != (struct map_node *)&map->head) {
00198                         map_free_strings(map, ptr);
00199                         ptr = (struct map_node *)ptr->lnode.next;
00200                 }
00201         }
00202         _stp_vfree(map->membuf);
00203         _stp_vfree(map);
00204 }
00205 
00206 /**********************  KEY FUNCTIONS *********************/
00207 
00208 
00218 void _stp_map_key_long_long(MAP map, long key1, long key2)
00219 {
00220         unsigned hv;
00221         struct hlist_head *head;
00222         struct hlist_node *e;
00223 
00224         if (map == NULL)
00225                 return;
00226 
00227         hv = hash_long(key1 ^ key2, HASH_TABLE_BITS);
00228         head = &map->hashes[hv];
00229 
00230         dbug ("hash for %ld,%ld is %d\n", key1, key2, hv);
00231 
00232         hlist_for_each(e, head) {
00233                 struct map_node *n =
00234                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00235                 dbug ("n =%lx  key=%ld,%ld\n", (long)n, n->key1.val, n->key2.val);
00236                 if (key1 == n->key1.val && key2 == n->key2.val) {
00237                         map->key = n;
00238                         dbug ("saving key %lx\n", (long)map->key);
00239                         map->create = 0;
00240                         return;
00241                 }
00242         }
00243 
00244         map->c_key1.val = key1;
00245         map->c_key2.val = key2;
00246         map->c_key1type = LONG;
00247         map->c_key2type = LONG;
00248         map->c_keyhead = head;
00249         map->create = 1;
00250 }
00251 
00261 void _stp_map_key_str_str(MAP map, char *key1, char *key2)
00262 {
00263         unsigned hv;
00264         struct hlist_head *head;
00265         struct hlist_node *e;
00266 
00267         if (map == NULL)
00268                 return;
00269 
00270         if (key1 == NULL) {
00271                 map->key = NULL;
00272                 return;
00273         }
00274 
00275         hv = string_hash(key1, key2);
00276         head = &map->hashes[hv];
00277 
00278         dbug ("hash for %s,%s is %d\n", key1, key2, hv);
00279 
00280         hlist_for_each(e, head) {
00281                 struct map_node *n =
00282                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00283                 dbug ("e =%lx  key=%s,%s\n", (long)e, n->key1.str,n->key2.str);
00284                 if (strcmp(key1, n->key1.str) == 0
00285                     && (key2 == NULL || strcmp(key2, n->key2.str) == 0)) {
00286                         map->key = n;
00287                         dbug ("saving key %lx\n", (long)map->key);
00288                         map->create = 0;
00289                         return;
00290                 }
00291         }
00292 
00293         map->c_key1.str = key1;
00294         map->c_key2.str = key2;
00295         map->c_key1type = STR;
00296         map->c_key2type = STR;
00297         map->c_keyhead = head;
00298         map->create = 1;
00299 }
00300 
00310 void _stp_map_key_str_long(MAP map, char *key1, long key2)
00311 {
00312         unsigned hv;
00313         struct hlist_head *head;
00314         struct hlist_node *e;
00315 
00316         if (map == NULL)
00317                 return;
00318 
00319         if (key1 == NULL) {
00320                 map->key = NULL;
00321                 return;
00322         }
00323 
00324         hv = mixed_hash(key1, key2);
00325         head = &map->hashes[hv];
00326 
00327         dbug ("hash for %s,%ld is %d\n", key1, key2, hv);
00328 
00329         hlist_for_each(e, head) {
00330                 struct map_node *n =
00331                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00332                 dbug ("e =%lx  key=%s,%ld\n", (long)e, n->key1.str,(long)n->key2.val);
00333                 if (strcmp(key1, n->key1.str) == 0 && key2 == n->key2.val) {
00334                         map->key = n;
00335                         dbug ("saving key %lx\n", (long)map->key);
00336                         map->create = 0;
00337                         return;
00338                 }
00339         }
00340 
00341         map->c_key1.str = key1;
00342         map->c_key2.val = key2;
00343         map->c_key1type = STR;
00344         map->c_key2type = LONG;
00345         map->c_keyhead = head;
00346         map->create = 1;
00347 }
00348 
00358 void _stp_map_key_long_str(MAP map, long key1, char *key2)
00359 {
00360         unsigned hv;
00361         struct hlist_head *head;
00362         struct hlist_node *e;
00363 
00364         if (map == NULL)
00365                 return;
00366 
00367         hv = mixed_hash(key2, key1);
00368         head = &map->hashes[hv];
00369         dbug ("hash for %ld,%s is %d\n", key1, key2, hv);
00370 
00371         hlist_for_each(e, head) {
00372                 struct map_node *n =
00373                         (struct map_node *)((long)e - sizeof(struct hlist_node));
00374                 dbug ("e =%lx  key=%ld,%s\n", (long)e, n->key1.val,n->key2.str);
00375                 if (key1 == n->key1.val && strcmp(key2, n->key2.str) == 0) {
00376                         map->key = n;
00377                         dbug ("saving key %lx\n", (long)map->key);
00378                         map->create = 0;
00379                         return;
00380                 }
00381         }
00382 
00383         map->c_key1.val = key1;
00384         map->c_key2.str = key2;
00385         map->c_key1type = LONG;
00386         map->c_key2type = STR;
00387         map->c_keyhead = head;
00388         map->create = 1;
00389 }
00390 
00399 void _stp_map_key_str(MAP map, char *key)
00400 {
00401         if (map == NULL)
00402                 return;
00403         _stp_map_key_str_str(map, key, NULL);
00404         map->c_key2type = NONE;
00405 }
00406 
00415 void _stp_map_key_long(MAP map, long key)
00416 {
00417         if (map == NULL)
00418                 return;
00419         _stp_map_key_long_long(map, key, 0);
00420         map->c_key2type = NONE;
00421 }
00422 
00423 /**********************  SET/GET VALUES *********************/
00424 
00425 static void map_copy_keys(MAP map, struct map_node *m)
00426 {
00427         m->key1type = map->c_key1type;
00428         m->key2type = map->c_key2type;
00429         switch (map->c_key1type) {
00430         case STR:
00431                 m->key1.str = _stp_alloc(strlen(map->c_key1.str) + 1);
00432                 strcpy(m->key1.str, map->c_key1.str);
00433                 break;
00434         case LONG:
00435                 m->key1.val = map->c_key1.val;
00436                 break;
00437         case NONE:
00438                 /* ERROR */
00439                 break;
00440         }
00441         switch (map->c_key2type) {
00442         case STR:
00443                 m->key2.str = _stp_alloc(strlen(map->c_key2.str) + 1);
00444                 strcpy(m->key2.str, map->c_key2.str);
00445                 break;
00446         case LONG:
00447                 m->key2.val = map->c_key2.val;
00448                 break;
00449         case NONE:
00450                 break;
00451         }
00452 
00453         /* add node to new hash list */
00454         hlist_add_head(&m->hnode, map->c_keyhead);
00455         
00456         map->key = m;
00457         map->create = 0;
00458         map->num++;
00459 }
00460 
00461 static void __stp_map_set_int64(MAP map, int64_t val, int add)
00462 {
00463         struct map_node_int64 *m;
00464 
00465         if (map == NULL)
00466                 return;
00467 
00468         if (map->create) {
00469                 if (val == 0)
00470                         return;
00471 
00472                 if (map->maxnum) {
00473                         if (list_empty(&map->pool)) {
00474                                 if (map->no_wrap) {
00475                                         /* ERROR. FIXME */
00476                                         return;
00477                                 }
00478                                 m = (struct map_node_int64 *)map->head.next;
00479                                 hlist_del_init(&m->n.hnode);
00480                                 map_free_strings(map, (struct map_node *)m);
00481                                 dbug ("got %lx off head\n", (long)m);
00482                         } else {
00483                                 m = (struct map_node_int64 *)map->pool.next;
00484                                 dbug ("got %lx off pool\n", (long)m);
00485                         }
00486                         list_move_tail(&m->n.lnode, &map->head);
00487                 } else {
00488                         m = (struct map_node_int64 *)
00489                             _stp_calloc(sizeof(struct map_node_int64));
00490                         /* add node to list */
00491                         list_add_tail(&m->n.lnode, &map->head);
00492                 }
00493 
00494                 /* copy the key(s) */
00495                 map_copy_keys(map, &m->n);
00496 
00497                 /* set the value */
00498                 m->val = val;
00499         } else {
00500                 if (map->key == NULL)
00501                         return;
00502 
00503                 if (val) {
00504                         m = (struct map_node_int64 *)map->key;
00505                         if (add)
00506                                 m->val += val;
00507                         else
00508                                 m->val = val;
00509                 } else if (!add) {
00510                         /* setting value to 0 is the same as deleting */
00511                         _stp_map_key_del(map);
00512                 }
00513         }
00514 }
00515 
00525 void _stp_map_set_int64(MAP map, int64_t val)
00526 {
00527         __stp_map_set_int64 (map, val, 0);
00528 }
00529 
00530 
00541 void _stp_map_add_int64(MAP map, int64_t val)
00542 {
00543         __stp_map_set_int64 (map, val, 1);
00544 }
00545 
00551 int64_t _stp_map_get_int64(MAP map)
00552 {
00553         struct map_node_int64 *m;
00554         if (map == NULL || map->create || map->key == NULL)
00555                 return 0;
00556         dbug ("%lx\n", (long)map->key);
00557         m = (struct map_node_int64 *)map->key;
00558         return m->val;
00559 }
00560 
00571 void _stp_map_set_str(MAP map, char *val)
00572 {
00573         struct map_node_str *m;
00574 
00575         if (map == NULL)
00576                 return;
00577 
00578         if (map->create) {
00579                 if (val == NULL)
00580                         return;
00581 
00582                 if (map->maxnum) {
00583                         if (list_empty(&map->pool)) {
00584                                 if (map->no_wrap) {
00585                                         /* ERROR. FIXME */
00586                                         return;
00587                                 }
00588                                 m = (struct map_node_str *)map->head.next;
00589                                 hlist_del_init(&m->n.hnode);
00590                                 map_free_strings(map, (struct map_node *)m);
00591                                 dbug ("got %lx off head\n", (long)m);
00592                         } else {
00593                                 m = (struct map_node_str *)map->pool.next;
00594                                 dbug ("got %lx off pool\n", (long)m);
00595                         }
00596                         list_move_tail(&m->n.lnode, &map->head);
00597                 } else {
00598                         m = (struct map_node_str *)
00599                             _stp_calloc(sizeof(struct map_node_str));
00600                         /* add node to list */
00601                         list_add_tail(&m->n.lnode, &map->head);
00602                 }
00603 
00604                 /* copy the key(s) */
00605                 map_copy_keys(map, &m->n);
00606 
00607                 /* set the value */
00608                 m->str = _stp_alloc(strlen(val) + 1);
00609                 strcpy(m->str, val);
00610         } else {
00611                 if (map->key == NULL)
00612                         return;
00613 
00614                 if (val) {
00615                         m = (struct map_node_str *)map->key;
00616                         if (m->str)
00617                                 _stp_free(m->str);
00618                         m->str = _stp_alloc(strlen(val) + 1);
00619                         strcpy(m->str, val);
00620                 } else {
00621                         /* setting value to 0 is the same as deleting */
00622                         _stp_map_key_del(map);
00623                 }
00624         }
00625 }
00626 
00632 char *_stp_map_get_str(MAP map)
00633 {
00634         struct map_node_str *m;
00635         if (map == NULL || map->create || map->key == NULL)
00636                 return NULL;
00637         dbug ("%lx\n", (long)map->key);
00638         m = (struct map_node_str *)map->key;
00639         return m->str;
00640 }
00641 
00656 void _stp_map_set_stat(MAP map, stat * stats)
00657 {
00658         struct map_node_stat *m;
00659 
00660         if (map == NULL)
00661                 return;
00662         dbug ("set_stat %lx\n", (long)map->key);
00663 
00664         if (map->create) {
00665                 if (stats == NULL)
00666                         return;
00667 
00668                 if (map->maxnum) {
00669                         if (list_empty(&map->pool)) {
00670                                 if (map->no_wrap) {
00671                                         /* ERROR. FIXME */
00672                                         return;
00673                                 }
00674                                 m = (struct map_node_stat *)map->head.next;
00675                                 hlist_del_init(&m->n.hnode);
00676                                 map_free_strings(map, (struct map_node *)m);
00677                                 dbug ("got %lx off head\n", (long)m);
00678                         } else {
00679                                 m = (struct map_node_stat *)map->pool.next;
00680                                 dbug ("got %lx off pool\n", (long)m);
00681                         }
00682                         list_move_tail(&m->n.lnode, &map->head);
00683                 } else {
00684                         m = (struct map_node_stat *)
00685                             _stp_calloc(sizeof(struct map_node_stat));
00686                         /* add node to list */
00687                         list_add_tail(&m->n.lnode, &map->head);
00688                 }
00689 
00690                 /* copy the key(s) */
00691                 map_copy_keys(map, &m->n);
00692 
00693                 /* set the value */
00694                 memcpy(&m->stats, stats, sizeof(stat));
00695         } else {
00696                 if (map->key == NULL)
00697                         return;
00698 
00699                 if (stats) {
00700                         m = (struct map_node_stat *)map->key;
00701                         memcpy(&m->stats, stats, sizeof(stat));
00702                 } else {
00703                         /* setting value to NULL is the same as deleting */
00704                         _stp_map_key_del(map);
00705                 }
00706         }
00707 }
00708 
00715 stat *_stp_map_get_stat(MAP map)
00716 {
00717         struct map_node_stat *m;
00718         if (map == NULL || map->create || map->key == NULL)
00719                 return NULL;
00720         dbug ("%lx\n", (long)map->key);
00721         m = (struct map_node_stat *)map->key;
00722         return &m->stats;
00723 }
00724 
00736 void _stp_map_stat_add(MAP map, int64_t val)
00737 {
00738         struct map_node_stat *m;
00739         if (map == NULL)
00740                 return;
00741 
00742         if (map->create) {
00743                 stat st = { 1, val, val, val };
00744                 /* histogram */
00745                 _stp_map_set_stat(map, &st);
00746                 return;
00747         }
00748 
00749         if (map->key == NULL)
00750                 return;
00751 
00752         dbug ("add_stat %lx\n", (long)map->key);
00753         m = (struct map_node_stat *)map->key;
00754         m->stats.count++;
00755         m->stats.sum += val;
00756         if (val > m->stats.max)
00757                 m->stats.max = val;
00758         if (val < m->stats.min)
00759                 m->stats.min = val;
00760         /* histogram */
00761 }
00762 
00763 /**********************  List Functions *********************/
00764 
00776 MAP _stp_list_new(unsigned max_entries, enum valtype type)
00777 {
00778   MAP map = _stp_map_new (max_entries, type);
00779   map->no_wrap = 1;
00780   return map;
00781 }
00782 
00788 inline void _stp_list_clear(MAP map)
00789 {
00790         if (map == NULL)
00791                 return;
00792 
00793         if (!list_empty(&map->head)) {
00794                 struct map_node *ptr = (struct map_node *)map->head.next;
00795 
00796                 while (ptr && ptr != (struct map_node *)&map->head) {
00797                         struct map_node *next = (struct map_node *)ptr->lnode.next;
00798 
00799                         /* remove node from old hash list */
00800                         hlist_del_init(&ptr->hnode);
00801 
00802                         /* remove from entry list */
00803                         list_del(&ptr->lnode);
00804                         
00805                         /* remove any allocated string storage */
00806                         map_free_strings(map, ptr);
00807                         
00808                         if (map->maxnum)
00809                                 list_add(&ptr->lnode, &map->pool);
00810                         else
00811                                 _stp_free(ptr);
00812 
00813                         map->num--;
00814                         ptr = next;
00815                 }
00816         }
00817 
00818         if (map->num != 0) {
00819                 dlog ("ERROR: list is supposed to be empty (has %d)\n", map->num);
00820         }
00821 }
00822 
00828 inline void _stp_list_add_str(MAP map, char *str)
00829 {
00830         _stp_map_key_long(map, map->num);
00831         _stp_map_set_str(map, str);
00832 }
00833 
00839 inline void _stp_list_add_int64(MAP map, int64_t val)
00840 {
00841         _stp_map_key_long(map, map->num);
00842         _stp_map_set_int64(map, val);
00843 }
00844 
00850 inline int _stp_list_size(MAP map)
00851 {
00852         return map->num;
00853 }

Generated on Mon Mar 21 13:29:45 2005 for SystemTap by  doxygen 1.4.1