--- /dev/null
+/* HashKit
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#include "common.h"
+
+uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length)
+{
+ return self->base_hash.function(key, key_length, self->base_hash.context);
+}
+
+static hashkit_return_t _set_function(struct hashkit_function_st *self, hashkit_hash_algorithm_t hash_algorithm)
+{
+ switch (hash_algorithm)
+ {
+ case HASHKIT_HASH_DEFAULT:
+ self->function= hashkit_one_at_a_time;
+ break;
+ case HASHKIT_HASH_MD5:
+ self->function= hashkit_md5;
+ break;
+ case HASHKIT_HASH_CRC:
+ self->function= hashkit_crc32;
+ break;
+ case HASHKIT_HASH_FNV1_64:
+ self->function= hashkit_fnv1_64;
+ break;
+ case HASHKIT_HASH_FNV1A_64:
+ self->function= hashkit_fnv1a_64;
+ break;
+ case HASHKIT_HASH_FNV1_32:
+ self->function= hashkit_fnv1_32;
+ break;
+ case HASHKIT_HASH_FNV1A_32:
+ self->function= hashkit_fnv1a_32;
+ break;
+ case HASHKIT_HASH_HSIEH:
+#ifdef HAVE_HSIEH_HASH
+ self->function= hashkit_hsieh;
+ break;
+#else
+ return HASHKIT_FAILURE;
+#endif
+ case HASHKIT_HASH_MURMUR:
+ self->function= hashkit_murmur;
+ break;
+ case HASHKIT_HASH_JENKINS:
+ self->function= hashkit_jenkins;
+ break;
+ case HASHKIT_HASH_CUSTOM:
+ case HASHKIT_HASH_MAX:
+ default:
+ return HASHKIT_FAILURE;
+ break;
+ }
+
+ self->context= NULL;
+
+ return HASHKIT_SUCCESS;
+}
+
+hashkit_return_t hashkit_set_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
+{
+ return _set_function(&self->base_hash, hash_algorithm);
+}
+
+hashkit_return_t hashkit_set_distribution_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
+{
+ return _set_function(&self->distribution_hash, hash_algorithm);
+}
+
+static hashkit_return_t _set_custom_function(struct hashkit_function_st *self, hashkit_hash_fn function, void *context)
+{
+ if (function)
+ {
+ self->function= function;
+ self->context= context;
+
+ return HASHKIT_SUCCESS;
+ }
+
+ return HASHKIT_FAILURE;
+}
+
+hashkit_return_t hashkit_set_custom_function(hashkit_st *self, hashkit_hash_fn function, void *context)
+{
+ return _set_custom_function(&self->base_hash, function, context);
+}
+
+hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context)
+{
+ return _set_custom_function(&self->distribution_hash, function, context);
+}
+
+static hashkit_hash_algorithm_t get_function_type(const hashkit_hash_fn function)
+{
+ if (function == hashkit_one_at_a_time)
+ {
+ return HASHKIT_HASH_DEFAULT;
+ }
+ else if (function == hashkit_md5)
+ {
+ return HASHKIT_HASH_MD5;
+ }
+ else if (function == hashkit_crc32)
+ {
+ return HASHKIT_HASH_CRC;
+ }
+ else if (function == hashkit_fnv1_64)
+ {
+ return HASHKIT_HASH_FNV1_64;
+ }
+ else if (function == hashkit_fnv1a_64)
+ {
+ return HASHKIT_HASH_FNV1A_64;
+ }
+ else if (function == hashkit_fnv1_32)
+ {
+ return HASHKIT_HASH_FNV1_32;
+ }
+ else if (function == hashkit_fnv1a_32)
+ {
+ return HASHKIT_HASH_FNV1A_32;
+ }
+#ifdef HAVE_HSIEH_HASH
+ else if (function == hashkit_hsieh)
+ {
+ return HASHKIT_HASH_HSIEH;
+ }
+#endif
+ else if (function == hashkit_murmur)
+ {
+ return HASHKIT_HASH_MURMUR;
+ }
+ else if (function == hashkit_jenkins)
+ {
+ return HASHKIT_HASH_JENKINS;
+ }
+
+ return HASHKIT_HASH_CUSTOM;
+}
+
+hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *self)
+{
+ return get_function_type(self->base_hash.function);
+}
+
+hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self)
+{
+ return get_function_type(self->distribution_hash.function);
+}
+
+uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
+{
+ switch (hash_algorithm)
+ {
+ case HASHKIT_HASH_DEFAULT:
+ return libhashkit_one_at_a_time(key, key_length);
+ case HASHKIT_HASH_MD5:
+ return libhashkit_md5(key, key_length);
+ case HASHKIT_HASH_CRC:
+ return libhashkit_crc32(key, key_length);
+ case HASHKIT_HASH_FNV1_64:
+ return libhashkit_fnv1_64(key, key_length);
+ case HASHKIT_HASH_FNV1A_64:
+ return libhashkit_fnv1a_64(key, key_length);
+ case HASHKIT_HASH_FNV1_32:
+ return libhashkit_fnv1_32(key, key_length);
+ case HASHKIT_HASH_FNV1A_32:
+ return libhashkit_fnv1a_32(key, key_length);
+ case HASHKIT_HASH_HSIEH:
+#ifdef HAVE_HSIEH_HASH
+ return libhashkit_hsieh(key, key_length);
+#else
+ return 1;
+#endif
+ case HASHKIT_HASH_MURMUR:
+ return libhashkit_murmur(key, key_length);
+ case HASHKIT_HASH_JENKINS:
+ return libhashkit_jenkins(key, key_length);
+ case HASHKIT_HASH_CUSTOM:
+ case HASHKIT_HASH_MAX:
+ default:
+#ifdef HAVE_DEBUG
+ fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
+ fflush(stderr);
+ assert(0);
+#endif
+ break;
+ }
+
+ return 1;
+}
--- /dev/null
+/* HashKit
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license. See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#ifndef HASHKIT_FUNCTION_H
+#define HASHKIT_FUNCTION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length);
+
+/**
+ This sets/gets the default function we will be using.
+*/
+HASHKIT_API
+hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
+
+HASHKIT_API
+hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context);
+
+HASHKIT_API
+hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash);
+
+/**
+ This sets/gets the function we use for distribution.
+*/
+HASHKIT_API
+hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
+
+HASHKIT_API
+hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context);
+
+HASHKIT_API
+hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self);
+
+/**
+ This is a utilitly function provided so that you can directly access hashes with a hashkit_st.
+*/
+
+HASHKIT_API
+uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HASHKIT_FUNCTION_H */
.function= hashkit_one_at_a_time,
.context= NULL
},
+ .flags= {
+ .is_base_same_distributed= false,
+ }
};
-/**
- @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 *self)
+static inline bool _hashkit_init(hashkit_st *self)
+{
+ self->base_hash= global_default_hash.base_hash;
+ self->distribution_hash= global_default_hash.base_hash;
+ self->flags= global_default_hash.flags;
+
+ return true;
+}
+
+static inline hashkit_st *_hashkit_create(hashkit_st *self)
{
if (self == NULL)
{
self->options.is_allocated= false;
}
- self->base_hash= global_default_hash.base_hash;
+ return self;
+}
+
+hashkit_st *hashkit_create(hashkit_st *self)
+{
+ self= _hashkit_create(self);
+ if (! self)
+ return self;
+
+ if (! _hashkit_init(self))
+ {
+ hashkit_free(self);
+ }
return self;
}
}
/* new_clone will be a pointer to destination */
- destination= hashkit_create(destination);
+ destination= _hashkit_create(destination);
// Should only happen on allocation failure.
if (destination == NULL)
}
destination->base_hash= source->base_hash;
+ destination->distribution_hash= source->distribution_hash;
+ destination->flags= source->flags;
return destination;
}
bool hashkit_compare(const hashkit_st *first, const hashkit_st *second)
{
if (first->base_hash.function == second->base_hash.function &&
- first->base_hash.context == second->base_hash.context)
- return true;
-
- return false;
-}
-
-uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length)
-{
- return self->base_hash.function(key, key_length, self->base_hash.context);
-}
-
-hashkit_return_t hashkit_set_base_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
-{
- switch (hash_algorithm)
+ 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:
- self->base_hash.function= hashkit_one_at_a_time;
- break;
- case HASHKIT_HASH_MD5:
- self->base_hash.function= hashkit_md5;
- break;
- case HASHKIT_HASH_CRC:
- self->base_hash.function= hashkit_crc32;
- break;
- case HASHKIT_HASH_FNV1_64:
- self->base_hash.function= hashkit_fnv1_64;
- break;
- case HASHKIT_HASH_FNV1A_64:
- self->base_hash.function= hashkit_fnv1a_64;
- break;
- case HASHKIT_HASH_FNV1_32:
- self->base_hash.function= hashkit_fnv1_32;
- break;
- case HASHKIT_HASH_FNV1A_32:
- self->base_hash.function= hashkit_fnv1a_32;
- break;
- case HASHKIT_HASH_HSIEH:
-#ifdef HAVE_HSIEH_HASH
- self->base_hash.function= hashkit_hsieh;
- break;
-#else
- return HASHKIT_FAILURE;
-#endif
- case HASHKIT_HASH_MURMUR:
- self->base_hash.function= hashkit_murmur;
- break;
- case HASHKIT_HASH_JENKINS:
- self->base_hash.function= hashkit_jenkins;
- break;
- case HASHKIT_HASH_CUSTOM:
- case HASHKIT_HASH_MAX:
- default:
- return HASHKIT_FAILURE;
- break;
- }
-
- self->base_hash.context= NULL;
-
- return HASHKIT_SUCCESS;
-}
-
-hashkit_return_t hashkit_set_base_function_custom(hashkit_st *self, hashkit_hash_fn function, void *context)
-{
- if (function)
- {
- self->base_hash.function= function;
- self->base_hash.context= context;
-
- return HASHKIT_SUCCESS;
- }
-
- return HASHKIT_FAILURE;
-}
-
-hashkit_hash_algorithm_t hashkit_get_base_function(const hashkit_st *self)
-{
- if (self->base_hash.function == hashkit_one_at_a_time)
- {
- return HASHKIT_HASH_DEFAULT;
- }
- else if (self->base_hash.function == hashkit_md5)
- {
- return HASHKIT_HASH_MD5;
- }
- else if (self->base_hash.function == hashkit_crc32)
- {
- return HASHKIT_HASH_CRC;
- }
- else if (self->base_hash.function == hashkit_fnv1_64)
- {
- return HASHKIT_HASH_FNV1_64;
- }
- else if (self->base_hash.function == hashkit_fnv1a_64)
- {
- return HASHKIT_HASH_FNV1A_64;
- }
- else if (self->base_hash.function == hashkit_fnv1_32)
- {
- return HASHKIT_HASH_FNV1_32;
- }
- else if (self->base_hash.function == hashkit_fnv1a_32)
- {
- return HASHKIT_HASH_FNV1A_32;
- }
-#ifdef HAVE_HSIEH_HASH
- else if (self->base_hash.function == hashkit_hsieh)
- {
- return HASHKIT_HASH_HSIEH;
- }
-#endif
- else if (self->base_hash.function == hashkit_murmur)
- {
- return HASHKIT_HASH_MURMUR;
- }
- else if (self->base_hash.function == hashkit_jenkins)
- {
- return HASHKIT_HASH_JENKINS;
- }
-
- return HASHKIT_HASH_CUSTOM;
-}
-
-uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
-{
- switch (hash_algorithm)
- {
- case HASHKIT_HASH_DEFAULT:
- return libhashkit_one_at_a_time(key, key_length);
- case HASHKIT_HASH_MD5:
- return libhashkit_md5(key, key_length);
- case HASHKIT_HASH_CRC:
- return libhashkit_crc32(key, key_length);
- case HASHKIT_HASH_FNV1_64:
- return libhashkit_fnv1_64(key, key_length);
- case HASHKIT_HASH_FNV1A_64:
- return libhashkit_fnv1a_64(key, key_length);
- case HASHKIT_HASH_FNV1_32:
- return libhashkit_fnv1_32(key, key_length);
- case HASHKIT_HASH_FNV1A_32:
- return libhashkit_fnv1a_32(key, key_length);
- case HASHKIT_HASH_HSIEH:
-#ifdef HAVE_HSIEH_HASH
- return libhashkit_hsieh(key, key_length);
-#else
- return 1;
-#endif
- case HASHKIT_HASH_MURMUR:
- return libhashkit_murmur(key, key_length);
- case HASHKIT_HASH_JENKINS:
- return libhashkit_jenkins(key, key_length);
- case HASHKIT_HASH_CUSTOM:
- case HASHKIT_HASH_MAX:
- default:
-#ifdef HAVE_DEBUG
- fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
- fflush(stderr);
- assert(0);
-#endif
- break;
+ return true;
}
- return 1;
+ return false;
}
#include <libhashkit/types.h>
#include <libhashkit/algorithm.h>
#include <libhashkit/behavior.h>
+#include <libhashkit/function.h>
#include <libhashkit/strerror.h>
#ifdef __cplusplus
struct hashkit_st
{
- struct {
+ struct hashkit_function_st {
hashkit_hash_fn function;
void *context;
- } base_hash;
+ } base_hash, distribution_hash;
+
+ struct {
+ bool is_base_same_distributed:1;
+ } flags;
struct {
bool is_allocated:1;
HASHKIT_API
void hashkit_free(hashkit_st *hash);
-HASHKIT_API
-uint32_t hashkit_generate_value(const hashkit_st *self, const char *key, size_t key_length);
-
-HASHKIT_API
-hashkit_return_t hashkit_set_base_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
-
-HASHKIT_API
-hashkit_hash_algorithm_t hashkit_get_base_function(const hashkit_st *hash);
-
-HASHKIT_API
-hashkit_return_t hashkit_set_base_function_custom(hashkit_st *hash, hashkit_hash_fn function, void *context);
-
-HASHKIT_API
-uint32_t libhashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm);
-
#define hashkit_is_allocated(__object) ((__object)->options.is_allocated)
#define hashkit_is_initialized(__object) ((__object)->options.is_initialized)
nobase_include_HEADERS+= \
libhashkit/algorithm.h \
libhashkit/behavior.h \
+ libhashkit/function.h \
libhashkit/hashkit.h \
libhashkit/strerror.h \
libhashkit/types.h \
libhashkit/behavior.c \
libhashkit/crc32.c \
libhashkit/fnv.c \
+ libhashkit/function.c \
libhashkit/hashkit.c \
libhashkit/jenkins.c \
libhashkit/ketama.c \
case MEMCACHED_BEHAVIOR_KETAMA:
return (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA) ? (uint64_t) 1 : 0;
case MEMCACHED_BEHAVIOR_HASH:
- return hashkit_get_base_function(&ptr->hashkit);
+ return hashkit_get_function(&ptr->hashkit);
case MEMCACHED_BEHAVIOR_KETAMA_HASH:
- return hashkit_get_base_function(&ptr->distribution_hashkit);
+ return hashkit_get_function(&ptr->distribution_hashkit);
case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
return ptr->server_failure_limit;
case MEMCACHED_BEHAVIOR_SORT_HOSTS:
memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_hash_t type)
{
hashkit_return_t rc;
- rc= hashkit_set_base_function(&ptr->hashkit, (hashkit_hash_algorithm_t)type);
+ rc= hashkit_set_function(&ptr->hashkit, (hashkit_hash_algorithm_t)type);
return rc == HASHKIT_SUCCESS ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
}
memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr)
{
- return (memcached_hash_t)hashkit_get_base_function(&ptr->hashkit);
+ return (memcached_hash_t)hashkit_get_function(&ptr->hashkit);
}
memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, memcached_hash_t type)
{
hashkit_return_t rc;
- rc= hashkit_set_base_function(&ptr->distribution_hashkit, (hashkit_hash_algorithm_t)type);
+ rc= hashkit_set_function(&ptr->distribution_hashkit, (hashkit_hash_algorithm_t)type);
return rc == HASHKIT_SUCCESS ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
}
memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr)
{
- return (memcached_hash_t)hashkit_get_base_function(&ptr->distribution_hashkit);
+ return (memcached_hash_t)hashkit_get_function(&ptr->distribution_hashkit);
}
return TEST_SUCCESS;
}
-static test_return_t hashkit_set_base_function_test(hashkit_st *hashk)
+static test_return_t hashkit_set_function_test(hashkit_st *hashk)
{
for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++)
{
const char **ptr;
uint32_t *list;
- rc= hashkit_set_base_function(hashk, algo);
+ rc= hashkit_set_function(hashk, algo);
/* Hsieh is disabled most of the time for patent issues */
if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH)
return libhashkit_md5(string, string_length);
}
-static test_return_t hashkit_set_base_function_custom_test(hashkit_st *hashk)
+static test_return_t hashkit_set_custom_function_test(hashkit_st *hashk)
{
hashkit_return_t rc;
uint32_t x;
const char **ptr;
- rc= hashkit_set_base_function_custom(hashk, hash_test_function, NULL);
+ rc= hashkit_set_custom_function(hashk, hash_test_function, NULL);
test_true(rc == HASHKIT_SUCCESS);
for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++)
return TEST_SUCCESS;
}
-static test_return_t hashkit_get_base_function_test(hashkit_st *hashk)
+static test_return_t hashkit_set_distribution_function_test(hashkit_st *hashk)
+{
+ for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++)
+ {
+ hashkit_return_t rc;
+
+ rc= hashkit_set_distribution_function(hashk, algo);
+
+ /* Hsieh is disabled most of the time for patent issues */
+ if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH)
+ continue;
+
+ if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_CUSTOM)
+ continue;
+
+ test_true(rc == HASHKIT_SUCCESS);
+ }
+
+ return TEST_SUCCESS;
+}
+
+static test_return_t hashkit_set_custom_distribution_function_test(hashkit_st *hashk)
+{
+ hashkit_return_t rc;
+
+ rc= hashkit_set_custom_distribution_function(hashk, hash_test_function, NULL);
+ test_true(rc == HASHKIT_SUCCESS);
+
+ return TEST_SUCCESS;
+}
+
+
+static test_return_t hashkit_get_function_test(hashkit_st *hashk)
{
for (hashkit_hash_algorithm_t algo = HASHKIT_HASH_DEFAULT; algo < HASHKIT_HASH_MAX; algo++)
{
if (HASHKIT_HASH_CUSTOM || HASHKIT_HASH_HSIEH)
continue;
- rc= hashkit_set_base_function(hashk, algo);
+ rc= hashkit_set_function(hashk, algo);
test_true(rc == HASHKIT_SUCCESS);
- test_true(hashkit_get_base_function(hashk) == algo);
+ test_true(hashkit_get_function(hashk) == algo);
}
return TEST_SUCCESS;
}
test_st hashkit_st_functions[] ={
{"hashkit_generate_value", 0, (test_callback_fn)hashkit_generate_value_test},
- {"hashkit_set_base_function", 0, (test_callback_fn)hashkit_set_base_function_test},
- {"hashkit_set_base_function_custom", 0, (test_callback_fn)hashkit_set_base_function_custom_test},
- {"hashkit_get_base_function", 0, (test_callback_fn)hashkit_get_base_function_test},
+ {"hashkit_set_function", 0, (test_callback_fn)hashkit_set_function_test},
+ {"hashkit_set_custom_function", 0, (test_callback_fn)hashkit_set_custom_function_test},
+ {"hashkit_get_function", 0, (test_callback_fn)hashkit_get_function_test},
+ {"hashkit_set_distribution_function", 0, (test_callback_fn)hashkit_set_distribution_function_test},
+ {"hashkit_set_custom_distribution_function", 0, (test_callback_fn)hashkit_set_custom_distribution_function_test},
{"hashkit_compare", 0, (test_callback_fn)hashkit_compare_test},
{0, 0, 0}
};