X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=libhashkit%2Fhashkit.c;h=47c9e580c7b50df985b16ad7457939399c6eb24d;hb=519261ca98528ebc5d854ed839f400aa03a3dc5c;hp=54033132cb8e23c03fa6a52a99797dd85faffb1a;hpb=55b5455291498ef63c1c34976552d58708a74732;p=awesomized%2Flibmemcached diff --git a/libhashkit/hashkit.c b/libhashkit/hashkit.c index 54033132..47c9e580 100644 --- a/libhashkit/hashkit.c +++ b/libhashkit/hashkit.c @@ -8,245 +8,101 @@ #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; }