Fix for 32bit Debian
[awesomized/libmemcached] / tests / libmemcached-1.0 / pool.cc
index 5b22c94ec8394643ffa87b08c0e3365547442d88..b6653139fda1bfb5afff89d0ebb346f2995aff88 100644 (file)
@@ -47,10 +47,16 @@ using namespace libtest;
 
 #include <semaphore.h>
 
-#include <libmemcached/memcached.h>
-#include <libmemcached/util.h>
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcachedutil-1.0/util.h>
+#include <libmemcached/is.h>
 #include <tests/pool.h>
 
+#include <pthread.h>
+#include <poll.h>
+
+#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);
 
   /*
@@ -235,7 +240,7 @@ struct test_pool_context_st {
   }
 };
 
-static void* connection_release(void *arg)
+static __attribute__((noreturn)) void* connection_release(void *arg)
 {
   test_pool_context_st *resource= static_cast<test_pool_context_st *>(arg);
   if (resource == NULL)
@@ -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;
+}