root/src/map.cc

Revision 5, 3.6 KB (checked in by nick, 3 years ago)
Line 
1#include "apachetop.h"
2
3/* string to hash map, and vice versa; for quick string lookups */
4
5extern Circle *c;
6extern time_t now;
7
8int map::create(int passed_size)
9{
10        size = passed_size;
11
12        tab = (struct hash_struct *)malloc(size * sizeof(struct hash_struct));
13
14        /* initialise map to be empty */
15        this->empty(0, size);
16
17        /* a hash for quick string lookups */
18        tab_hash = new OAHash;
19        tab_hash->create(size*9);
20       
21        return 0;
22}
23
24void map::empty(int from, int to)
25{
26        int x;
27        struct hash_struct *ptr;
28
29        for(ptr = &tab[from], x = from; x < to; ++ptr, ++x)
30        {
31                ptr->refcount = 0;
32                ptr->pos = x;
33                ptr->string = NULL;
34                ptr->time = 0;
35        }
36
37        return;
38}
39
40int map::destroy(void)
41{
42        free(tab);
43
44        tab_hash->destroy();
45        delete tab_hash;
46
47        return 0;
48}
49
50int map::resize(int newsize)
51{
52        int x;
53        struct hash_struct *newtab;
54
55        /* we have to resize the tab, then clear the hash, remake the hash
56         * at the newsize*5, then re-populate the hash. Remaking the hash is
57         * quite expensive, so we'd like to do this as infrequently as
58         * possible */
59        newtab = (struct hash_struct *)
60            realloc(tab, newsize * sizeof(struct hash_struct));
61       
62        /* did it work? */
63        if (!newtab)
64        {
65                perror("realloc map");
66                exit(1);
67        }
68
69        tab = newtab;
70
71        /* empty the new area */
72        this->empty(size, newsize);
73
74        /* remake the hash since memory addresses may have moved */
75        delete tab_hash;
76        tab_hash = new OAHash;
77        tab_hash->create(newsize*9);
78        for (x = 0 ; x < size ; ++x)
79        {
80                tab_hash->insert(tab[x].string, &tab[x]);
81        }
82
83//      dprintf("%p resize from %d to %d\n", this, size, newsize);
84
85        size = newsize;
86
87        return 0;
88}
89
90int map::insert(char *string)
91{
92        int x;
93        struct hash_struct *ptr;
94       
95        /* if this string is in the map, return existing position only */
96        if ((x = this->lookup(string)) != -1)
97        {
98                /* we wanted to insert, but didn't, so the refcount for this
99                 * particular entry is incremented */
100                tab[x].refcount++;
101
102//              dprintf("%d Found %p %d for %s\n", time(NULL), this, x, string);
103                return x;
104        }
105       
106        /* find free table slot FIXME make this more efficient */
107        for (ptr = &tab[0], x = 0; x <= size; ++ptr, ++x)
108        {
109                if (x == size)
110                {
111                        /* none free, make room */
112                        this->resize(size * 2);
113
114                        /* realloc may well move the table in
115                         * memory so update the pointer */
116                        ptr = &tab[x];
117
118                        break;
119                }
120
121                /* if this map entry has a refcount of zero (this is new in
122                 * v0.12) then nothing is pointing at it, hopefully, so it
123                 * can be nuked */
124                if (ptr->refcount == 0)
125                        break;
126        }
127
128        /* if we are re-using, free up the old data */
129        if (ptr->string)
130        {
131                tab_hash->remove(ptr->string);
132                free(ptr->string);
133        }
134
135//      dprintf("%d Using %p %d for %s\n", time(NULL), this, x, string);
136
137        /* make entry in our table */
138        ptr->time = now;
139        ptr->refcount = 1;
140        ptr->string = strdup(string);
141
142        /* add into hash */
143        tab_hash->insert(ptr->string, ptr);
144
145        return x;
146}
147
148int map::remove(char *string)
149{
150        struct hash_struct *ptr;
151
152        /* find string in hash */
153        if ((ptr = (struct hash_struct *)tab_hash->lookup(string)))
154        {
155//              dprintf("%d Remove %p %d for %s\n", time(NULL), this, ptr->pos, string);
156
157                /* remove from table */
158                free(ptr->string);
159                ptr->string = NULL;
160                ptr->time = 0;
161                ptr->refcount = 0;
162
163                /* remove from hash */
164                tab_hash->remove(string);
165        }
166
167        return 0;
168}
169
170int map::lookup(char *string)
171{
172        struct hash_struct *ptr;
173
174        if ((ptr = (struct hash_struct *)tab_hash->lookup(string)))
175        {
176                ptr->time = now; /* touch it, so insert won't remove */
177                return ptr->pos;
178        }
179
180        return -1;
181}
182
183char *map::reverse(int pos)
184{
185        /* return pointer to char for this string pos */
186        return tab[pos].string;
187}
188
189void map::sub_ref(int pos)
190{
191//      dprintf("%d subref %p %d for %s\n",
192//          time(NULL), this, pos, tab[pos].string);
193       
194        if (tab[pos].refcount > 0)
195                tab[pos].refcount--;
196
197}
Note: See TracBrowser for help on using the browser.