X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=tests%2Flibmemcached-1.0%2Fpool.cc;h=9da4a0f953d235b736acdc026df232e5d0859eef;hb=25efe3485198149616820ab4e52d2f18f0abe5a7;hp=5b22c94ec8394643ffa87b08c0e3365547442d88;hpb=e268471e4642c16281dc65b2f0ad9b897786c0b4;p=m6w6%2Flibmemcached diff --git a/tests/libmemcached-1.0/pool.cc b/tests/libmemcached-1.0/pool.cc index 5b22c94e..9da4a0f9 100644 --- a/tests/libmemcached-1.0/pool.cc +++ b/tests/libmemcached-1.0/pool.cc @@ -47,10 +47,16 @@ using namespace libtest; #include -#include -#include +#include +#include +#include #include +#include +#include + +#include "libmemcached/instance.h" + #ifndef __INTEL_COMPILER #pragma GCC diagnostic ignored "-Wstrict-aliasing" #endif @@ -58,20 +64,19 @@ using namespace libtest; test_return_t memcached_pool_test(memcached_st *) { - memcached_return_t rc; const char *config_string= "--SERVER=host10.example.com --SERVER=host11.example.com --SERVER=host10.example.com --POOL-MIN=10 --POOL-MAX=32"; char buffer[2048]; - rc= libmemcached_check_configuration(config_string, sizeof(config_string) -1, buffer, sizeof(buffer)); - test_true_got(rc != MEMCACHED_SUCCESS, buffer); + test_compare(libmemcached_check_configuration(config_string, sizeof(config_string) -1, buffer, sizeof(buffer)), MEMCACHED_PARSE_ERROR); memcached_pool_st* pool= memcached_pool(config_string, strlen(config_string)); - test_true_got(pool, strerror(errno)); + test_true(pool); + memcached_return_t rc; memcached_st *memc= memcached_pool_pop(pool, false, &rc); - test_true(rc == MEMCACHED_SUCCESS); + test_compare(rc, MEMCACHED_SUCCESS); test_true(memc); /* @@ -319,3 +324,195 @@ test_return_t connection_pool3_test(memcached_st *memc) return TEST_SUCCESS; } + +static memcached_st * create_single_instance_memcached(const memcached_st *original_memc, const char *options) +{ + /* + If no options are given, copy over at least the binary flag. + */ + char options_buffer[1024]= { 0 }; + if (options == NULL) + { + if (memcached_is_binary(original_memc)) + { + snprintf(options_buffer, sizeof(options_buffer), "--BINARY"); + } + } + + /* + * I only want to hit _one_ server so I know the number of requests I'm + * sending in the pipeline. + */ + memcached_server_instance_st instance= memcached_server_instance_by_position(original_memc, 0); + + char server_string[1024]; + int server_string_length; + if (instance->type == MEMCACHED_CONNECTION_UNIX_SOCKET) + { + if (options) + { + server_string_length= snprintf(server_string, sizeof(server_string), "--SOCKET=\"%s\" %s", + memcached_server_name(instance), options); + } + else + { + server_string_length= snprintf(server_string, sizeof(server_string), "--SOCKET=\"%s\"", + memcached_server_name(instance)); + } + } + else + { + if (options) + { + server_string_length= snprintf(server_string, sizeof(server_string), "--server=%s:%d %s", + memcached_server_name(instance), int(memcached_server_port(instance)), + options); + } + else + { + server_string_length= snprintf(server_string, sizeof(server_string), "--server=%s:%d", + memcached_server_name(instance), int(memcached_server_port(instance))); + } + } + + if (server_string_length <= 0) + { + return NULL; + } + + char errror_buffer[1024]; + if (memcached_failed(libmemcached_check_configuration(server_string, server_string_length, errror_buffer, sizeof(errror_buffer)))) + { + Error << "Failed to parse (" << server_string << ") " << errror_buffer; + return NULL; + } + + return memcached(server_string, server_string_length); +} + +pthread_mutex_t mutex= PTHREAD_MUTEX_INITIALIZER; +static bool _running= false; + +static void set_running(const bool arg) +{ + int error; + if ((error= pthread_mutex_lock(&mutex)) != 0) + { + fatal_message(strerror(error)); + } + + _running= arg; + + if ((error= pthread_mutex_unlock(&mutex)) != 0) + { + fatal_message(strerror(error)); + } +} + +static bool running() +{ + int error; + bool ret; + + if ((error= pthread_mutex_lock(&mutex)) != 0) + { + fatal_message(strerror(error)); + } + + ret= _running; + + if ((error= pthread_mutex_unlock(&mutex)) != 0) + { + fatal_message(strerror(error)); + } + + return ret; +} + +static void *worker_thread(void *ctx) +{ + memcached_pool_st *pool= (memcached_pool_st *)ctx; + + while (running()) + { + memcached_return_t rc; + memcached_st *mc= memcached_pool_pop(pool, true, &rc); + + if (mc == NULL) + { + Error << "failed to fetch a connection from the pool" << memcached_strerror(NULL, rc); + dream(1, 0); + continue; + } + + rc= memcached_set(mc, "test:kv", 7, "value", 5, 600, 0); + if (memcached_failed(rc)) + { + Out << "failed memcached_set()"; + } + + rc= memcached_pool_push(pool, mc); + if (memcached_failed(rc)) + { + Error << "failed to release a connection to the pool" << memcached_strerror(NULL, rc); + } + } + + return NULL; +} + +#define NUM_THREADS 20 +test_return_t regression_bug_962815(memcached_st *memc) +{ + pthread_t pid[NUM_THREADS]; + + test_false(running()); + + memcached_st *master = create_single_instance_memcached(memc, 0); + test_true(master); + + memcached_pool_st *pool= memcached_pool_create(master, 5, 10); + + test_true(pool); + + set_running(true); + + for (size_t x=0; x < NUM_THREADS; x++) + { + test_compare(0, pthread_create(&pid[x], NULL, worker_thread, (void*)pool)); + } + + { + pollfd fds[1]; + memset(fds, 0, sizeof(pollfd)); + fds[0].fd= -1; //STDIN_FILENO; + fds[0].events= POLLIN; + fds[0].revents= 0; + + int active_fd; + if ((active_fd= poll(fds, 1, 5000)) == -1) + { + Error << "poll() failed with:" << strerror(errno); + } + test_zero(active_fd); + + set_running(false); + } + + for (size_t x=0; x < NUM_THREADS; x++) + { + test_compare(0, pthread_join(pid[x], NULL)); + } + + if (pool) + { + memcached_pool_destroy(pool); + } + + if (master) + { + memcached_free(master); + } + + return TEST_SUCCESS; +}