2 * Copyright (C) 2006-2009 Brian Aker
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
11 inline static bool _is_allocated(const hashkit_st
*hashk
)
13 return hashk
->options
.is_allocated
== true;
16 inline static bool _is_initialized(const hashkit_st
*hashk
)
18 return hashk
->options
.is_initialized
== true;
22 @note We make no assumptions that "hashk" has been, or not been allocated from heap/stack. We just know we didn't do it.
24 hashkit_st
*hashkit_create(hashkit_st
*hashk
)
28 hashk
= (hashkit_st
*)malloc(sizeof(hashkit_st
));
34 hashk
->options
.is_allocated
= true;
38 hashk
->options
.is_allocated
= false;
41 hashk
->options
.is_initialized
= true;
43 hashk
->distribution
= HASHKIT_DISTRIBUTION_MODULA
;
44 hashk
->continuum_count
= 0;
45 hashk
->continuum_points_count
= 0;
47 hashk
->context_size
= 0;
48 hashk
->continuum
= NULL
;
50 hashk
->active_fn
= NULL
;
51 hashk
->continuum_hash_fn
= NULL
;
52 hashk
->continuum_key_fn
= NULL
;
54 hashk
->weight_fn
= NULL
;
61 void hashkit_free(hashkit_st
*hashk
)
63 assert(_is_initialized(hashk
) == true);
65 if (hashk
->continuum
!= NULL
)
67 free(hashk
->continuum
);
71 We don't know if hashk is pointing to something else,
72 so we go on and set is_initialized.
74 hashk
->options
.is_initialized
= false;
76 if (_is_allocated(hashk
))
83 @note We do assume source is valid. If source does not exist, we allocate.
85 hashkit_st
*hashkit_clone(hashkit_st
*destination
, const hashkit_st
*source
)
87 hashkit_st
*new_clone
;
91 return hashkit_create(destination
);
95 assert(_is_initialized(source
) == true);
98 /* new_clone will be a pointer to destination */
99 new_clone
= hashkit_create(destination
);
100 assert((destination
? ((_is_allocated(new_clone
) == false)) : (_is_allocated(new_clone
) == true)));
102 // Should only happen on allocation failure.
103 if (new_clone
== NULL
)
108 // For the moment we will not clone this.
109 new_clone
->continuum
= NULL
;
111 new_clone
->distribution
= source
->distribution
;
112 new_clone
->continuum_count
= source
->continuum_count
;
113 new_clone
->continuum_points_count
= source
->continuum_points_count
;
114 new_clone
->list_size
= source
->list_size
;
115 new_clone
->context_size
= source
->context_size
;
118 new_clone
->hash_fn
= source
->hash_fn
;
119 new_clone
->active_fn
= source
->active_fn
;
120 new_clone
->continuum_hash_fn
= source
->continuum_hash_fn
;
121 new_clone
->continuum_key_fn
= source
->continuum_key_fn
;
122 new_clone
->sort_fn
= source
->sort_fn
;
123 new_clone
->weight_fn
= source
->weight_fn
;
124 new_clone
->list
= source
->list
;
131 void hashkit_set_list(hashkit_st
*hashkit
, void *list
, size_t list_size
, size_t context_size
)
134 hashkit
->list_size
= list_size
;
135 hashkit
->context_size
= context_size
;
139 uint32_t hashkit_value(hashkit_st
*hashkit
, const char *key
, size_t key_length
)
141 if (hashkit
->hash_fn
== NULL
)
142 return hashkit_default(key
, key_length
);
144 return hashkit
->hash_fn(key
, key_length
);
148 uint32_t hashkit_index(hashkit_st
*hashkit
, uint32_t hash_value
)
150 if (hashkit
->list_size
== 1)
153 switch (hashkit
->distribution
)
155 case HASHKIT_DISTRIBUTION_MODULA
:
156 return hash_value
% (uint32_t)hashkit
->list_size
;
158 case HASHKIT_DISTRIBUTION_RANDOM
:
159 return (uint32_t)random() % (uint32_t)hashkit
->list_size
;
161 case HASHKIT_DISTRIBUTION_KETAMA
:
163 hashkit_continuum_point_st
*begin
, *end
, *left
, *right
, *middle
;
164 begin
= left
= hashkit
->continuum
;
165 end
= right
= hashkit
->continuum
+ hashkit
->continuum_points_count
;
169 middle
= left
+ (right
- left
) / 2;
170 if (middle
->value
< hash_value
)
180 case HASHKIT_DISTRIBUTION_MAX
:
182 /* We have added a distribution without extending the logic */
183 return hash_value
% (uint32_t)hashkit
->list_size
;
190 int hashkit_run_distribution(hashkit_st
*hashkit
)
192 switch (hashkit
->distribution
)
194 case HASHKIT_DISTRIBUTION_MODULA
:
195 if (hashkit
->sort_fn
!= NULL
&& hashkit
->list_size
> 1)
196 hashkit
->sort_fn(hashkit
->list
, hashkit
->list_size
);
198 case HASHKIT_DISTRIBUTION_RANDOM
:
200 case HASHKIT_DISTRIBUTION_KETAMA
:
201 return update_continuum(hashkit
);
202 case HASHKIT_DISTRIBUTION_MAX
:
204 /* We have added a distribution without extending the logic */
213 uint32_t hashkit_generate_value(const char *key
, size_t key_length
, hashkit_hash_algorithm_t hash_algorithm
)
215 switch (hash_algorithm
)
217 case HASHKIT_HASH_DEFAULT
:
218 return hashkit_default(key
, key_length
);
219 case HASHKIT_HASH_MD5
:
220 return hashkit_md5(key
, key_length
);
221 case HASHKIT_HASH_CRC
:
222 return hashkit_crc32(key
, key_length
);
223 case HASHKIT_HASH_FNV1_64
:
224 return hashkit_fnv1_64(key
, key_length
);
225 case HASHKIT_HASH_FNV1A_64
:
226 return hashkit_fnv1a_64(key
, key_length
);
227 case HASHKIT_HASH_FNV1_32
:
228 return hashkit_fnv1_32(key
, key_length
);
229 case HASHKIT_HASH_FNV1A_32
:
230 return hashkit_fnv1a_32(key
, key_length
);
231 case HASHKIT_HASH_HSIEH
:
232 #ifdef HAVE_HSIEH_HASH
233 return hashkit_hsieh(key
, key_length
);
237 case HASHKIT_HASH_MURMUR
:
238 return hashkit_murmur(key
, key_length
);
239 case HASHKIT_HASH_JENKINS
:
240 return hashkit_jenkins(key
, key_length
);
241 case HASHKIT_HASH_MAX
:
244 fprintf(stderr
, "hashkit_hash_t was extended but hashkit_generate_value was not updated\n");