4 static uint64_t FNV_64_INIT
= 0xcbf29ce484222325LL
;
5 static uint64_t FNV_64_PRIME
= 0x100000001b3LL
;
7 static uint32_t FNV_32_INIT
= 2166136261UL;
8 static uint32_t FNV_32_PRIME
= 16777619;
11 static uint32_t internal_generate_hash(const char *key
, size_t key_length
);
12 static uint32_t internal_generate_md5(const char *key
, size_t key_length
);
14 uint32_t generate_hash_value(const char *key
, size_t key_length
, memcached_hash hash_algorithm
)
16 uint32_t hash
= 1; /* Just here to remove compile warning */
19 switch (hash_algorithm
)
21 case MEMCACHED_HASH_DEFAULT
:
22 hash
= internal_generate_hash(key
, key_length
);
24 case MEMCACHED_HASH_MD5
:
25 hash
= internal_generate_md5(key
, key_length
);
27 case MEMCACHED_HASH_CRC
:
28 hash
= ((hash_crc32(key
, key_length
) >> 16) & 0x7fff);
32 /* FNV hash'es lifted from Dustin Sallings work */
33 case MEMCACHED_HASH_FNV1_64
:
35 /* Thanks to pierre@demartines.com for the pointer */
38 temp_hash
= FNV_64_INIT
;
39 for (x
= 0; x
< key_length
; x
++)
41 temp_hash
*= FNV_64_PRIME
;
44 hash
= (uint32_t)temp_hash
;
47 case MEMCACHED_HASH_FNV1A_64
:
50 for (x
= 0; x
< key_length
; x
++)
57 case MEMCACHED_HASH_FNV1_32
:
60 for (x
= 0; x
< key_length
; x
++)
67 case MEMCACHED_HASH_FNV1A_32
:
70 for (x
= 0; x
< key_length
; x
++)
77 case MEMCACHED_HASH_HSIEH
:
79 hash
= hsieh_hash(key
, key_length
);
82 case MEMCACHED_HASH_MURMUR
:
84 hash
= murmur_hash(key
, key_length
);
87 case MEMCACHED_HASH_JENKINS
:
89 hash
=jenkins_hash(key
, key_length
, 13);
96 uint32_t generate_hash(memcached_st
*ptr
, const char *key
, size_t key_length
)
98 uint32_t hash
= 1; /* Just here to remove compile warning */
101 WATCHPOINT_ASSERT(ptr
->number_of_hosts
);
103 if (ptr
->number_of_hosts
== 1)
106 hash
= generate_hash_value(key
, key_length
, ptr
->hash
);
107 WATCHPOINT_ASSERT(hash
);
111 static uint32_t dispatch_host(memcached_st
*ptr
, uint32_t hash
)
113 switch (ptr
->distribution
)
115 case MEMCACHED_DISTRIBUTION_CONSISTENT
:
116 case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA
:
118 uint32_t num
= ptr
->continuum_points_counter
;
119 WATCHPOINT_ASSERT(ptr
->continuum
);
122 memcached_continuum_item_st
*begin
, *end
, *left
, *right
, *middle
;
123 begin
= left
= ptr
->continuum
;
124 end
= right
= ptr
->continuum
+ num
;
128 middle
= left
+ (right
- left
) / 2;
129 if (middle
->value
< hash
)
139 case MEMCACHED_DISTRIBUTION_MODULA
:
140 return hash
% ptr
->number_of_hosts
;
141 case MEMCACHED_DISTRIBUTION_RANDOM
:
142 return random() % ptr
->number_of_hosts
;
144 WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
145 return hash
% ptr
->number_of_hosts
;
148 WATCHPOINT_ASSERT(0); /* We should never reach here */
153 One day make this public, and have it return the actual memcached_server_st
154 to the calling application.
156 uint32_t memcached_generate_hash(memcached_st
*ptr
, const char *key
, size_t key_length
)
158 uint32_t hash
= 1; /* Just here to remove compile warning */
160 WATCHPOINT_ASSERT(ptr
->number_of_hosts
);
162 if (ptr
->number_of_hosts
== 1)
165 if (ptr
->flags
& MEM_HASH_WITH_PREFIX_KEY
)
167 int temp_len
= ptr
->prefix_key_length
+ key_length
;
168 char *temp
= (char *)malloc(temp_len
);
169 strncpy(temp
, ptr
->prefix_key
, ptr
->prefix_key_length
);
170 strncpy(temp
+ ptr
->prefix_key_length
, key
, key_length
);
171 hash
= generate_hash(ptr
, temp
, temp_len
);
176 hash
= generate_hash(ptr
, key
, key_length
);
179 WATCHPOINT_ASSERT(hash
);
181 return dispatch_host(ptr
, hash
);
184 static uint32_t internal_generate_hash(const char *key
, size_t key_length
)
186 const char *ptr
= key
;
192 value
+= (value
<< 10);
193 value
^= (value
>> 6);
195 value
+= (value
<< 3);
196 value
^= (value
>> 11);
197 value
+= (value
<< 15);
199 return value
== 0 ? 1 : value
;
202 static uint32_t internal_generate_md5(const char *key
, size_t key_length
)
204 unsigned char results
[16];
206 md5_signature((unsigned char*)key
, (unsigned int)key_length
, results
);
208 return ((uint32_t) (results
[3] & 0xFF) << 24)
209 | ((uint32_t) (results
[2] & 0xFF) << 16)
210 | ((uint32_t) (results
[1] & 0xFF) << 8)
211 | (results
[0] & 0xFF);