Merge in pid/ping status.
authorBrian Aker <brian@tangent.org>
Wed, 6 Jul 2011 18:15:01 +0000 (11:15 -0700)
committerBrian Aker <brian@tangent.org>
Wed, 6 Jul 2011 18:15:01 +0000 (11:15 -0700)
libmemcached/util/pid.cc
libmemcached/util/ping.cc
libtest/killpid.cc
libtest/memcached.cc
libtest/server.cc
libtest/server.h
libtest/test.cc
tests/cycle.cc
tests/include.am
tests/libmemcached_world.h

index 75edd518c7843a1ac051398da2dedfe5fae2d5d4..d9ba79c7b28bdd36aee9251fe1b8e83435296082 100644 (file)
 
 pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret)
 {
-  memcached_st *memc_ptr= memcached_create(NULL);
-
   pid_t pid= -1;
 
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return pid;
+  }
+
   memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
   if (memcached_success(rc))
   {
-    if (memcached_success(memcached_version(memc_ptr)))
+    memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+    if (stat and stat->pid > 0)
+    {
+      pid= stat->pid;
+    }
+    else if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
     {
-      memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
-      if (stat and stat->pid > 0)
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(memc_ptr, 0);
+
+      if (instance and instance->error_messages)
       {
-        pid= stat->pid;
+        rc= memcached_server_error_return(instance);
       }
-
-      memcached_stat_free(memc_ptr, stat);
     }
+    else if (memcached_success(rc))
+    {
+      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+    }
+
+    memcached_stat_free(memc_ptr, stat);
   }
   memcached_free(memc_ptr);
 
-  if (ret)
-  {
-    *ret= rc;
-  }
+  *ret= rc;
 
   return pid;
 }
index 52489b95fdef180a4fd97076bb2d04cb19a96be7..839810d4d7478c530cad35811918a022abe42333 100644 (file)
 
 bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
 {
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
   memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return false;
+  }
 
   memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
   if (memcached_success(rc))
@@ -63,10 +72,7 @@ bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_retu
   }
   memcached_free(memc_ptr);
 
-  if (ret)
-  {
-    *ret= rc;
-  }
+  *ret= rc;
 
   return memcached_success(rc);
 }
index e963f4a7eab1e7fa53d979c97cc24ccc26003cf1..ca8a659b80b798580e0725499f81a51090b8aaf2 100644 (file)
 
 bool kill_pid(pid_t pid_arg)
 {
-  if ((kill(pid_arg, SIGTERM) == -1))
+  if (pid_arg <= 1)
+    return false;
+
+  if ((::kill(pid_arg, SIGTERM) == -1))
   {
     switch (errno)
     {
index e7e87f262006b0ed7f04bdccc93e61c806ceaf42..adaa30f617df920721d23dc8da5b38ce2b161f6d 100644 (file)
 
 #define CERR_PREFIX std::endl << __FILE__ << ":" << __LINE__ << " "
 
-static void global_sleep(void)
-{
-  static struct timespec global_sleep_value= { 0, 50000 };
+#define SOCKET_FILE "/tmp/memcached.socket"
 
-#ifdef WIN32
-  sleep(1);
-#else
-  nanosleep(&global_sleep_value, NULL);
-#endif
+static pid_t __getpid(server_st& server)
+{
+  memcached_return_t rc;
+  pid_t pid= libmemcached_util_getpid(server.hostname, server.port(), &rc);
+  return pid;
 }
 
-#define SOCKET_FILE "/tmp/memcached.socket"
+static bool __ping(server_st& server)
+{
+  memcached_return_t rc;
+  bool ret= libmemcached_util_ping(server.hostname, server.port(), &rc);
+  return ret;
+}
 
 static bool cycle_server(server_st& server)
 {
@@ -123,6 +126,12 @@ bool server_startup(server_startup_st *construct)
   }
   else
   {
+    for (uint32_t x= 0; x < construct->count; x++)
+    {
+      server_st &server= construct->server[x];
+      server.set_methods(__getpid, __ping);
+    }
+
     std::string server_config_string;
 
     uint32_t port_base= 0;
@@ -170,34 +179,14 @@ bool server_startup(server_startup_st *construct)
           snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u",
                    MEMCACHED_BINARY, server.port(), server.port());
         }
+        server.set_command(buffer);
 
-        int status= system(buffer);
-        if (status == -1)
+        if (not server.start())
         {
           std::cerr << CERR_PREFIX << "Failed system(" << buffer << ")" << std::endl;
           return false;
         }
-        fprintf(stderr, "STARTING SERVER: %s\n", buffer);
-
-        int count= 30;
-        memcached_return_t rc;
-        while (not libmemcached_util_ping(server.hostname, server.port(), &rc) and --count)
-        {
-          global_sleep();
-        }
-
-        if (memcached_failed(rc))
-        {
-          std::cerr << CERR_PREFIX << "libmemcached_util_ping() failed:" << memcached_strerror(NULL, rc) << " Connection:" << server << std::endl;
-          return false;
-        }
-
-        server.set_pid(libmemcached_util_getpid(server.hostname, server.port(), &rc));
-        if (not server.has_pid())
-        {
-          std::cerr << CERR_PREFIX << "libmemcached_util_getpid() failed" << memcached_strerror(NULL, rc) << " Connection: " << server << std::endl;
-          return false;
-        }
+        std::cerr << "STARTING SERVER: " << buffer << " pid:" << server.pid() << std::endl;
       }
 
       server_config_string+= "--server=";
@@ -205,9 +194,9 @@ bool server_startup(server_startup_st *construct)
       server_config_string+= ":";
       server_config_string+= boost::lexical_cast<std::string>(server.port());
       server_config_string+= " ";
-      fprintf(stderr, " Port %d\n", server.port());
     }
 
+    // Socket
     {
       server_st &server= construct->server[construct->count -1];
 
@@ -225,7 +214,7 @@ bool server_startup(server_startup_st *construct)
         {
           if (not cycle_server(server))
           {
-            std::cerr << CERR_PREFIX << "Found server " << server << ", could not flush it, so trying next port." << std::endl;
+            std::cerr << CERR_PREFIX << "Found server " << server << ", could not flush it, failing since socket file is not available." << std::endl;
             return false;
           }
         }
@@ -239,34 +228,14 @@ bool server_startup(server_startup_st *construct)
       {
         char buffer[FILENAME_MAX];
         snprintf(buffer, sizeof(buffer), "%s -d -t 1 -s %s", MEMCACHED_BINARY, SOCKET_FILE);
+        server.set_command(buffer);
 
-        int status= system(buffer);
-        if (status == -1)
+        if (not server.start())
         {
           std::cerr << CERR_PREFIX << "Failed system(" << buffer << ")" << std::endl;
           return false;
         }
-        fprintf(stderr, "STARTING SERVER: %s\n", buffer);
-
-        int count= 30;
-        memcached_return_t rc;
-        while (not libmemcached_util_ping(server.hostname, server.port(), &rc) and --count)
-        {
-          global_sleep();
-        }
-
-        if (memcached_failed(rc))
-        {
-          std::cerr << CERR_PREFIX << "libmemcached_util_ping() failed:" << memcached_strerror(NULL, rc) << " Connection:" << server << std::endl;
-          return false;
-        }
-
-        server.set_pid(libmemcached_util_getpid(server.hostname, server.port(), &rc));
-        if (not server.has_pid())
-        {
-          std::cerr << CERR_PREFIX << "libmemcached_util_getpid() failed" << memcached_strerror(NULL, rc) << " Connection: " << server << std::endl;
-          return false;
-        }
+        std::cerr << "STARTING SERVER: " << buffer << " pid:" << server.pid() << std::endl;
       }
 
       {
index 78c2a771895474d86c7958017951d63fba77d412..d9175dba0516140b0ca20403641f323d59fe41fc 100644 (file)
@@ -3,7 +3,6 @@
  *  Libmemcached library
  *
  *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
  *
  *  Redistribution and use in source and binary forms, with or without
  *  modification, are permitted provided that the following conditions are
@@ -37,6 +36,8 @@
 
 #include <config.h>
 #include <iostream>
+#include <cstdlib>
+#include <cassert>
 
 #include <libtest/server.h>
 #include <libtest/killpid.h>
@@ -55,30 +56,77 @@ std::ostream& operator<<(std::ostream& output, const server_st &arg)
   return output;  // for multiple << operators
 }
 
+static void global_sleep(void)
+{
+  static struct timespec global_sleep_value= { 0, 50000 };
+
+#ifdef WIN32
+  sleep(1);
+#else
+  nanosleep(&global_sleep_value, NULL);
+#endif
+}
+
 server_st::~server_st()
 {
-  if (not _used)
+  if (has_pid())
   {
     kill();
   }
 }
 
+bool server_st::start()
+{
+  assert(not _command.empty());
+  assert(not has_pid());
+
+  if (has_pid())
+    return false;
+
+  if (system(_command.c_str()) == -1)
+    return false;
+
+  int count= 30;
+  while (not ping() and --count)
+  {
+    global_sleep();
+  }
+
+  if (count == 0)
+  {
+    return false;
+  }
+
+  _pid= get_pid();
+
+  return has_pid();
+}
+
 void server_st::reset_pid()
 {
   pid_file[0]= 0;
   _pid= -1;
 }
 
-bool server_st::kill()
+pid_t server_st::pid()
 {
-  if (not has_pid() and pid_file[0] == 0)
+  if (not has_pid())
   {
-    return true;
+    _pid= get_pid();
   }
-  
-  if (has_pid())
+
+  return _pid;
+}
+
+
+bool server_st::kill()
+{
+  if (is_used())
+    return false;
+
+  if ((_pid= get_pid()))
   {
-    kill_pid(pid());
+    kill_pid(_pid);
     if (pid_file[0])
     {
       unlink(pid_file); // If this happens we may be dealing with a dead server that left its pid file.
@@ -87,6 +135,7 @@ bool server_st::kill()
 
     return true;
   }
+#if 0
   else if (pid_file[0])
   {
     kill_file(pid_file);
@@ -94,6 +143,10 @@ bool server_st::kill()
 
     return true;
   }
+#endif
 
   return false;
 }
+
+server_startup_st::~server_startup_st()
+{ }
index c209881e3de25c3cf2b23ab97b87b44012de5235..198e0f6abdc3b8981abcd3aece67c3d63976ac93 100644 (file)
 
 #define SERVERS_TO_CREATE 5
 
+struct server_st;
+
+typedef pid_t (test_server_getpid)(server_st &);
+typedef bool (test_server_ping)(server_st &);
+
 struct server_st {
 private:
   bool _used;
   pid_t _pid;
   in_port_t _port;
   char pid_file[FILENAME_MAX]; // Did we start it, or was it just sitting there?
+  std::string _command;
+  test_server_getpid *__get_pid;
+  test_server_ping *__ping;
+
 public:
 
   char hostname[NI_MAXHOST];
@@ -30,12 +39,36 @@ public:
   server_st() :
     _used(false),
     _pid(-1),
-    _port(0)
+    _port(0),
+    __get_pid(NULL),
+    __ping(NULL)
   {
     pid_file[0]= 0;
     strncpy(hostname, "localhost", sizeof(hostname));
   }
 
+  void set_methods(test_server_getpid *get_pid_arg, test_server_ping *ping_arg)
+  {
+    __get_pid= get_pid_arg;
+    __ping= ping_arg;
+  }
+
+  bool ping()
+  {
+    if (__ping)
+      return __ping(*this);
+
+    return false;
+  }
+
+  pid_t get_pid()
+  {
+    if (__get_pid)
+      return _pid= __get_pid(*this);
+
+    return -1;
+  }
+
   void set_port(in_port_t arg)
   {
     _port= arg;
@@ -48,23 +81,20 @@ public:
 
   bool has_port() const
   {
-    return not _port == 0;
+    return (_port != 0);
   }
 
-  void set_used()
+  void set_command(const char *arg)
   {
-    _used= true;
+    _command= arg;
   }
 
-  void set_pid(pid_t arg)
+  void set_used()
   {
-    _pid= arg;
+    _used= true;
   }
 
-  pid_t pid() const
-  {
-    return _pid;
-  }
+  pid_t pid();
 
   bool is_used() const
   {
@@ -75,7 +105,7 @@ public:
 
   bool has_pid()
   {
-    return _pid > 0;
+    return (_pid > 1);
   }
 
   bool is_socket() const
@@ -89,6 +119,7 @@ public:
   }
 
   bool kill();
+  bool start();
 
 private:
   void reset_pid();
@@ -108,8 +139,7 @@ struct server_startup_st
     udp(0)
   { }
 
-  ~server_startup_st()
-  { }
+  ~server_startup_st();
 };
 
 #ifdef __cplusplus
index 49f3893b49b1d99458b6606d4f664688354b21ec..29c26ca447fa3698913f923b9813ee8c1dd54ac7 100644 (file)
@@ -138,15 +138,18 @@ static void *sig_thread(void *arg)
     int error;
     while ((error= sigwait(set, &sig)) == EINTR) ;
 
-    std::cerr << std::endl << "Signal handling thread got signal " <<  strsignal(sig) << std::endl;
     switch (sig)
     {
     case SIGSEGV:
     case SIGINT:
     case SIGABRT:
+      std::cerr << std::endl << "Signal handling thread got signal " <<  strsignal(sig) << std::endl;
       __shutdown= SHUTDOWN_FORCED;
+      break;
 
     default:
+      std::cerr << std::endl << "Signal handling thread got unexpected signal " <<  strsignal(sig) << std::endl;
+    case SIGUSR1:
       break;
     }
   }
@@ -163,6 +166,7 @@ static void setup_signals(pthread_t& thread)
   sigaddset(&set, SIGSEGV);
   sigaddset(&set, SIGABRT);
   sigaddset(&set, SIGINT);
+  sigaddset(&set, SIGUSR1);
 
   int error;
   if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
@@ -372,6 +376,10 @@ cleanup:
 
   stats_print(&stats);
 
+  void *retval;
+  pthread_kill(thread, SIGUSR1);
+  pthread_join(thread, &retval);
+
   delete world;
 
   return stats.failed == 0 and __shutdown == SHUTDOWN_GRACEFUL ? EXIT_SUCCESS : EXIT_FAILURE;
index 3b0aa2410770cee3e76c63d2d57154765f94a828..25ca66cc2d3b9bc1b8bf8ed94df7f5a24ee7b5a2 100644 (file)
 #include <libtest/common.h>
 
 #include <libmemcached/common.h>
+#include <libmemcached/is.h>
+#include <libmemcached/util.h>
+
+#include <iostream>
 
 
 #include <libtest/server.h>
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-test_st ping[] ={
+static test_return_t alive(memcached_st *memc)
+{
+  test_true(memc);
+  test_true(memcached_is_allocated(memc));
+  for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
+  {
+    memcached_server_instance_st instance= memcached_server_instance_by_position(memc, x);
+    test_true(instance);
+
+    test_true(libmemcached_util_ping(memcached_server_name(instance),
+                                     memcached_server_port(instance), NULL));
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t valid(memcached_st *memc)
+{
+  test_true(memc);
+  test_true(memcached_is_allocated(memc));
+
+  for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
+  {
+    memcached_server_instance_st instance= memcached_server_instance_by_position(memc, x);
+    test_true(instance);
+
+    pid_t pid= libmemcached_util_getpid(memcached_server_name(instance),
+                                        memcached_server_port(instance), NULL);
+    test_true(pid != -1);
+  }
+
+  return TEST_SUCCESS;
+}
+
+test_st ping_tests[] ={
+  {"alive", true, (test_callback_fn*)alive },
+  {0, 0, 0}
+};
+
+test_st getpid_tests[] ={
+  {"valid", true, (test_callback_fn*)valid },
   {0, 0, 0}
 };
 
 collection_st collection[] ={
+  {"libmemcached_util_ping()", 0, 0, ping_tests},
+  {"libmemcached_util_getpid()", 0, 0, getpid_tests},
   {0, 0, 0, 0}
 };
 
+#if 0
 static server_startup_st *world_create(test_return_t *error)
 {
   server_startup_st *servers= new server_startup_st();
@@ -78,8 +125,10 @@ static test_return_t world_destroy(server_startup_st *servers)
 
   return TEST_SUCCESS;
 }
+#endif
 
 
+#include "tests/libmemcached_world.h"
 
 void get_world(Framework *world)
 {
@@ -87,5 +136,15 @@ void get_world(Framework *world)
 
   world->_create= (test_callback_create_fn*)world_create;
   world->_destroy= (test_callback_fn*)world_destroy;
+
+  world->item._startup= (test_callback_fn*)world_test_startup;
+  world->item.set_pre((test_callback_fn*)world_pre_run);
+  world->item.set_post((test_callback_fn*)world_post_run);
+  world->_on_error= (test_callback_error_fn*)world_on_error;
+
+  world->collection_startup= (test_callback_fn*)world_container_startup;
+  world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
+
+  world->runner= &defualt_libmemcached_runner;
 }
 
index e254670979273aba36d3c3434b43f3de2aadb775..d6d3dab0a4a520e478720d1d00db65fe5f48d2bd 100644 (file)
@@ -305,6 +305,9 @@ gdb-cycle: tests/cycle
 gdb-memslap: clients/memslap
        $(DEBUG_COMMAND)  $(MEMSLAP_COMMAND)
 
+valgrind-cycle: tests/cycle
+       $(VALGRIND_COMMAND)  $(CYCLE_COMMAND)
+
 valgrind-mem: tests/testapp
        $(VALGRIND_COMMAND)  $(MEM_COMMAND)
 
index a6de23a0f520bc1252d11c14003dcbdedcc0f194..dfdddbefe00796336603fa2af813c8c9ef42eef8 100644 (file)
@@ -40,8 +40,6 @@ test_return_t world_post_run(libmemcached_test_container_st *);
 test_return_t world_on_error(test_return_t, libmemcached_test_container_st *);
 test_return_t world_destroy(libmemcached_test_container_st *);
 
-static libmemcached_test_container_st global_container;
-
 /**
   @note generic shutdown/startup for libmemcached tests.
 */
@@ -50,9 +48,8 @@ test_return_t world_container_shutdown(libmemcached_test_container_st *container
 
 libmemcached_test_container_st *world_create(test_return_t *error)
 {
-  global_container.construct.count= SERVERS_TO_CREATE;
-  global_container.construct.udp= 0;
-  if (not server_startup(&global_container.construct))
+  libmemcached_test_container_st *global_container= new libmemcached_test_container_st();
+  if (not server_startup(&global_container->construct))
   {
     *error= TEST_FAILURE;
     return NULL;
@@ -60,7 +57,7 @@ libmemcached_test_container_st *world_create(test_return_t *error)
 
   *error= TEST_SUCCESS;
 
-  return &global_container;
+  return global_container;
 }
 
 test_return_t world_container_startup(libmemcached_test_container_st *container)
@@ -150,6 +147,8 @@ test_return_t world_destroy(libmemcached_test_container_st *container)
   sasl_done();
 #endif
 
+  delete container;
+
   return TEST_SUCCESS;
 }