Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 682 lines (594 sloc) 21.851 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>
93c6642 @bradfitz whitespace changes only
bradfitz authored
7 * "By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net.
1ea89bd @bradfitz remove all trailing whitespace, not just first occurrence. :)
bradfitz authored
8 * You may use this code any way you wish, private, educational,
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
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 */
56b8339 Merge multithreaded into trunk, commit #2 (first commit only did the
Steven Grimm authored
15
16 #include "memcached.h"
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
17 #include <sys/stat.h>
18 #include <sys/socket.h>
19 #include <sys/signal.h>
20 #include <sys/resource.h>
21 #include <fcntl.h>
c6975ef Part 1 of the Windows compatibility patch
Paul Lindner authored
22 #include <netinet/in.h>
23 #include <errno.h>
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
18a72ad @bradfitz version 1.1.6
bradfitz authored
27 #include <assert.h>
7f09e20 Do hash expansion in it's own thread
Trond Norbye authored
28 #include <pthread.h>
29
30 static pthread_cond_t maintenance_cond = PTHREAD_COND_INITIALIZER;
31
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
32
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
33 /*
34 * Since the hash function does bit manipulation, it needs to know
35 * whether it's big or little-endian. ENDIAN_LITTLE and ENDIAN_BIG
36 * are set in the configure script.
37 */
38 #if ENDIAN_BIG == 1
39 # define HASH_LITTLE_ENDIAN 0
40 # define HASH_BIG_ENDIAN 1
41 #else
42 # if ENDIAN_LITTLE == 1
43 # define HASH_LITTLE_ENDIAN 1
44 # define HASH_BIG_ENDIAN 0
45 # else
46 # define HASH_LITTLE_ENDIAN 0
47 # define HASH_BIG_ENDIAN 0
48 # endif
49 #endif
50
51 #define rot(x,k) (((x)<<(k)) ^ ((x)>>(32-(k))))
52
53 /*
54 -------------------------------------------------------------------------------
55 mix -- mix 3 32-bit values reversibly.
56
57 This is reversible, so any information in (a,b,c) before mix() is
58 still in (a,b,c) after mix().
59
60 If four pairs of (a,b,c) inputs are run through mix(), or through
61 mix() in reverse, there are at least 32 bits of the output that
62 are sometimes the same for one pair and different for another pair.
63 This was tested for:
64 * pairs that differed by one bit, by two bits, in any combination
65 of top bits of (a,b,c), or in any combination of bottom bits of
66 (a,b,c).
67 * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
68 the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
69 is commonly produced by subtraction) look like a single 1-bit
70 difference.
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
71 * the base values were pseudorandom, all zero but one bit set, or
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
72 all zero plus a counter that starts at zero.
73
74 Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
75 satisfy this are
76 4 6 8 16 19 4
77 9 15 3 18 27 15
78 14 9 3 7 17 3
79 Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing
80 for "differ" defined as + with a one-bit base and a two-bit delta. I
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
81 used http://burtleburtle.net/bob/hash/avalanche.html to choose
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
82 the operations, constants, and arrangements of the variables.
83
84 This does not achieve avalanche. There are input bits of (a,b,c)
85 that fail to affect some output bits of (a,b,c), especially of a. The
86 most thoroughly mixed value is c, but it doesn't really even achieve
87 avalanche in c.
88
89 This allows some parallelism. Read-after-writes are good at doubling
90 the number of bits affected, so the goal of mixing pulls in the opposite
91 direction as the goal of parallelism. I did what I could. Rotates
92 seem to cost as much as shifts on every machine I could lay my hands
93 on, and rotates are much kinder to the top and bottom bits, so I used
94 rotates.
95 -------------------------------------------------------------------------------
96 */
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
97 #define mix(a,b,c) \
98 { \
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
99 a -= c; a ^= rot(c, 4); c += b; \
100 b -= a; b ^= rot(a, 6); a += c; \
101 c -= b; c ^= rot(b, 8); b += a; \
102 a -= c; a ^= rot(c,16); c += b; \
103 b -= a; b ^= rot(a,19); a += c; \
104 c -= b; c ^= rot(b, 4); b += a; \
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
105 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
106
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
107 /*
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
108 -------------------------------------------------------------------------------
109 final -- final mixing of 3 32-bit values (a,b,c) into c
110
111 Pairs of (a,b,c) values differing in only a few bits will usually
112 produce values of c that look totally different. This was tested for
113 * pairs that differed by one bit, by two bits, in any combination
114 of top bits of (a,b,c), or in any combination of bottom bits of
115 (a,b,c).
116 * "differ" is defined as +, -, ^, or ~^. For + and -, I transformed
117 the output delta to a Gray code (a^(a>>1)) so a string of 1's (as
118 is commonly produced by subtraction) look like a single 1-bit
119 difference.
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
120 * the base values were pseudorandom, all zero but one bit set, or
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
121 all zero plus a counter that starts at zero.
122
123 These constants passed:
124 14 11 25 16 4 14 24
125 12 14 25 16 4 14 24
126 and these came close:
127 4 8 15 26 3 22 24
128 10 8 15 26 3 22 24
129 11 8 15 26 3 22 24
130 -------------------------------------------------------------------------------
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
131 */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
132 #define final(a,b,c) \
133 { \
134 c ^= b; c -= rot(b,14); \
135 a ^= c; a -= rot(c,11); \
136 b ^= a; b -= rot(a,25); \
137 c ^= b; c -= rot(b,16); \
138 a ^= c; a -= rot(c,4); \
139 b ^= a; b -= rot(a,14); \
140 c ^= b; c -= rot(b,24); \
141 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
142
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
143 #if HASH_LITTLE_ENDIAN == 1
56b8339 Merge multithreaded into trunk, commit #2 (first commit only did the
Steven Grimm authored
144 uint32_t hash(
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
145 const void *key, /* the key to hash */
146 size_t length, /* length of the key */
77dde9f multiple cleanups/refactoring, see ChangeLog
Paul Lindner authored
147 const uint32_t initval) /* initval */
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
148 {
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
149 uint32_t a,b,c; /* internal state */
150 union { const void *ptr; size_t i; } u; /* needed for Mac Powerbook G4 */
151
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
152 /* Set up the internal state */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
153 a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
154
155 u.ptr = key;
156 if (HASH_LITTLE_ENDIAN && ((u.i & 0x3) == 0)) {
157 const uint32_t *k = key; /* read 32-bit chunks */
158 #ifdef VALGRIND
159 const uint8_t *k8;
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
160 #endif /* ifdef VALGRIND */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
161
162 /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
163 while (length > 12)
164 {
165 a += k[0];
166 b += k[1];
167 c += k[2];
168 mix(a,b,c);
169 length -= 12;
170 k += 3;
171 }
172
173 /*----------------------------- handle the last (probably partial) block */
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
174 /*
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
175 * "k[2]&0xffffff" actually reads beyond the end of the string, but
176 * then masks off the part it's not allowed to read. Because the
177 * string is aligned, the masked-off tail is in the same word as the
178 * rest of the string. Every machine with memory protection I've seen
179 * does it on word boundaries, so is OK with this. But VALGRIND will
180 * still catch it and complain. The masking trick does make the hash
181 * noticably faster for short strings (like English words).
182 */
183 #ifndef VALGRIND
184
185 switch(length)
186 {
187 case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
188 case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
189 case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
190 case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
191 case 8 : b+=k[1]; a+=k[0]; break;
192 case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
193 case 6 : b+=k[1]&0xffff; a+=k[0]; break;
194 case 5 : b+=k[1]&0xff; a+=k[0]; break;
195 case 4 : a+=k[0]; break;
196 case 3 : a+=k[0]&0xffffff; break;
197 case 2 : a+=k[0]&0xffff; break;
198 case 1 : a+=k[0]&0xff; break;
199 case 0 : return c; /* zero length strings require no mixing */
200 }
201
202 #else /* make valgrind happy */
203
204 k8 = (const uint8_t *)k;
205 switch(length)
206 {
207 case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
208 case 11: c+=((uint32_t)k8[10])<<16; /* fall through */
209 case 10: c+=((uint32_t)k8[9])<<8; /* fall through */
210 case 9 : c+=k8[8]; /* fall through */
211 case 8 : b+=k[1]; a+=k[0]; break;
212 case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */
213 case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */
214 case 5 : b+=k8[4]; /* fall through */
215 case 4 : a+=k[0]; break;
216 case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */
217 case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */
218 case 1 : a+=k8[0]; break;
219 case 0 : return c; /* zero length strings require no mixing */
220 }
221
222 #endif /* !valgrind */
223
224 } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) {
225 const uint16_t *k = key; /* read 16-bit chunks */
226 const uint8_t *k8;
227
228 /*--------------- all but last block: aligned reads and different mixing */
229 while (length > 12)
230 {
231 a += k[0] + (((uint32_t)k[1])<<16);
232 b += k[2] + (((uint32_t)k[3])<<16);
233 c += k[4] + (((uint32_t)k[5])<<16);
234 mix(a,b,c);
235 length -= 12;
236 k += 6;
237 }
238
239 /*----------------------------- handle the last (probably partial) block */
240 k8 = (const uint8_t *)k;
241 switch(length)
242 {
243 case 12: c+=k[4]+(((uint32_t)k[5])<<16);
244 b+=k[2]+(((uint32_t)k[3])<<16);
245 a+=k[0]+(((uint32_t)k[1])<<16);
246 break;
eca55c9 Add patch for changable verbosity levels
Paul Lindner authored
247 case 11: c+=((uint32_t)k8[10])<<16; /* @fallthrough */
248 case 10: c+=k[4]; /* @fallthrough@ */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
249 b+=k[2]+(((uint32_t)k[3])<<16);
250 a+=k[0]+(((uint32_t)k[1])<<16);
251 break;
eca55c9 Add patch for changable verbosity levels
Paul Lindner authored
252 case 9 : c+=k8[8]; /* @fallthrough */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
253 case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
254 a+=k[0]+(((uint32_t)k[1])<<16);
255 break;
eca55c9 Add patch for changable verbosity levels
Paul Lindner authored
256 case 7 : b+=((uint32_t)k8[6])<<16; /* @fallthrough */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
257 case 6 : b+=k[2];
258 a+=k[0]+(((uint32_t)k[1])<<16);
259 break;
eca55c9 Add patch for changable verbosity levels
Paul Lindner authored
260 case 5 : b+=k8[4]; /* @fallthrough */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
261 case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
262 break;
eca55c9 Add patch for changable verbosity levels
Paul Lindner authored
263 case 3 : a+=((uint32_t)k8[2])<<16; /* @fallthrough */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
264 case 2 : a+=k[0];
265 break;
266 case 1 : a+=k8[0];
267 break;
268 case 0 : return c; /* zero length strings require no mixing */
269 }
270
271 } else { /* need to read the key one byte at a time */
272 const uint8_t *k = key;
273
274 /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
275 while (length > 12)
276 {
277 a += k[0];
278 a += ((uint32_t)k[1])<<8;
279 a += ((uint32_t)k[2])<<16;
280 a += ((uint32_t)k[3])<<24;
281 b += k[4];
282 b += ((uint32_t)k[5])<<8;
283 b += ((uint32_t)k[6])<<16;
284 b += ((uint32_t)k[7])<<24;
285 c += k[8];
286 c += ((uint32_t)k[9])<<8;
287 c += ((uint32_t)k[10])<<16;
288 c += ((uint32_t)k[11])<<24;
289 mix(a,b,c);
290 length -= 12;
291 k += 12;
292 }
293
294 /*-------------------------------- last block: affect all 32 bits of (c) */
295 switch(length) /* all the case statements fall through */
296 {
297 case 12: c+=((uint32_t)k[11])<<24;
298 case 11: c+=((uint32_t)k[10])<<16;
299 case 10: c+=((uint32_t)k[9])<<8;
300 case 9 : c+=k[8];
301 case 8 : b+=((uint32_t)k[7])<<24;
302 case 7 : b+=((uint32_t)k[6])<<16;
303 case 6 : b+=((uint32_t)k[5])<<8;
304 case 5 : b+=k[4];
305 case 4 : a+=((uint32_t)k[3])<<24;
306 case 3 : a+=((uint32_t)k[2])<<16;
307 case 2 : a+=((uint32_t)k[1])<<8;
308 case 1 : a+=k[0];
309 break;
310 case 0 : return c; /* zero length strings require no mixing */
311 }
312 }
313
314 final(a,b,c);
315 return c; /* zero length strings require no mixing */
316 }
317
318 #elif HASH_BIG_ENDIAN == 1
319 /*
320 * hashbig():
321 * This is the same as hashword() on big-endian machines. It is different
322 * from hashlittle() on all machines. hashbig() takes advantage of
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
323 * big-endian byte ordering.
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
324 */
56b8339 Merge multithreaded into trunk, commit #2 (first commit only did the
Steven Grimm authored
325 uint32_t hash( const void *key, size_t length, const uint32_t initval)
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
326 {
327 uint32_t a,b,c;
328 union { const void *ptr; size_t i; } u; /* to cast key to (size_t) happily */
329
330 /* Set up the internal state */
331 a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
332
333 u.ptr = key;
334 if (HASH_BIG_ENDIAN && ((u.i & 0x3) == 0)) {
335 const uint32_t *k = key; /* read 32-bit chunks */
336 #ifdef VALGRIND
337 const uint8_t *k8;
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
338 #endif /* ifdef VALGRIND */
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
339
340 /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
341 while (length > 12)
342 {
343 a += k[0];
344 b += k[1];
345 c += k[2];
346 mix(a,b,c);
347 length -= 12;
348 k += 3;
349 }
350
351 /*----------------------------- handle the last (probably partial) block */
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
352 /*
28a8165 Update hash function to Jenkins2006.
Steven Grimm authored
353 * "k[2]<<8" actually reads beyond the end of the string, but
354 * then shifts out the part it's not allowed to read. Because the
355 * string is aligned, the illegal read is in the same word as the
356 * rest of the string. Every machine with memory protection I've seen
357 * does it on word boundaries, so is OK with this. But VALGRIND will
358 * still catch it and complain. The masking trick does make the hash
359 * noticably faster for short strings (like English words).
360 */
361 #ifndef VALGRIND
362
363 switch(length)
364 {
365 case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
366 case 11: c+=k[2]&0xffffff00; b+=k[1]; a+=k[0]; break;
367 case 10: c+=k[2]&0xffff0000; b+=k[1]; a+=k[0]; break;
368 case 9 : c+=k[2]&0xff000000; b+=k[1]; a+=k[0]; break;
369 case 8 : b+=k[1]; a+=k[0]; break;
370 case 7 : b+=k[1]&0xffffff00; a+=k[0]; break;
371 case 6 : b+=k[1]&0xffff0000; a+=k[0]; break;
372 case 5 : b+=k[1]&0xff000000; a+=k[0]; break;
373 case 4 : a+=k[0]; break;
374 case 3 : a+=k[0]&0xffffff00; break;
375 case 2 : a+=k[0]&0xffff0000; break;
376 case 1 : a+=k[0]&0xff000000; break;
377 case 0 : return c; /* zero length strings require no mixing */
378 }
379
380 #else /* make valgrind happy */
381
382 k8 = (const uint8_t *)k;
383 switch(length) /* all the case statements fall through */
384 {
385 case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
386 case 11: c+=((uint32_t)k8[10])<<8; /* fall through */
387 case 10: c+=((uint32_t)k8[9])<<16; /* fall through */
388 case 9 : c+=((uint32_t)k8[8])<<24; /* fall through */
389 case 8 : b+=k[1]; a+=k[0]; break;
390 case 7 : b+=((uint32_t)k8[6])<<8; /* fall through */
391 case 6 : b+=((uint32_t)k8[5])<<16; /* fall through */
392 case 5 : b+=((uint32_t)k8[4])<<24; /* fall through */
393 case 4 : a+=k[0]; break;
394 case 3 : a+=((uint32_t)k8[2])<<8; /* fall through */
395 case 2 : a+=((uint32_t)k8[1])<<16; /* fall through */
396 case 1 : a+=((uint32_t)k8[0])<<24; break;
397 case 0 : return c;
398 }
399
400 #endif /* !VALGRIND */
401
402 } else { /* need to read the key one byte at a time */
403 const uint8_t *k = key;
404
405 /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
406 while (length > 12)
407 {
408 a += ((uint32_t)k[0])<<24;
409 a += ((uint32_t)k[1])<<16;
410 a += ((uint32_t)k[2])<<8;
411 a += ((uint32_t)k[3]);
412 b += ((uint32_t)k[4])<<24;
413 b += ((uint32_t)k[5])<<16;
414 b += ((uint32_t)k[6])<<8;
415 b += ((uint32_t)k[7]);
416 c += ((uint32_t)k[8])<<24;
417 c += ((uint32_t)k[9])<<16;
418 c += ((uint32_t)k[10])<<8;
419 c += ((uint32_t)k[11]);
420 mix(a,b,c);
421 length -= 12;
422 k += 12;
423 }
424
425 /*-------------------------------- last block: affect all 32 bits of (c) */
426 switch(length) /* all the case statements fall through */
427 {
428 case 12: c+=k[11];
429 case 11: c+=((uint32_t)k[10])<<8;
430 case 10: c+=((uint32_t)k[9])<<16;
431 case 9 : c+=((uint32_t)k[8])<<24;
432 case 8 : b+=k[7];
433 case 7 : b+=((uint32_t)k[6])<<8;
434 case 6 : b+=((uint32_t)k[5])<<16;
435 case 5 : b+=((uint32_t)k[4])<<24;
436 case 4 : a+=k[3];
437 case 3 : a+=((uint32_t)k[2])<<8;
438 case 2 : a+=((uint32_t)k[1])<<16;
439 case 1 : a+=((uint32_t)k[0])<<24;
440 break;
441 case 0 : return c;
442 }
443 }
444
445 final(a,b,c);
446 return c;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
447 }
bb3a4c9 conn_add_to_freelist returns bool
Paul Lindner authored
448 #else /* HASH_XXX_ENDIAN == 1 */
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
449 #error Must define HASH_BIG_ENDIAN or HASH_LITTLE_ENDIAN
bb3a4c9 conn_add_to_freelist returns bool
Paul Lindner authored
450 #endif /* HASH_XXX_ENDIAN == 1 */
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
451
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
452 typedef unsigned long int ub4; /* unsigned 4-byte quantities */
453 typedef unsigned char ub1; /* unsigned 1-byte quantities */
454
455 /* how many powers of 2's worth of buckets we use */
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
456 static unsigned int hashpower = 16;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
457
458 #define hashsize(n) ((ub4)1<<(n))
459 #define hashmask(n) (hashsize(n)-1)
460
461 /* Main hash table. This is where we look except during expansion. */
462 static item** primary_hashtable = 0;
463
464 /*
465 * Previous hash table. During expansion, we look here for keys that haven't
466 * been moved over to the primary yet.
467 */
468 static item** old_hashtable = 0;
469
470 /* Number of items in the hash table. */
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
471 static unsigned int hash_items = 0;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
472
473 /* Flag: Are we in the middle of expanding now? */
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
474 static bool expanding = false;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
475
476 /*
477 * During expansion we migrate values with bucket granularity; this is how
478 * far we've gotten so far. Ranges from 0 .. hashsize(hashpower - 1) - 1.
479 */
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
480 static unsigned int expand_bucket = 0;
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
481
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
482 void assoc_init(void) {
984053c @dustin Use calloc for allocating the hash table vs. malloc+memset.
dustin authored
483 primary_hashtable = calloc(hashsize(hashpower), sizeof(void *));
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
484 if (! primary_hashtable) {
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
485 fprintf(stderr, "Failed to init hashtable.\n");
c842507 use EXIT_* constants
Paul Lindner authored
486 exit(EXIT_FAILURE);
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
487 }
488 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
489
77dde9f multiple cleanups/refactoring, see ChangeLog
Paul Lindner authored
490 item *assoc_find(const char *key, const size_t nkey) {
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
491 uint32_t hv = hash(key, nkey, 0);
492 item *it;
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
493 unsigned int oldbucket;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
494
495 if (expanding &&
496 (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket)
497 {
498 it = old_hashtable[oldbucket];
499 } else {
500 it = primary_hashtable[hv & hashmask(hashpower)];
501 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
502
6895721 Add DTrace probes for Solaris/etc.
Trond Norbye authored
503 item *ret = NULL;
504 int depth = 0;
f6d334e @bradfitz 2003-06-10
bradfitz authored
505 while (it) {
6895721 Add DTrace probes for Solaris/etc.
Trond Norbye authored
506 if ((nkey == it->nkey) && (memcmp(key, ITEM_key(it), nkey) == 0)) {
507 ret = it;
508 break;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
509 }
f6d334e @bradfitz 2003-06-10
bradfitz authored
510 it = it->h_next;
6895721 Add DTrace probes for Solaris/etc.
Trond Norbye authored
511 ++depth;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
512 }
80ec095 Add DTrace probes to the binary protocol
Trond Norbye authored
513 MEMCACHED_ASSOC_FIND(key, nkey, depth);
6895721 Add DTrace probes for Solaris/etc.
Trond Norbye authored
514 return ret;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
515 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
516
7917af4 @bradfitz misc fixes as suggested by avva. lot of comment updates, mostly.
bradfitz authored
517 /* returns the address of the item pointer before the key. if *item == 0,
518 the item wasn't found */
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
519
77dde9f multiple cleanups/refactoring, see ChangeLog
Paul Lindner authored
520 static item** _hashitem_before (const char *key, const size_t nkey) {
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
521 uint32_t hv = hash(key, nkey, 0);
522 item **pos;
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
523 unsigned int oldbucket;
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
524
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
525 if (expanding &&
526 (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket)
527 {
528 pos = &old_hashtable[oldbucket];
529 } else {
530 pos = &primary_hashtable[hv & hashmask(hashpower)];
531 }
532
533 while (*pos && ((nkey != (*pos)->nkey) || memcmp(key, ITEM_key(*pos), nkey))) {
f6d334e @bradfitz 2003-06-10
bradfitz authored
534 pos = &(*pos)->h_next;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
535 }
536 return pos;
537 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
538
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
539 /* grows the hashtable to the next power of 2. */
540 static void assoc_expand(void) {
541 old_hashtable = primary_hashtable;
542
543 primary_hashtable = calloc(hashsize(hashpower + 1), sizeof(void *));
544 if (primary_hashtable) {
56b8339 Merge multithreaded into trunk, commit #2 (first commit only did the
Steven Grimm authored
545 if (settings.verbose > 1)
546 fprintf(stderr, "Hash table expansion starting\n");
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
547 hashpower++;
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
548 expanding = true;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
549 expand_bucket = 0;
7f09e20 Do hash expansion in it's own thread
Trond Norbye authored
550 pthread_cond_signal(&maintenance_cond);
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
551 } else {
552 primary_hashtable = old_hashtable;
56b8339 Merge multithreaded into trunk, commit #2 (first commit only did the
Steven Grimm authored
553 /* Bad news, but we can keep running. */
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
554 }
555 }
556
7917af4 @bradfitz misc fixes as suggested by avva. lot of comment updates, mostly.
bradfitz authored
557 /* Note: this isn't an assoc_update. The key must not already exist to call this */
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
558 int assoc_insert(item *it) {
559 uint32_t hv;
44ef96e gcc -pedantic changes, comments, signed/unsigned changes. also conver…
Paul Lindner authored
560 unsigned int oldbucket;
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
561
562 assert(assoc_find(ITEM_key(it), it->nkey) == 0); /* shouldn't have duplicately named things defined */
563
564 hv = hash(ITEM_key(it), it->nkey, 0);
565 if (expanding &&
566 (oldbucket = (hv & hashmask(hashpower - 1))) >= expand_bucket)
567 {
568 it->h_next = old_hashtable[oldbucket];
569 old_hashtable[oldbucket] = it;
570 } else {
571 it->h_next = primary_hashtable[hv & hashmask(hashpower)];
572 primary_hashtable[hv & hashmask(hashpower)] = it;
573 }
574
575 hash_items++;
576 if (! expanding && hash_items > (hashsize(hashpower) * 3) / 2) {
577 assoc_expand();
578 }
579
80ec095 Add DTrace probes to the binary protocol
Trond Norbye authored
580 MEMCACHED_ASSOC_INSERT(ITEM_key(it), it->nkey, hash_items);
f6d334e @bradfitz 2003-06-10
bradfitz authored
581 return 1;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
582 }
86969ea @bradfitz restore blank lines I over-zealously destroyed earlier.
bradfitz authored
583
77dde9f multiple cleanups/refactoring, see ChangeLog
Paul Lindner authored
584 void assoc_delete(const char *key, const size_t nkey) {
217dcce Incorporate changes from "performance" branch (revisions 414-419).
Steven Grimm authored
585 item **before = _hashitem_before(key, nkey);
586
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
587 if (*before) {
6895721 Add DTrace probes for Solaris/etc.
Trond Norbye authored
588 item *nxt;
589 hash_items--;
590 /* The DTrace probe cannot be triggered as the last instruction
591 * due to possible tail-optimization by the compiler
592 */
80ec095 Add DTrace probes to the binary protocol
Trond Norbye authored
593 MEMCACHED_ASSOC_DELETE(key, nkey, hash_items);
6895721 Add DTrace probes for Solaris/etc.
Trond Norbye authored
594 nxt = (*before)->h_next;
f6d334e @bradfitz 2003-06-10
bradfitz authored
595 (*before)->h_next = 0; /* probably pointless, but whatever. */
596 *before = nxt;
597 return;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
598 }
b80ab7c update clean-whitespace, add automated whitespace test, and clean whi…
Paul Lindner authored
599 /* Note: we never actually get here. the callers don't delete things
c08383a @bradfitz more debug asserts
bradfitz authored
600 they can't find. */
601 assert(*before != 0);
8bdbe4a @bradfitz but we do want trailing newline at end of file
bradfitz authored
602 }
7f09e20 Do hash expansion in it's own thread
Trond Norbye authored
603
604
605 static volatile int do_run_maintenance_thread = 1;
606
607 extern pthread_mutex_t cache_lock;
608 #define DEFAULT_HASH_BULK_MOVE 1
609 int hash_bulk_move = DEFAULT_HASH_BULK_MOVE;
610
611 static void *assoc_maintenance_thread(void *arg) {
612
613 while (do_run_maintenance_thread) {
614
615 /* Lock the cache, and bulk move multiple buckets to the new
616 * hash table. */
617 pthread_mutex_lock(&cache_lock);
618
619 for (int ii = 0; ii < hash_bulk_move && expanding; ++ii) {
620 item *it, *next;
621 int bucket;
622
623 for (it = old_hashtable[expand_bucket]; NULL != it; it = next) {
624 next = it->h_next;
625
626 bucket = hash(ITEM_key(it), it->nkey, 0) & hashmask(hashpower);
627 it->h_next = primary_hashtable[bucket];
628 primary_hashtable[bucket] = it;
629 }
630
631 old_hashtable[expand_bucket] = NULL;
632
633 expand_bucket++;
634 if (expand_bucket == hashsize(hashpower - 1)) {
635 expanding = false;
636 free(old_hashtable);
637 if (settings.verbose > 1)
638 fprintf(stderr, "Hash table expansion done\n");
639 }
640 }
641
642 if (!expanding) {
643 /* We are done expanding.. just wait for next invocation */
644 pthread_cond_wait(&maintenance_cond, &cache_lock);
645 }
646
647 pthread_mutex_unlock(&cache_lock);
648 }
649 return NULL;
650 }
651
652 static pthread_t maintenance_tid;
653
654 int start_assoc_maintenance_thread() {
655 int ret;
656 char *env = getenv("MEMCACHED_HASH_BULK_MOVE");
657 if (env != NULL) {
658 hash_bulk_move = atoi(env);
659 if (hash_bulk_move == 0) {
660 hash_bulk_move = DEFAULT_HASH_BULK_MOVE;
661 }
662 }
663 if ((ret = pthread_create(&maintenance_tid, NULL,
664 assoc_maintenance_thread, NULL)) != 0) {
665 fprintf(stderr, "Can't create thread: %s\n", strerror(ret));
666 return -1;
667 }
668 return 0;
669 }
670
671 void stop_assoc_maintenance_thread() {
672 pthread_mutex_lock(&cache_lock);
673 do_run_maintenance_thread = 0;
674 pthread_cond_signal(&maintenance_cond);
675 pthread_mutex_unlock(&cache_lock);
676
677 /* Wait for the maintenance thread to stop */
678 pthread_join(maintenance_tid, NULL);
679 }
680
681
Something went wrong with that request. Please try again.