5 static uint64_t FNV_64_INIT
= UINT64_C(0xcbf29ce484222325);
6 static uint64_t FNV_64_PRIME
= UINT64_C(0x100000001b3);
8 static uint32_t FNV_32_INIT
= 2166136261UL;
9 static uint32_t FNV_32_PRIME
= 16777619;
12 static uint32_t internal_generate_hash(const char *key
, size_t key_length
);
13 static uint32_t internal_generate_md5(const char *key
, size_t key_length
);
15 uint32_t memcached_generate_hash_value(const char *key
, size_t key_length
, memcached_hash_t hash_algorithm
)
17 uint32_t hash
= 1; /* Just here to remove compile warning */
20 switch (hash_algorithm
)
22 case MEMCACHED_HASH_DEFAULT
:
23 hash
= internal_generate_hash(key
, key_length
);
25 case MEMCACHED_HASH_MD5
:
26 hash
= internal_generate_md5(key
, key_length
);
28 case MEMCACHED_HASH_CRC
:
29 hash
= ((hash_crc32(key
, key_length
) >> 16) & 0x7fff);
33 /* FNV hash'es lifted from Dustin Sallings work */
34 case MEMCACHED_HASH_FNV1_64
:
36 /* Thanks to pierre@demartines.com for the pointer */
39 temp_hash
= FNV_64_INIT
;
40 for (x
= 0; x
< key_length
; x
++)
42 temp_hash
*= FNV_64_PRIME
;
43 temp_hash
^= (uint64_t)key
[x
];
45 hash
= (uint32_t)temp_hash
;
48 case MEMCACHED_HASH_FNV1A_64
:
50 hash
= (uint32_t) FNV_64_INIT
;
51 for (x
= 0; x
< key_length
; x
++)
53 uint32_t val
= (uint32_t)key
[x
];
55 hash
*= (uint32_t) FNV_64_PRIME
;
59 case MEMCACHED_HASH_FNV1_32
:
62 for (x
= 0; x
< key_length
; x
++)
64 uint32_t val
= (uint32_t)key
[x
];
70 case MEMCACHED_HASH_FNV1A_32
:
73 for (x
= 0; x
< key_length
; x
++)
75 uint32_t val
= (uint32_t)key
[x
];
81 case MEMCACHED_HASH_HSIEH
:
83 #ifdef HAVE_HSIEH_HASH
84 hash
= hsieh_hash(key
, key_length
);
88 case MEMCACHED_HASH_MURMUR
:
90 hash
= murmur_hash(key
, key_length
);
93 case MEMCACHED_HASH_JENKINS
:
95 hash
= jenkins_hash(key
, key_length
, 13);
98 case MEMCACHED_HASH_MAX
:
101 WATCHPOINT_ASSERT(0);
109 uint32_t generate_hash(memcached_st
*ptr
, const char *key
, size_t key_length
)
111 uint32_t hash
= 1; /* Just here to remove compile warning */
114 WATCHPOINT_ASSERT(ptr
->number_of_hosts
);
116 if (ptr
->number_of_hosts
== 1)
119 hash
= memcached_generate_hash_value(key
, key_length
, ptr
->hash
);
120 WATCHPOINT_ASSERT(hash
);
124 static uint32_t dispatch_host(memcached_st
*ptr
, uint32_t hash
)
126 switch (ptr
->distribution
)
128 case MEMCACHED_DISTRIBUTION_CONSISTENT
:
129 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
:
130 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
:
132 uint32_t num
= ptr
->continuum_points_counter
;
133 WATCHPOINT_ASSERT(ptr
->continuum
);
136 memcached_continuum_item_st
*begin
, *end
, *left
, *right
, *middle
;
137 begin
= left
= ptr
->continuum
;
138 end
= right
= ptr
->continuum
+ num
;
142 middle
= left
+ (right
- left
) / 2;
143 if (middle
->value
< hash
)
152 case MEMCACHED_DISTRIBUTION_MODULA
:
153 return hash
% ptr
->number_of_hosts
;
154 case MEMCACHED_DISTRIBUTION_RANDOM
:
155 return (uint32_t) random() % ptr
->number_of_hosts
;
156 case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX
:
158 WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
159 return hash
% ptr
->number_of_hosts
;
165 One day make this public, and have it return the actual memcached_server_st
166 to the calling application.
168 uint32_t memcached_generate_hash(memcached_st
*ptr
, const char *key
, size_t key_length
)
170 uint32_t hash
= 1; /* Just here to remove compile warning */
172 WATCHPOINT_ASSERT(ptr
->number_of_hosts
);
174 if (ptr
->number_of_hosts
== 1)
177 if (ptr
->flags
.hash_with_prefix_key
)
179 size_t temp_length
= ptr
->prefix_key_length
+ key_length
;
180 char temp
[temp_length
];
182 if (temp_length
> MEMCACHED_MAX_KEY
-1)
185 strncpy(temp
, ptr
->prefix_key
, ptr
->prefix_key_length
);
186 strncpy(temp
+ ptr
->prefix_key_length
, key
, key_length
);
187 hash
= generate_hash(ptr
, temp
, temp_length
);
191 hash
= generate_hash(ptr
, key
, key_length
);
194 WATCHPOINT_ASSERT(hash
);
196 if (memcached_behavior_get(ptr
, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS
) && ptr
->next_distribution_rebuild
)
200 if (gettimeofday(&now
, NULL
) == 0 &&
201 now
.tv_sec
> ptr
->next_distribution_rebuild
)
203 run_distribution(ptr
);
207 return dispatch_host(ptr
, hash
);
210 static uint32_t internal_generate_hash(const char *key
, size_t key_length
)
212 const char *ptr
= key
;
217 uint32_t val
= (uint32_t) *ptr
++;
219 value
+= (value
<< 10);
220 value
^= (value
>> 6);
222 value
+= (value
<< 3);
223 value
^= (value
>> 11);
224 value
+= (value
<< 15);
226 return value
== 0 ? 1 : (uint32_t) value
;
229 static uint32_t internal_generate_md5(const char *key
, size_t key_length
)
231 unsigned char results
[16];
233 md5_signature((unsigned char*)key
, (unsigned int)key_length
, results
);
235 return ((uint32_t) (results
[3] & 0xFF) << 24)
236 | ((uint32_t) (results
[2] & 0xFF) << 16)
237 | ((uint32_t) (results
[1] & 0xFF) << 8)
238 | (results
[0] & 0xFF);