Updated for custom hash functions/setting functions.
[awesomized/libmemcached] / libhashkit / hashkit.c
index 54033132cb8e23c03fa6a52a99797dd85faffb1a..64158f989f671f1b003b79c1b92cd9478b6de07c 100644 (file)
@@ -8,74 +8,44 @@
 
 #include "common.h"
 
-inline static bool _is_allocated(const hashkit_st *hashk)
-{
-  return hashk->options.is_allocated == true;
-}
-
-inline static bool _is_initialized(const hashkit_st *hashk)
-{
-  return hashk->options.is_initialized == true;
-}
+static const hashkit_st global_default_hash= {
+  .base_hash= {
+    .function= hashkit_one_at_a_time,
+    .context= NULL
+  },
+};
 
 /**
   @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)
+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;
+  self->base_hash= global_default_hash.base_hash;
+
+  return self;
 }
 
 
-void hashkit_free(hashkit_st *hashk)
+void hashkit_free(hashkit_st *self)
 {
-  assert(_is_initialized(hashk) == true);
-
-  if (hashk->continuum != NULL)
+  if (hashkit_is_allocated(self))
   {
-    free(hashk->continuum);
-  }
-
-  /**
-    We don't know if hashk is pointing to something else,
-    so we go on and set is_initialized.
-  */
-  hashk->options.is_initialized= false;
-
-  if (_is_allocated(hashk))
-  {
-    free(hashk);
+    free(self);
   }
 }
 
@@ -84,138 +54,99 @@ void hashkit_free(hashkit_st *hashk)
 */
 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;
-
+  destination->base_hash= source->base_hash;
 
-  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;
+  return destination;
 }
 
 
-uint32_t hashkit_value(hashkit_st *hashkit, const char *key, size_t key_length)
+uint32_t hashkit_generate_value(const hashkit_st *self, 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);
+  return self->base_hash.function(key, key_length);
 }
 
-
-uint32_t hashkit_index(hashkit_st *hashkit, uint32_t hash_value)
+hashkit_return_t hashkit_set_base_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
 {
-  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:
+  switch (hash_algorithm)
   {
-    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:
+  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_MAX:
   default:
-    /* We have added a distribution without extending the logic */
-    return hash_value % (uint32_t)hashkit->list_size;
+    return HASHKIT_FAILURE;
+    break;
   }
 
-  /* NOTREACHED */
-}
+  self->base_hash.context= NULL;
 
+  return HASHKIT_SUCCESS;
+}
 
-int hashkit_run_distribution(hashkit_st *hashkit)
+hashkit_return_t hashkit_set_base_function_custom(hashkit_st *self, hashkit_hash_fn function, void *context)
 {
-  switch (hashkit->distribution)
+  if (function)
   {
-  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;
+    self->base_hash.function= function;
+    self->base_hash.context= context;
+
+    return HASHKIT_SUCCESS;
   }
 
-  return 0;
+  return HASHKIT_FAILURE;
 }
-#endif
-
 
-uint32_t hashkit_generate_value(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
+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 hashkit_default(key, key_length);
+    return hashkit_one_at_a_time(key, key_length);
   case HASHKIT_HASH_MD5:
     return hashkit_md5(key, key_length);
   case HASHKIT_HASH_CRC:
@@ -241,7 +172,7 @@ uint32_t hashkit_generate_value(const char *key, size_t key_length, hashkit_hash
   case HASHKIT_HASH_MAX:
   default:
 #ifdef HAVE_DEBUG
-    fprintf(stderr, "hashkit_hash_t was extended but hashkit_generate_value was not updated\n");
+    fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
     fflush(stderr);
     assert(0);
 #endif