static test_return_t hashkit_digest_test(hashkit_st *hashk) { uint32_t value; value= hashkit_digest(hashk, "a", sizeof("a")); return TEST_SUCCESS; }
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_custom_function(hashk, hash_test_function, NULL); test_true(rc == HASHKIT_SUCCESS); for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) { uint32_t hash_val; hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr)); test_true(md5_values[x] == hash_val); } return TEST_SUCCESS; }
static memcached_return_t update_continuum(memcached_st *ptr) { uint32_t host_index; uint32_t continuum_index= 0; uint32_t value; memcached_server_st *list; uint32_t pointer_index; uint32_t pointer_counter= 0; uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER; uint32_t pointer_per_hash= 1; uint64_t total_weight= 0; uint64_t is_ketama_weighted= 0; uint64_t is_auto_ejecting= 0; uint32_t points_per_server= 0; uint32_t live_servers= 0; struct timeval now; if (gettimeofday(&now, NULL) != 0) { ptr->cached_errno = errno; return MEMCACHED_ERRNO; } list = memcached_server_list(ptr); /* count live servers (those without a retry delay set) */ is_auto_ejecting= _is_auto_eject_host(ptr); if (is_auto_ejecting) { live_servers= 0; ptr->next_distribution_rebuild= 0; for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index) { if (list[host_index].next_retry <= now.tv_sec) live_servers++; else { if (ptr->next_distribution_rebuild == 0 || list[host_index].next_retry < ptr->next_distribution_rebuild) ptr->next_distribution_rebuild= list[host_index].next_retry; } } } else { live_servers= memcached_server_count(ptr); } is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER); if (live_servers == 0) return MEMCACHED_SUCCESS; if (live_servers > ptr->continuum_count) { memcached_continuum_item_st *new_ptr; new_ptr= libmemcached_realloc(ptr, ptr->continuum, sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server); if (new_ptr == 0) return MEMCACHED_MEMORY_ALLOCATION_FAILURE; ptr->continuum= new_ptr; ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION; } if (is_ketama_weighted) { for (host_index = 0; host_index < memcached_server_count(ptr); ++host_index) { if (list[host_index].weight == 0) { list[host_index].weight = 1; } if (! is_auto_ejecting || list[host_index].next_retry <= now.tv_sec) total_weight += list[host_index].weight; } } for (host_index= 0; host_index < memcached_server_count(ptr); ++host_index) { if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec) continue; if (is_ketama_weighted) { float pct = (float)list[host_index].weight / (float)total_weight; pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4); pointer_per_hash= 4; #ifdef DEBUG printf("ketama_weighted:%s|%d|%llu|%u\n", list[host_index].hostname, list[host_index].port, (unsigned long long)list[host_index].weight, pointer_per_server); #endif } if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY) { for (pointer_index= 0; pointer_index < pointer_per_server / pointer_per_hash; pointer_index++) { char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= ""; size_t sort_host_length; // Spymemcached ketema key format is: hostname/ip:port-index // If hostname is not available then: /ip:port-index sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, "/%s:%u-%u", list[host_index].hostname, (uint32_t)list[host_index].port, pointer_index); #ifdef DEBUG printf("update_continuum: key is %s\n", sort_host); #endif WATCHPOINT_ASSERT(sort_host_length); if (is_ketama_weighted) { for (uint32_t x= 0; x < pointer_per_hash; x++) { value= ketama_server_hash(sort_host, sort_host_length, x); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } else { value= hashkit_digest(&ptr->distribution_hashkit, sort_host, sort_host_length); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } } else { for (pointer_index= 1; pointer_index <= pointer_per_server / pointer_per_hash; pointer_index++) { char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= ""; size_t sort_host_length; if (list[host_index].port == MEMCACHED_DEFAULT_PORT) { sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, "%s-%u", list[host_index].hostname, pointer_index - 1); } else { sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH, "%s:%u-%u", list[host_index].hostname, (uint32_t)list[host_index].port, pointer_index - 1); } WATCHPOINT_ASSERT(sort_host_length); if (is_ketama_weighted) { for (uint32_t x = 0; x < pointer_per_hash; x++) { value= ketama_server_hash(sort_host, sort_host_length, x); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } else { value= hashkit_digest(&ptr->distribution_hashkit, sort_host, sort_host_length); ptr->continuum[continuum_index].index= host_index; ptr->continuum[continuum_index++].value= value; } } } pointer_counter+= pointer_per_server; } WATCHPOINT_ASSERT(ptr); WATCHPOINT_ASSERT(ptr->continuum); WATCHPOINT_ASSERT(memcached_server_count(ptr) * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE); ptr->continuum_points_counter= pointer_counter; qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp); #ifdef DEBUG for (pointer_index= 0; memcached_server_count(ptr) && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++) { WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value); } #endif return MEMCACHED_SUCCESS; }
static uint32_t generate_hash(const memcached_st *ptr, const char *key, size_t key_length) { return hashkit_digest(&ptr->hashkit, key, key_length); }
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++) { hashkit_return_t rc; uint32_t x; const char **ptr; uint32_t *list; rc= hashkit_set_function(hashk, algo); /* Hsieh is disabled most of the time for patent issues */ #ifndef HAVE_HSIEH_HASH if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_HSIEH) continue; #endif #ifndef HAVE_MURMUR_HASH if (rc == HASHKIT_FAILURE && algo == HASHKIT_HASH_MURMUR) continue; #endif if (rc == HASHKIT_INVALID_ARGUMENT && algo == HASHKIT_HASH_CUSTOM) continue; test_true_got(rc == HASHKIT_SUCCESS, hashkit_strerror(NULL, rc)); switch (algo) { case HASHKIT_HASH_DEFAULT: list= one_at_a_time_values; break; case HASHKIT_HASH_MD5: list= md5_values; break; case HASHKIT_HASH_CRC: list= crc_values; break; case HASHKIT_HASH_FNV1_64: list= fnv1_64_values; break; case HASHKIT_HASH_FNV1A_64: list= fnv1a_64_values; break; case HASHKIT_HASH_FNV1_32: list= fnv1_32_values; break; case HASHKIT_HASH_FNV1A_32: list= fnv1a_32_values; break; case HASHKIT_HASH_HSIEH: list= hsieh_values; break; case HASHKIT_HASH_MURMUR: list= murmur_values; break; case HASHKIT_HASH_JENKINS: list= jenkins_values; break; case HASHKIT_HASH_CUSTOM: case HASHKIT_HASH_MAX: default: list= NULL; break; } // Now we make sure we did set the hash correctly. if (list) { for (ptr= list_to_hash, x= 0; *ptr; ptr++, x++) { uint32_t hash_val; hash_val= hashkit_digest(hashk, *ptr, strlen(*ptr)); test_true(list[x] == hash_val); } } else { return TEST_FAILURE; } } return TEST_SUCCESS; }
static test_return_t hashkit_digest_test(hashkit_st *hashk) { hashkit_digest(hashk, "a", sizeof("a")); return TEST_SUCCESS; }
uint32_t digest(const char *key, size_t key_length) { return hashkit_digest(&self, key, key_length); }
uint32_t digest(std::string& str) { return hashkit_digest(&self, str.c_str(), str.length()); }