Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 203 lines (173 sloc) 6.07 kb
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Hash table
4 *
5 * The hash function used here is by Bob Jenkins, 1996:
6 * <http://burtleburtle.net/bob/hash/doobs.html>
7 * "By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net.
8 * You may use this code any way you wish, private, educational,
9 * or commercial. It's free."
10 *
11 * The rest of the file is licensed under the BSD license. See LICENSE.
12 *
13 * $Id$
14 */
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/socket.h>
20 #include <sys/signal.h>
21 #include <sys/resource.h>
22 #include <sys/mman.h>
23 #include <fcntl.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <netinet/in.h>
29 #include <errno.h>
30 #include <event.h>
31 #include <malloc.h>
32
33 #include "memcached.h"
34
35 typedef unsigned long int ub4; /* unsigned 4-byte quantities */
36 typedef unsigned char ub1; /* unsigned 1-byte quantities */
37
38 typedef struct _hashitem {
39 struct _hashitem *next;
40 item *item;
41 } hashitem;
42
43 /* hard-code one million buckets, for now (2**20 == 4MB hash) */
44 #define HASHPOWER 20
45
46 #define hashsize(n) ((ub4)1<<(n))
47 #define hashmask(n) (hashsize(n)-1)
48
49 #define mix(a,b,c) \
50 { \
51 a -= b; a -= c; a ^= (c>>13); \
52 b -= c; b -= a; b ^= (a<<8); \
53 c -= a; c -= b; c ^= (b>>13); \
54 a -= b; a -= c; a ^= (c>>12); \
55 b -= c; b -= a; b ^= (a<<16); \
56 c -= a; c -= b; c ^= (b>>5); \
57 a -= b; a -= c; a ^= (c>>3); \
58 b -= c; b -= a; b ^= (a<<10); \
59 c -= a; c -= b; c ^= (b>>15); \
60 }
61
62 /*
63 --------------------------------------------------------------------
64 hash() -- hash a variable-length key into a 32-bit value
65 k : the key (the unaligned variable-length array of bytes)
66 len : the length of the key, counting by bytes
67 initval : can be any 4-byte value
68 Returns a 32-bit value. Every bit of the key affects every bit of
69 the return value. Every 1-bit and 2-bit delta achieves avalanche.
70 About 6*len+35 instructions.
71
72 The best hash table sizes are powers of 2. There is no need to do
73 mod a prime (mod is sooo slow!). If you need less than 32 bits,
74 use a bitmask. For example, if you need only 10 bits, do
75 h = (h & hashmask(10));
76 In which case, the hash table should have hashsize(10) elements.
77
78 If you are hashing n strings (ub1 **)k, do it like this:
79 for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
80
81 By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
82 code any way you wish, private, educational, or commercial. It's free.
83
84 See http://burtleburtle.net/bob/hash/evahash.html
85 Use for hash table lookup, or anything where one collision in 2^^32 is
86 acceptable. Do NOT use for cryptographic purposes.
87 --------------------------------------------------------------------
88 */
89
90 ub4 hash( k, length, initval)
91 register ub1 *k; /* the key */
92 register ub4 length; /* the length of the key */
93 register ub4 initval; /* the previous hash, or an arbitrary value */
94 {
95 register ub4 a,b,c,len;
96
97 /* Set up the internal state */
98 len = length;
99 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
100 c = initval; /* the previous hash value */
101
102 /*---------------------------------------- handle most of the key */
103 while (len >= 12)
104 {
105 a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
106 b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
107 c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
108 mix(a,b,c);
109 k += 12; len -= 12;
110 }
111
112 /*------------------------------------- handle the last 11 bytes */
113 c += length;
114 switch(len) /* all the case statements fall through */
115 {
116 case 11: c+=((ub4)k[10]<<24);
117 case 10: c+=((ub4)k[9]<<16);
118 case 9 : c+=((ub4)k[8]<<8);
119 /* the first byte of c is reserved for the length */
120 case 8 : b+=((ub4)k[7]<<24);
121 case 7 : b+=((ub4)k[6]<<16);
122 case 6 : b+=((ub4)k[5]<<8);
123 case 5 : b+=k[4];
124 case 4 : a+=((ub4)k[3]<<24);
125 case 3 : a+=((ub4)k[2]<<16);
126 case 2 : a+=((ub4)k[1]<<8);
127 case 1 : a+=k[0];
128 /* case 0: nothing left to add */
129 }
130 mix(a,b,c);
131 /*-------------------------------------------- report the result */
132 return c;
133 }
134
135 static hashitem** hashtable = 0;
136
137 void assoc_init(void) {
138 unsigned int hash_size = hashsize(HASHPOWER) * sizeof(void*);
139 hashtable = malloc(hash_size);
140 if (! hashtable) {
141 fprintf(stderr, "Failed to init hashtable.\n");
142 exit(1);
143 }
144 memset(hashtable, 0, hash_size);
145 }
146
147 item *assoc_find(char *key) {
148 ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
149 hashitem *hi = hashtable[hv];
150 int depth = 0;
151
152 while (hi) {
153 item *it = hi->item;
154 if (strcmp(key, it->key) == 0)
155 return it;
156 hi = hi->next;
157 }
158 return 0;
159 }
160
161 /* returns the address of a hashitem* before the key. if *hashitem == 0,
162 the item wasn't found, and a new node should be allocated */
163
164 static hashitem** _hashitem_before (char *key) {
165 ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
166 hashitem **pos = &hashtable[hv];
167
168 while (*pos && strcmp(key, (*pos)->item->key)) {
169 pos = &(*pos)->next;
170 }
171 return pos;
172 }
173
174 int assoc_insert(char *key, item *it) {
175 hashitem **before = _hashitem_before(key);
176
177 /* item already existed, so we're just updating it */
178 if (*before) {
179 (*before)->item = it;
180 return 1;
181
182 /* have to allocate a new item */
183 } else {
184 hashitem* hi = (hashitem*) slabs_alloc(slabs_clsid(sizeof(hashitem)));
185 if (! hi) return 0;
186 hi->next = 0;
187 hi->item = it;
188 *before = hi;
189 return 1;
190 }
191 }
192
193 void assoc_delete(char *key) {
194 hashitem **before = _hashitem_before(key);
195
196 if (*before) {
197 hashitem *it = *before;
198 *before = it->next;
199 slabs_free(it, slabs_clsid(sizeof(hashitem)));
200 }
201 }
202
Something went wrong with that request. Please try again.