From: Trond Norbye Date: Sun, 14 Jun 2009 18:52:39 +0000 (+0200) Subject: merge upstream X-Git-Tag: 0.31~15^2~1 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;ds=sidebyside;h=921abbe1906e77cc18cbe8859bc5afe9494d780e;hp=-c;p=m6w6%2Flibmemcached merge upstream --- 921abbe1906e77cc18cbe8859bc5afe9494d780e diff --combined libmemcached/memcached.c index b880d833,5991aabb..4e8ec062 --- a/libmemcached/memcached.c +++ b/libmemcached/memcached.c @@@ -20,6 -20,9 +20,9 @@@ memcached_st *memcached_create(memcache { memset(ptr, 0, sizeof(memcached_st)); } + + memcached_set_memory_allocators(ptr, NULL, NULL, NULL, NULL); + result_ptr= memcached_result_create(ptr, &ptr->result); WATCHPOINT_ASSERT(result_ptr); ptr->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT; @@@ -45,20 -48,10 +48,10 @@@ void memcached_free(memcached_st *ptr ptr->on_cleanup(ptr); if (ptr->continuum) - { - if (ptr->call_free) - ptr->call_free(ptr, ptr->continuum); - else - free(ptr->continuum); - } + ptr->call_free(ptr, ptr->continuum); if (ptr->is_allocated) - { - if (ptr->call_free) - ptr->call_free(ptr, ptr); - else - free(ptr); - } + ptr->call_free(ptr, ptr); else memset(ptr, 0, sizeof(memcached_st)); } @@@ -105,13 -98,13 +98,14 @@@ memcached_st *memcached_clone(memcached new_clone->call_free= source->call_free; new_clone->call_malloc= source->call_malloc; new_clone->call_realloc= source->call_realloc; + new_clone->call_calloc= source->call_calloc; new_clone->get_key_failure= source->get_key_failure; new_clone->delete_trigger= source->delete_trigger; new_clone->server_failure_limit= source->server_failure_limit; new_clone->io_msg_watermark= source->io_msg_watermark; new_clone->io_bytes_watermark= source->io_bytes_watermark; new_clone->io_key_prefetch= source->io_key_prefetch; + new_clone->number_of_replicas= source->number_of_replicas; if (source->hosts) rc= memcached_server_push(new_clone, source->hosts); @@@ -143,3 -136,14 +137,14 @@@ return new_clone; } + void *memcached_get_user_data(memcached_st *ptr) + { + return ptr->user_data; + } + + void *memcached_set_user_data(memcached_st *ptr, void *data) + { + void *ret= ptr->user_data; + ptr->user_data= data; + return ret; + } diff --combined libmemcached/memcached.h index 47cc4c56,607fb4b6..23f5d99a --- a/libmemcached/memcached.h +++ b/libmemcached/memcached.h @@@ -116,10 -116,10 +116,11 @@@ struct memcached_st memcached_free_function call_free; memcached_malloc_function call_malloc; memcached_realloc_function call_realloc; + memcached_calloc_function call_calloc; memcached_trigger_key get_key_failure; memcached_trigger_delete_key delete_trigger; char prefix_key[MEMCACHED_PREFIX_KEY_MAX_SIZE]; + uint32_t number_of_replicas; }; @@@ -231,10 -231,29 +232,29 @@@ void *memcached_callback_get(memcached_ memcached_return memcached_dump(memcached_st *ptr, memcached_dump_func *function, void *context, uint32_t number_of_callbacks); + memcached_return memcached_set_memory_allocators(memcached_st *ptr, + memcached_malloc_function mem_malloc, + memcached_free_function mem_free, + memcached_realloc_function mem_realloc, + memcached_calloc_function mem_calloc); + + void memcached_get_memory_allocators(memcached_st *ptr, + memcached_malloc_function *mem_malloc, + memcached_free_function *mem_free, + memcached_realloc_function *mem_realloc, + memcached_calloc_function *mem_calloc); + + void *memcached_get_user_data(memcached_st *ptr); + void *memcached_set_user_data(memcached_st *ptr, void *data); + #ifdef __cplusplus } #endif #include + #ifdef MEMCACHED_INTERNAL + #include + #endif + #endif /* __MEMCACHED_H__ */ diff --combined tests/function.c index 3113fb1f,99ad776a..7b13b1b6 --- a/tests/function.c +++ b/tests/function.c @@@ -215,6 -215,7 +215,7 @@@ static test_return clone_test(memcache assert(clone->call_free == memc->call_free); assert(clone->call_malloc == memc->call_malloc); assert(clone->call_realloc == memc->call_realloc); + assert(clone->call_calloc == memc->call_calloc); assert(clone->connect_timeout == memc->connect_timeout); assert(clone->delete_trigger == memc->delete_trigger); assert(clone->distribution == memc->distribution); @@@ -235,7 -236,6 +236,7 @@@ assert(clone->server_failure_limit == memc->server_failure_limit); assert(clone->snd_timeout == memc->snd_timeout); assert(clone->user_data == memc->user_data); + assert(clone->number_of_replicas == memc->number_of_replicas); memcached_free(clone); } @@@ -263,6 -263,16 +264,16 @@@ return 0; } + static test_return userdata_test(memcached_st *memc) + { + void* foo; + assert(memcached_set_user_data(memc, foo) == NULL); + assert(memcached_get_user_data(memc) == foo); + assert(memcached_set_user_data(memc, NULL) == foo); + + return TEST_SUCCESS; + } + static test_return connection_test(memcached_st *memc) { memcached_return rc; @@@ -1542,9 -1552,6 +1553,9 @@@ static test_return behavior_test(memca value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE); assert(value > 0); + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, value + 1); + assert((value + 1) == memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS)); return 0; } @@@ -3040,24 -3047,6 +3051,24 @@@ static memcached_return pre_binary(mem return rc; } +static memcached_return pre_replication(memcached_st *memc) +{ + memcached_return rc= MEMCACHED_FAILURE; + if (pre_binary(memc) == MEMCACHED_SUCCESS) + { + /* + * Make sure that we store the item on all servers + * (master + replicas == number of servers) + */ + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, + memc->number_of_hosts - 1); + assert(rc == MEMCACHED_SUCCESS); + assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS) == memc->number_of_hosts - 1); + } + + return rc; +} + static void my_free(memcached_st *ptr __attribute__((unused)), void *mem) { free(mem); @@@ -3065,7 -3054,11 +3076,11 @@@ static void *my_malloc(memcached_st *ptr __attribute__((unused)), const size_t size) { - return calloc(1, size); + void *ret= malloc(size); + if (ret != NULL) + memset(ret, 0xff, size); + + return ret; } static void *my_realloc(memcached_st *ptr __attribute__((unused)), void *mem, const size_t size) @@@ -3073,6 -3066,11 +3088,11 @@@ return realloc(mem, size); } + static void *my_calloc(memcached_st *ptr __attribute__((unused)), size_t nelem, const size_t size) + { + return calloc(nelem, size); + } + static memcached_return set_prefix(memcached_st *memc) { memcached_return rc; @@@ -3140,7 -3138,7 +3160,7 @@@ return MEMCACHED_SUCCESS; } - static memcached_return set_memory_alloc(memcached_st *memc) + static memcached_return deprecated_set_memory_alloc(memcached_st *memc) { void *test_ptr= NULL; void *cb_ptr= NULL; @@@ -3182,6 -3180,30 +3202,30 @@@ assert(rc == MEMCACHED_SUCCESS); assert(test_ptr == cb_ptr); } + return MEMCACHED_SUCCESS; + } + + static memcached_return set_memory_alloc(memcached_st *memc) + { + memcached_return rc; + rc= memcached_set_memory_allocators(memc, NULL, my_free, + my_realloc, my_calloc); + assert(rc == MEMCACHED_FAILURE); + + rc= memcached_set_memory_allocators(memc, my_malloc, my_free, + my_realloc, my_calloc); + + memcached_malloc_function mem_malloc; + memcached_free_function mem_free; + memcached_realloc_function mem_realloc; + memcached_calloc_function mem_calloc; + memcached_get_memory_allocators(memc, &mem_malloc, &mem_free, + &mem_realloc, &mem_calloc); + + assert(mem_malloc == my_malloc); + assert(mem_realloc == my_realloc); + assert(mem_calloc == my_calloc); + assert(mem_free == my_free); return MEMCACHED_SUCCESS; } @@@ -3520,175 -3542,6 +3564,175 @@@ static test_return connection_pool_test } #endif +static test_return replication_set_test(memcached_st *memc) +{ + memcached_return rc; + memcached_st *clone= memcached_clone(NULL, memc); + memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0); + + rc= memcached_set(memc, "bubba", 5, "0", 1, 0, 0); + assert(rc == MEMCACHED_SUCCESS); + + /* + ** "bubba" should now be stored on all of our servers. We don't have an + ** easy to use API to address each individual server, so I'll just iterate + ** through a bunch of "master keys" and I should most likely hit all of the + ** servers... + */ + for (int x= 'a'; x <= 'z'; ++x) + { + char key[2]= { [0]= (char)x }; + size_t len; + uint32_t flags; + char *val= memcached_get_by_key(clone, key, 1, "bubba", 5, + &len, &flags, &rc); + assert(rc == MEMCACHED_SUCCESS); + assert(val != NULL); + free(val); + } + + memcached_free(clone); + + return TEST_SUCCESS; +} + +static test_return replication_get_test(memcached_st *memc) +{ + memcached_return rc; + + /* + * Don't do the following in your code. I am abusing the internal details + * within the library, and this is not a supported interface. + * This is to verify correct behavior in the library + */ + for (int host= 0; host < memc->number_of_hosts; ++host) { + memcached_st *clone= memcached_clone(NULL, memc); + clone->hosts[host].port= 0; + + for (int x= 'a'; x <= 'z'; ++x) + { + char key[2]= { [0]= (char)x }; + size_t len; + uint32_t flags; + char *val= memcached_get_by_key(clone, key, 1, "bubba", 5, + &len, &flags, &rc); + assert(rc == MEMCACHED_SUCCESS); + assert(val != NULL); + free(val); + } + + memcached_free(clone); + } + + return TEST_SUCCESS; +} + +static test_return replication_mget_test(memcached_st *memc) +{ + memcached_return rc; + memcached_st *clone= memcached_clone(NULL, memc); + memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0); + + char *keys[]= { "bubba", "key1", "key2", "key3" }; + size_t len[]= { 5, 4, 4, 4 }; + + for (int x=0; x< 4; ++x) + { + rc= memcached_set(memc, keys[x], len[x], "0", 1, 0, 0); + assert(rc == MEMCACHED_SUCCESS); + } + + /* + * Don't do the following in your code. I am abusing the internal details + * within the library, and this is not a supported interface. + * This is to verify correct behavior in the library + */ + memcached_result_st result_obj; + for (int host= 0; host < clone->number_of_hosts; ++host) { + memcached_st *clone= memcached_clone(NULL, memc); + clone->hosts[host].port= 0; + + for (int x= 'a'; x <= 'z'; ++x) + { + char key[2]= { [0]= (char)x }; + + rc= memcached_mget_by_key(clone, key, 1, keys, len, 4); + assert(rc == MEMCACHED_SUCCESS); + + memcached_result_st *results= memcached_result_create(clone, &result_obj); + assert(results); + + int hits= 0; + while ((results= memcached_fetch_result(clone, &result_obj, &rc)) != NULL) + { + ++hits; + } + assert(hits == 4); + memcached_result_free(&result_obj); + } + + memcached_free(clone); + } + + return TEST_SUCCESS; +} + +static test_return replication_delete_test(memcached_st *memc) +{ + memcached_return rc; + memcached_st *clone= memcached_clone(NULL, memc); + /* Delete the items from all of the servers except 1 */ + uint64_t repl= memcached_behavior_get(memc, + MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS); + memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, --repl); + + char *keys[]= { "bubba", "key1", "key2", "key3" }; + size_t len[]= { 5, 4, 4, 4 }; + + for (int x=0; x< 4; ++x) + { + rc= memcached_delete_by_key(memc, keys[0], len[0], keys[x], len[x], 0); + assert(rc == MEMCACHED_SUCCESS); + } + + /* + * Don't do the following in your code. I am abusing the internal details + * within the library, and this is not a supported interface. + * This is to verify correct behavior in the library + */ + int hash= memcached_generate_hash(memc, keys[0], len[0]); + for (int x= 0; x < (repl + 1); ++x) { + clone->hosts[hash].port= 0; + if (++hash == clone->number_of_hosts) + hash= 0; + } + + memcached_result_st result_obj; + for (int host= 0; host < clone->number_of_hosts; ++host) { + for (int x= 'a'; x <= 'z'; ++x) + { + char key[2]= { [0]= (char)x }; + + rc= memcached_mget_by_key(clone, key, 1, keys, len, 4); + assert(rc == MEMCACHED_SUCCESS); + + memcached_result_st *results= memcached_result_create(clone, &result_obj); + assert(results); + + int hits= 0; + while ((results= memcached_fetch_result(clone, &result_obj, &rc)) != NULL) + { + ++hits; + } + assert(hits == 4); + memcached_result_free(&result_obj); + } + } + memcached_free(clone); + + return TEST_SUCCESS; +} + static void increment_request_id(uint16_t *id) { (*id)++; @@@ -4288,6 -4141,7 +4332,7 @@@ test_st tests[] = {"connection_test", 0, connection_test}, {"callback_test", 0, callback_test}, {"behavior_test", 0, behavior_test}, + {"userdata_test", 0, userdata_test}, {"error", 0, error_test }, {"set", 0, set_test }, {"set2", 0, set_test2 }, @@@ -4393,14 -4247,6 +4438,14 @@@ test_st user_tests[] = {0, 0, 0} }; +test_st replication_tests[]= { + {"set", 1, replication_set_test }, + {"get", 0, replication_get_test }, + {"mget", 0, replication_mget_test }, + {"delete", 0, replication_delete_test }, + {0, 0, 0} +}; + test_st generate_tests[] ={ {"generate_pairs", 1, generate_pairs }, {"generate_data", 1, generate_data }, @@@ -4484,6 -4330,7 +4529,7 @@@ collection_st collection[] = {"poll_timeout", poll_timeout, 0, tests}, {"gets", enable_cas, 0, tests}, {"consistent", enable_consistent, 0, tests}, + {"deprecated_memory_allocators", deprecated_set_memory_alloc, 0, tests}, {"memory_allocators", set_memory_alloc, 0, tests}, {"prefix", set_prefix, 0, tests}, {"version_1_2_3", check_for_1_2_3, 0, version_1_2_3}, @@@ -4504,7 -4351,6 +4550,7 @@@ {"consistent_ketama", pre_behavior_ketama, 0, consistent_tests}, {"consistent_ketama_weighted", pre_behavior_ketama_weighted, 0, consistent_weighted_tests}, {"test_hashes", 0, 0, hash_tests}, + {"replication", pre_replication, 0, replication_tests}, {0, 0, 0, 0} };