X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=tests%2Flibmemcached-1.0%2Fpool.cc;h=6156ecad89acbdd2db7fa726b8bec9dfb3934a50;hb=fbdf9f2089a2653c8ea8150af22852ebc61ce42d;hp=f6214e0d3b5b5f103de029d2d9f35d9bc7b2b1bf;hpb=2565909cfc50c91a28a91da59131815f3d23227d;p=m6w6%2Flibmemcached diff --git a/tests/libmemcached-1.0/pool.cc b/tests/libmemcached-1.0/pool.cc index f6214e0d..6156ecad 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 @@ -238,10 +244,9 @@ struct test_pool_context_st { static void* connection_release(void *arg) { test_pool_context_st *resource= static_cast(arg); - assert(resource); if (resource == NULL) { - abort(); + fatal_message("resource == NULL"); } // Release all of the memc we are holding @@ -320,3 +325,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; +}