Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 189 lines (163 sloc) 5.867 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>
18a72ad @bradfitz version 1.1.6
bradfitz authored
32 #include <assert.h>
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
33
34 #include "memcached.h"
35
36 typedef unsigned long int ub4; /* unsigned 4-byte quantities */
37 typedef unsigned char ub1; /* unsigned 1-byte quantities */
38
39 /* hard-code one million buckets, for now (2**20 == 4MB hash) */
40 #define HASHPOWER 20
41
42 #define hashsize(n) ((ub4)1<<(n))
43 #define hashmask(n) (hashsize(n)-1)
44
45 #define mix(a,b,c) \
46 { \
47 a -= b; a -= c; a ^= (c>>13); \
48 b -= c; b -= a; b ^= (a<<8); \
49 c -= a; c -= b; c ^= (b>>13); \
50 a -= b; a -= c; a ^= (c>>12); \
51 b -= c; b -= a; b ^= (a<<16); \
52 c -= a; c -= b; c ^= (b>>5); \
53 a -= b; a -= c; a ^= (c>>3); \
54 b -= c; b -= a; b ^= (a<<10); \
55 c -= a; c -= b; c ^= (b>>15); \
56 }
57
58 /*
59 --------------------------------------------------------------------
60 hash() -- hash a variable-length key into a 32-bit value
61 k : the key (the unaligned variable-length array of bytes)
62 len : the length of the key, counting by bytes
63 initval : can be any 4-byte value
64 Returns a 32-bit value. Every bit of the key affects every bit of
65 the return value. Every 1-bit and 2-bit delta achieves avalanche.
66 About 6*len+35 instructions.
67
68 The best hash table sizes are powers of 2. There is no need to do
69 mod a prime (mod is sooo slow!). If you need less than 32 bits,
70 use a bitmask. For example, if you need only 10 bits, do
71 h = (h & hashmask(10));
72 In which case, the hash table should have hashsize(10) elements.
73
74 If you are hashing n strings (ub1 **)k, do it like this:
75 for (i=0, h=0; i<n; ++i) h = hash( k[i], len[i], h);
76
77 By Bob Jenkins, 1996. bob_jenkins@burtleburtle.net. You may use this
78 code any way you wish, private, educational, or commercial. It's free.
79
80 See http://burtleburtle.net/bob/hash/evahash.html
81 Use for hash table lookup, or anything where one collision in 2^^32 is
82 acceptable. Do NOT use for cryptographic purposes.
83 --------------------------------------------------------------------
84 */
85
86 ub4 hash( k, length, initval)
87 register ub1 *k; /* the key */
88 register ub4 length; /* the length of the key */
89 register ub4 initval; /* the previous hash, or an arbitrary value */
90 {
91 register ub4 a,b,c,len;
92
93 /* Set up the internal state */
94 len = length;
95 a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */
96 c = initval; /* the previous hash value */
97
98 /*---------------------------------------- handle most of the key */
99 while (len >= 12)
100 {
101 a += (k[0] +((ub4)k[1]<<8) +((ub4)k[2]<<16) +((ub4)k[3]<<24));
102 b += (k[4] +((ub4)k[5]<<8) +((ub4)k[6]<<16) +((ub4)k[7]<<24));
103 c += (k[8] +((ub4)k[9]<<8) +((ub4)k[10]<<16)+((ub4)k[11]<<24));
104 mix(a,b,c);
105 k += 12; len -= 12;
106 }
107
108 /*------------------------------------- handle the last 11 bytes */
109 c += length;
110 switch(len) /* all the case statements fall through */
111 {
112 case 11: c+=((ub4)k[10]<<24);
113 case 10: c+=((ub4)k[9]<<16);
114 case 9 : c+=((ub4)k[8]<<8);
115 /* the first byte of c is reserved for the length */
116 case 8 : b+=((ub4)k[7]<<24);
117 case 7 : b+=((ub4)k[6]<<16);
118 case 6 : b+=((ub4)k[5]<<8);
119 case 5 : b+=k[4];
120 case 4 : a+=((ub4)k[3]<<24);
121 case 3 : a+=((ub4)k[2]<<16);
122 case 2 : a+=((ub4)k[1]<<8);
123 case 1 : a+=k[0];
124 /* case 0: nothing left to add */
125 }
126 mix(a,b,c);
127 /*-------------------------------------------- report the result */
128 return c;
129 }
130
f6d334e @bradfitz 2003-06-10
bradfitz authored
131 static item** hashtable = 0;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
132
133 void assoc_init(void) {
134 unsigned int hash_size = hashsize(HASHPOWER) * sizeof(void*);
135 hashtable = malloc(hash_size);
136 if (! hashtable) {
137 fprintf(stderr, "Failed to init hashtable.\n");
138 exit(1);
139 }
140 memset(hashtable, 0, hash_size);
141 }
142
143 item *assoc_find(char *key) {
144 ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
f6d334e @bradfitz 2003-06-10
bradfitz authored
145 item *it = hashtable[hv];
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
146
f6d334e @bradfitz 2003-06-10
bradfitz authored
147 while (it) {
148 if (strcmp(key, ITEM_key(it)) == 0)
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
149 return it;
f6d334e @bradfitz 2003-06-10
bradfitz authored
150 it = it->h_next;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
151 }
152 return 0;
153 }
154
7917af4 @bradfitz misc fixes as suggested by avva. lot of comment updates, mostly.
bradfitz authored
155 /* returns the address of the item pointer before the key. if *item == 0,
156 the item wasn't found */
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
157
f6d334e @bradfitz 2003-06-10
bradfitz authored
158 static item** _hashitem_before (char *key) {
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
159 ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
f6d334e @bradfitz 2003-06-10
bradfitz authored
160 item **pos = &hashtable[hv];
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
161
f6d334e @bradfitz 2003-06-10
bradfitz authored
162 while (*pos && strcmp(key, ITEM_key(*pos))) {
163 pos = &(*pos)->h_next;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
164 }
165 return pos;
166 }
167
7917af4 @bradfitz misc fixes as suggested by avva. lot of comment updates, mostly.
bradfitz authored
168 /* Note: this isn't an assoc_update. The key must not already exist to call this */
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
169 int assoc_insert(char *key, item *it) {
7917af4 @bradfitz misc fixes as suggested by avva. lot of comment updates, mostly.
bradfitz authored
170 ub4 hv = hash(key, strlen(key), 0) & hashmask(HASHPOWER);
171 it->h_next = hashtable[hv];
172 hashtable[hv] = it;
f6d334e @bradfitz 2003-06-10
bradfitz authored
173 return 1;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
174 }
175
176 void assoc_delete(char *key) {
f6d334e @bradfitz 2003-06-10
bradfitz authored
177 item **before = _hashitem_before(key);
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
178 if (*before) {
f6d334e @bradfitz 2003-06-10
bradfitz authored
179 item *nxt = (*before)->h_next;
180 (*before)->h_next = 0; /* probably pointless, but whatever. */
181 *before = nxt;
182 return;
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
183 }
7917af4 @bradfitz misc fixes as suggested by avva. lot of comment updates, mostly.
bradfitz authored
184 /* Note: we never actually get here. the callers don't delete things
c08383a @bradfitz more debug asserts
bradfitz authored
185 they can't find. */
186 assert(*before != 0);
825db0f @bradfitz stop using Judy for string mappings and use a hash table instead, which
bradfitz authored
187 }
188
Something went wrong with that request. Please try again.