#include "common.h"
-inline static bool _is_allocated(const hashkit_st *hashk)
-{
- return hashk->options.is_allocated == true;
-}
+static const hashkit_st global_default_hash= {
+ .base_hash= {
+ .function= hashkit_one_at_a_time,
+ .context= NULL
+ },
+ .flags= {
+ .is_base_same_distributed= false,
+ }
+};
-inline static bool _is_initialized(const hashkit_st *hashk)
+static inline bool _hashkit_init(hashkit_st *self)
{
- return hashk->options.is_initialized == true;
+ self->base_hash= global_default_hash.base_hash;
+ self->distribution_hash= global_default_hash.base_hash;
+ self->flags= global_default_hash.flags;
+
+ return true;
}
-/**
- @note We make no assumptions that "hashk" has been, or not been allocated from heap/stack. We just know we didn't do it.
-*/
-hashkit_st *hashkit_create(hashkit_st *hashk)
+static inline hashkit_st *_hashkit_create(hashkit_st *self)
{
- if (hashk == NULL)
+ if (self == NULL)
{
- hashk= (hashkit_st *)malloc(sizeof(hashkit_st));
- if (hashk == NULL)
+ self= (hashkit_st *)malloc(sizeof(hashkit_st));
+ if (self == NULL)
{
return NULL;
}
- hashk->options.is_allocated= true;
+ self->options.is_allocated= true;
}
else
{
- hashk->options.is_allocated= false;
+ self->options.is_allocated= false;
}
- hashk->options.is_initialized= true;
-
- hashk->distribution= HASHKIT_DISTRIBUTION_MODULA;
- hashk->continuum_count= 0;
- hashk->continuum_points_count= 0;
- hashk->list_size= 0;
- hashk->context_size= 0;
- hashk->continuum= NULL;
- hashk->hash_fn= NULL;
- hashk->active_fn= NULL;
- hashk->continuum_hash_fn= NULL;
- hashk->continuum_key_fn= NULL;
- hashk->sort_fn= NULL;
- hashk->weight_fn= NULL;
- hashk->list= NULL;
-
- return hashk;
+ return self;
}
-
-void hashkit_free(hashkit_st *hashk)
+hashkit_st *hashkit_create(hashkit_st *self)
{
- assert(_is_initialized(hashk) == true);
+ self= _hashkit_create(self);
+ if (! self)
+ return self;
- if (hashk->continuum != NULL)
+ if (! _hashkit_init(self))
{
- free(hashk->continuum);
+ hashkit_free(self);
}
- /**
- We don't know if hashk is pointing to something else,
- so we go on and set is_initialized.
- */
- hashk->options.is_initialized= false;
+ return self;
+}
+
- if (_is_allocated(hashk))
+void hashkit_free(hashkit_st *self)
+{
+ if (hashkit_is_allocated(self))
{
- free(hashk);
+ free(self);
}
}
-/**
- @note We do assume source is valid. If source does not exist, we allocate.
-*/
hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source)
{
- hashkit_st *new_clone;
-
if (source == NULL)
{
return hashkit_create(destination);
}
- else
- {
- assert(_is_initialized(source) == true);
- }
/* new_clone will be a pointer to destination */
- new_clone= hashkit_create(destination);
- assert((destination ? ((_is_allocated(new_clone) == false)) : (_is_allocated(new_clone) == true)));
+ destination= _hashkit_create(destination);
// Should only happen on allocation failure.
- if (new_clone == NULL)
+ if (destination == NULL)
{
return NULL;
}
- // For the moment we will not clone this.
- new_clone->continuum= NULL;
-
- new_clone->distribution= source->distribution;
- new_clone->continuum_count= source->continuum_count;
- new_clone->continuum_points_count= source->continuum_points_count;
- new_clone->list_size= source->list_size;
- new_clone->context_size= source->context_size;
-
-
- new_clone->hash_fn= source->hash_fn;
- new_clone->active_fn= source->active_fn;
- new_clone->continuum_hash_fn= source->continuum_hash_fn;
- new_clone->continuum_key_fn= source->continuum_key_fn;
- new_clone->sort_fn= source->sort_fn;
- new_clone->weight_fn= source->weight_fn;
- new_clone->list= source->list;
-
- return new_clone;
-}
-
-
-#if 0
-void hashkit_set_list(hashkit_st *hashkit, void *list, size_t list_size, size_t context_size)
-{
- hashkit->list= list;
- hashkit->list_size= list_size;
- hashkit->context_size= context_size;
-}
-
-
-uint32_t hashkit_value(hashkit_st *hashkit, const char *key, size_t key_length)
-{
- if (hashkit->hash_fn == NULL)
- return hashkit_default(key, key_length);
-
- return hashkit->hash_fn(key, key_length);
-}
-
-
-uint32_t hashkit_index(hashkit_st *hashkit, uint32_t hash_value)
-{
- if (hashkit->list_size == 1)
- return 0;
-
- switch (hashkit->distribution)
- {
- case HASHKIT_DISTRIBUTION_MODULA:
- return hash_value % (uint32_t)hashkit->list_size;
-
- case HASHKIT_DISTRIBUTION_RANDOM:
- return (uint32_t)random() % (uint32_t)hashkit->list_size;
-
- case HASHKIT_DISTRIBUTION_KETAMA:
- {
- hashkit_continuum_point_st *begin, *end, *left, *right, *middle;
- begin= left= hashkit->continuum;
- end= right= hashkit->continuum + hashkit->continuum_points_count;
-
- while (left < right)
- {
- middle= left + (right - left) / 2;
- if (middle->value < hash_value)
- left= middle + 1;
- else
- right= middle;
- }
- if (right == end)
- right= begin;
- return right->index;
- }
-
- case HASHKIT_DISTRIBUTION_MAX:
- default:
- /* We have added a distribution without extending the logic */
- return hash_value % (uint32_t)hashkit->list_size;
- }
-
- /* NOTREACHED */
-}
-
-
-int hashkit_run_distribution(hashkit_st *hashkit)
-{
- switch (hashkit->distribution)
- {
- case HASHKIT_DISTRIBUTION_MODULA:
- if (hashkit->sort_fn != NULL && hashkit->list_size > 1)
- hashkit->sort_fn(hashkit->list, hashkit->list_size);
- break;
- case HASHKIT_DISTRIBUTION_RANDOM:
- break;
- case HASHKIT_DISTRIBUTION_KETAMA:
- return update_continuum(hashkit);
- case HASHKIT_DISTRIBUTION_MAX:
- default:
- /* We have added a distribution without extending the logic */
- break;
- }
+ destination->base_hash= source->base_hash;
+ destination->distribution_hash= source->distribution_hash;
+ destination->flags= source->flags;
- return 0;
+ return destination;
}
-#endif
-
-uint32_t hashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
+bool hashkit_compare(const hashkit_st *first, const hashkit_st *second)
{
- switch (hash_algorithm)
+ if (first->base_hash.function == second->base_hash.function &&
+ first->base_hash.context == second->base_hash.context &&
+ first->distribution_hash.function == second->distribution_hash.function &&
+ first->distribution_hash.context == second->distribution_hash.context &&
+ first->flags.is_base_same_distributed == second->flags.is_base_same_distributed)
{
- case HASHKIT_HASH_DEFAULT:
- return hashkit_default(key, key_length);
- case HASHKIT_HASH_MD5:
- return hashkit_md5(key, key_length);
- case HASHKIT_HASH_CRC:
- return hashkit_crc32(key, key_length);
- case HASHKIT_HASH_FNV1_64:
- return hashkit_fnv1_64(key, key_length);
- case HASHKIT_HASH_FNV1A_64:
- return hashkit_fnv1a_64(key, key_length);
- case HASHKIT_HASH_FNV1_32:
- return hashkit_fnv1_32(key, key_length);
- case HASHKIT_HASH_FNV1A_32:
- return hashkit_fnv1a_32(key, key_length);
- case HASHKIT_HASH_HSIEH:
-#ifdef HAVE_HSIEH_HASH
- return hashkit_hsieh(key, key_length);
-#else
- return 1;
-#endif
- case HASHKIT_HASH_MURMUR:
- return hashkit_murmur(key, key_length);
- case HASHKIT_HASH_JENKINS:
- return hashkit_jenkins(key, key_length);
- case HASHKIT_HASH_MAX:
- default:
-#ifdef HAVE_DEBUG
- fprintf(stderr, "hashkit_hash_t was extended but hashkit_generate_value was not updated\n");
- fflush(stderr);
- assert(0);
-#endif
- break;
+ return true;
}
- return 1;
+ return false;
}