X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=tests%2Ffunction.c;h=affa176ff80653c488b25eabdc230438a0c3770e;hb=0e753ada42b4ded0b5336cf16eee42f790433e98;hp=13daaa29f32909a5ddf1b0860425d2d07839848c;hpb=35a37b8f10e31646efb89325331c171ecae87d78;p=m6w6%2Flibmemcached diff --git a/tests/function.c b/tests/function.c index 13daaa29..affa176f 100644 --- a/tests/function.c +++ b/tests/function.c @@ -1465,8 +1465,8 @@ static test_return_t mget_execute(memcached_st *memc) int max_keys= binary ? 20480 : 1; - char **keys= calloc(max_keys, sizeof(char*)); - size_t *key_length=calloc(max_keys, sizeof(size_t)); + char **keys= calloc((size_t)max_keys, sizeof(char*)); + size_t *key_length=calloc((size_t)max_keys, sizeof(size_t)); /* First add all of the items.. */ char blob[1024] = {0}; @@ -1474,7 +1474,7 @@ static test_return_t mget_execute(memcached_st *memc) for (int x= 0; x < max_keys; ++x) { char k[251]; - key_length[x]= snprintf(k, sizeof(k), "0200%u", x); + key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%u", x); keys[x]= strdup(k); assert(keys[x] != NULL); rc= memcached_add(memc, keys[x], key_length[x], blob, sizeof(blob), 0, 0); @@ -1484,9 +1484,8 @@ static test_return_t mget_execute(memcached_st *memc) /* Try to get all of them with a large multiget */ unsigned int counter= 0; memcached_execute_function callbacks[1]= { [0]= &callback_counter }; - rc= memcached_mget_execute(memc, NULL, 0, - (const char**)keys, key_length, - max_keys, callbacks, &counter, 1); + rc= memcached_mget_execute(memc, (const char**)keys, key_length, + (size_t)max_keys, callbacks, &counter, 1); if (binary) { @@ -1496,7 +1495,7 @@ static test_return_t mget_execute(memcached_st *memc) assert(rc == MEMCACHED_END); /* Verify that we got all of the items */ - assert(counter == max_keys); + assert(counter == (unsigned int)max_keys); } else { @@ -2757,6 +2756,57 @@ static test_return_t auto_eject_hosts(memcached_st *trash) return TEST_SUCCESS; } +static test_return_t output_ketama_weighted_keys(memcached_st *trash) +{ + (void) trash; + + memcached_return rc; + memcached_st *memc= memcached_create(NULL); + assert(memc); + + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, 1); + assert(rc == MEMCACHED_SUCCESS); + + uint64_t value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED); + assert(value == 1); + + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, MEMCACHED_HASH_MD5); + assert(rc == MEMCACHED_SUCCESS); + + value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_KETAMA_HASH); + assert(value == MEMCACHED_HASH_MD5); + + memcached_server_st *server_pool; + server_pool = memcached_servers_parse("10.0.1.1:11211,10.0.1.2:11211,10.0.1.3:11211,10.0.1.4:11211,10.0.1.5:11211,10.0.1.6:11211,10.0.1.7:11211,10.0.1.8:11211,192.168.1.1:11211,192.168.100.1:11211"); + memcached_server_push(memc, server_pool); + + FILE *fp; + if ((fp = fopen("ketama_keys.txt", "w"))) + { + // noop + } else { + printf("cannot write to file ketama_keys.txt"); + return TEST_FAILURE; + } + + for (int x= 0; x < 10000; x++) + { + char key[10]; + sprintf(key, "%d", x); + + uint32_t server_idx = memcached_generate_hash(memc, key, strlen(key)); + char *hostname = memc->hosts[server_idx].hostname; + unsigned int port = memc->hosts[server_idx].port; + fprintf(fp, "key %s is on host /%s:%u\n", key, hostname, port); + } + fclose(fp); + memcached_server_list_free(server_pool); + memcached_free(memc); + + return TEST_SUCCESS; +} + + static test_return_t result_static(memcached_st *memc) { memcached_result_st result; @@ -4797,6 +4847,114 @@ static test_return_t regression_bug_442914(memcached_st *memc) return TEST_SUCCESS; } +static test_return_t regression_bug_447342(memcached_st *memc) +{ + if (memc->number_of_hosts < 3 || pre_replication(memc) != MEMCACHED_SUCCESS) + return TEST_SKIPPED; + + memcached_return rc; + + rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 2); + assert(rc == MEMCACHED_SUCCESS); + + const size_t max_keys= 100; + char **keys= calloc(max_keys, sizeof(char*)); + size_t *key_length=calloc(max_keys, sizeof(size_t)); + + for (int x= 0; x < (int)max_keys; ++x) + { + char k[251]; + key_length[x]= (size_t)snprintf(k, sizeof(k), "0200%u", x); + keys[x]= strdup(k); + assert(keys[x] != NULL); + rc= memcached_set(memc, k, key_length[x], k, key_length[x], 0, 0); + assert(rc == MEMCACHED_SUCCESS); + } + + /* + ** We are using the quiet commands to store the replicas, so we need + ** to ensure that all of them are processed before we can continue. + ** In the test we go directly from storing the object to trying to + ** receive the object from all of the different servers, so we + ** could end up in a race condition (the memcached server hasn't yet + ** processed the quiet command from the replication set when it process + ** the request from the other client (created by the clone)). As a + ** workaround for that we call memcached_quit to send the quit command + ** to the server and wait for the response ;-) If you use the test code + ** as an example for your own code, please note that you shouldn't need + ** to do this ;-) + */ + memcached_quit(memc); + + /* Verify that all messages are stored, and we didn't stuff too much + * into the servers + */ + rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys); + assert(rc == MEMCACHED_SUCCESS); + + unsigned int counter= 0; + memcached_execute_function callbacks[1]= { [0]= &callback_counter }; + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + /* Verify that we received all of the key/value pairs */ + assert(counter == (unsigned int)max_keys); + + memcached_quit(memc); + /* + * 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. Fake that two servers + * are dead.. + */ + unsigned int port0= memc->hosts[0].port; + unsigned int port2= memc->hosts[2].port; + memc->hosts[0].port= 0; + memc->hosts[2].port= 0; + + rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys); + assert(rc == MEMCACHED_SUCCESS); + + counter= 0; + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + assert(counter == (unsigned int)max_keys); + + /* restore the memc handle */ + memc->hosts[0].port= port0; + memc->hosts[2].port= port2; + + memcached_quit(memc); + + /* Remove half of the objects */ + for (int x= 0; x < (int)max_keys; ++x) + if (x & 1) + { + rc= memcached_delete(memc, keys[x], key_length[x], 0); + assert(rc == MEMCACHED_SUCCESS); + } + + memcached_quit(memc); + memc->hosts[0].port= 0; + memc->hosts[2].port= 0; + + /* now retry the command, this time we should have cache misses */ + rc= memcached_mget(memc, (const char* const *)keys, key_length, max_keys); + assert(rc == MEMCACHED_SUCCESS); + + counter= 0; + rc= memcached_fetch_execute(memc, callbacks, (void *)&counter, 1); + assert(counter == (unsigned int)(max_keys >> 1)); + + /* Release allocated resources */ + for (size_t x= 0; x < max_keys; ++x) + free(keys[x]); + free(keys); + free(key_length); + + /* restore the memc handle */ + memc->hosts[0].port= port0; + memc->hosts[2].port= port2; + return TEST_SUCCESS; +} + /* Test memcached_server_get_last_disconnect * For a working server set, shall be NULL * For a set of non existing server, shall not be NULL @@ -5064,6 +5222,7 @@ test_st regression_tests[]= { {"lp:434843 buffered", 1, regression_bug_434843_buffered }, {"lp:421108", 1, regression_bug_421108 }, {"lp:442914", 1, regression_bug_442914 }, + {"lp:447342", 1, regression_bug_447342 }, {0, 0, 0} }; @@ -5109,6 +5268,7 @@ test_st hsieh_availability[] ={ test_st ketama_auto_eject_hosts[] ={ {"auto_eject_hosts", 1, auto_eject_hosts }, + {"output_ketama_weighted_keys", 1, output_ketama_weighted_keys }, {0, 0, 0} };