1 /* Copyright (C) 2004 Christopher Clark <firstname.lastname@cl.cam.ac.uk> */
2 
3 /*
4  * There are duplicates of this code in:
5  *  - tools/blktap2/drivers/hashtable.c
6  */
7 
8 #include "hashtable.h"
9 #include "hashtable_private.h"
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <math.h>
14 #include <stdint.h>
15 
16 /*
17 Credit for primes table: Aaron Krowne
18  http://br.endernet.org/~akrowne/
19  http://planetmath.org/encyclopedia/GoodHashTablePrimes.html
20 */
21 static const unsigned int primes[] = {
22 53, 97, 193, 389,
23 769, 1543, 3079, 6151,
24 12289, 24593, 49157, 98317,
25 196613, 393241, 786433, 1572869,
26 3145739, 6291469, 12582917, 25165843,
27 50331653, 100663319, 201326611, 402653189,
28 805306457, 1610612741
29 };
30 const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]);
31 const unsigned int max_load_factor = 65; /* percentage */
32 
33 /*****************************************************************************/
34 struct hashtable *
create_hashtable(unsigned int minsize,unsigned int (* hashf)(void *),int (* eqf)(void *,void *))35 create_hashtable(unsigned int minsize,
36                  unsigned int (*hashf) (void*),
37                  int (*eqf) (void*,void*))
38 {
39     struct hashtable *h;
40     unsigned int pindex, size = primes[0];
41 
42     /* Check requested hashtable isn't too large */
43     if (minsize > (1u << 30)) return NULL;
44 
45     /* Enforce size as prime */
46     for (pindex=0; pindex < prime_table_length; pindex++) {
47         if (primes[pindex] > minsize) { size = primes[pindex]; break; }
48     }
49 
50     h = (struct hashtable *)calloc(1, sizeof(struct hashtable));
51     if (NULL == h)
52         goto err0;
53     h->table = (struct entry **)calloc(size, sizeof(struct entry *));
54     if (NULL == h->table)
55         goto err1;
56 
57     h->tablelength  = size;
58     h->primeindex   = pindex;
59     h->entrycount   = 0;
60     h->hashfn       = hashf;
61     h->eqfn         = eqf;
62     h->loadlimit    = (unsigned int)(((uint64_t)size * max_load_factor) / 100);
63     return h;
64 
65 err1:
66    free(h);
67 err0:
68    return NULL;
69 }
70 
71 /*****************************************************************************/
72 unsigned int
hash(struct hashtable * h,void * k)73 hash(struct hashtable *h, void *k)
74 {
75     /* Aim to protect against poor hash functions by adding logic here
76      * - logic taken from java 1.4 hashtable source */
77     unsigned int i = h->hashfn(k);
78     i += ~(i << 9);
79     i ^=  ((i >> 14) | (i << 18)); /* >>> */
80     i +=  (i << 4);
81     i ^=  ((i >> 10) | (i << 22)); /* >>> */
82     return i;
83 }
84 
85 /*****************************************************************************/
86 static int
hashtable_expand(struct hashtable * h)87 hashtable_expand(struct hashtable *h)
88 {
89     /* Double the size of the table to accomodate more entries */
90     struct entry **newtable;
91     struct entry *e;
92     struct entry **pE;
93     unsigned int newsize, i, index;
94     /* Check we're not hitting max capacity */
95     if (h->primeindex == (prime_table_length - 1)) return 0;
96     newsize = primes[++(h->primeindex)];
97 
98     newtable = (struct entry **)calloc(newsize, sizeof(struct entry*));
99     if (NULL != newtable)
100     {
101         /* This algorithm is not 'stable'. ie. it reverses the list
102          * when it transfers entries between the tables */
103         for (i = 0; i < h->tablelength; i++) {
104             while (NULL != (e = h->table[i])) {
105                 h->table[i] = e->next;
106                 index = indexFor(newsize,e->h);
107                 e->next = newtable[index];
108                 newtable[index] = e;
109             }
110         }
111         free(h->table);
112         h->table = newtable;
113     }
114     /* Plan B: realloc instead */
115     else
116     {
117         newtable = (struct entry **)
118                    realloc(h->table, newsize * sizeof(struct entry *));
119         if (NULL == newtable) { (h->primeindex)--; return 0; }
120         h->table = newtable;
121         memset(newtable[h->tablelength], 0, newsize - h->tablelength);
122         for (i = 0; i < h->tablelength; i++) {
123             for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) {
124                 index = indexFor(newsize,e->h);
125                 if (index == i)
126                 {
127                     pE = &(e->next);
128                 }
129                 else
130                 {
131                     *pE = e->next;
132                     e->next = newtable[index];
133                     newtable[index] = e;
134                 }
135             }
136         }
137     }
138     h->tablelength = newsize;
139     h->loadlimit   = (unsigned int)
140         (((uint64_t)newsize * max_load_factor) / 100);
141     return -1;
142 }
143 
144 /*****************************************************************************/
145 unsigned int
hashtable_count(struct hashtable * h)146 hashtable_count(struct hashtable *h)
147 {
148     return h->entrycount;
149 }
150 
151 /*****************************************************************************/
152 int
hashtable_insert(struct hashtable * h,void * k,void * v)153 hashtable_insert(struct hashtable *h, void *k, void *v)
154 {
155     /* This method allows duplicate keys - but they shouldn't be used */
156     unsigned int index;
157     struct entry *e;
158     if (++(h->entrycount) > h->loadlimit)
159     {
160         /* Ignore the return value. If expand fails, we should
161          * still try cramming just this value into the existing table
162          * -- we may not have memory for a larger table, but one more
163          * element may be ok. Next time we insert, we'll try expanding again.*/
164         hashtable_expand(h);
165     }
166     e = (struct entry *)calloc(1, sizeof(struct entry));
167     if (NULL == e) { --(h->entrycount); return 0; } /*oom*/
168     e->h = hash(h,k);
169     index = indexFor(h->tablelength,e->h);
170     e->k = k;
171     e->v = v;
172     e->next = h->table[index];
173     h->table[index] = e;
174     return -1;
175 }
176 
177 /*****************************************************************************/
178 void * /* returns value associated with key */
hashtable_search(struct hashtable * h,void * k)179 hashtable_search(struct hashtable *h, void *k)
180 {
181     struct entry *e;
182     unsigned int hashvalue, index;
183     hashvalue = hash(h,k);
184     index = indexFor(h->tablelength,hashvalue);
185     e = h->table[index];
186     while (NULL != e)
187     {
188         /* Check hash value to short circuit heavier comparison */
189         if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v;
190         e = e->next;
191     }
192     return NULL;
193 }
194 
195 /*****************************************************************************/
196 void * /* returns value associated with key */
hashtable_remove(struct hashtable * h,void * k)197 hashtable_remove(struct hashtable *h, void *k)
198 {
199     /* TODO: consider compacting the table when the load factor drops enough,
200      *       or provide a 'compact' method. */
201 
202     struct entry *e;
203     struct entry **pE;
204     void *v;
205     unsigned int hashvalue, index;
206 
207     hashvalue = hash(h,k);
208     index = indexFor(h->tablelength,hash(h,k));
209     pE = &(h->table[index]);
210     e = *pE;
211     while (NULL != e)
212     {
213         /* Check hash value to short circuit heavier comparison */
214         if ((hashvalue == e->h) && (h->eqfn(k, e->k)))
215         {
216             *pE = e->next;
217             h->entrycount--;
218             v = e->v;
219             freekey(e->k);
220             free(e);
221             return v;
222         }
223         pE = &(e->next);
224         e = e->next;
225     }
226     return NULL;
227 }
228 
229 /*****************************************************************************/
230 /* destroy */
231 void
hashtable_destroy(struct hashtable * h,int free_values)232 hashtable_destroy(struct hashtable *h, int free_values)
233 {
234     unsigned int i;
235     struct entry *e, *f;
236     struct entry **table = h->table;
237     if (free_values)
238     {
239         for (i = 0; i < h->tablelength; i++)
240         {
241             e = table[i];
242             while (NULL != e)
243             { f = e; e = e->next; freekey(f->k); free(f->v); free(f); }
244         }
245     }
246     else
247     {
248         for (i = 0; i < h->tablelength; i++)
249         {
250             e = table[i];
251             while (NULL != e)
252             { f = e; e = e->next; freekey(f->k); free(f); }
253         }
254     }
255     free(h->table);
256     free(h);
257 }
258 
259 /*
260  * Copyright (c) 2002, Christopher Clark
261  * All rights reserved.
262  *
263  * Redistribution and use in source and binary forms, with or without
264  * modification, are permitted provided that the following conditions
265  * are met:
266  *
267  * * Redistributions of source code must retain the above copyright
268  * notice, this list of conditions and the following disclaimer.
269  *
270  * * Redistributions in binary form must reproduce the above copyright
271  * notice, this list of conditions and the following disclaimer in the
272  * documentation and/or other materials provided with the distribution.
273  *
274  * * Neither the name of the original author; nor the names of any contributors
275  * may be used to endorse or promote products derived from this software
276  * without specific prior written permission.
277  *
278  *
279  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
280  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
281  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
282  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
283  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
284  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
285  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
286  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
287  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
288  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
289  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
290 */
291