Merge in sasl update
authorBrian Aker <brian@tangent.org>
Mon, 15 Aug 2011 07:10:59 +0000 (00:10 -0700)
committerBrian Aker <brian@tangent.org>
Mon, 15 Aug 2011 07:10:59 +0000 (00:10 -0700)
73 files changed:
.bzrignore
Makefile.am
clients/include.am
clients/memcat.cc
clients/memcp.cc
clients/memdump.cc
clients/memflush.cc
clients/memping.cc [new file with mode: 0644]
clients/memrm.cc
clients/utilities.cc
config/autorun.sh
configure.ac
libmemcached/connect.cc
libmemcached/include.am
libmemcached/memcached.cc
libmemcached/protocol/include.am
libmemcached/sasl.c [deleted file]
libmemcached/sasl.cc [new file with mode: 0644]
libmemcached/sasl.h
libmemcached/util/include.am
libmemcached/util/pid.cc
libmemcached/util/pid.h
libmemcached/util/ping.cc
libmemcached/util/ping.h
libmemcachedinternal/util/include.am
libtest/blobslap_worker.cc
libtest/cmdline.cc
libtest/cmdline.h
libtest/common.h
libtest/comparison.hpp
libtest/framework.h
libtest/gearmand.cc
libtest/gearmand.h
libtest/include.am
libtest/killpid.cc
libtest/killpid.h
libtest/libtool.cc [new file with mode: 0644]
libtest/libtool.hpp [new file with mode: 0644]
libtest/memcached.cc
libtest/memcached.h
libtest/server.cc
libtest/server.h
libtest/signal.cc
libtest/skiptest.cc [new file with mode: 0644]
libtest/test.cc
libtest/test.hpp
libtest/unittest.cc
libtest/version.h.in [new file with mode: 0644]
m4/acx_pthread.m4 [deleted file]
m4/ax_pthread.m4 [new file with mode: 0644]
m4/ax_with_prog.m4 [new file with mode: 0644]
m4/enable_utillib.m4
m4/libgearmand.m4 [deleted file]
m4/memcached.m4
m4/memcached_sasl.m4 [new file with mode: 0644]
m4/pandora_have_protobuf.m4 [deleted file]
m4/pandora_pthread.m4 [deleted file]
m4/pandora_sasl.m4 [deleted file]
support/libmemcached.pc.in
tests/atomsmasher.cc
tests/c_sasl_test.c [new file with mode: 0644]
tests/cycle.cc
tests/include.am
tests/libmemcached_world.h
tests/mem_functions.cc
tests/mem_udp.cc
tests/plus.cpp
tests/sasl.cc [new file with mode: 0644]
util/include.am
util/pidfile.cc
util/pidfile.hpp
util/signal.cc [new file with mode: 0644]
util/signal.hpp [new file with mode: 0644]

index 27188105add92a99d80639159408d9a887f878bf..034514bb07d3fab2b9dd4447002125c9bfaae7f7 100644 (file)
@@ -120,3 +120,8 @@ tests/testplus
 tests/testudp
 tests/var/
 unittests/unittests
+libtest/version.h
+clients/memping
+libtest/skiptest
+tests/sasl
+tests/c_sasl_test
index 5b600d5a6c24b565ee7091c2e32d11b0baa3db76..2ecc8f2c1c175b46daf551b4b4a8aecab11cc789 100644 (file)
@@ -24,14 +24,7 @@ EXTRA_DIST= \
            README.win32 \
            config/autorun.sh \
            config/pandora-plugin \
-           config/uncrustify.cfg \
-           m4/ac_cxx_header_stdcxx_98.m4 \
-           m4/acx_pthread.m4  \
-           m4/gettext.m4 \
-           m4/iconv.m4 \
-           m4/pkg.m4 \
-           m4/po.m4 \
-           m4/progtest.m4
+           config/uncrustify.cfg
 
 libmemcached_libmemcached_la_LDFLAGS=
 
index 98511366033a56f474dca4efdaddc7d4430381d0..8fc8c00bc2674b3fb9161f250c2a0739d78fc49d 100644 (file)
@@ -3,7 +3,6 @@
 # All paths should be given relative to the root
 
 CLIENTS_LDADDS= \
-               $(LIBM) \
                clients/libutilities.la \
                libmemcached/libmemcached.la
 
@@ -19,6 +18,7 @@ bin_PROGRAMS+= \
        clients/memerror \
        clients/memflush \
        clients/memparse \
+       clients/memping \
        clients/memrm \
        clients/memslap \
        clients/memstat
@@ -69,13 +69,17 @@ clients_memrm_LDADD= $(CLIENTS_LDADDS)
 clients_memflush_SOURCES= clients/memflush.cc
 clients_memflush_LDADD= $(CLIENTS_LDADDS)
 
+clients_memping_SOURCES= clients/memping.cc
+clients_memping_LDADD= $(CLIENTS_LDADDS) libmemcached/libmemcachedutil.la
+
 clients_memerror_SOURCES= clients/memerror.cc
 clients_memerror_LDADD= $(CLIENTS_LDADDS)
 
 clients_memslap_SOURCES = clients/memslap.cc
 clients_memslap_SOURCES+= clients/generator.cc clients/execute.cc
 clients_memslap_CXXFLAGS = ${PTHREAD_CFLAGS}
-clients_memslap_LDADD = $(PTHREAD_LIBS) $(CLIENTS_LDADDS)
+clients_memslap_LDADD= $(CLIENTS_LDADDS)
+clients_memslap_LDADD+= $(PTHREAD_LIBS)
 
 clients_memaslap_SOURCES= \
                          clients/memaslap.c \
index 12df34799a160b16c066999c4e8937d915fd427f..fdbcb67ea5180edee241bfe378aa2235dbf3ca0c 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "config.h"
 
+#include <iostream>
 #include <stdio.h>
 #include <inttypes.h>
 #include <string.h>
@@ -73,7 +74,14 @@ int main(int argc, char *argv[])
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                          (uint64_t)opt_binary);
 
-  if (!initialize_sasl(memc, opt_username, opt_passwd))
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username and initialize_sasl(memc, opt_username, opt_passwd) == false)
   {
     memcached_free(memc);
     return EXIT_FAILURE;
index 3869242b171c8cff803dda17624d4c3b0606bee2..2a73390bad50eb771c069cd45aa9864e3653b9e6 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "config.h"
 
+#include <iostream>
 #include <stdio.h>
 #include <stdlib.h>
 #include <inttypes.h>
@@ -114,8 +115,17 @@ int main(int argc, char *argv[])
   memcached_server_list_free(servers);
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                          (uint64_t)opt_binary);
-  if (!initialize_sasl(memc, opt_username, opt_passwd))
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (initialize_sasl(memc, opt_username, opt_passwd) == false)
   {
+    std::cerr << "Failed to initialize SASL support." << std::endl;
     memcached_free(memc);
     return EXIT_FAILURE;
   }
index 0e81dad491849f43c8b9b668b5f2cdd640bc3f63..6f3c3e53796c3cebd8aa3e81ba12c94320b855a6 100644 (file)
 
 #include "config.h"
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <unistd.h>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fcntl.h>
 #include <getopt.h>
-#include <sys/types.h>
+#include <inttypes.h>
+#include <iostream>
 #include <sys/stat.h>
 #include <sys/types.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <strings.h>
-#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <libmemcached/memcached.h>
 
@@ -89,8 +89,18 @@ int main(int argc, char *argv[])
   memcached_server_list_free(servers);
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                          (uint64_t)opt_binary);
-  if (!initialize_sasl(memc, opt_username, opt_passwd))
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
   {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username and initialize_sasl(memc, opt_username, opt_passwd) == false)
+  {
+    std::cerr << "Failed to initialize SASL support." << std::endl;
+
     memcached_free(memc);
     return EXIT_FAILURE;
   }
index 848bc1e7d1677937d620afd91fc9a1171b6bc35a..b19c286067c627801ff853fb6f0368c95e5c5000 100644 (file)
  */
 #include "config.h"
 
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
+#include <cstdio>
+#include <cstring>
 #include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
 #include <libmemcached/memcached.h>
 #include "client_options.h"
 #include "utilities.h"
@@ -60,6 +62,14 @@ int main(int argc, char *argv[])
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                          (uint64_t) opt_binary);
 
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+
   if (!initialize_sasl(memc, opt_username, opt_passwd))
   {
     memcached_free(memc);
diff --git a/clients/memping.cc b/clients/memping.cc
new file mode 100644 (file)
index 0000000..ee245cd
--- /dev/null
@@ -0,0 +1,147 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include "config.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <libmemcached/memcached.h>
+#include <libmemcached/util.h>
+#include "client_options.h"
+#include "utilities.h"
+
+#include <iostream>
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static time_t opt_expire= 0;
+static char *opt_servers= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+#define PROGRAM_NAME "memping"
+#define PROGRAM_DESCRIPTION "Ping a server to see if it is alive"
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+    else
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  int exit_code= EXIT_SUCCESS;
+  memcached_server_st *servers= memcached_servers_parse(opt_servers);
+  {
+    for (uint32_t x= 0; x < memcached_server_list_count(servers); x++)
+    {
+      memcached_return_t instance_rc;
+      const char *hostname= servers[x].hostname;
+      in_port_t port= servers[x].port;
+
+      if (libmemcached_util_ping2(hostname, port, opt_username, opt_passwd, &instance_rc) == false)
+      {
+        std::cerr << "Failed to ping " << hostname << ":" << port << " " << memcached_strerror(NULL, instance_rc) <<  std::endl;
+        exit_code= EXIT_FAILURE;
+      }
+    }
+  }
+  memcached_server_list_free(servers);
+
+  free(opt_servers);
+
+  shutdown_sasl();
+
+  return exit_code;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+  {
+    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+    {0, 0, 0, 0},
+  };
+  int option_index= 0;
+  int option_rv;
+
+  while (1)
+  {
+    option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1) break;
+    switch (option_rv)
+    {
+    case 0:
+      break;
+    case OPT_BINARY:
+      opt_binary = 1;
+      break;
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose = OPT_VERBOSE;
+      break;
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose = OPT_DEBUG;
+      break;
+    case OPT_VERSION: /* --version or -V */
+      version_command(PROGRAM_NAME);
+      break;
+    case OPT_HELP: /* --help or -h */
+      help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+      break;
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+    case OPT_EXPIRE: /* --expire */
+      opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10);
+      break;
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(1);
+    default:
+      abort();
+    }
+  }
+}
index d4d93c2e9c2621e80b3bc56613889f715802f231..0551e326755969ff714f30ba1916be6bf0f12a74 100644 (file)
  */
 #include "config.h"
 
-#include <stdio.h>
-#include <unistd.h>
+#include <cstdio>
+#include <cstring>
 #include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
 #include <libmemcached/memcached.h>
-#include <string.h>
 #include "client_options.h"
 #include "utilities.h"
 
@@ -43,7 +45,7 @@ int main(int argc, char *argv[])
   options_parse(argc, argv);
   initialize_sockets();
 
-  if (!opt_servers)
+  if (opt_servers == 0)
   {
     char *temp;
 
@@ -65,8 +67,18 @@ int main(int argc, char *argv[])
   memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
                          (uint64_t) opt_binary);
 
-  if (!initialize_sasl(memc, opt_username, opt_passwd))
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+
+  if (opt_username and initialize_sasl(memc, opt_username, opt_passwd) == false)
   {
+    std::cerr << "Failed to initialize SASL support." << std::endl;
+
     memcached_free(memc);
     return EXIT_FAILURE;
   }
index ca109adcfa66bd1229e0dbaa9ee0640356451d1d..8be59abb4e9cc12f12e29935ab7c2c3fe9ecc490 100644 (file)
@@ -127,10 +127,12 @@ void process_hash_option(memcached_st *memc, char *opt_hash)
   }
 }
 
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
+
 static char *username;
 static char *passwd;
 
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+
 static int get_username(void *context, int id, const char **result, unsigned int *len)
 {
   (void)context;
@@ -139,7 +141,9 @@ static int get_username(void *context, int id, const char **result, unsigned int
 
   *result= username;
   if (len)
+  {
      *len= (username == NULL) ? 0 : (unsigned int)strlen(username);
+  }
 
   return SASL_OK;
 }
@@ -181,44 +185,55 @@ static sasl_callback_t sasl_callbacks[] = {
   { SASL_CB_PASS, (local_sasl_fn)get_password, NULL },
   { SASL_CB_LIST_END, NULL, NULL }
 };
+
 #endif
 
 bool initialize_sasl(memcached_st *memc, char *user, char *password)
 {
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return false;
+  }
+
+  if (memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, (uint64_t)true) == 0)
+  {
+    return false;
+  }
+
   if (user != NULL && password != NULL)
   {
     username= user;
     passwd= password;
 
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
     if (sasl_client_init(NULL) != SASL_OK)
     {
       fprintf(stderr, "Failed to initialize sasl library!\n");
       return false;
     }
     memcached_set_sasl_callbacks(memc, sasl_callbacks);
-  }
 #else
-  (void)memc;
-  (void)user;
-  (void)password;
+    (void)memc;
 #endif
+  }
 
   return true;
 }
 
 void shutdown_sasl(void)
 {
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  if (username != NULL || passwd != NULL)
+  if (username or passwd)
+  {
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
     sasl_done();
 #endif
+  }
 }
 
 void initialize_sockets(void)
 {
   /* Define the function for all platforms to avoid #ifdefs in each program */
-#ifdef WIN32
+#if defined(WIN32) && WIN32
   WSADATA wsaData;
   if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0)
   {
index 3b076d1a12c71eba41bb1e392c1d56f1ed53092f..79d6629edb06c92ef7e97ef69bc9be6beb5cee66 100755 (executable)
@@ -1,2 +1,2 @@
 #!/bin/sh
-autoreconf -ivf
+autoreconf -ivf -Wall
index 153fdb1f9b4c3351e97d9a2823365b86d635b5da..5fc2c6c73c5e186cbbeaadda3f6df2200290b336 100644 (file)
@@ -52,21 +52,34 @@ AC_SUBST(MEMCACHED_LIBRARY_VERSION)
 HASHKIT_LIBRARY_VERSION=1:0:0
 AC_SUBST(HASHKIT_LIBRARY_VERSION)
 
-AC_DEFINE([HAVE_LIBMEMCACHED], [ 1 ], [dummy rule for libtest])
-AC_SUBST(HAVE_LIBMEMCACHED, 1)
-AM_CONDITIONAL(HAVE_LIBMEMCACHED, true)
 LT_INIT
+m4_include([m4/memcached.m4])
+m4_include([m4/memcached_sasl.m4])
+
+AM_CONDITIONAL(BUILDING_LIBMEMCACHED, true)
+AM_CONDITIONAL(HAVE_LIBMEMCACHED, false)
+AC_SUBST(_WITH_LIBMEMCACHED_SUPPORT, ["_WITH_LIBMEMCACHED_SUPPORT 1"])
+
+AM_CONDITIONAL(BUILDING_GEARMAN, false)
+AM_CONDITIONAL(HAVE_LIBGEARMAN, false)
+AC_SUBST(_WITH_LIBGEARMAN_SUPPORT, ["_WITH_LIBGEARMAN_SUPPORT 0"])
 
 AC_SEARCH_LIBS(getopt_long, gnugetopt)
 AC_SEARCH_LIBS(gethostbyname, nsl)
 
 PANDORA_HAVE_LIBEVENT
-my_saved_libs="$LIBS"
-LIBS=
-PANDORA_REQUIRE_PTHREAD
-LIBS="$my_saved_libs"
+
+case "$target_os" in
+  *linux*)
+       AS_IF([test "x$GCC" = "xyes"],
+             [
+              LDFLAGS="$LDFLAGS -z relro -z now"
+              ])
+   ;;
+   esac
 
 dnl Specialty checks
+ACX_PTHREAD
 CONFIG_EXTRA
 DETECT_BYTEORDER
 ENABLE_UTILLIB
@@ -75,12 +88,9 @@ ENABLE_HSIEH_HASH
 ENABLE_MURMUR_HASH
 ENABLE_MEMASLAP
 PROTOCOL_BINARY_TEST
-WITH_MEMCACHED
 ENABLE_DEPRECATED
 PANDORA_HAVE_LIBINNODB
-PANDORA_PRINT_CALLSTACK
 PANDORA_HAVE_SASL
-WITH_LIBGEARMAN
 
 AC_CHECK_FUNCS([alarm])
 AC_CHECK_FUNCS([dup2])
@@ -109,6 +119,7 @@ AC_CHECK_HEADERS([netdb.h])
 AC_CHECK_HEADERS([netinet/in.h])
 AC_CHECK_HEADERS([stddef.h])
 AC_CHECK_HEADERS([sys/time.h])
+AC_CHECK_HEADERS([sasl/sasl.h])
 AC_FUNC_ALLOCA
 AC_FUNC_ERROR_AT_LINE
 AC_FUNC_FORK
@@ -130,7 +141,13 @@ AC_TYPE_UINT8_T
 
 dnl The sasl functions should only be visible if we build with sasl support
 AS_IF([test "x$ac_cv_sasl" = "xyes"],
-      [LIBMEMCACHED_WITH_SASL_SUPPORT="#define LIBMEMCACHED_WITH_SASL_SUPPORT 1"])
+      [
+        [ LIBMEMCACHED_WITH_SASL_SUPPORT="#define LIBMEMCACHED_WITH_SASL_SUPPORT 1" ]
+      ],
+      [
+        [ LIBMEMCACHED_WITH_SASL_SUPPORT="#define LIBMEMCACHED_WITH_SASL_SUPPORT 0" ]
+       ]
+      )
 AC_SUBST(LIBMEMCACHED_WITH_SASL_SUPPORT)
 
 AC_CHECK_HEADERS([atomic.h])
@@ -161,6 +178,7 @@ AC_CONFIG_FILES([
   support/libmemcached.pc
   support/libmemcached.spec
   support/libmemcached-fc.spec
+  libtest/version.h
   ])
 AC_OUTPUT
 
index 07bb545b2bbe55f603f6ade5617ea4f21e5154af..3c12339c4a7f16315fc134e88aeff8d5840c63a8 100644 (file)
@@ -593,18 +593,19 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st ptr)
   case MEMCACHED_CONNECTION_UDP:
   case MEMCACHED_CONNECTION_TCP:
     rc= network_connect(ptr);
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-    if (ptr->fd != INVALID_SOCKET and ptr->root->sasl.callbacks)
+    if (LIBMEMCACHED_WITH_SASL_SUPPORT)
     {
-      rc= memcached_sasl_authenticate_connection(ptr);
-      if (memcached_failed(rc) and ptr->fd != INVALID_SOCKET)
+      if (ptr->fd != INVALID_SOCKET and ptr->root->sasl.callbacks)
       {
-        WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
-        (void)closesocket(ptr->fd);
-        ptr->fd= INVALID_SOCKET;
+        rc= memcached_sasl_authenticate_connection(ptr);
+        if (memcached_failed(rc) and ptr->fd != INVALID_SOCKET)
+        {
+          WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
+          (void)closesocket(ptr->fd);
+          ptr->fd= INVALID_SOCKET;
+        }
       }
     }
-#endif
     break;
 
   case MEMCACHED_CONNECTION_UNIX_SOCKET:
index 4950f3ca6409e16313c8e323cb3e0834d3981859..425cec0b87d4aaf771da785ff1a57333a3accc37 100644 (file)
@@ -141,10 +141,8 @@ libmemcached_libmemcached_la_DEPENDENCIES=
 libmemcached_libmemcached_la_LIBADD= $(LIBM)
 libmemcached_libmemcached_la_LDFLAGS+= ${AM_LDFLAGS} -version-info ${MEMCACHED_LIBRARY_VERSION}
 
-if HAVE_SASL
-libmemcached_libmemcached_la_LDFLAGS+= $(LTLIBSASL) $(LTLIBSASL2)
-libmemcached_libmemcached_la_SOURCES += libmemcached/sasl.c
-endif
+libmemcached_libmemcached_la_LIBADD+= $(LTLIBSASL) $(LTLIBSASL2)
+libmemcached_libmemcached_la_SOURCES += libmemcached/sasl.cc
 
 if HAVE_DTRACE
 BUILT_SOURCES+= libmemcached/dtrace_probes.h
index 359a4403bdbf07c2ae2e92babe8d844f5119a5e1..ce3fb8e39ce612b3c451162dbcd3e4db03bab0fe 100644 (file)
@@ -165,11 +165,9 @@ static void _free(memcached_st *ptr, bool release_st)
 
   memcached_error_free(*ptr);
 
-  if (ptr->sasl.callbacks)
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT and ptr->sasl.callbacks)
   {
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
     memcached_destroy_sasl_auth_data(ptr);
-#endif
   }
 
   if (release_st)
@@ -374,8 +372,7 @@ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
   new_clone->_namespace= memcached_array_clone(new_clone, source->_namespace);
   new_clone->configure.filename= memcached_array_clone(new_clone, source->_namespace);
 
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  if (source->sasl.callbacks)
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT and source->sasl.callbacks)
   {
     if (memcached_clone_sasl(new_clone, source) != MEMCACHED_SUCCESS)
     {
@@ -383,7 +380,6 @@ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
       return NULL;
     }
   }
-#endif
 
   rc= run_distribution(new_clone);
 
index 9c4c1bc29587838cbf18184054389851194f5f8a..d5bd9c46e6617233c616b3d2299aa53da91a5a62 100644 (file)
@@ -15,12 +15,14 @@ libmemcached_libmemcachedprotocol_la_SOURCES=  \
 libmemcached_libmemcachedprotocol_la_CFLAGS= \
                                             ${AM_CFLAGS} \
                                             ${NO_CONVERSION} \
-                                            ${PTHREAD_CFLAGS} \
                                             -DBUILDING_LIBMEMCACHED
+libmemcached_libmemcachedprotocol_la_CFLAGS+= ${PTHREAD_CFLAGS}
 
 libmemcached_libmemcachedprotocol_la_CXXFLAGS= \
                                               ${AM_CXXFLAGS} \
-                                              ${PTHREAD_CFLAGS} \
                                               -DBUILDING_LIBMEMCACHED
+libmemcached_libmemcachedprotocol_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
 
-libmemcached_libmemcachedprotocol_la_LDFLAGS= ${AM_LDFLAGS} ${PTHREAD_LIBS} -version-info ${MEMCACHED_PROTOCAL_LIBRARY_VERSION}
+libmemcached_libmemcachedprotocol_la_LIBADD= ${PTHREAD_LIBS}
+libmemcached_libmemcachedprotocol_la_LDFLAGS= ${AM_LDFLAGS}
+libmemcached_libmemcachedprotocol_la_LDFLAGS+= -version-info ${MEMCACHED_PROTOCAL_LIBRARY_VERSION}
diff --git a/libmemcached/sasl.c b/libmemcached/sasl.c
deleted file mode 100644 (file)
index 434d2db..0000000
+++ /dev/null
@@ -1,408 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  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
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include <iso646.h>
-
-void memcached_set_sasl_callbacks(memcached_st *ptr,
-                                  const sasl_callback_t *callbacks)
-{
-  ptr->sasl.callbacks= callbacks;
-  ptr->sasl.is_allocated= false;
-}
-
-const sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr)
-{
-  return ptr->sasl.callbacks;
-}
-
-/**
- * Resolve the names for both ends of a connection
- * @param fd socket to check
- * @param laddr local address (out)
- * @param raddr remote address (out)
- * @return true on success false otherwise (errno contains more info)
- */
-static memcached_return_t resolve_names(int fd, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length)
-{
-  char host[NI_MAXHOST];
-  char port[NI_MAXSERV];
-  struct sockaddr_storage saddr;
-  socklen_t salen= sizeof(saddr);
-
-  if (getsockname(fd, (struct sockaddr *)&saddr, &salen) < 0)
-  {
-    return MEMCACHED_ERRNO;
-  }
-
-  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
-  {
-    return MEMCACHED_HOST_LOOKUP_FAILURE;
-  }
-
-  (void)snprintf(laddr, laddr_length, "%s;%s", host, port);
-  salen= sizeof(saddr);
-
-  if (getpeername(fd, (struct sockaddr *)&saddr, &salen) < 0)
-  {
-    return MEMCACHED_ERRNO;
-  }
-
-  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host),
-                   port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
-  {
-    return MEMCACHED_HOST_LOOKUP_FAILURE;
-  }
-
-  (void)snprintf(raddr, raddr_length, "%s;%s", host, port);
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *server)
-{
-  /* SANITY CHECK: SASL can only be used with the binary protocol */
-  if (!server->root->flags.binary_protocol)
-    return MEMCACHED_FAILURE;
-
-  /* Try to get the supported mech from the server. Servers without SASL
-   * support will return UNKNOWN COMMAND, so we can just treat that
-   * as authenticated
-   */
-  protocol_binary_request_no_extras request= {
-    .message.header.request= {
-      .magic= PROTOCOL_BINARY_REQ,
-      .opcode= PROTOCOL_BINARY_CMD_SASL_LIST_MECHS
-    }
-  };
-
-  if (memcached_io_write(server, request.bytes,
-                        sizeof(request.bytes), 1) != sizeof(request.bytes))
-  {
-    return MEMCACHED_WRITE_FAILURE;
-  }
-
-  memcached_server_response_increment(server);
-
-  char mech[MEMCACHED_MAX_BUFFER];
-  memcached_return_t rc= memcached_response(server, mech, sizeof(mech), NULL);
-  if (memcached_failed(rc))
-  {
-    if (rc == MEMCACHED_PROTOCOL_ERROR)
-    {
-      /* If the server doesn't support SASL it will return PROTOCOL_ERROR.
-       * This error may also be returned for other errors, but let's assume
-       * that the server don't support SASL and treat it as success and
-       * let the client fail with the next operation if the error was
-       * caused by another problem....
-       */
-      rc= MEMCACHED_SUCCESS;
-    }
-
-    return rc;
-  }
-
-  /* set ip addresses */
-  char laddr[NI_MAXHOST + NI_MAXSERV];
-  char raddr[NI_MAXHOST + NI_MAXSERV];
-
-  if (memcached_failed(rc= resolve_names(server->fd, laddr, sizeof(laddr), raddr, sizeof(raddr))))
-  {
-    return rc;
-  }
-
-  sasl_conn_t *conn;
-  int ret= sasl_client_new("memcached", server->hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn);
-  if (ret != SASL_OK)
-  {
-    return MEMCACHED_AUTH_PROBLEM;
-  }
-
-  const char *data;
-  const char *chosenmech;
-  unsigned int len;
-  ret= sasl_client_start(conn, mech, NULL, &data, &len, &chosenmech);
-
-  if (ret != SASL_OK && ret != SASL_CONTINUE)
-  {
-    rc= MEMCACHED_AUTH_PROBLEM;
-    goto end;
-  }
-
-  uint16_t keylen= (uint16_t)strlen(chosenmech);
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_AUTH;
-  request.message.header.request.keylen= htons(keylen);
-  request.message.header.request.bodylen= htonl(len + keylen);
-
-  do {
-    /* send the packet */
-
-    struct libmemcached_io_vector_st vector[]=
-    {
-      { .length= sizeof(request.bytes), .buffer= request.bytes },
-      { .length= keylen, .buffer= chosenmech },
-      { .length= len, .buffer= data }
-    };
-
-    if (memcached_io_writev(server, vector, 3, true) == -1)
-    {
-      rc= MEMCACHED_WRITE_FAILURE;
-      goto end;
-    }
-    memcached_server_response_increment(server);
-
-    /* read the response */
-    rc= memcached_response(server, NULL, 0, NULL);
-    if (rc != MEMCACHED_AUTH_CONTINUE)
-    {
-      goto end;
-    }
-
-    ret= sasl_client_step(conn, memcached_result_value(&server->root->result),
-                          (unsigned int)memcached_result_length(&server->root->result),
-                          NULL, &data, &len);
-
-    if (ret != SASL_OK && ret != SASL_CONTINUE)
-    {
-      rc= MEMCACHED_AUTH_PROBLEM;
-      goto end;
-    }
-
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_STEP;
-    request.message.header.request.bodylen= htonl(len + keylen);
-  } while (true);
-
-end:
-  /* Release resources */
-  sasl_dispose(&conn);
-
-  return rc;
-}
-
-static int get_username(void *context, int id, const char **result,
-                        unsigned int *len)
-{
-  if (!context || !result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME))
-  {
-    return SASL_BADPARAM;
-  }
-
-  *result= context;
-  if (len)
-  {
-    *len= (unsigned int)strlen(*result);
-  }
-
-  return SASL_OK;
-}
-
-static int get_password(sasl_conn_t *conn, void *context, int id,
-                        sasl_secret_t **psecret)
-{
-  if (!conn || ! psecret || id != SASL_CB_PASS)
-  {
-    return SASL_BADPARAM;
-  }
-
-  *psecret= context;
-
-  return SASL_OK;
-}
-
-memcached_return_t memcached_set_sasl_auth_data(memcached_st *ptr,
-                                                const char *username,
-                                                const char *password)
-{
-  if (ptr == NULL || username == NULL ||
-      password == NULL || ptr->sasl.callbacks != NULL)
-  {
-    return MEMCACHED_FAILURE;
-  }
-
-  sasl_callback_t *callbacks= libmemcached_calloc(ptr, 4, sizeof(sasl_callback_t));
-  size_t password_length= strlen(password);
-  size_t username_length= strlen(username);
-  char *name= libmemcached_malloc(ptr, username_length +1);
-  sasl_secret_t *secret= libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
-
-  if (callbacks == NULL || name == NULL || secret == NULL)
-  {
-    libmemcached_free(ptr, callbacks);
-    libmemcached_free(ptr, name);
-    libmemcached_free(ptr, secret);
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  secret->len= password_length;
-  memcpy(secret->data, password, password_length);
-  secret->data[password_length]= 0;
-
-  callbacks[0].id= SASL_CB_USER;
-  callbacks[0].proc= get_username;
-  callbacks[0].context= strncpy(name, username, username_length +1);
-  callbacks[1].id= SASL_CB_AUTHNAME;
-  callbacks[1].proc= get_username;
-  callbacks[1].context= name;
-  callbacks[2].id= SASL_CB_PASS;
-  callbacks[2].proc= get_password;
-  callbacks[2].context= secret;
-  callbacks[3].id= SASL_CB_LIST_END;
-
-  ptr->sasl.callbacks= callbacks;
-  ptr->sasl.is_allocated= true;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr)
-{
-   if (ptr == NULL || ptr->sasl.callbacks == NULL)
-   {
-     return MEMCACHED_FAILURE;
-   }
-
-   if (ptr->sasl.is_allocated)
-   {
-     libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
-     libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
-     libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
-     ptr->sasl.is_allocated= false;
-   }
-
-   ptr->sasl.callbacks= NULL;
-
-   return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source)
-{
-
-  if (source->sasl.callbacks == NULL)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  /* Hopefully we are using our own callback mechanisms.. */
-  if (source->sasl.callbacks[0].id == SASL_CB_USER &&
-      source->sasl.callbacks[0].proc == get_username &&
-      source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
-      source->sasl.callbacks[1].proc == get_username &&
-      source->sasl.callbacks[2].id == SASL_CB_PASS &&
-      source->sasl.callbacks[2].proc == get_password &&
-      source->sasl.callbacks[3].id == SASL_CB_LIST_END)
-  {
-    sasl_secret_t *secret= source->sasl.callbacks[2].context;
-    return memcached_set_sasl_auth_data(clone,
-                                        source->sasl.callbacks[0].context,
-                                        (const char*)secret->data);
-  }
-
-  /*
-   * But we're not. It may work if we know what the user tries to pass
-   * into the list, but if we don't know the ID we don't know how to handle
-   * the context...
-   */
-  size_t total= 0;
-
-  while (source->sasl.callbacks[total].id != SASL_CB_LIST_END)
-  {
-    switch (source->sasl.callbacks[total].id)
-    {
-    case SASL_CB_USER:
-    case SASL_CB_AUTHNAME:
-    case SASL_CB_PASS:
-       break;
-    default:
-       /* I don't know how to deal with this... */
-       return MEMCACHED_NOT_SUPPORTED;
-    }
-
-    ++total;
-  }
-
-  sasl_callback_t *callbacks= libmemcached_calloc(clone, total + 1, sizeof(sasl_callback_t));
-  if (callbacks == NULL)
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-  memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t));
-
-  /* Now update the context... */
-  for (size_t x= 0; x < total; ++x)
-  {
-    if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME)
-    {
-      callbacks[x].context= libmemcached_malloc(clone, strlen(source->sasl.callbacks[x].context));
-
-      if (callbacks[x].context == NULL)
-      {
-        /* Failed to allocate memory, clean up previously allocated memory */
-        for (size_t y= 0; y < x; ++y)
-        {
-          libmemcached_free(clone, clone->sasl.callbacks[y].context);
-        }
-
-        libmemcached_free(clone, callbacks);
-        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-      }
-      strncpy(callbacks[x].context, source->sasl.callbacks[x].context, sizeof(callbacks[x].context));
-    }
-    else
-    {
-      sasl_secret_t *src = source->sasl.callbacks[x].context;
-      sasl_secret_t *n = libmemcached_malloc(clone, src->len + 1 + sizeof(*n));
-      if (n == NULL)
-      {
-        /* Failed to allocate memory, clean up previously allocated memory */
-        for (size_t y= 0; y < x; ++y)
-        {
-          libmemcached_free(clone, clone->sasl.callbacks[y].context);
-        }
-
-        libmemcached_free(clone, callbacks);
-        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-      }
-      memcpy(n, src, src->len + 1 + sizeof(*n));
-      callbacks[x].context= n;
-    }
-  }
-
-  clone->sasl.callbacks= callbacks;
-  clone->sasl.is_allocated= true;
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/sasl.cc b/libmemcached/sasl.cc
new file mode 100644 (file)
index 0000000..4f18ca2
--- /dev/null
@@ -0,0 +1,475 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  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
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <cassert>
+
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+
+#include <sasl/sasl.h>
+
+void memcached_set_sasl_callbacks(memcached_st *ptr,
+                                  const sasl_callback_t *callbacks)
+{
+  ptr->sasl.callbacks= const_cast<sasl_callback_t *>(callbacks);
+  ptr->sasl.is_allocated= false;
+}
+
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr)
+{
+  return ptr->sasl.callbacks;
+}
+
+/**
+ * Resolve the names for both ends of a connection
+ * @param fd socket to check
+ * @param laddr local address (out)
+ * @param raddr remote address (out)
+ * @return true on success false otherwise (errno contains more info)
+ */
+static memcached_return_t resolve_names(memcached_server_st& server, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length)
+{
+  char host[NI_MAXHOST];
+  char port[NI_MAXSERV];
+  struct sockaddr_storage saddr;
+  socklen_t salen= sizeof(saddr);
+
+  if (getsockname(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
+  {
+    return memcached_set_errno(server, MEMCACHED_ERRNO, MEMCACHED_AT);
+  }
+
+  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
+  {
+    return MEMCACHED_HOST_LOOKUP_FAILURE;
+  }
+
+  (void)snprintf(laddr, laddr_length, "%s;%s", host, port);
+  salen= sizeof(saddr);
+
+  if (getpeername(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
+  {
+    return memcached_set_errno(server, MEMCACHED_ERRNO, MEMCACHED_AT);
+  }
+
+  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host),
+                   port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
+  {
+    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
+  }
+
+  (void)snprintf(raddr, raddr_length, "%s;%s", host, port);
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *server)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (server == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  /* SANITY CHECK: SASL can only be used with the binary protocol */
+  if (server->root->flags.binary_protocol == false)
+  {
+    return MEMCACHED_PROTOCOL_ERROR;
+  }
+
+  /* Try to get the supported mech from the server. Servers without SASL
+   * support will return UNKNOWN COMMAND, so we can just treat that
+   * as authenticated
+ */
+  protocol_binary_request_no_extras request= { };
+  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_LIST_MECHS;
+
+  if (memcached_io_write(server, request.bytes,
+                         sizeof(request.bytes), 1) != sizeof(request.bytes))
+  {
+    return MEMCACHED_WRITE_FAILURE;
+  }
+
+  memcached_server_response_increment(server);
+
+  char mech[MEMCACHED_MAX_BUFFER];
+  memcached_return_t rc= memcached_response(server, mech, sizeof(mech), NULL);
+  if (memcached_failed(rc))
+  {
+    if (rc == MEMCACHED_PROTOCOL_ERROR)
+    {
+      /* If the server doesn't support SASL it will return PROTOCOL_ERROR.
+       * This error may also be returned for other errors, but let's assume
+       * that the server don't support SASL and treat it as success and
+       * let the client fail with the next operation if the error was
+       * caused by another problem....
+     */
+      rc= MEMCACHED_SUCCESS;
+    }
+
+    return rc;
+  }
+
+  /* set ip addresses */
+  char laddr[NI_MAXHOST + NI_MAXSERV];
+  char raddr[NI_MAXHOST + NI_MAXSERV];
+
+  if (memcached_failed(rc= resolve_names(*server, laddr, sizeof(laddr), raddr, sizeof(raddr))))
+  {
+    return rc;
+  }
+
+  int ret;
+  if ((ret= sasl_client_init(NULL)) != SASL_OK)
+  {
+    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
+    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
+                               memcached_string_make_from_cstr(sasl_error_msg));
+  }
+
+  sasl_conn_t *conn;
+  if ((ret= sasl_client_new("memcached", server->hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)
+  {
+    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
+    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
+                               memcached_string_make_from_cstr(sasl_error_msg));
+  }
+
+  const char *data;
+  const char *chosenmech;
+  unsigned int len;
+  ret= sasl_client_start(conn, mech, NULL, &data, &len, &chosenmech);
+  if (ret != SASL_OK and ret != SASL_CONTINUE)
+  {
+    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
+    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
+                               memcached_string_make_from_cstr(sasl_error_msg));
+  }
+  uint16_t keylen= (uint16_t)strlen(chosenmech);
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_AUTH;
+  request.message.header.request.keylen= htons(keylen);
+  request.message.header.request.bodylen= htonl(len + keylen);
+
+  do {
+    /* send the packet */
+
+    struct libmemcached_io_vector_st vector[]=
+    {
+      { sizeof(request.bytes), request.bytes },
+      { keylen, chosenmech },
+      { len, data }
+    };
+
+    if (memcached_io_writev(server, vector, 3, true) == -1)
+    {
+      rc= MEMCACHED_WRITE_FAILURE;
+      break;
+    }
+    memcached_server_response_increment(server);
+
+    /* read the response */
+    rc= memcached_response(server, NULL, 0, NULL);
+    if (rc != MEMCACHED_AUTH_CONTINUE)
+    {
+      break;
+    }
+
+    ret= sasl_client_step(conn, memcached_result_value(&server->root->result),
+                          (unsigned int)memcached_result_length(&server->root->result),
+                          NULL, &data, &len);
+
+    if (ret != SASL_OK && ret != SASL_CONTINUE)
+    {
+      rc= MEMCACHED_AUTH_PROBLEM;
+      break;
+    }
+
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_STEP;
+    request.message.header.request.bodylen= htonl(len + keylen);
+  } while (true);
+
+  /* Release resources */
+  sasl_dispose(&conn);
+
+  return memcached_set_error(*server, rc, MEMCACHED_AT);
+}
+
+static int get_username(void *context, int id, const char **result, unsigned int *len)
+{
+  if (!context || !result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME))
+  {
+    return SASL_BADPARAM;
+  }
+
+  *result= (char *)context;
+  if (len)
+  {
+    *len= (unsigned int)strlen(*result);
+  }
+
+  return SASL_OK;
+}
+
+static int get_password(sasl_conn_t *conn, void *context, int id,
+                        sasl_secret_t **psecret)
+{
+  if (!conn || ! psecret || id != SASL_CB_PASS)
+  {
+    return SASL_BADPARAM;
+  }
+
+  *psecret= (sasl_secret_t *)context;
+
+  return SASL_OK;
+}
+
+memcached_return_t memcached_set_sasl_auth_data(memcached_st *ptr,
+                                                const char *username,
+                                                const char *password)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (ptr == NULL or username == NULL or password == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  memcached_destroy_sasl_auth_data(ptr);
+
+  sasl_callback_t *callbacks= (sasl_callback_t*)libmemcached_calloc(ptr, 4, sizeof(sasl_callback_t));
+  size_t password_length= strlen(password);
+  size_t username_length= strlen(username);
+  char *name= (char *)libmemcached_malloc(ptr, username_length +1);
+  sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
+
+  if (callbacks == NULL or name == NULL or secret == NULL)
+  {
+    libmemcached_free(ptr, callbacks);
+    libmemcached_free(ptr, name);
+    libmemcached_free(ptr, secret);
+    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
+
+  secret->len= password_length;
+  memcpy(secret->data, password, password_length);
+  secret->data[password_length]= 0;
+
+  callbacks[0].id= SASL_CB_USER;
+  callbacks[0].proc= (int (*)())get_username;
+  callbacks[0].context= strncpy(name, username, username_length +1);
+  callbacks[1].id= SASL_CB_AUTHNAME;
+  callbacks[1].proc= (int (*)())get_username;
+  callbacks[1].context= name;
+  callbacks[2].id= SASL_CB_PASS;
+  callbacks[2].proc= (int (*)())get_password;
+  callbacks[2].context= secret;
+  callbacks[3].id= SASL_CB_LIST_END;
+
+  ptr->sasl.callbacks= callbacks;
+  ptr->sasl.is_allocated= true;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (ptr->sasl.callbacks == NULL)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  if (ptr->sasl.is_allocated)
+  {
+    libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
+    libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
+    libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
+    ptr->sasl.is_allocated= false;
+  }
+
+  ptr->sasl.callbacks= NULL;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (clone == NULL or source == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (source->sasl.callbacks == NULL)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  /* Hopefully we are using our own callback mechanisms.. */
+  if (source->sasl.callbacks[0].id == SASL_CB_USER &&
+      source->sasl.callbacks[0].proc ==  (int (*)())get_username &&
+      source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
+      source->sasl.callbacks[1].proc ==  (int (*)())get_username &&
+      source->sasl.callbacks[2].id == SASL_CB_PASS &&
+      source->sasl.callbacks[2].proc ==  (int (*)())get_password &&
+      source->sasl.callbacks[3].id == SASL_CB_LIST_END)
+  {
+    sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
+    return memcached_set_sasl_auth_data(clone,
+                                        (const char*)source->sasl.callbacks[0].context,
+                                        (const char*)secret->data);
+  }
+
+  /*
+   * But we're not. It may work if we know what the user tries to pass
+   * into the list, but if we don't know the ID we don't know how to handle
+   * the context...
+ */
+  size_t total= 0;
+
+  while (source->sasl.callbacks[total].id != SASL_CB_LIST_END)
+  {
+    switch (source->sasl.callbacks[total].id)
+    {
+    case SASL_CB_USER:
+    case SASL_CB_AUTHNAME:
+    case SASL_CB_PASS:
+      break;
+    default:
+      /* I don't know how to deal with this... */
+      return MEMCACHED_NOT_SUPPORTED;
+    }
+
+    ++total;
+  }
+
+  sasl_callback_t *callbacks= (sasl_callback_t*)libmemcached_calloc(clone, total +1, sizeof(sasl_callback_t));
+  if (callbacks == NULL)
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+  memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t));
+
+  /* Now update the context... */
+  for (size_t x= 0; x < total; ++x)
+  {
+    if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME)
+    {
+      callbacks[x].context= (sasl_callback_t*)libmemcached_malloc(clone, strlen((const char*)source->sasl.callbacks[x].context));
+
+      if (callbacks[x].context == NULL)
+      {
+        /* Failed to allocate memory, clean up previously allocated memory */
+        for (size_t y= 0; y < x; ++y)
+        {
+          libmemcached_free(clone, clone->sasl.callbacks[y].context);
+        }
+
+        libmemcached_free(clone, callbacks);
+        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+      }
+      strncpy((char*)callbacks[x].context, (const char*)source->sasl.callbacks[x].context, sizeof(callbacks[x].context));
+    }
+    else
+    {
+      sasl_secret_t *src= (sasl_secret_t *)source->sasl.callbacks[x].context;
+      sasl_secret_t *n= (sasl_secret_t*)libmemcached_malloc(clone, src->len + 1 + sizeof(*n));
+      if (n == NULL)
+      {
+        /* Failed to allocate memory, clean up previously allocated memory */
+        for (size_t y= 0; y < x; ++y)
+        {
+          libmemcached_free(clone, clone->sasl.callbacks[y].context);
+        }
+
+        libmemcached_free(clone, callbacks);
+        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+      }
+      memcpy(n, src, src->len + 1 + sizeof(*n));
+      callbacks[x].context= n;
+    }
+  }
+
+  clone->sasl.callbacks= callbacks;
+  clone->sasl.is_allocated= true;
+
+  return MEMCACHED_SUCCESS;
+}
+
+#else
+
+void memcached_set_sasl_callbacks(memcached_st *, const sasl_callback_t *)
+{
+}
+
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *)
+{
+  return NULL;
+}
+
+memcached_return_t memcached_set_sasl_auth_data(memcached_st *, const char *, const char *)
+{
+  return MEMCACHED_NOT_SUPPORTED;
+}
+
+memcached_return_t memcached_clone_sasl(memcached_st *, const  memcached_st *)
+{
+  return MEMCACHED_NOT_SUPPORTED;
+}
+
+#endif
index 5a0236bf9ae5c39e79ed51efe6f86e4038369742..8602246d9523cb8f71bc70af6219abf33b105543 100644 (file)
 
 #pragma once
 
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
 #include <sasl/sasl.h>
+#else
+#define sasl_callback_t void
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -58,7 +61,7 @@ memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr);
 
 
 LIBMEMCACHED_API
-const sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr);
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr);
 
 LIBMEMCACHED_LOCAL
 memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source);
@@ -70,17 +73,11 @@ memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *s
 }
 #endif
 
-#endif /* LIBMEMCACHED_WITH_SASL_SUPPORT */
-
 struct memcached_sasl_st {
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-    const sasl_callback_t *callbacks;
-#else
-    const void *callbacks;
-#endif
-    /*
-    ** Did we allocate data inside the callbacks, or did the user
-    ** supply that.
-    */
-    bool is_allocated;
+  sasl_callback_t *callbacks;
+  /*
+   ** Did we allocate data inside the callbacks, or did the user
+   ** supply that.
+ */
+  bool is_allocated;
 };
index 2f44651761e4cba157164ffe8aeb26150fe3d627..10f3b944331153457ae040e6555e5f8737289582 100644 (file)
@@ -19,17 +19,13 @@ libmemcached_libmemcachedutil_la_SOURCES= \
                                          libmemcached/util/ping.cc \
                                          libmemcached/util/pool.cc \
                                          libmemcached/util/version.cc
-libmemcached_libmemcachedutil_la_CFLAGS= \
-                                        ${AM_CFLAGS} \
-                                        ${NO_CONVERSION} \
-                                        ${PTHREAD_CFLAGS} \
-                                        -DBUILDING_LIBMEMCACHED
 libmemcached_libmemcachedutil_la_CXXFLAGS= \
                                           ${AM_CXXFLAGS} \
                                           ${NO_CONVERSION} \
-                                          ${PTHREAD_CFLAGS} \
                                           -DBUILDING_LIBMEMCACHED
-libmemcached_libmemcachedutil_la_LIBADD= libmemcached/libmemcached.la ${PTHREAD_LIBS}
+libmemcached_libmemcachedutil_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
+libmemcached_libmemcachedutil_la_LIBADD= libmemcached/libmemcached.la
+libmemcached_libmemcachedutil_la_LIBADD+= ${PTHREAD_LIBS}
 libmemcached_libmemcachedutil_la_LDFLAGS= ${AM_LDFLAGS} -version-info ${MEMCACHED_UTIL_LIBRARY_VERSION}
 libmemcached_libmemcachedutil_la_DEPENDENCIES= libmemcached/libmemcached.la
 
index 2d7a86ddd8a18c6e9b6d9cc0a8f2511ae05917ed..de009fbbdfac38f8b5c3d84b4189158065b814db 100644 (file)
@@ -92,3 +92,74 @@ pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_r
   return pid;
 }
 
+pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret)
+{
+  if (username == NULL)
+  {
+    return libmemcached_util_getpid(hostname, port, ret);
+  }
+
+  pid_t pid= -1;
+
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    *ret= MEMCACHED_NOT_SUPPORTED;
+    return pid;
+  }
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return -1;
+  }
+
+  if (memcached_failed(*ret= memcached_behavior_set(memc_ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
+  {
+    memcached_free(memc_ptr);
+    return false;
+  }
+
+  if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
+  {
+    memcached_free(memc_ptr);
+    return false;
+  }
+
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+    if (memcached_success(rc) and stat and stat->pid != -1)
+    {
+      pid= stat->pid;
+    }
+    else if (memcached_success(rc))
+    {
+      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+    }
+    else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
+    {
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(memc_ptr, 0);
+
+      assert_msg(instance and instance->error_messages, " ");
+      if (instance and instance->error_messages)
+      {
+        rc= memcached_server_error_return(instance);
+      }
+    }
+
+    memcached_stat_free(memc_ptr, stat);
+  }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
+
+  return pid;
+}
index f2fb74888ad71b1703138bc98c569847ea6515e2..4101c11f03bb80ff5ddb94901e71df02cbb670e7 100644 (file)
@@ -43,6 +43,9 @@ extern "C" {
 LIBMEMCACHED_API
 pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
 
+LIBMEMCACHED_API
+pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret);
+
 #ifdef __cplusplus
 }
 #endif
index 45f94b19c17602ab68f87d1bc587212a12b773c7..907f6dc03bee0e3add3c81193d3fcd97e8f61ee2 100644 (file)
@@ -40,7 +40,6 @@
 #include <libmemcached/common.h>
 #include <libmemcached/memcached_util.h>
 
-
 bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
 {
   memcached_return_t unused;
@@ -77,3 +76,63 @@ bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_retu
 
   return memcached_success(rc);
 }
+
+bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret)
+{
+  if (username == NULL)
+  {
+    return libmemcached_util_ping(hostname, port, ret);
+  }
+
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    *ret= MEMCACHED_NOT_SUPPORTED;
+    return false;
+  }
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return false;
+  }
+
+  if (memcached_failed(*ret= memcached_behavior_set(memc_ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
+  {
+    memcached_free(memc_ptr);
+    return false;
+  }
+
+  if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
+  {
+    memcached_free(memc_ptr);
+    return false;
+  }
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    rc= memcached_version(memc_ptr);
+  }
+
+  if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+  {
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc_ptr, 0);
+
+    assert_msg(instance and instance->error_messages, " ");
+    if (instance and instance->error_messages)
+    {
+      rc= memcached_server_error_return(instance);
+    }
+  }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
+
+  return memcached_success(rc);
+}
index e9f3bc5005c89d27120b7af5fc6df68b4ec55343..faea8b2b68f3ee88f77bb1e71fc223f9a579d9b5 100644 (file)
@@ -44,6 +44,9 @@ extern "C" {
 LIBMEMCACHED_API
 bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret);
 
+LIBMEMCACHED_API
+bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret);
+
 #ifdef __cplusplus
 }
 #endif
index 6458925577953dcb63aeb17fb897f2df6ec08b0a..7b5e800726a5a53c0ecf264e2a22cc873a2aef95 100644 (file)
@@ -8,18 +8,12 @@
 noinst_LTLIBRARIES+= libmemcachedinternal/libmemcachedutilinternal.la
 
 libmemcachedinternal_libmemcachedutilinternal_la_SOURCES= $(libmemcached_libmemcachedutil_la_SOURCES)
-libmemcachedinternal_libmemcachedutilinternal_la_CFLAGS= \
-                                                        ${AM_CFLAGS} \
-                                                        ${NO_CONVERSION} \
-                                                        ${PTHREAD_CFLAGS} \
-                                                        -DBUILDING_LIBMEMCACHEDINTERNAL
 libmemcachedinternal_libmemcachedutilinternal_la_CXXFLAGS= \
                                                           ${AM_CXXFLAGS} \
                                                           ${NO_CONVERSION} \
-                                                          ${PTHREAD_CFLAGS} \
                                                           -DBUILDING_LIBMEMCACHEDINTERNAL
+libmemcachedinternal_libmemcachedutilinternal_la_CXXFLAGS+= ${PTHREAD_CFLAGS}
 libmemcachedinternal_libmemcachedutilinternal_la_LIBADD= libmemcachedinternal/libmemcachedinternal.la ${PTHREAD_LIBS}
-libmemcachedinternal_libmemcachedutilinternal_la_LDFLAGS= ${AM_LDFLAGS} -version-info ${MEMCACHED_UTIL_LIBRARY_VERSION}
-libmemcachedinternal_libmemcachedutilinternal_la_DEPENDENCIES= libmemcached/libmemcached.la
+libmemcachedinternal_libmemcachedutilinternal_la_DEPENDENCIES= libmemcachedinternal/libmemcachedinternal.la
 
 
index c7ac0a02ced740113360b798e99d4910333219ea..378f82688f4510187e3fdbf39410751d83c2c903 100644 (file)
@@ -21,6 +21,7 @@
 
 
 #include <libtest/common.h>
+
 #include <libtest/blobslap_worker.h>
 #include <libtest/killpid.h>
 
@@ -51,24 +52,35 @@ private:
 public:
   BlobslapWorker(in_port_t port_arg) :
     Server("localhost", port_arg)
-  { }
+  { 
+    set_pid_file();
+  }
 
   pid_t get_pid(bool error_is_ok)
   {
-    if (not pid_file().empty())
+    if (pid_file().empty())
     {
-      Wait wait(pid_file(), 0);
+      Error << "pid_file was empty";
+      return -1;
+    }
 
-      if (error_is_ok and not wait.successful())
-      {
-        Error << "Pidfile was not found:" << pid_file();
-        return -1;
+    Wait wait(pid_file(), 0);
 
-        return get_pid_from_file(pid_file());
-      }
+    if (error_is_ok and not wait.successful())
+    {
+      Error << "Pidfile was not found:" << pid_file();
+      return -1;
+    }
+
+    std::stringstream error_message;
+    pid_t ret= get_pid_from_file(pid_file(), error_message);
+
+    if (error_is_ok and is_pid_valid(ret) == false)
+    {
+      Error << error_message.str();
     }
 
-    return -1;
+    return ret;
   }
 
   bool ping()
@@ -86,12 +98,15 @@ public:
       return false;
     }
 
-    pid_t local_pid= get_pid_from_file(pid_file());
-    if (local_pid <= 0)
+    std::stringstream error_message;
+    pid_t local_pid= get_pid_from_file(pid_file(), error_message);
+    if (is_pid_valid(local_pid) == false)
     {
+      Error << error_message.str();
       return false;
     }
 
+    // Use kill to determine is the process exist
     if (::kill(local_pid, 0) == 0)
     {
       return true;
@@ -122,7 +137,7 @@ public:
 
   const char *log_file_option()
   {
-    return NULL;
+    return "--log-file=";
   }
 
   const char *port_option()
index 6c71f9b0935a13f8b4b78f49f864010dc82c016e..421fa006f53feffcafd7530d0237b9533b6e83e7 100644 (file)
 
 #include <libtest/common.h>
 
-#include <libtest/cmdline.h>
-
 using namespace libtest;
 
 #include <cstdlib>
 #include <string>
 #include <sstream>
 
+namespace libtest {
+
 bool exec_cmdline(const std::string& executable, const char *args[])
 {
   std::stringstream arg_buffer;
 
-  arg_buffer << "./libtool --mode=execute ";
+  arg_buffer << libtool();
 
   if (getenv("LIBTEST_TEST_ENVIRONMENT"))
   {
@@ -63,3 +63,10 @@ bool exec_cmdline(const std::string& executable, const char *args[])
 
   return true;
 }
+
+const char *gearmand_binary() 
+{
+  return GEARMAND_BINARY;
+}
+
+} // namespace exec_cmdline
index cfe29575965ef122e32c197b96e2cc4c564fcd05..dcb4b0ab2b78b0ccea3fdb96e2c84d82ddb3e5af 100644 (file)
 
 #pragma once
 
+namespace libtest {
+
 bool exec_cmdline(const std::string& executable, const char *args[]);
+
+const char *gearmand_binary(); 
+
+}
index 7a7f1ff0fec127e23c10d7219498c91cde69187e..8f2c010892080544b5552896d9c151123c9f4b07 100644 (file)
@@ -20,7 +20,7 @@
  */
 
 /*
-  Common include file for libmemached
+  Common include file for libtest
 */
 
 #pragma once
 #include <fnmatch.h>
 #endif
 
+static inline bool is_pid_valid(const pid_t pid)
+{
+  return (pid > 1) ? true : false;
+}
+
+#include <libtest/gearmand.h>
+#include <libtest/blobslap_worker.h>
+#include <libtest/memcached.h>
+
+#include <libtest/libtool.hpp>
+
 #include <libtest/test.hpp>
index 8656e49935447ba2a5e20d120a1ebe6a5eb286fe..5c687fc3a6500b5d153b00802b73ca51934f7cbc 100644 (file)
 
 #include <typeinfo>
 #include <libtest/strerror.h>
+
+#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
 #include <libmemcached/memcached.h>
+#endif
+
+#if defined(HAVE_LIBGEARMAN) && HAVE_LIBGEARMAN
+#include <libgearman/gearman.h>
+#endif
 
 namespace libtest {
 
@@ -40,24 +47,39 @@ bool _compare_true_hint(const char *file, int line, const char *func, T_comparab
 }
 
 template <class T_comparable>
-bool _compare(const char *file, int line, const char *func, T_comparable __expected, T_comparable __actual)
+bool _compare(const char *file, int line, const char *func, const T_comparable __expected, const T_comparable __actual)
 {
   if (__expected != __actual)
   {
-    if (typeid(__expected) == typeid(memcached_return_t))
+    if (typeid(__expected) == typeid(test_return_t))
+    {
+      const char *expected_str= test_strerror(test_return_t(__expected));
+      const char *got_str= test_strerror(test_return_t(__actual));
+
+      libtest::stream::make_cerr(file, line, func) << "Expected \"" 
+        << expected_str
+        << "\" got \"" 
+        << got_str
+        << "\"";
+    }
+#if (defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED)
+    else if (typeid(__expected) == typeid(memcached_return_t))
     {
       libtest::stream::make_cerr(file, line, func) << "Expected \"" 
         << memcached_strerror(NULL, memcached_return_t(__expected)) 
         << "\" got \"" 
         << memcached_strerror(NULL, memcached_return_t(__actual)) << "\"";
     }
-    else if (typeid(__expected) == typeid(test_return_t))
+#endif
+#if defined(HAVE_LIBGEARMAN) && HAVE_LIBGEARMAN
+    else if (typeid(__expected) == typeid(gearman_return_t))
     {
       libtest::stream::make_cerr(file, line, func) << "Expected \"" 
-        << test_strerror(test_return_t(__expected)) 
+        << gearman_strerror(gearman_return_t(__expected)) 
         << "\" got \"" 
-        << test_strerror(test_return_t(__actual)) << "\"";
+        << gearman_strerror(gearman_return_t(__actual)) << "\"";
     }
+#endif
     else
     {
       libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\"";
index 69941b1bc8faaf1e62aaf054406b45678b30681d..90908244c47506a655c50b3bcf64dbbeb9a0ab7d 100644 (file)
@@ -143,6 +143,11 @@ public:
   {
     _servers.set_socket();
   }
+
+  void set_sasl(const std::string& username_arg, const std::string& password_arg)
+  {
+    _servers.set_sasl(username_arg, password_arg);
+  }
   
   /**
     Runner represents the callers for the tests. If not implemented we will use
index 9a7649ef07114a058fbbab2a969b424d4a509cc4..deac09f3562cd2754b63e049fb9ff4d93cce56f8 100644 (file)
@@ -21,6 +21,7 @@
 
 
 #include <libtest/common.h>
+
 #include <libtest/gearmand.h>
 
 #include "util/instance.hpp"
@@ -36,6 +37,7 @@ using namespace libtest;
 #include <cstring>
 #include <iostream>
 #include <signal.h>
+#include <sstream>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
@@ -65,13 +67,12 @@ public:
   bool call(const bool success, const std::string &response)
   {
     _pid= -1;
-
     if (success and response.size())
     {
       _pid= atoi(response.c_str());
     }
 
-    if (_pid < 1)
+    if (is_pid_valid(_pid) == false)
     {
       _pid= -1;
       return false;
@@ -83,13 +84,15 @@ public:
 
 using namespace libtest;
 
-class Gearmand : public Server
+class Gearmand : public libtest::Server
 {
 private:
 public:
   Gearmand(const std::string& host_arg, in_port_t port_arg) :
-    Server(host_arg, port_arg)
-  { }
+    libtest::Server(host_arg, port_arg)
+  {
+    set_pid_file();
+  }
 
   pid_t get_pid(bool error_is_ok)
   {
@@ -182,9 +185,6 @@ public:
   bool build(int argc, const char *argv[]);
 };
 
-
-#include <sstream>
-
 bool Gearmand::build(int argc, const char *argv[])
 {
   std::stringstream arg_buffer;
@@ -208,7 +208,7 @@ bool Gearmand::build(int argc, const char *argv[])
 
 namespace libtest {
 
-Server *build_gearmand(const char *hostname, in_port_t try_port)
+libtest::Server *build_gearmand(const char *hostname, in_port_t try_port)
 {
   return new Gearmand(hostname, try_port);
 }
index 22aaa7133b756790e76dfe0204f57efab2b19988..f6aa6c32c2f07fb62c93d952327573d7173035ae 100644 (file)
 
 #pragma once
 
+#include <arpa/inet.h>
+
+namespace libtest { class Server; }
+
 namespace libtest {
 
-Server *build_gearmand(const char *hostname, in_port_t try_port);
+libtest::Server *build_gearmand(const char *hostname, in_port_t try_port);
 
 }
index 2ed437c2af36ad30c087cc84a5f6807219e9b8a7..3ee7d3f9547de3676ae51502729d790cc7ae4836 100644 (file)
@@ -20,9 +20,7 @@
 # All paths should be given relative to the root
 # 
 
-LIBTEST_TMP = ${abs_top_builddir}/tests/var/tmp/
-
-LIBTOOL_COMMAND=$(LIBTOOL) --mode=execute
+LIBTOOL_COMMAND= ${abs_top_builddir}/libtool --mode=execute
 VALGRIND_COMMAND= $(LIBTOOL_COMMAND) valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
 HELGRIND_COMMAND= $(LIBTOOL_COMMAND) valgrind --tool=helgrind --read-var-info=yes --error-exitcode=1 
 DRD_COMMAND= $(LIBTOOL_COMMAND) valgrind --tool=drd
@@ -34,12 +32,25 @@ export HELGRIND_COMMAND
 export DRD_COMMAND
 export GDB_COMMAND
 
+valgrind:
+       @echo make check TESTS_ENVIRONMENT="\"$(VALGRIND_COMMAND)\""
+
+helgrind:
+       @echo make check TESTS_ENVIRONMENT="\"$(HELGRIND_COMMAND)\""
+
+drd:
+       @echo make check TESTS_ENVIRONMENT="\"$(DRD_COMMAND)\""
+
 EXTRA_DIST+= libtest/run.gdb
 
 CLEANFILES+= \
-            tests/var/log/* \
-            tests/var/run/* \
-            tests/var/tmp/*
+            tmp_chroot/var/log/* \
+            tmp_chroot/var/run/* \
+            tmp_chroot/var/tmp/*
+
+.PHONY: distclean-libtest-check
+distclean-libtest-check:
+       -rm -rf tmp_chroot
 
 noinst_HEADERS+= \
                 libtest/blobslap_worker.h \
@@ -55,6 +66,7 @@ noinst_HEADERS+= \
                 libtest/gearmand.h \
                 libtest/get.h \
                 libtest/killpid.h \
+                libtest/libtool.hpp \
                 libtest/memcached.h \
                 libtest/runner.h \
                 libtest/server.h \
@@ -73,70 +85,104 @@ libtest_libtest_la_SOURCES= \
                            libtest/cmdline.cc \
                            libtest/framework.cc \
                            libtest/killpid.cc \
+                           libtest/libtool.cc \
                            libtest/runner.cc \
                            libtest/server.cc \
                            libtest/signal.cc \
                            libtest/test.cc
 
-libtest_libtest_la_CFLAGS= ${AM_CFLAGS}
-libtest_libtest_la_CFLAGS+= ${NO_CONVERSION}
-libtest_libtest_la_CFLAGS+= $(PTHREAD_CFLAGS)
-libtest_libtest_la_CFLAGS+= -DBUILDING_LIBTEST
-libtest_libtest_la_CPPFLAGS= ${AM_CPPFLAGS}
-libtest_libtest_la_CPPFLAGS+= ${NO_CONVERSION}
-libtest_libtest_la_CPPFLAGS+= $(PTHREAD_LIBS)
-libtest_libtest_la_CPPFLAGS+= -DBUILDING_LIBTEST
 libtest_libtest_la_CXXFLAGS= ${AM_CXXFLAGS}
 libtest_libtest_la_CXXFLAGS+= ${NO_CONVERSION}
 libtest_libtest_la_CXXFLAGS+= -DBUILDING_LIBTEST
 libtest_libtest_la_CXXFLAGS+= $(PTHREAD_CFLAGS)
+libtest_libtest_la_CXXFLAGS+= -DLIBTEST_TEMP="\"tmp_chroot\""
 libtest_libtest_la_LIBADD=
 libtest_libtest_la_LIBADD+= $(PTHREAD_LIBS)
+libtest_libtest_la_DEPENDENCIES= libtest_tmp_dir
 
-LIBTEST_LDADD= libtest/libtest.la
+# Declare unittest so that we can append to it
+libtest_unittest_CXXFLAGS=
+libtest_unittest_LDADD=
+libtest_unittest_DEPENDENCIES=
 
-if HAVE_LIBMEMCACHED
+# We are either building in tree, or with
+if BUILDING_LIBMEMCACHED
+libtest_libtest_la_DEPENDENCIES+= libmemcached/libmemcached.la
+libtest_libtest_la_DEPENDENCIES+= libmemcached/libmemcachedutil.la
 libtest_libtest_la_LIBADD+= libmemcached/libmemcached.la
 libtest_libtest_la_LIBADD+= libmemcached/libmemcachedutil.la
 libtest_libtest_la_SOURCES+= libtest/memcached.cc
+libtest_libtest_la_CXXFLAGS+= -DHAVE_LIBMEMCACHED
+
+libtest_unittest_CXXFLAGS+= -DHAVE_LIBMEMCACHED
+libtest_unittest_LDADD+= libmemcached/libmemcached.la
+libtest_unittest_LDADD+= libmemcached/libmemcachedutil.la
+libtest_unittest_DEPENDENCIES+= libmemcached/libmemcached.la
+libtest_unittest_DEPENDENCIES+= libmemcached/libmemcachedutil.la
+else
+if HAVE_LIBMEMCACHED
+libtest_libtest_la_LIBADD+= $(libmemcached_LIBS)
+libtest_libtest_la_SOURCES+= libtest/memcached.cc
+else
+libtest_libtest_la_CXXFLAGS+= -DHAVE_LIBMEMCACHED=0
+libtest_unittest_CXXFLAGS+= -DHAVE_LIBMEMCACHED=0
+endif
 endif
 
+if BUILDING_GEARMAN
+libtest_libtest_la_DEPENDENCIES+= libgearman/libgearman.la
+libtest_libtest_la_LIBADD+= libgearman/libgearman.la
+libtest_libtest_la_SOURCES+= libtest/blobslap_worker.cc
+libtest_libtest_la_SOURCES+= libtest/gearmand.cc
+libtest_libtest_la_SOURCES+= util/instance.cc
+libtest_libtest_la_SOURCES+= util/operation.cc
+libtest_libtest_la_CXXFLAGS+= -DHAVE_LIBGEARMAN
+libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BINARY="\"${abs_top_builddir}/gearmand/gearmand\""
+libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BLOBSLAP_WORKER="\"${abs_top_builddir}/benchmark/blobslap_worker\""
+
+libtest_unittest_CXXFLAGS+= -DHAVE_LIBGEARMAN
+libtest_unittest_LDADD+= libgearman/libgearman.la
+libtest_unittest_DEPENDENCIES+= libgearman/libgearman.la
+else
 if HAVE_LIBGEARMAN
-LIBTEST_LDADD+= libgearman/libgearman.la
+libtest_libtest_la_DEPENDENCIES+= libgearman/libgearman.la
+libtest_libtest_la_LIBADD+= $(libgearman_LIBS)
 libtest_libtest_la_SOURCES+= libtest/blobslap_worker.cc
 libtest_libtest_la_SOURCES+= libtest/gearmand.cc
 libtest_libtest_la_SOURCES+= util/instance.cc
 libtest_libtest_la_SOURCES+= util/operation.cc
+else
+libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BINARY=0
+libtest_libtest_la_CXXFLAGS+= -DGEARMAND_BLOBSLAP_WORKER=0
+libtest_libtest_la_CXXFLAGS+= -DHAVE_LIBGEARMAN=0
+libtest_unittest_CXXFLAGS+= -DGEARMAND_BINARY=0
+libtest_unittest_CXXFLAGS+= -DHAVE_LIBGEARMAN=0
+endif
 endif
 
-libtest_tmp_dir: tests/var/log tests/var/tmp tests/var/run clearn-var
-
-clearn-var:
-       @rm -f tests/var/log/*
-       @rm -f tests/var/run/*
-       @rm -f tests/var/tmp/*
+libtest_tmp_dir: tmp_chroot/var/log tmp_chroot/var/tmp tmp_chroot/var/run
 
-tests/var:
-       @$(mkdir_p) tests/var
+tmp_chroot:
+       @$(mkdir_p) tmp_chroot
 
-tests/var/log: tests/var
-       @$(mkdir_p) tests/var/log
+tmp_chroot/var: tmp_chroot
+       @$(mkdir_p) tmp_chroot/var
 
-tests/var/tmp: tests/var
-       @$(mkdir_p) tests/var/tmp
+tmp_chroot/var/log: tmp_chroot/var
+       @$(mkdir_p) tmp_chroot/var/log
 
-tests/var/run: tests/var
-       @$(mkdir_p) tests/var/run
+tmp_chroot/var/tmp: tmp_chroot/var
+       @$(mkdir_p) tmp_chroot/var/tmp
 
-.PHONY+= tests/var
+tmp_chroot/var/run: tmp_chroot/var
+       @$(mkdir_p) tmp_chroot/var/run
 
 
-libtest_unittest_CFLAGS=
-libtest_unittest_LDADD= ${LIBTEST_LDADD}
-libtest_unittest_DEPENDENCIES= ${LIBTEST_LDADD} libtest_tmp_dir
+libtest_unittest_CXXFLAGS+= ${AM_CXXFLAGS}
+libtest_unittest_DEPENDENCIES+= libtest/libtest.la libtest_tmp_dir
+libtest_unittest_LDADD+= libtest/libtest.la
 libtest_unittest_SOURCES= libtest/unittest.cc
 check_PROGRAMS+= libtest/unittest
-noinst_PROGRAMS+= libtest/unittest
 test-unittest: libtest/unittest
        @libtest/unittest
 
@@ -152,6 +198,10 @@ helgrind-unittest: libtest/unittest
 drd-unittest: libtest/unittest
        @$(DRD_COMMAND) libtest/unittest
 
+libtest_skiptest_LDADD= libtest/libtest.la
+libtest_skiptest_SOURCES= libtest/skiptest.cc
+check_PROGRAMS+= libtest/skiptest
+noinst_PROGRAMS+= libtest/skiptest
+
 libtest_wait_SOURCES= libtest/wait.cc
 noinst_PROGRAMS+= libtest/wait
-
index 7bbdd6365ef51a1f5bc0e4d0b0dbdf3bfc581266..8a1543f4892968a05235bce05690815ba9dc5453 100644 (file)
@@ -25,6 +25,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <iostream>
+#include <sstream>
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/types.h>
@@ -114,14 +115,18 @@ pid_t kill_file(const std::string &filename)
   return ret;
 }
 
-pid_t get_pid_from_file(const std::string &filename)
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define LIBTEST_AT __FILE__ ":" TOSTRING(__LINE__)
+
+pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message)
 {
   pid_t ret= -1;
   FILE *fp;
 
   if (filename.empty())
   {
-    Error << "empty pid file";
+    error_message << LIBTEST_AT << " empty pid file";
     return ret;
   }
 
@@ -135,11 +140,23 @@ pid_t get_pid_from_file(const std::string &filename)
     if (ptr)
     {
       ret= (pid_t)atoi(pid_buffer);
-      if (ret <= 0)
+      if (ret < 1)
       {
-        return ret;
+        error_message << LIBTEST_AT << " Invalid pid was read from file " << filename;
       }
     }
+    else
+    {
+      error_message << LIBTEST_AT << " File " << filename << " was empty ";
+    }
+
+    return ret;
+  }
+  else
+  {
+    char buffer[1024];
+    char *current_directory= getcwd(buffer, sizeof(buffer));
+    error_message << "Error while opening " << current_directory << "/" << filename << " " << strerror(errno);
   }
   
   return ret;
index 83c7bb0a94c87591a7e7dd584c81246d3ff86b24..becfd0ed8f0be7c460a7e31e9296c7ea835ea06b 100644 (file)
@@ -27,4 +27,4 @@ bool kill_pid(pid_t pid_arg);
 
 pid_t kill_file(const std::string &filename);
 
-pid_t get_pid_from_file(const std::string &filename);
+pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message);
diff --git a/libtest/libtool.cc b/libtest/libtool.cc
new file mode 100644 (file)
index 0000000..c7aa29d
--- /dev/null
@@ -0,0 +1,58 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <libtest/common.h>
+#include <string>
+
+char _libtool[1024]= { 0 };
+
+namespace libtest {
+
+const char *libtool(void)
+{
+  if (_libtool[0])
+  {
+    std::string libtool_buffer;
+    if (getenv("srcdir"))
+    {
+      libtool_buffer+= getenv("srcdir");
+      libtool_buffer+= "/";
+    }
+    else
+    {
+      libtool_buffer+= "./";
+    }
+
+    libtool_buffer+= "libtool";
+    if (access(libtool_buffer.c_str(), R_OK | W_OK | X_OK))
+    {
+      return NULL;
+    }
+
+    libtool_buffer+= " --mode=execute ";
+
+    snprintf(_libtool, sizeof(_libtool), "%s", libtool_buffer.c_str());
+  }
+
+  return _libtool;
+}
+
+}
diff --git a/libtest/libtool.hpp b/libtest/libtool.hpp
new file mode 100644 (file)
index 0000000..d523aa2
--- /dev/null
@@ -0,0 +1,28 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#pragma once
+
+namespace libtest {
+
+const char *libtool(void);
+
+}
index 910ea809396dc2ad5476702cefe882cc5ecc5426..3aba25430b20b35eabf0378dab5c3d659f45c096 100644 (file)
@@ -49,13 +49,39 @@ using namespace libtest;
 
 using namespace libtest;
 
-class Memcached : public Server
+class Memcached : public libtest::Server
 {
+  std::string _username;
+  std::string _password;
+
 public:
-  Memcached(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg) :
-    Server(host_arg, port_arg, is_socket_arg)
+  Memcached(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg, const std::string& username_arg, const std::string& password_arg) :
+    libtest::Server(host_arg, port_arg, is_socket_arg),
+    _username(username_arg),
+    _password(password_arg)
   { }
 
+  Memcached(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg) :
+    libtest::Server(host_arg, port_arg, is_socket_arg)
+  {
+    set_pid_file();
+  }
+
+  virtual const char *sasl() const
+  {
+    return NULL;
+  }
+
+  const std::string& password() const
+  {
+    return _password;
+  }
+
+  const std::string& username() const
+  {
+    return _username;
+  }
+
   pid_t get_pid(bool error_is_ok)
   {
     // Memcached is slow to start, so we need to do this
@@ -74,14 +100,28 @@ public:
     memcached_return_t rc;
     if (has_socket())
     {
-      local_pid= libmemcached_util_getpid(socket().c_str(), port(), &rc);
+      if (username().empty())
+      {
+        local_pid= libmemcached_util_getpid(socket().c_str(), 0, &rc);
+      }
+      else
+      {
+        local_pid= libmemcached_util_getpid2(socket().c_str(), 0, username().c_str(), password().c_str(), &rc);
+      }
     }
     else
     {
-      local_pid= libmemcached_util_getpid(hostname().c_str(), port(), &rc);
+      if (username().empty())
+      {
+        local_pid= libmemcached_util_getpid(hostname().c_str(), port(), &rc);
+      }
+      else
+      {
+        local_pid= libmemcached_util_getpid2(hostname().c_str(), port(), username().c_str(), password().c_str(), &rc);
+      }
     }
 
-    if (error_is_ok and ((memcached_failed(rc) or local_pid < 1)))
+    if (error_is_ok and ((memcached_failed(rc) or not is_pid_valid(local_pid))))
     {
       Error << "libmemcached_util_getpid(" << memcached_strerror(NULL, rc) << ") pid: " << local_pid << " for:" << *this;
     }
@@ -105,19 +145,42 @@ public:
 
     memcached_return_t rc;
     bool ret;
+
     if (has_socket())
     {
-      ret= libmemcached_util_ping(socket().c_str(), 0, &rc);
+      if (username().empty())
+      {
+        ret= libmemcached_util_ping(socket().c_str(), 0, &rc);
+      }
+      else
+      {
+        ret= libmemcached_util_ping2(socket().c_str(), 0, username().c_str(), password().c_str(), &rc);
+      }
     }
     else
     {
-      ret= libmemcached_util_ping(hostname().c_str(), port(), &rc);
+      if (username().empty())
+      {
+        ret= libmemcached_util_ping(hostname().c_str(), port(), &rc);
+      }
+      else
+      {
+        ret= libmemcached_util_ping2(hostname().c_str(), port(), username().c_str(), password().c_str(), &rc);
+      }
     }
 
     if (memcached_failed(rc) or not ret)
     {
-      Error << "libmemcached_util_ping(" << memcached_strerror(NULL, rc) << ")";
+      if (username().empty())
+      {
+        Error << "libmemcached_util_ping(" << hostname() << ", " << port() << ") error: " << memcached_strerror(NULL, rc);
+      }
+      else
+      {
+        Error << "libmemcached_util_ping2(" << hostname() << ", " << port() << ", " << username() << ", " << password() << ") error: " << memcached_strerror(NULL, rc);
+      }
     }
+
     return ret;
   }
 
@@ -161,6 +224,11 @@ public:
     return false;
   }
 
+  bool broken_socket_cleanup()
+  {
+    return true;
+  }
+
   // Memcached's pidfile is broken
   bool broken_pid_file()
   {
@@ -170,6 +238,30 @@ public:
   bool build(int argc, const char *argv[]);
 };
 
+class MemcachedSaSL : public Memcached
+{
+public:
+  MemcachedSaSL(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg, const std::string& username_arg, const std::string &password_arg) :
+    Memcached(host_arg, port_arg, is_socket_arg, username_arg, password_arg)
+  { }
+
+  const char *name()
+  {
+    return "memcached-sasl";
+  };
+
+  const char *sasl() const
+  {
+    return " -S -B binary ";
+  }
+
+  const char *executable()
+  {
+    return MEMCACHED_SASL_BINARY;
+  }
+
+};
+
 
 #include <sstream>
 
@@ -186,6 +278,11 @@ bool Memcached::build(int argc, const char *argv[])
   arg_buffer << " -m 128 ";
   arg_buffer << " -M ";
 
+  if (sasl())
+  {
+    arg_buffer << sasl();
+  }
+
   for (int x= 1 ; x < argc ; x++)
   {
     arg_buffer << " " << argv[x] << " ";
@@ -198,14 +295,25 @@ bool Memcached::build(int argc, const char *argv[])
 
 namespace libtest {
 
-Server *build_memcached(const std::string& hostname, const in_port_t try_port)
+libtest::Server *build_memcached(const std::string& hostname, const in_port_t try_port)
 {
   return new Memcached(hostname, try_port, false);
 }
 
-Server *build_memcached_socket(const std::string& hostname, const in_port_t try_port)
+libtest::Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port)
+{
+  return new Memcached(socket_file, try_port, true);
+}
+
+
+libtest::Server *build_memcached_sasl(const std::string& hostname, const in_port_t try_port, const std::string& username, const std::string &password)
+{
+  return new MemcachedSaSL(hostname, try_port, false,  username, password);
+}
+
+libtest::Server *build_memcached_sasl_socket(const std::string& socket_file, const in_port_t try_port, const std::string& username, const std::string &password)
 {
-  return new Memcached(hostname, try_port, true);
+  return new MemcachedSaSL(socket_file, try_port, true, username, password);
 }
 
 }
index 575ba00104c4e24d73010617415981dabcb8759f..a08996140189c69648823700d6306faa5ad96125 100644 (file)
 
 namespace libtest {
 
-LIBTEST_API
-Server *build_memcached(const std::string& hostname, const in_port_t try_port);
+libtest::Server *build_memcached(const std::string& hostname, const in_port_t try_port);
 
-LIBTEST_API
-Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port);
+libtest::Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port);
+
+libtest::Server *build_memcached_sasl(const std::string& hostname, const in_port_t try_port, const std::string& username, const std::string& password);
+
+libtest::Server *build_memcached_sasl_socket(const std::string& socket_file, const in_port_t try_port, const std::string& username, const std::string& password);
 
 }
 
index b8fb603e13696fdadc9bdcfa6cb97a6f719bbf6d..603b3f4577083b354a60e08929466e0af1750591 100644 (file)
@@ -42,15 +42,6 @@ static inline std::string &rtrim(std::string &s)
 #include <libtest/stream.h>
 #include <libtest/killpid.h>
 
-#ifdef HAVE_LIBGEARMAN
-#include <libtest/gearmand.h>
-#include <libtest/blobslap_worker.h>
-#endif
-
-#ifdef HAVE_LIBMEMCACHED
-#include <libtest/memcached.h>
-#endif
-
 extern "C" {
   static bool exited_successfully(int status)
   {
@@ -136,7 +127,7 @@ bool Server::cycle()
 
   // Try to ping, and kill the server #limit number of times
   pid_t current_pid;
-  while (--limit and (current_pid= get_pid()) != -1)
+  while (--limit and is_pid_valid(current_pid= get_pid()))
   {
     if (kill(current_pid))
     {
@@ -201,22 +192,22 @@ bool Server::start()
     return false;
   }
 
-  if (is_helgrind())
+  if (is_helgrind() or is_valgrind())
   {
     sleep(4);
   }
 
   if (pid_file_option() and not pid_file().empty())
   {
-    Wait wait(pid_file());
+    Wait wait(pid_file(), 8);
 
     if (not wait.successful())
     {
-      Error << "Unable to open pidfile: " << pid_file();
+      Error << "Unable to open pidfile for: " << _running;
     }
   }
 
-  int count= is_helgrind() ? 20 : 5;
+  int count= is_helgrind() or is_valgrind() ? 20 : 5;
   while (not ping() and --count)
   {
     nap();
@@ -224,7 +215,12 @@ bool Server::start()
 
   if (count == 0)
   {
-    Error << "Failed to ping() server once started:" << *this;
+    // If we happen to have a pid file, lets try to kill it
+    if (pid_file_option() and not pid_file().empty())
+    {
+      kill_file(pid_file());
+    }
+    Error << "Failed to ping() server started with:" << _running;
     _running.clear();
     return false;
   }
@@ -258,7 +254,7 @@ bool Server::set_socket_file()
   }
   else
   {
-    snprintf(file_buffer, sizeof(file_buffer), "tests/var/run/%s.socketXXXXXX", name());
+    snprintf(file_buffer, sizeof(file_buffer), "var/run/%s.socketXXXXXX", name());
   }
 
   int fd;
@@ -286,7 +282,7 @@ bool Server::set_pid_file()
   }
   else
   {
-    snprintf(file_buffer, sizeof(file_buffer), "tests/var/run/%s.pidXXXXXX", name());
+    snprintf(file_buffer, sizeof(file_buffer), "var/run/%s.pidXXXXXX", name());
   }
 
   int fd;
@@ -308,7 +304,7 @@ bool Server::set_log_file()
   char file_buffer[FILENAME_MAX];
   file_buffer[0]= 0;
 
-  snprintf(file_buffer, sizeof(file_buffer), "tests/var/log/%s.logXXXXXX", name());
+  snprintf(file_buffer, sizeof(file_buffer), "var/log/%s.logXXXXXX", name());
   int fd;
   if ((fd= mkstemp(file_buffer)) == -1)
   {
@@ -325,10 +321,9 @@ bool Server::set_log_file()
 void Server::rebuild_base_command()
 {
   _base_command.clear();
-  if (is_libtool() and getenv("LIBTOOL_COMMAND"))
+  if (is_libtool())
   {
-    _base_command+= getenv("LIBTOOL_COMMAND");
-    _base_command+= " ";
+    _base_command+= libtool();
   }
 
   if (is_debug() and getenv("GDB_COMMAND"))
@@ -373,7 +368,7 @@ bool Server::args(std::string& options)
   // Update pid_file
   if (pid_file_option())
   {
-    if (not set_pid_file())
+    if (_pid_file.empty() and not set_pid_file())
     {
       return false;
     }
@@ -437,6 +432,11 @@ bool Server::kill(pid_t pid_arg)
       unlink(pid_file().c_str());
     }
 
+    if (broken_socket_cleanup() and has_socket() and not socket().empty())
+    {
+      unlink(socket().c_str());
+    }
+
     reset_pid();
 
     return true;
@@ -544,44 +544,80 @@ bool server_startup(server_startup_st& construct, const std::string& server_type
     }
   }
 
-  Server *server= NULL;
+  libtest::Server *server= NULL;
   if (0)
   { }
   else if (server_type.compare("gearmand") == 0)
   {
-#ifdef GEARMAND_BINARY
-  #ifdef HAVE_LIBGEARMAN
-    server= build_gearmand("localhost", try_port);
-  #else
-    Error << "Libgearman was not found";
-  #endif
-#else
-    Error << "No gearmand binary is available";
-#endif
+    if (GEARMAND_BINARY)
+    {
+      if (HAVE_LIBGEARMAN)
+      {
+        server= build_gearmand("localhost", try_port);
+      }
+      else
+      {
+        Error << "Libgearman was not found";
+      }
+    } 
+    else
+    {
+      Error << "No gearmand binary is available";
+    }
   }
   else if (server_type.compare("blobslap_worker") == 0)
   {
-#ifdef GEARMAND_BINARY
-  #ifdef HAVE_LIBGEARMAN
-    server= build_blobslap_worker(try_port);
-  #else
-    Error << "Libgearman was not found";
-  #endif
-#else
-    Error << "No gearmand binary is available";
-#endif
+    if (GEARMAND_BINARY and GEARMAND_BLOBSLAP_WORKER)
+    {
+      if (HAVE_LIBGEARMAN)
+      {
+        server= build_blobslap_worker(try_port);
+      }
+      else
+      {
+        Error << "Libgearman was not found";
+      }
+    }
+    else
+    {
+      Error << "No gearmand binary is available";
+    }
+  }
+  else if (server_type.compare("memcached-sasl") == 0)
+  {
+    if (MEMCACHED_SASL_BINARY)
+    {
+      if (HAVE_LIBMEMCACHED)
+      {
+        server= build_memcached_sasl("localhost", try_port, construct.username(), construct.password());
+      }
+      else
+      {
+        Error << "Libmemcached was not found";
+      }
+    }
+    else
+    {
+      Error << "No memcached binary that was compiled with sasl is available";
+    }
   }
   else if (server_type.compare("memcached") == 0)
   {
-#ifdef MEMCACHED_BINARY
-#ifdef HAVE_LIBMEMCACHED
-    server= build_memcached("localhost", try_port);
-#else
-    Error << "Libmemcached was not found";
-#endif
-#else
-    Error << "No memcached binary is available";
-#endif
+    if (MEMCACHED_BINARY)
+    {
+      if (HAVE_LIBMEMCACHED)
+      {
+        server= build_memcached("localhost", try_port);
+      }
+      else
+      {
+        Error << "Libmemcached was not found";
+      }
+    }
+    else
+    {
+      Error << "No memcached binary is available";
+    }
   }
   else
   {
@@ -650,17 +686,41 @@ bool server_startup_st::start_socket_server(const std::string& server_type, cons
   {
     Error << "Socket files are not supported for gearmand yet";
   }
+  else if (server_type.compare("memcached-sasl") == 0)
+  {
+    if (MEMCACHED_SASL_BINARY)
+    {
+      if (HAVE_LIBMEMCACHED)
+      {
+        server= build_memcached_sasl_socket("localhost", try_port, username(), password());
+      }
+      else
+      {
+        Error << "Libmemcached was not found";
+      }
+    }
+    else
+    {
+      Error << "No memcached binary is available";
+    }
+  }
   else if (server_type.compare("memcached") == 0)
   {
-#ifdef MEMCACHED_BINARY
-#ifdef HAVE_LIBMEMCACHED
-    server= build_memcached_socket("localhost", try_port);
-#else
-    Error << "Libmemcached was not found";
-#endif
-#else
-    Error << "No memcached binary is available";
-#endif
+    if (MEMCACHED_BINARY)
+    {
+      if (HAVE_LIBMEMCACHED)
+      {
+        server= build_memcached_socket("localhost", try_port);
+      }
+      else
+      {
+        Error << "Libmemcached was not found";
+      }
+    }
+    else
+    {
+      Error << "No memcached binary is available";
+    }
   }
   else
   {
index a38bf428e60eb39103c8b442057e434aab696f8a..b4a48446c538f6e459fb72a17ac3edbfd741b9d9 100644 (file)
@@ -36,6 +36,7 @@ struct Server {
 private:
   bool _is_socket;
   std::string _socket;
+  std::string _sasl;
   std::string _pid_file;
   std::string _log_file;
   std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
@@ -60,6 +61,11 @@ public:
   virtual const char *log_file_option()= 0;
   virtual bool is_libtool()= 0;
 
+  virtual bool broken_socket_cleanup()
+  {
+    return false;
+  }
+
   virtual const char *socket_file_option() const
   {
     return NULL;
@@ -165,13 +171,13 @@ public:
 
 protected:
   void nap();
+  bool set_pid_file();
 
 private:
   bool is_helgrind() const;
   bool is_valgrind() const;
   bool is_debug() const;
   bool set_log_file();
-  bool set_pid_file();
   bool set_socket_file();
   void rebuild_base_command();
   void reset_pid();
@@ -184,6 +190,9 @@ class server_startup_st
 private:
   std::string server_list;
   bool _socket;
+  bool _sasl;
+  std::string _username;
+  std::string _password;
 
 public:
 
@@ -192,6 +201,7 @@ public:
 
   server_startup_st() :
     _socket(false),
+    _sasl(false),
     udp(0)
   { }
 
@@ -204,6 +214,17 @@ public:
     return servers.size();
   }
 
+  const std::string& password() const
+  {
+    return _password;
+  }
+
+  const std::string& username() const
+  {
+    return _username;
+  }
+
+
   bool is_debug() const;
   bool is_helgrind() const;
   bool is_valgrind() const;
@@ -213,11 +234,23 @@ public:
     return _socket;
   }
 
+  bool sasl()
+  {
+    return _sasl;
+  }
+
   void set_socket()
   {
     _socket= true;
   }
 
+  void set_sasl(const std::string& username_arg, const std::string& password_arg)
+  {
+    _sasl= true;
+    _username= username_arg;
+    _password= password_arg;
+  }
+
 
   void shutdown(bool remove= false);
   void push_server(Server *);
index 50234d8d9b1921a47ed821fce4b86959f3cf05a0..ed017b2befe10ff6769435c756544a2381a9513a 100644 (file)
@@ -85,11 +85,18 @@ void SignalThread::test()
 
 SignalThread::~SignalThread()
 {
+  if (not is_shutdown())
+  {
+    set_shutdown(SHUTDOWN_GRACEFUL);
+  }
+
+#if 0
   if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true)
   {
     void *retval;
     pthread_join(thread, &retval);
   }
+#endif
   sem_destroy(&lock);
 }
 
diff --git a/libtest/skiptest.cc b/libtest/skiptest.cc
new file mode 100644 (file)
index 0000000..784f3a8
--- /dev/null
@@ -0,0 +1,48 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <config.h>
+
+#include <libtest/test.hpp>
+
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace libtest;
+
+
+collection_st collection[] ={
+  {0, 0, 0, 0}
+};
+
+static void *world_create(server_startup_st&, test_return_t& rc)
+{
+  rc= TEST_SKIPPED;
+
+  return NULL;
+}
+
+void get_world(Framework *world)
+{
+  world->collections= collection;
+  world->_create= world_create;
+}
index 1ed6157835e79d8ea16cc6ddd3f2e5067ee44b56..5c43e40b35d9f0211d076c19d24c6864fe7dfa59 100644 (file)
@@ -149,10 +149,41 @@ int main(int argc, char *argv[])
 {
   srandom((unsigned int)time(NULL));
 
+  if (getenv("LIBTEST_QUIET"))
+  {
+    close(STDOUT_FILENO);
+  }
+
+  char buffer[1024];
+  if (getenv("LIBTEST_TMP"))
+  {
+    snprintf(buffer, sizeof(buffer), "%s", getenv("LIBTEST_TMP"));
+  }
+  else
+  {
+    snprintf(buffer, sizeof(buffer), "%s", LIBTEST_TEMP);
+  }
+
+  if (chdir(buffer) == -1)
+  {
+    char getcwd_buffer[1024];
+    char *dir= getcwd(getcwd_buffer, sizeof(getcwd_buffer));
+
+    Error << "Unable to chdir() from " << dir << " to " << buffer << " errno:" << strerror(errno);
+    return EXIT_FAILURE;
+  }
+
+  if (libtest::libtool() == NULL)
+  {
+    Error << "Failed to locate libtool";
+    return EXIT_FAILURE;
+  }
+
   world= new Framework();
 
   if (not world)
   {
+    Error << "Failed to create Framework()";
     return EXIT_FAILURE;
   }
 
@@ -182,7 +213,7 @@ int main(int argc, char *argv[])
   case TEST_FATAL:
   case TEST_FAILURE:
   case TEST_MEMORY_ALLOCATION_FAILURE:
-    Error << argv[0] << "create() failed";
+    Error << argv[0] << " failed in Framework::create()";
     delete world;
     return EXIT_FAILURE;
   }
index 3e834b02950c52eb66920a4d77cd34de56501f20..1933ef4b6aa4237e49e1cd9532fa7598d91c4de2 100644 (file)
@@ -30,6 +30,7 @@
 #include <arpa/inet.h>
 
 #include <libtest/visibility.h>
+#include <libtest/version.h>
 
 #include <libtest/error.h>
 #include <libtest/server.h>
index e3272783ca2094b4fc745a7591f349c59e06a920..d2c965bac504641e3b042abab78041f3219855ef 100644 (file)
@@ -113,28 +113,88 @@ static test_return_t local_not_test(void *)
   return TEST_SUCCESS;
 }
 
-#if 0
-static test_return_t pause_test(void *)
+static test_return_t var_exists_test(void *)
 {
-  (void)getchar();
+  test_compare(0, access("var", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_tmp_exists_test(void *)
+{
+  test_compare(0, access("var/tmp", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_run_exists_test(void *)
+{
+  test_compare(0, access("var/run", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_log_exists_test(void *)
+{
+  test_compare(0, access("var/log", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_tmp_test(void *)
+{
+  FILE *file= fopen("var/tmp/junk", "w+");
+  char buffer[1024];
+  const char *dir= getcwd(buffer, sizeof(buffer));
+  test_true_got(file, dir);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_run_test(void *)
+{
+  FILE *file= fopen("var/run/junk", "w+");
+  test_true(file);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_log_test(void *)
+{
+  FILE *file= fopen("var/log/junk", "w+");
+  test_true(file);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_tmp_rm_test(void *)
+{
+  test_true(unlink("var/tmp/junk") == 0);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_run_rm_test(void *)
+{
+  test_true(unlink("var/run/junk") == 0);
   return TEST_SUCCESS;
 }
-#endif
 
+static test_return_t var_log_rm_test(void *)
+{
+  test_true(unlink("var/log/junk") == 0);
+  return TEST_SUCCESS;
+}
 
 static test_return_t gearmand_cycle_test(void *object)
 {
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-#ifndef HAVE_LIBGEARMAN
-  return TEST_SKIPPED;
-#endif
+  if (HAVE_LIBGEARMAN)
+  {
+    const char *argv[1]= { "cycle_gearmand" };
+    test_true(server_startup(*servers, "gearmand", 9999, 1, argv));
 
-  const char *argv[1]= { "cycle_gearmand" };
-  test_true(server_startup(*servers, "gearmand", 9999, 1, argv));
+    return TEST_SUCCESS;
+  }
 
-  return TEST_SUCCESS;
+  return TEST_SKIPPED;
 }
 
 static test_return_t memcached_cycle_test(void *object)
@@ -142,14 +202,15 @@ static test_return_t memcached_cycle_test(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-#if !defined(MEMCACHED_BINARY) || !defined(HAVE_LIBMEMCACHED)
-  return TEST_SKIPPED;
-#endif
+  if (MEMCACHED_BINARY and HAVE_LIBMEMCACHED) 
+  {
+    const char *argv[1]= { "cycle_memcached" };
+    test_true(server_startup(*servers, "memcached", 9998, 1, argv));
 
-  const char *argv[1]= { "cycle_memcached" };
-  test_true(server_startup(*servers, "memcached", 9998, 1, argv));
+    return TEST_SUCCESS;
+  }
 
-  return TEST_SUCCESS;
+  return TEST_SKIPPED;
 }
 
 static test_return_t memcached_socket_cycle_test(void *object)
@@ -157,14 +218,15 @@ static test_return_t memcached_socket_cycle_test(void *object)
   server_startup_st *servers= (server_startup_st*)object;
   test_true(servers);
 
-#if !defined(MEMCACHED_BINARY) || !defined(HAVE_LIBMEMCACHED)
-  return TEST_SKIPPED;
-#endif
+  if (MEMCACHED_BINARY and HAVE_LIBMEMCACHED)
+  {
+    const char *argv[1]= { "cycle_memcached" };
+    test_true(servers->start_socket_server("memcached", 9997, 1, argv));
 
-  const char *argv[1]= { "cycle_memcached" };
-  test_true(servers->start_socket_server("memcached", 9997, 1, argv));
+    return TEST_SUCCESS;
+  }
 
-  return TEST_SUCCESS;
+  return TEST_SKIPPED;
 }
 
 test_st gearmand_tests[] ={
@@ -201,10 +263,25 @@ test_st local_log[] ={
   {0, 0, 0}
 };
 
+test_st directories_tests[] ={
+  {"var exists", 0, var_exists_test },
+  {"var/tmp exists", 0, var_tmp_exists_test },
+  {"var/run exists", 0, var_run_exists_test },
+  {"var/log exists", 0, var_log_exists_test },
+  {"var/tmp", 0, var_tmp_test },
+  {"var/run", 0, var_run_test },
+  {"var/log", 0, var_log_test },
+  {"var/tmp rm", 0, var_tmp_rm_test },
+  {"var/run rm", 0, var_run_rm_test },
+  {"var/log rm", 0, var_log_rm_test },
+  {0, 0, 0}
+};
+
 collection_st collection[] ={
   {"environment", 0, 0, environment_tests},
   {"return values", 0, 0, tests_log},
   {"local", 0, 0, local_log},
+  {"directories", 0, 0, directories_tests},
   {"gearmand", 0, 0, gearmand_tests},
   {"memcached", 0, 0, memcached_tests},
   {0, 0, 0, 0}
diff --git a/libtest/version.h.in b/libtest/version.h.in
new file mode 100644 (file)
index 0000000..a670a2e
--- /dev/null
@@ -0,0 +1,37 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LIBTEST@_WITH_LIBMEMCACHED_SUPPORT@
+#define LIBTEST@_WITH_LIBGEARMAN_SUPPORT@
+
+#define LIBTEST_VERSION_STRING "@VERSION@"
+#define LIBTEST_VERSION_HEX @HEX_VERSION@
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/m4/acx_pthread.m4 b/m4/acx_pthread.m4
deleted file mode 100644 (file)
index 0a86dff..0000000
+++ /dev/null
@@ -1,271 +0,0 @@
-# ===========================================================================
-#              http://autoconf-archive.cryp.to/acx_pthread.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
-#
-# DESCRIPTION
-#
-#   This macro figures out how to build C programs using POSIX threads. It
-#   sets the PTHREAD_LIBS output variable to the threads library and linker
-#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler
-#   flags that are needed. (The user can also force certain compiler
-#   flags/libs to be tested by setting these environment variables.)
-#
-#   Also sets PTHREAD_CC to any special C compiler that is needed for
-#   multi-threaded programs (defaults to the value of CC otherwise). (This
-#   is necessary on AIX to use the special cc_r compiler alias.)
-#
-#   NOTE: You are assumed to not only compile your program with these flags,
-#   but also link it with them as well. e.g. you should link with
-#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
-#
-#   If you are only building threads programs, you may wish to use these
-#   variables in your default LIBS, CFLAGS, and CC:
-#
-#          LIBS="$PTHREAD_LIBS $LIBS"
-#          CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-#          CC="$PTHREAD_CC"
-#
-#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
-#   has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
-#   (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
-#
-#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
-#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
-#   is not found. If ACTION-IF-FOUND is not specified, the default action
-#   will define HAVE_PTHREAD.
-#
-#   Please let the authors know if this macro fails on any platform, or if
-#   you have any other suggestions or comments. This macro was based on work
-#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
-#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
-#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
-#   grateful for the helpful feedback of numerous users.
-#
-# LICENSE
-#
-#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
-#
-#   This program is free software: you can redistribute it and/or modify it
-#   under the terms of the GNU General Public License as published by the
-#   Free Software Foundation, either version 3 of the License, or (at your
-#   option) any later version.
-#
-#   This program is distributed in the hope that it will be useful, but
-#   WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-#   Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License along
-#   with this program. If not, see <http://www.gnu.org/licenses/>.
-#
-#   As a special exception, the respective Autoconf Macro's copyright owner
-#   gives unlimited permission to copy, distribute and modify the configure
-#   scripts that are the output of Autoconf when processing the Macro. You
-#   need not follow the terms of the GNU General Public License when using
-#   or distributing such scripts, even though portions of the text of the
-#   Macro appear in them. The GNU General Public License (GPL) does govern
-#   all other use of the material that constitutes the Autoconf Macro.
-#
-#   This special exception to the GPL applies to versions of the Autoconf
-#   Macro released by the Autoconf Archive. When you make and distribute a
-#   modified version of the Autoconf Macro, you may extend this special
-#   exception to the GPL to apply to your modified version as well.
-
-AC_DEFUN([ACX_PTHREAD], [
-AC_REQUIRE([AC_CANONICAL_HOST])
-AC_LANG_SAVE
-AC_LANG_C
-acx_pthread_ok=no
-
-# We used to check for pthread.h first, but this fails if pthread.h
-# requires special compiler flags (e.g. on True64 or Sequent).
-# It gets checked for in the link test anyway.
-
-# First of all, check if the user has set any of the PTHREAD_LIBS,
-# etcetera environment variables, and if threads linking works using
-# them:
-if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
-        save_CFLAGS="$CFLAGS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-        save_LIBS="$LIBS"
-        LIBS="$PTHREAD_LIBS $LIBS"
-        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
-        AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
-        AC_MSG_RESULT($acx_pthread_ok)
-        if test x"$acx_pthread_ok" = xno; then
-                PTHREAD_LIBS=""
-                PTHREAD_CFLAGS=""
-        fi
-        LIBS="$save_LIBS"
-        CFLAGS="$save_CFLAGS"
-fi
-
-# We must check for the threads library under a number of different
-# names; the ordering is very important because some systems
-# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
-# libraries is broken (non-POSIX).
-
-# Create a list of thread flags to try.  Items starting with a "-" are
-# C compiler flags, and other items are library names, except for "none"
-# which indicates that we try without any flags at all, and "pthread-config"
-# which is a program returning the flags for the Pth emulation library.
-
-acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
-
-# The ordering *is* (sometimes) important.  Some notes on the
-# individual items follow:
-
-# pthreads: AIX (must check this before -lpthread)
-# none: in case threads are in libc; should be tried before -Kthread and
-#       other compiler flags to prevent continual compiler warnings
-# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
-# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
-# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
-# -pthreads: Solaris/gcc
-# -mthreads: Mingw32/gcc, Lynx/gcc
-# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
-#      doesn't hurt to check since this sometimes defines pthreads too;
-#      also defines -D_REENTRANT)
-#      ... -mt is also the pthreads flag for HP/aCC
-# pthread: Linux, etcetera
-# --thread-safe: KAI C++
-# pthread-config: use pthread-config program (for GNU Pth library)
-
-case "${host_cpu}-${host_os}" in
-        *solaris*)
-
-        # On Solaris (at least, for some versions), libc contains stubbed
-        # (non-functional) versions of the pthreads routines, so link-based
-        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
-        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
-        # a function called by this macro, so we could check for that, but
-        # who knows whether they'll stub that too in a future libc.)  So,
-        # we'll just look for -pthreads and -lpthread first:
-
-        acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
-        ;;
-esac
-
-if test x"$acx_pthread_ok" = xno; then
-for flag in $acx_pthread_flags; do
-
-        case $flag in
-                none)
-                AC_MSG_CHECKING([whether pthreads work without any flags])
-                ;;
-
-                -*)
-                AC_MSG_CHECKING([whether pthreads work with $flag])
-                PTHREAD_CFLAGS="$flag"
-                ;;
-
-               pthread-config)
-               AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
-               if test x"$acx_pthread_config" = xno; then continue; fi
-               PTHREAD_CFLAGS="`pthread-config --cflags`"
-               PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
-               ;;
-
-                *)
-                AC_MSG_CHECKING([for the pthreads library -l$flag])
-                PTHREAD_LIBS="-l$flag"
-                ;;
-        esac
-
-        save_LIBS="$LIBS"
-        save_CFLAGS="$CFLAGS"
-        LIBS="$PTHREAD_LIBS $LIBS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-
-        # Check for various functions.  We must include pthread.h,
-        # since some functions may be macros.  (On the Sequent, we
-        # need a special flag -Kthread to make this header compile.)
-        # We check for pthread_join because it is in -lpthread on IRIX
-        # while pthread_create is in libc.  We check for pthread_attr_init
-        # due to DEC craziness with -lpthreads.  We check for
-        # pthread_cleanup_push because it is one of the few pthread
-        # functions on Solaris that doesn't have a non-functional libc stub.
-        # We try pthread_create on general principles.
-        AC_TRY_LINK([#include <pthread.h>],
-                    [pthread_t th; pthread_join(th, 0);
-                     pthread_attr_init(0); pthread_cleanup_push(0, 0);
-                     pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
-                    [acx_pthread_ok=yes])
-
-        LIBS="$save_LIBS"
-        CFLAGS="$save_CFLAGS"
-
-        AC_MSG_RESULT($acx_pthread_ok)
-        if test "x$acx_pthread_ok" = xyes; then
-                break;
-        fi
-
-        PTHREAD_LIBS=""
-        PTHREAD_CFLAGS=""
-done
-fi
-
-# Various other checks:
-if test "x$acx_pthread_ok" = xyes; then
-        save_LIBS="$LIBS"
-        LIBS="$PTHREAD_LIBS $LIBS"
-        save_CFLAGS="$CFLAGS"
-        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-
-        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
-       AC_MSG_CHECKING([for joinable pthread attribute])
-       attr_name=unknown
-       for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
-           AC_TRY_LINK([#include <pthread.h>], [int attr=$attr; return attr;],
-                        [attr_name=$attr; break])
-       done
-        AC_MSG_RESULT($attr_name)
-        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
-            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
-                               [Define to necessary symbol if this constant
-                                uses a non-standard name on your system.])
-        fi
-
-        AC_MSG_CHECKING([if more special flags are required for pthreads])
-        flag=no
-        case "${host_cpu}-${host_os}" in
-            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
-            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
-        esac
-        AC_MSG_RESULT(${flag})
-        if test "x$flag" != xno; then
-            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
-        fi
-
-        LIBS="$save_LIBS"
-        CFLAGS="$save_CFLAGS"
-
-        # More AIX lossage: must compile with xlc_r or cc_r
-       if test x"$GCC" != xyes; then
-          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
-        else
-          PTHREAD_CC=$CC
-       fi
-else
-        PTHREAD_CC="$CC"
-fi
-
-AC_SUBST(PTHREAD_LIBS)
-AC_SUBST(PTHREAD_CFLAGS)
-AC_SUBST(PTHREAD_CC)
-
-# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
-if test x"$acx_pthread_ok" = xyes; then
-        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
-        :
-else
-        acx_pthread_ok=no
-        $2
-fi
-AC_LANG_RESTORE
-])dnl ACX_PTHREAD
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
new file mode 100644 (file)
index 0000000..a6bf596
--- /dev/null
@@ -0,0 +1,302 @@
+# ===========================================================================
+#        http://www.gnu.org/software/autoconf-archive/ax_pthread.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+#
+# DESCRIPTION
+#
+#   This macro figures out how to build C programs using POSIX threads. It
+#   sets the PTHREAD_LIBS output variable to the threads library and linker
+#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler
+#   flags that are needed. (The user can also force certain compiler
+#   flags/libs to be tested by setting these environment variables.)
+#
+#   Also sets PTHREAD_CC to any special C compiler that is needed for
+#   multi-threaded programs (defaults to the value of CC otherwise). (This
+#   is necessary on AIX to use the special cc_r compiler alias.)
+#
+#   NOTE: You are assumed to not only compile your program with these flags,
+#   but also link it with them as well. e.g. you should link with
+#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
+#
+#   If you are only building threads programs, you may wish to use these
+#   variables in your default LIBS, CFLAGS, and CC:
+#
+#     LIBS="$PTHREAD_LIBS $LIBS"
+#     CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+#     CC="$PTHREAD_CC"
+#
+#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
+#   has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
+#   (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
+#
+#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
+#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
+#   PTHREAD_CFLAGS.
+#
+#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
+#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
+#   is not found. If ACTION-IF-FOUND is not specified, the default action
+#   will define HAVE_PTHREAD.
+#
+#   Please let the authors know if this macro fails on any platform, or if
+#   you have any other suggestions or comments. This macro was based on work
+#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
+#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
+#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
+#   grateful for the helpful feedback of numerous users.
+#
+#   Updated for Autoconf 2.68 by Daniel Richard G.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
+#   Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
+#
+#   This program is free software: you can redistribute it and/or modify it
+#   under the terms of the GNU General Public License as published by the
+#   Free Software Foundation, either version 3 of the License, or (at your
+#   option) any later version.
+#
+#   This program is distributed in the hope that it will be useful, but
+#   WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+#   Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License along
+#   with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+#   As a special exception, the respective Autoconf Macro's copyright owner
+#   gives unlimited permission to copy, distribute and modify the configure
+#   scripts that are the output of Autoconf when processing the Macro. You
+#   need not follow the terms of the GNU General Public License when using
+#   or distributing such scripts, even though portions of the text of the
+#   Macro appear in them. The GNU General Public License (GPL) does govern
+#   all other use of the material that constitutes the Autoconf Macro.
+#
+#   This special exception to the GPL applies to versions of the Autoconf
+#   Macro released by the Autoconf Archive. When you make and distribute a
+#   modified version of the Autoconf Macro, you may extend this special
+#   exception to the GPL to apply to your modified version as well.
+
+#serial 16
+
+AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
+AC_DEFUN([AX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PUSH([C])
+ax_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+        AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes)
+        AC_MSG_RESULT($ax_pthread_ok)
+        if test x"$ax_pthread_ok" = xno; then
+                PTHREAD_LIBS=""
+                PTHREAD_CFLAGS=""
+        fi
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try.  Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all, and "pthread-config"
+# which is a program returning the flags for the Pth emulation library.
+
+ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
+
+# The ordering *is* (sometimes) important.  Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+#       other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+#      doesn't hurt to check since this sometimes defines pthreads too;
+#      also defines -D_REENTRANT)
+#      ... -mt is also the pthreads flag for HP/aCC
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+# pthread-config: use pthread-config program (for GNU Pth library)
+
+case "${host_cpu}-${host_os}" in
+        *solaris*)
+
+        # On Solaris (at least, for some versions), libc contains stubbed
+        # (non-functional) versions of the pthreads routines, so link-based
+        # tests will erroneously succeed.  (We need to link with -pthreads/-mt/
+        # -lpthread.)  (The stubs are missing pthread_cleanup_push, or rather
+        # a function called by this macro, so we could check for that, but
+        # who knows whether they'll stub that too in a future libc.)  So,
+        # we'll just look for -pthreads and -lpthread first:
+
+        ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
+        ;;
+
+        *-darwin*)
+        ax_pthread_flags="-pthread $ax_pthread_flags"
+        ;;
+esac
+
+if test x"$ax_pthread_ok" = xno; then
+for flag in $ax_pthread_flags; do
+
+        case $flag in
+                none)
+                AC_MSG_CHECKING([whether pthreads work without any flags])
+                ;;
+
+                -*)
+                AC_MSG_CHECKING([whether pthreads work with $flag])
+                PTHREAD_CFLAGS="$flag"
+                ;;
+
+                pthread-config)
+                AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no)
+                if test x"$ax_pthread_config" = xno; then continue; fi
+                PTHREAD_CFLAGS="`pthread-config --cflags`"
+                PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
+                ;;
+
+                *)
+                AC_MSG_CHECKING([for the pthreads library -l$flag])
+                PTHREAD_LIBS="-l$flag"
+                ;;
+        esac
+
+        save_LIBS="$LIBS"
+        save_CFLAGS="$CFLAGS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Check for various functions.  We must include pthread.h,
+        # since some functions may be macros.  (On the Sequent, we
+        # need a special flag -Kthread to make this header compile.)
+        # We check for pthread_join because it is in -lpthread on IRIX
+        # while pthread_create is in libc.  We check for pthread_attr_init
+        # due to DEC craziness with -lpthreads.  We check for
+        # pthread_cleanup_push because it is one of the few pthread
+        # functions on Solaris that doesn't have a non-functional libc stub.
+        # We try pthread_create on general principles.
+        AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
+                        static void routine(void *a) { a = 0; }
+                        static void *start_routine(void *a) { return a; }],
+                       [pthread_t th; pthread_attr_t attr;
+                        pthread_create(&th, 0, start_routine, 0);
+                        pthread_join(th, 0);
+                        pthread_attr_init(&attr);
+                        pthread_cleanup_push(routine, 0);
+                        pthread_cleanup_pop(0) /* ; */])],
+                [ax_pthread_ok=yes],
+                [])
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        AC_MSG_RESULT($ax_pthread_ok)
+        if test "x$ax_pthread_ok" = xyes; then
+                break;
+        fi
+
+        PTHREAD_LIBS=""
+        PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$ax_pthread_ok" = xyes; then
+        save_LIBS="$LIBS"
+        LIBS="$PTHREAD_LIBS $LIBS"
+        save_CFLAGS="$CFLAGS"
+        CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+        # Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
+        AC_MSG_CHECKING([for joinable pthread attribute])
+        attr_name=unknown
+        for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
+            AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
+                           [int attr = $attr; return attr /* ; */])],
+                [attr_name=$attr; break],
+                [])
+        done
+        AC_MSG_RESULT($attr_name)
+        if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
+            AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
+                               [Define to necessary symbol if this constant
+                                uses a non-standard name on your system.])
+        fi
+
+        AC_MSG_CHECKING([if more special flags are required for pthreads])
+        flag=no
+        case "${host_cpu}-${host_os}" in
+            *-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
+            *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+        esac
+        AC_MSG_RESULT(${flag})
+        if test "x$flag" != xno; then
+            PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+        fi
+
+        AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
+            ax_cv_PTHREAD_PRIO_INHERIT, [
+                AC_LINK_IFELSE([
+                    AC_LANG_PROGRAM([[#include <pthread.h>]], [[int i = PTHREAD_PRIO_INHERIT;]])],
+                    [ax_cv_PTHREAD_PRIO_INHERIT=yes],
+                    [ax_cv_PTHREAD_PRIO_INHERIT=no])
+            ])
+        AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
+            AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.]))
+
+        LIBS="$save_LIBS"
+        CFLAGS="$save_CFLAGS"
+
+        # More AIX lossage: must compile with xlc_r or cc_r
+        if test x"$GCC" != xyes; then
+          AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
+        else
+          PTHREAD_CC=$CC
+        fi
+else
+        PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$ax_pthread_ok" = xyes; then
+        ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+        :
+else
+        ax_pthread_ok=no
+        $2
+fi
+AC_LANG_POP
+])dnl AX_PTHREAD
diff --git a/m4/ax_with_prog.m4 b/m4/ax_with_prog.m4
new file mode 100644 (file)
index 0000000..f337c05
--- /dev/null
@@ -0,0 +1,70 @@
+# ===========================================================================
+#       http://www.gnu.org/software/autoconf-archive/ax_with_prog.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_WITH_PROG([VARIABLE],[program],[VALUE-IF-NOT-FOUND],[PATH])
+#
+# DESCRIPTION
+#
+#   Locates an installed program binary, placing the result in the precious
+#   variable VARIABLE. Accepts a present VARIABLE, then --with-program, and
+#   failing that searches for program in the given path (which defaults to
+#   the system path). If program is found, VARIABLE is set to the full path
+#   of the binary; if it is not found VARIABLE is set to VALUE-IF-NOT-FOUND
+#   if provided, unchanged otherwise.
+#
+#   A typical example could be the following one:
+#
+#     AX_WITH_PROG(PERL,perl)
+#
+#   NOTE: This macro is based upon the original AX_WITH_PYTHON macro from
+#   Dustin J. Mitchell <dustin@cs.uchicago.edu>.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Francesco Salvestrini <salvestrini@users.sourceforge.net>
+#   Copyright (c) 2008 Dustin J. Mitchell <dustin@cs.uchicago.edu>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 16
+
+AC_DEFUN([AX_WITH_PROG],[
+    AC_PREREQ([2.61])
+
+    pushdef([VARIABLE],$1)
+    pushdef([EXECUTABLE],$2)
+    pushdef([VALUE_IF_NOT_FOUND],$3)
+    pushdef([PATH_PROG],$4)
+
+    AC_ARG_VAR(VARIABLE,Absolute path to EXECUTABLE executable)
+
+    AS_IF(test -z "$VARIABLE",[
+        AC_MSG_CHECKING(whether EXECUTABLE executable path has been provided)
+        AC_ARG_WITH(EXECUTABLE,AS_HELP_STRING([--with-EXECUTABLE=[[[PATH]]]],absolute path to EXECUTABLE executable), [
+            AS_IF([test "$withval" != yes && test "$withval" != no],[
+                VARIABLE="$withval"
+                AC_MSG_RESULT($VARIABLE)
+            ],[
+                VARIABLE=""
+                AC_MSG_RESULT([no])
+                AS_IF([test "$withval" != no], [
+                  AC_PATH_PROG([]VARIABLE[],[]EXECUTABLE[],[]VALUE_IF_NOT_FOUND[],[]PATH_PROG[])
+                ])
+            ])
+        ],[
+            AC_MSG_RESULT([no])
+            AC_PATH_PROG([]VARIABLE[],[]EXECUTABLE[],[]VALUE_IF_NOT_FOUND[],[]PATH_PROG[])
+        ])
+    ])
+
+    popdef([PATH_PROG])
+    popdef([VALUE_IF_NOT_FOUND])
+    popdef([EXECUTABLE])
+    popdef([VARIABLE])
+])
index d77922d3473ba1ff7a96924222a66b9ea3edd7b9..e9730f1b9f866f5171f9218390a8ec2c2f466e98 100644 (file)
@@ -6,7 +6,7 @@ AC_DEFUN([ENABLE_UTILLIB],[
     [BUILD_UTILLIB="yes"])
 
   if test "x$BUILD_UTILLIB" = "xyes"; then
-    if test x"$acx_pthread_ok" != "xyes"; then
+    if test x"$ax_pthread_ok" != "xyes"; then
       AC_MSG_ERROR([Sorry you need POSIX thread library to build libmemcachedutil.])
     fi
     AC_DEFINE([HAVE_LIBMEMCACHEDUTIL], [1], [Enables libmemcachedutil Support])
diff --git a/m4/libgearmand.m4 b/m4/libgearmand.m4
deleted file mode 100644 (file)
index c90d02f..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-AC_DEFUN([_WITH_LIBGEARMAN],
-  [ AC_ARG_ENABLE([libgearman],
-   [AS_HELP_STRING([--disable-libgearman],
-     [Build with libgearman support @<:@default=on@:>@])],
-     [ac_enable_libgearman="$enableval"],
-     [ac_enable_libgearman="yes"])
-
-     AS_IF([test "x$ac_enable_libgearman" = "xyes"],
-       [ PKG_CHECK_MODULES([libgearman], [ libgearman >= 0.24 ], 
-                          [AC_DEFINE([HAVE_LIBGEARMAN], [ 1 ], [Enable libgearman support])],
-                          [ac_enable_libgearman="no"] )])
-
-     AM_CONDITIONAL(HAVE_LIBGEARMAN, test "x${ac_enable_libgearman}" = "xyes")
-     ])
-
-AC_DEFUN([WITH_LIBGEARMAN], [ AC_REQUIRE([_WITH_LIBGEARMAN]) ])
index 010fb42900de16b05c07b0572a062b4e74d29ed6..0b8592fe546f14657c9d7081d90faa4b63b6a3a4 100644 (file)
@@ -1,31 +1,8 @@
-AC_DEFUN([WITH_MEMCACHED],
-  [AC_ARG_WITH([memcached],
-    [AS_HELP_STRING([--with-memcached],
-      [Memcached binary to use for make test])],
-    [ac_cv_with_memcached="$withval"],
-    [ac_cv_with_memcached=memcached])
-
-  # just ignore the user if --without-memcached is passed.. it is
-  # only used by make test
-  AS_IF([test "x$withval" = "xno"],
-    [
-      ac_cv_with_memcached=memcached
-      MEMC_BINARY=memcached
-    ],
-    [
-       AS_IF([test -f "$withval"],
-         [
-           ac_cv_with_memcached=$withval
-           MEMC_BINARY=$withval
-         ],
-         [
-           AC_PATH_PROG([MEMC_BINARY], [$ac_cv_with_memcached], "no")
-           AS_IF([test "x$MEMC_BINARY" = "xno"],
-             AC_MSG_ERROR(["could not find memcached binary"]))
-         ])
-    ])
-
-  AC_DEFINE_UNQUOTED([MEMCACHED_BINARY], "$MEMC_BINARY",
-            [Name of the memcached binary used in make test])
-  AC_SUBST(MEMC_BINARY)
-])
+AX_WITH_PROG(MEMCACHED_BINARY,memcached)
+AS_IF([test -f "$ac_cv_path_MEMCACHED_BINARY"],
+      [
+        AC_DEFINE_UNQUOTED([MEMCACHED_BINARY], "$ac_cv_path_MEMCACHED_BINARY", [Name of the memcached binary used in make test])
+       ],
+       [
+        AC_DEFINE([MEMCACHED_BINARY], [0], [Name of the memcached binary used in make test])
+      ])
diff --git a/m4/memcached_sasl.m4 b/m4/memcached_sasl.m4
new file mode 100644 (file)
index 0000000..5983c11
--- /dev/null
@@ -0,0 +1,8 @@
+AX_WITH_PROG(MEMCACHED_SASL_BINARY,memcached_sasl)
+AS_IF([test -f "$ac_cv_path_MEMCACHED_SASL_BINARY"],
+      [
+        AC_DEFINE_UNQUOTED([MEMCACHED_SASL_BINARY], "$ac_cv_path_MEMCACHED_SASL_BINARY", [Name of the memcached_sasl binary used in make test])
+       ],
+       [
+        AC_DEFINE([MEMCACHED_SASL_BINARY], [0], [Name of the memcached_sasl binary used in make test])
+      ])
diff --git a/m4/pandora_have_protobuf.m4 b/m4/pandora_have_protobuf.m4
deleted file mode 100644 (file)
index 47f4cd4..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-dnl -*- mode: m4; c-basic-offset: 2; indent-tabs-mode: nil; -*-
-dnl vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
-dnl   
-dnl pandora-build: A pedantic build system
-dnl Copyright (C) 2009 Sun Microsystems, Inc.
-dnl This file is free software; Sun Microsystems
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-dnl
-dnl From Monty Taylor
-
-dnl --------------------------------------------------------------------
-dnl  Check for Google Proto Buffers
-dnl --------------------------------------------------------------------
-
-AC_DEFUN([_PANDORA_SEARCH_LIBPROTOBUF],[
-  AC_REQUIRE([PANDORA_HAVE_PTHREAD])
-
-  AC_LANG_PUSH([C++])
-  save_CXXFLAGS="${CXXFLAGS}"
-  CXXFLAGS="${PTHREAD_CFLAGS} ${CXXFLAGS}"
-  AC_LIB_HAVE_LINKFLAGS(protobuf,,
-    [#include <google/protobuf/descriptor.h>],
-    [google::protobuf::FileDescriptor* file;],
-    [system])
-  CXXFLAGS="${PTHREAD_CFLAGS} ${save_CXXFLAGS}"
-  LIBPROTOBUF="${LIBPROTOBUF} ${PTHREAD_LIBS}"
-  LTLIBPROTOBUF="${LTLIBPROTOBUF} ${PTHREAD_LIBS}"
-  AC_LANG_POP()
-])
-
-AC_DEFUN([PANDORA_HAVE_LIBPROTOBUF],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBPROTOBUF])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_LIBPROTOBUF],[
-  AC_REQUIRE([PANDORA_HAVE_LIBPROTOBUF])
-  AS_IF([test x$ac_cv_libprotobuf = xno],
-      AC_MSG_ERROR([libprotobuf is required for ${PACKAGE}. On Debian this can be found in libprotobuf-dev. On RedHat this can be found in protobuf-devel.]))
-])
-
-AC_DEFUN([PANDORA_PROTOBUF_REQUIRE_VERSION],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBPROTOBUF])
-  p_recent_ver=$1
-  p_recent_ver_major=`echo $p_recent_ver | cut -f1 -d.`
-  p_recent_ver_minor=`echo $p_recent_ver | cut -f2 -d.`
-  p_recent_ver_patch=`echo $p_recent_ver | cut -f3 -d.`
-  p_recent_ver_hex=`printf "%d%03d%03d" $p_recent_ver_major $p_recent_ver_minor $p_recent_ver_patch` 
-  AC_LANG_PUSH([C++])
-  AC_CACHE_CHECK([for protobuf >= $p_recent_ver],
-    [drizzle_cv_protobuf_recent],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#include <google/protobuf/descriptor.h>
-#if GOOGLE_PROTOBUF_VERSION < $p_recent_ver_hex
-# error Your version of Protobuf is too old
-#endif
-      ]])],
-    [drizzle_cv_protobuf_recent=yes],
-    [drizzle_cv_protobuf_recent=no])])
-  AS_IF([test "$drizzle_cv_protobuf_recent" = "no"],[
-    AC_MSG_ERROR([Your version of Google Protocol Buffers is too old. ${PACKAGE} requires at least version $p_recent_ver])
-  ])
-  AC_LANG_POP()
-])
-
-AC_DEFUN([_PANDORA_SEARCH_PROTOC],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBPROTOBUF])
-  AC_PATH_PROG([PROTOC],[protoc],[no],[$LIBPROTOBUF_PREFIX/bin:$PATH])
-])
-
-AC_DEFUN([PANDORA_HAVE_PROTOC],[
-  AC_REQUIRE([_PANDORA_SEARCH_PROTOC])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_PROTOC],[
-  AC_REQUIRE([PANDORA_HAVE_PROTOC])
-  AS_IF([test "x$PROTOC" = "xno"],[
-    AC_MSG_ERROR([Couldn't find the protoc compiler. On Debian this can be found in protobuf-compiler. On RedHat this can be found in protobuf-compiler.])
-  ])
-])
-
-
diff --git a/m4/pandora_pthread.m4 b/m4/pandora_pthread.m4
deleted file mode 100644 (file)
index a411116..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-dnl -*- mode: m4; c-basic-offset: 2; indent-tabs-mode: nil; -*-
-dnl vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
-dnl   
-dnl pandora-build: A pedantic build system
-dnl Copyright (C) 2009 Sun Microsystems, Inc.
-dnl This file is free software; Sun Microsystems
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-dnl
-dnl From Monty Taylor
-
-
-dnl --------------------------------------------------------------------
-dnl  Check for libpthread
-dnl --------------------------------------------------------------------
-
-AC_DEFUN([PANDORA_PTHREAD_YIELD],[
-  AC_REQUIRE([ACX_PTHREAD])
-
-  save_CFLAGS="${CFLAGS}"
-  save_CXXFLAGS="${CXXFLAGS}"
-  CFLAGS="${PTHREAD_CFLAGS} ${CFLAGS}"
-  CXXFLAGS="${PTHREAD_CFLAGS} ${CXXFLAGS}"
-  dnl Some OSes like Mac OS X have that as a replacement for pthread_yield()
-  AC_CHECK_FUNCS(pthread_yield_np)
-  AC_CACHE_CHECK([if pthread_yield takes zero arguments],
-    [pandora_cv_pthread_yield_zero_arg],
-    [AC_LINK_IFELSE([
-      AC_LANG_PROGRAM([[
-#include <pthread.h>
-        ]],[[
-  pthread_yield();
-        ]])],
-      [pandora_cv_pthread_yield_zero_arg=yes],
-      [pandora_cv_pthread_yield_zero_arg=no])])
-  AS_IF([test "$pandora_cv_pthread_yield_zero_arg" = "yes"],[
-    AC_DEFINE([HAVE_PTHREAD_YIELD_ZERO_ARG], [1],
-              [pthread_yield that doesn't take any arguments])
-  ])
-
-  AC_CACHE_CHECK([if pthread_yield takes one argument],
-    [pandora_cv_pthread_yield_one_arg],
-    [AC_LINK_IFELSE([
-      AC_LANG_PROGRAM([[
-#include <pthread.h>
-        ]],[[
-  pthread_yield(0);
-        ]])],
-      [pandora_cv_pthread_yield_one_arg=yes],
-      [pandora_cv_pthread_yield_one_arg=no])])
-  AS_IF([test "$pandora_cv_pthread_yield_one_arg" = "yes"],[
-    AC_DEFINE([HAVE_PTHREAD_YIELD_ONE_ARG], [1],
-              [pthread_yield function with one argument])
-  ])
-
-  AC_CHECK_FUNCS(pthread_attr_getstacksize pthread_attr_setprio \
-    pthread_attr_setschedparam \
-    pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
-    pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
-    pthread_setprio_np pthread_setschedparam pthread_sigmask \
-    pthread_attr_create rwlock_init
-)
-
-
-
-# Check definition of pthread_getspecific
-AC_CACHE_CHECK([args to pthread_getspecific], [pandora_cv_getspecific_args],
-  [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#if !defined(_REENTRANT)
-#define _REENTRANT
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS 
-#define _POSIX_PTHREAD_SEMANTICS 
-#endif
-#include <pthread.h>
-   ]], [[
-void *pthread_getspecific(pthread_key_t key);
-pthread_getspecific((pthread_key_t) NULL);
-   ]])],
-    [pandora_cv_getspecific_args=POSIX],
-    [pandora_cv_getspecific_args=other])])
-  if test "$pandora_cv_getspecific_args" = "other"
-  then
-    AC_DEFINE([HAVE_NONPOSIX_PTHREAD_GETSPECIFIC], [1],
-              [For some non posix threads])
-  fi
-
-  # Check definition of pthread_mutex_init
-  AC_CACHE_CHECK([args to pthread_mutex_init], [pandora_cv_mutex_init_args],
-    [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-#ifndef _REENTRANT
-#define _REENTRANT
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-#define _POSIX_PTHREAD_SEMANTICS 
-#endif
-#include <pthread.h> ]], [[ 
-  pthread_mutexattr_t attr;
-  pthread_mutex_t mp;
-  pthread_mutex_init(&mp,&attr); ]])],
-      [pandora_cv_mutex_init_args=POSIX],
-      [pandora_cv_mutex_init_args=other])])
-  if test "$pandora_cv_mutex_init_args" = "other"
-  then
-    AC_DEFINE([HAVE_NONPOSIX_PTHREAD_MUTEX_INIT], [1],
-              [For some non posix threads])
-  fi
-#---END:
-
-#---START: Used in for client configure
-# Check definition of readdir_r
-AC_CACHE_CHECK([args to readdir_r], [pandora_cv_readdir_r],
-  [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#ifndef _REENTRANT
-#define _REENTRANT
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS 
-#define _POSIX_PTHREAD_SEMANTICS 
-#endif
-#include <pthread.h>
-#include <dirent.h>]], [[ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
-readdir_r((DIR *) NULL, (struct dirent *) NULL, (struct dirent **) NULL); ]])],
-    [pandora_cv_readdir_r=POSIX],
-    [pandora_cv_readdir_r=other])])
-if test "$pandora_cv_readdir_r" = "POSIX"
-then
-  AC_DEFINE([HAVE_READDIR_R], [1], [POSIX readdir_r])
-fi
-
-# Check definition of posix sigwait()
-AC_CACHE_CHECK([style of sigwait], [pandora_cv_sigwait],
-  [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#ifndef _REENTRANT
-#define _REENTRANT
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-#define _POSIX_PTHREAD_SEMANTICS 
-#endif
-#include <pthread.h>
-#include <signal.h>
-      ]], [[
-#ifndef _AIX
-sigset_t set;
-int sig;
-sigwait(&set,&sig);
-#endif
-      ]])],
-    [pandora_cv_sigwait=POSIX],
-    [pandora_cv_sigwait=other])])
-if test "$pandora_cv_sigwait" = "POSIX"
-then
-  AC_DEFINE([HAVE_SIGWAIT], [1], [POSIX sigwait])
-fi
-
-if test "$pandora_cv_sigwait" != "POSIX"
-then
-unset pandora_cv_sigwait
-# Check definition of posix sigwait()
-AC_CACHE_CHECK([style of sigwait], [pandora_cv_sigwait],
-  [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#ifndef _REENTRANT
-#define _REENTRANT
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-#define _POSIX_PTHREAD_SEMANTICS 
-#endif
-#include <pthread.h>
-#include <signal.h>
-      ]], [[
-sigset_t set;
-int sig;
-sigwait(&set);
-      ]])],
-    [pandora_cv_sigwait=NONPOSIX],
-    [pandora_cv_sigwait=other])])
-if test "$pandora_cv_sigwait" = "NONPOSIX"
-then
-  AC_DEFINE([HAVE_NONPOSIX_SIGWAIT], [1], [sigwait with one argument])
-fi
-fi
-#---END:
-
-# Check if pthread_attr_setscope() exists
-AC_CACHE_CHECK([for pthread_attr_setscope], [pandora_cv_pthread_attr_setscope],
-  [AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#ifndef _REENTRANT
-#define _REENTRANT
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-#define _POSIX_PTHREAD_SEMANTICS 
-#endif
-#include <pthread.h>
-      ]], [[
-pthread_attr_t thr_attr;
-pthread_attr_setscope(&thr_attr,0);
-      ]])],
-    [pandora_cv_pthread_attr_setscope=yes],
-    [pandora_cv_pthread_attr_setscope=no])])
-if test "$pandora_cv_pthread_attr_setscope" = "yes"
-then
-  AC_DEFINE([HAVE_PTHREAD_ATTR_SETSCOPE], [1], [pthread_attr_setscope])
-fi
-
-
-AC_CACHE_CHECK([if pthread_yield takes zero arguments], ac_cv_pthread_yield_zero_arg,
-[AC_TRY_LINK([#define _GNU_SOURCE
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[
-  pthread_yield();
-], ac_cv_pthread_yield_zero_arg=yes, ac_cv_pthread_yield_zero_arg=yeso)])
-if test "$ac_cv_pthread_yield_zero_arg" = "yes"
-then
-  AC_DEFINE([HAVE_PTHREAD_YIELD_ZERO_ARG], [1],
-            [pthread_yield that doesn't take any arguments])
-fi
-AC_CACHE_CHECK([if pthread_yield takes 1 argument], ac_cv_pthread_yield_one_arg,
-[AC_TRY_LINK([#define _GNU_SOURCE
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[
-  pthread_yield(0);
-], ac_cv_pthread_yield_one_arg=yes, ac_cv_pthread_yield_one_arg=no)])
-if test "$ac_cv_pthread_yield_one_arg" = "yes"
-then
-  AC_DEFINE([HAVE_PTHREAD_YIELD_ONE_ARG], [1],
-            [pthread_yield function with one argument])
-fi
-
-  CFLAGS="${save_CFLAGS}"
-  CXXFLAGS="${save_CXXFLAGS}"
-])
-
-
-AC_DEFUN([_PANDORA_SEARCH_PTHREAD],[
-  AC_REQUIRE([ACX_PTHREAD])
-  LIBS="${PTHREAD_LIBS} ${LIBS}"
-  AM_CFLAGS="${PTHREAD_CFLAGS} ${AM_CFLAGS}"
-  AM_CXXFLAGS="${PTHREAD_CFLAGS} ${AM_CXXFLAGS}"
-  PANDORA_PTHREAD_YIELD
-])
-
-
-AC_DEFUN([PANDORA_HAVE_PTHREAD],[
-  AC_REQUIRE([_PANDORA_SEARCH_PTHREAD])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_PTHREAD],[
-  AC_REQUIRE([PANDORA_HAVE_PTHREAD])
-  AS_IF([test "x$acx_pthread_ok" != "xyes"],[
-    AC_MSG_ERROR(could not find libpthread)])
-])
diff --git a/m4/pandora_sasl.m4 b/m4/pandora_sasl.m4
deleted file mode 100644 (file)
index ca4a21d..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-dnl  Copyright (C) 2009 Sun Microsystems, Inc.
-dnl This file is free software; Sun Microsystems, Inc.
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_SASL],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for sasl
-  dnl --------------------------------------------------------------------
-  AC_ARG_ENABLE([sasl],
-    [AS_HELP_STRING([--disable-sasl],
-      [Build with sasl support @<:@default=on@:>@])],
-    [ac_enable_sasl="$enableval"],
-    [ac_enable_sasl="yes"])
-
-  AS_IF([test "x$ac_enable_sasl" = "xyes"],
-    [
-      AC_LIB_HAVE_LINKFLAGS(sasl,,[
-        #include <stdlib.h>
-        #include <sasl/sasl.h>
-      ],[
-        sasl_server_init(NULL, NULL);
-      ])
-
-      AS_IF([test "x${ac_cv_libsasl}" != "xyes" ],
-            [
-              AC_LIB_HAVE_LINKFLAGS(sasl2,,[
-                #include <stdlib.h>
-                #include <sasl/sasl.h>
-              ],[
-                sasl_server_init(NULL, NULL);
-              ])
-              HAVE_LIBSASL="$HAVE_LIBSASL2"
-              LIBSASL="$LIBSASL2"
-              LIBSASL_PREFIX="$LIBSASL2_PREFIX"
-             LTLIBSASL="$LT_LIBSASL2"
-            ])
-    ])
-
-  AS_IF([test "x${ac_cv_libsasl}" = "xyes" -o "x${ac_cv_libsasl2}" = "xyes"],
-        [ac_cv_sasl=yes],
-        [ac_cv_sasl=no])
-
-  AM_CONDITIONAL(HAVE_LIBSASL, [test "x${ac_cv_libsasl}" = "xyes"])
-  AM_CONDITIONAL(HAVE_LIBSASL2, [test "x${ac_cv_libsasl2}" = "xyes"])
-  AM_CONDITIONAL(HAVE_SASL, [test "x${ac_cv_sasl}" = "xyes"])
-])
-
-AC_DEFUN([PANDORA_HAVE_SASL],[
-  AC_REQUIRE([_PANDORA_SEARCH_SASL])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_SASL],[
-  AC_REQUIRE([_PANDORA_SEARCH_SASL])
-  AS_IF([test "x${ac_cv_sasl}" = "xno"],
-    AC_MSG_ERROR([SASL (libsasl or libsasl2) is required for ${PACKAGE}]))
-])
-
-AC_DEFUN([_PANDORA_SEARCH_LIBSASL],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for libsasl
-  dnl --------------------------------------------------------------------
-
-  AC_ARG_ENABLE([libsasl],
-    [AS_HELP_STRING([--disable-libsasl],
-      [Build with libsasl support @<:@default=on@:>@])],
-    [ac_enable_libsasl="$enableval"],
-    [ac_enable_libsasl="yes"])
-
-  AS_IF([test "x$ac_enable_libsasl" = "xyes"],[
-    AC_LIB_HAVE_LINKFLAGS(sasl,,[
-      #include <stdlib.h>
-      #include <sasl/sasl.h>
-    ],[
-      sasl_server_init(NULL, NULL);
-    ])
-  ],[
-    ac_cv_libsasl="no"
-  ])
-
-  AM_CONDITIONAL(HAVE_LIBSASL, [test "x${ac_cv_libsasl}" = "xyes"])
-])
-
-AC_DEFUN([PANDORA_HAVE_LIBSASL],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBSASL])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_LIBSASL],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBSASL])
-  AS_IF([test "x${ac_cv_libsasl}" = "xno"],
-    AC_MSG_ERROR([libsasl is required for ${PACKAGE}]))
-])
-
-AC_DEFUN([_PANDORA_SEARCH_LIBSASL2],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for libsasl2
-  dnl --------------------------------------------------------------------
-
-  AC_ARG_ENABLE([libsasl2],
-    [AS_HELP_STRING([--disable-libsasl2],
-      [Build with libsasl2 support @<:@default=on@:>@])],
-    [ac_enable_libsasl2="$enableval"],
-    [ac_enable_libsasl2="yes"])
-
-  AS_IF([test "x$ac_enable_libsasl2" = "xyes"],[
-    AC_LIB_HAVE_LINKFLAGS(sasl2,,[
-      #include <stdlib.h>
-      #include <sasl2/sasl2.h>
-    ],[
-      sasl2_server_init(NULL, NULL);
-    ])
-  ],[
-    ac_cv_libsasl2="no"
-  ])
-
-  AM_CONDITIONAL(HAVE_LIBSASL2, [test "x${ac_cv_libsasl2}" = "xyes"])
-])
-
-AC_DEFUN([PANDORA_HAVE_LIBSASL2],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBSASL2])
-])
-
-AC_DEFUN([PANDORA_REQUIRE_LIBSASL2],[
-  AC_REQUIRE([_PANDORA_SEARCH_LIBSASL2])
-  AS_IF([test "x${ac_cv_libsasl2}" = "xno"],
-    AC_MSG_ERROR([libsasl2 is required for ${PACKAGE}]))
-])
index 03031f92bb8ea36a94e7537f59cde3b768db4b16..d801291302e8994de936257d9f7dafcbadd2fb9d 100644 (file)
@@ -4,7 +4,8 @@ libdir=@libdir@
 includedir=@includedir@
 
 Name: libmemcached
-Description: libmemcached C library.
+URL: http://libmemcachd.org/
+Description: libmemcached C/C++ library.
 Version: @VERSION@
-Libs: @LTLIBSASL@ @LTLIBSASL2@ -L${libdir} -lmemcached -lmemcachedutil -pthread
+Libs: -L${libdir} -lmemcached -lmemcachedutil
 Cflags: -I${includedir}
index 573e7f53f62f129a628aff3748c02a3c09d6bb4b..6949bcd6f2c184d0c37966ad8ec5459525f74f79 100644 (file)
@@ -281,6 +281,7 @@ collection_st collection[] ={
 };
 
 
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
 #define SERVERS_TO_CREATE 5
 
 #include "libmemcached_world.h"
diff --git a/tests/c_sasl_test.c b/tests/c_sasl_test.c
new file mode 100644 (file)
index 0000000..18e3f42
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached C sasl test app
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * @file @brief C dummy test, aka testing C linking, etc
+ */
+
+#include <stdlib.h>
+
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#endif
+
+#include <libmemcached/memcached.h>
+
+int main(void)
+{
+  memcached_st *memc= memcached_create(NULL);
+  memcached_free(memc);
+
+  return EXIT_SUCCESS;
+}
+
index 957b52b0caacef3d8ee80c782708f65aa3da6ae6..5693b04db2a294f344c81e9b25ed691f4e74e845 100644 (file)
@@ -127,6 +127,7 @@ collection_st collection[] ={
 };
 
 
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
 #include "tests/libmemcached_world.h"
 
 void get_world(Framework *world)
index 18dbdb6b94f5536d4a92f87f1267bd330392e262..b5f4fb0d44d1b5eb69c5a222c54b5d1cf05dfc1a 100644 (file)
@@ -41,7 +41,8 @@ noinst_HEADERS+= \
 
 # Cycle should always run first
 tests_cycle_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
-tests_cycle_CXXFLAGS =  $(AM_CXXFLAGS) ${PTHREAD_CFLAGS}
+tests_cycle_CXXFLAGS= $(AM_CXXFLAGS)
+tests_cycle_CXXFLAGS+= ${PTHREAD_CFLAGS}
 tests_cycle_SOURCES= tests/cycle.cc
 tests_cycle_DEPENDENCIES= $(TESTS_LDADDS)
 tests_cycle_LDADD= $(tests_cycle_DEPENDENCIES)
@@ -84,7 +85,6 @@ tests_testapp_DEPENDENCIES= \
                            libhashkit/libhashkit.la \
                            libmemcached/libmemcachedutil.la
 tests_testapp_LDADD= \
-                    $(LIBSASL) \
                     ${PTHREAD_LIBS} \
                     libmemcached/libmemcached.la \
                     libmemcached/libmemcachedutil.la \
@@ -93,10 +93,38 @@ tests_testapp_LDADD= \
 check_PROGRAMS+= tests/testapp
 noinst_PROGRAMS+= tests/testapp
 
+tests_sasl_CXXFLAGS =  $(AM_CXXFLAGS) ${PTHREAD_CFLAGS}
+tests_sasl_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
+tests_sasl_SOURCES= \
+                   tests/basic.cc \
+                   tests/debug.cc \
+                   tests/deprecated.cc \
+                   tests/error_conditions.cc \
+                   tests/ketama.cc \
+                   tests/sasl.cc \
+                   tests/namespace.cc \
+                   tests/parser.cc \
+                   tests/pool.cc \
+                   tests/print.cc \
+                   tests/replication.cc \
+                   tests/virtual_buckets.cc
+tests_sasl_SOURCES+= clients/generator.cc clients/execute.cc
+tests_sasl_DEPENDENCIES= \
+                        libmemcached/libmemcached.la \
+                        libtest/libtest.la
+tests_sasl_LDADD= \
+                 ${PTHREAD_LIBS} \
+                 libmemcached/libmemcached.la \
+                 libmemcached/libmemcachedutil.la \
+                 libtest/libtest.la \
+                 libhashkit/libhashkit.la
+check_PROGRAMS+= tests/sasl
+noinst_PROGRAMS+= tests/sasl
+
 tests_testplus_SOURCES= tests/plus.cpp
 tests_testplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX)
 tests_testplus_DEPENDENCIES= $(TESTS_LDADDS)
-tests_testplus_LDADD= $(tests_testplus_DEPENDENCIES) $(LIBSASL)
+tests_testplus_LDADD= $(tests_testplus_DEPENDENCIES)
 check_PROGRAMS+= tests/testplus
 noinst_PROGRAMS+= tests/testplus
 
@@ -107,13 +135,13 @@ tests_atomsmasher_SOURCES= \
                           clients/generator.cc \
                           clients/execute.cc
 tests_atomsmasher_DEPENDENCIES= $(TESTS_LDADDS)
-tests_atomsmasher_LDADD= $(tests_atomsmasher_DEPENDENCIES) $(LIBSASL)
+tests_atomsmasher_LDADD= $(tests_atomsmasher_DEPENDENCIES)
 noinst_PROGRAMS+= tests/atomsmasher
 
 tests_testudp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
 tests_testudp_SOURCES= tests/mem_udp.cc
 tests_testudp_DEPENDENCIES= $(TESTS_LDADDS)
-tests_testudp_LDADD= $(tests_testudp_DEPENDENCIES) $(LIBSASL)
+tests_testudp_LDADD= $(tests_testudp_DEPENDENCIES)
 check_PROGRAMS+= tests/testudp
 noinst_PROGRAMS+= tests/testudp
 
@@ -151,12 +179,19 @@ tests_c_test_DEPENDENCIES= libmemcached/libmemcached.la
 check_PROGRAMS+=tests/c_test
 noinst_PROGRAMS+=tests/c_test
 
+# Test linking with C application/SASL include
+tests_c_sasl_test_SOURCES= tests/c_sasl_test.c
+tests_c_sasl_test_LDADD= libmemcached/libmemcached.la
+tests_c_sasl_test_DEPENDENCIES= libmemcached/libmemcached.la
+check_PROGRAMS+=tests/c_sasl_test
+noinst_PROGRAMS+=tests/c_sasl_test
+
 test: check
 
-check-local: tests/var $(TEST_DOCS)
+check-local: $(TEST_DOCS)
        @echo "Tests completed"
 
-test-x: tests/var test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat
+test-x: test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat
        @echo "Tests completed"
 
 test-memcat: clients/memcat clients/memcp
@@ -266,6 +301,10 @@ valgrind-memerror: clients/memerror
 test-mem: tests/var tests/testapp
        @tests/testapp
 
+test-sasl: tests/sasl
+       @tests/sasl
+
+
 test-udp: tests/var tests/testudp
        @tests/testudp
 
@@ -293,6 +332,9 @@ pahole-mem: tests/testapp
 gdb-mem: tests/testapp
        @$(DEBUG_COMMAND)  tests/testapp
 
+gdb-sasl: tests/sasl
+       @$(DEBUG_COMMAND)  tests/sasl
+
 gdb-atom: tests/atomsmasher
        @$(DEBUG_COMMAND) tests/testudp
 
@@ -373,7 +415,5 @@ callgrind:
        $(LIBTOOL) --mode=execute valgrind --tool=callgrind --callgrind-out-file=tests/callgrind.out.%p  tests/testapp
        callgrind_annotate tests/callgrind.out.* --auto=yes > tests/callgrind.out
 
-test-no-outputdiff: test
-
 hudson-valgrind: tests/testapp
        $(VALGRIND_COMMAND) --log-file=tests/valgrind.out tests/testapp
index 968c235e6f027cc089061307682469c1b91d8b08..17561838c05d3967fb217182602e23ac1cfa006f 100644 (file)
@@ -28,10 +28,15 @@ struct libmemcached_test_container_st
 };
 
 #define SERVERS_TO_CREATE 5
-#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
 
 static void *world_create(server_startup_st& servers, test_return_t& error)
 {
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    error= TEST_SKIPPED;
+    return NULL;
+  }
+
   in_port_t max_port;
   for (uint32_t x= 0; x < SERVERS_TO_CREATE; x++)
   {
@@ -52,20 +57,43 @@ static void *world_create(server_startup_st& servers, test_return_t& error)
 
     max_port= port;
     const char *argv[1]= { "memcached" };
-    if (not server_startup(servers, "memcached", port, 1, argv))
+    if (servers.sasl())
     {
-      error= TEST_FAILURE;
-      return NULL;
+      if (not server_startup(servers, "memcached-sasl", port, 1, argv))
+      {
+        error= TEST_FAILURE;
+        return NULL;
+      }
+    }
+    else
+    {
+      if (not server_startup(servers, "memcached", port, 1, argv))
+      {
+        error= TEST_FAILURE;
+        return NULL;
+      }
     }
   }
 
   if (servers.socket())
   {
-    const char *argv[1]= { "memcached" };
-    if (not servers.start_socket_server("memcached", max_port +1, 1, argv))
+    if (servers.sasl())
+    {
+      const char *argv[1]= { "memcached" };
+      if (not servers.start_socket_server("memcached-sasl", max_port +1, 1, argv))
+      {
+        error= TEST_FAILURE;
+        return NULL;
+      }
+    }
+    else
     {
-      error= TEST_FAILURE;
-      return NULL;
+      const char *argv[1]= { "memcached" };
+      if (not servers.start_socket_server("memcached", max_port +1, 1, argv))
+      {
+        error= TEST_FAILURE;
+        return NULL;
+      }
     }
   }
 
@@ -95,6 +123,21 @@ static test_return_t world_container_startup(libmemcached_test_container_st *con
   container->parent= memcached(container->construct.option_string().c_str(), container->construct.option_string().size());
   test_true(container->parent);
 
+  if (container->construct.sasl())
+  {
+    if (memcached_failed(memcached_behavior_set(container->parent, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
+    {
+      memcached_free(container->parent);
+      return TEST_FAILURE;
+    }
+
+    if (memcached_failed(memcached_set_sasl_auth_data(container->parent, container->construct.username().c_str(), container->construct.password().c_str())))
+    {
+      memcached_free(container->parent);
+      return TEST_FAILURE;
+    }
+  }
+
   for (uint32_t host= 0; host < memcached_server_count(container->parent); ++host)
   {
     memcached_server_instance_st instance=
@@ -174,8 +217,11 @@ static test_return_t world_on_error(test_return_t test_state, libmemcached_test_
 static bool world_destroy(void *object)
 {
   libmemcached_test_container_st *container= (libmemcached_test_container_st *)object;
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  sasl_done();
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT)
+  {
+    sasl_done();
+  }
 #endif
 
   delete container;
index 7418cc218ecaa7a45c02cd6c7c6eb2fbb359cc0d..6845074b96e3637a9e7e6d0d163e696f5cd4a838 100644 (file)
@@ -1288,10 +1288,11 @@ static test_return_t stats_servername_test(memcached_st *memc)
   memcached_server_instance_st instance=
     memcached_server_instance_by_position(memc, 0);
 
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  if (memcached_get_sasl_callbacks(memc) != NULL)
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT and memcached_get_sasl_callbacks(memc))
+  {
     return TEST_SKIPPED;
-#endif
+  }
+
   test_compare(MEMCACHED_SUCCESS, memcached_stat_servername(&memc_stat, NULL,
                                                             memcached_server_name(instance),
                                                             memcached_server_port(instance)));
@@ -3627,32 +3628,6 @@ static test_return_t pre_binary(memcached_st *memc)
   return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
 }
 
-static test_return_t pre_sasl(memcached_st *memc)
-{
-  memcached_return_t rc= MEMCACHED_FAILURE;
-
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  const char *server= getenv("LIBMEMCACHED_TEST_SASL_SERVER");
-  const char *user= getenv("LIBMEMCACHED_TEST_SASL_USERNAME");
-  const char *pass= getenv("LIBMEMCACHED_TEST_SASL_PASSWORD");
-
-  if (server and user and pass)
-  {
-    memcached_server_st *servers= memcached_servers_parse(server);
-    test_true(servers);
-    memcached_servers_reset(memc);
-    test_true(memcached_server_push(memc, servers) == MEMCACHED_SUCCESS);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
-    rc= memcached_set_sasl_auth_data(memc, user, pass);
-    test_compare(MEMCACHED_SUCCESS, rc);
-  }
-#else
-  (void)memc;
-#endif
-
-  return rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_SKIPPED;
-}
-
 static test_return_t pre_replication(memcached_st *memc)
 {
   test_skip(TEST_SUCCESS, pre_binary(memc));
@@ -5838,39 +5813,6 @@ static test_return_t regression_bug_(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
-/*
- * Test that the sasl authentication works. We cannot use the default
- * pool of servers, because that would require that all servers we want
- * to test supports SASL authentication, and that they use the default
- * creds.
- */
-static test_return_t sasl_auth_test(memcached_st *memc)
-{
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  test_compare(MEMCACHED_SUCCESS, memcached_set(memc, "foo", 3, "bar", 3, (time_t)0, (uint32_t)0));
-  test_compare(MEMCACHED_SUCCESS, memcached_delete(memc, "foo", 3, 0));
-  test_compare(MEMCACHED_SUCCESS, memcached_destroy_sasl_auth_data(memc));
-  test_compare(MEMCACHED_FAILURE, memcached_destroy_sasl_auth_data(memc));
-  test_compare(MEMCACHED_FAILURE, memcached_destroy_sasl_auth_data(NULL));
-  memcached_quit(memc);
-
-  test_compare(MEMCACHED_SUCCESS,
-               memcached_set_sasl_auth_data(memc,
-                                            getenv("LIBMEMCACHED_TEST_SASL_USERNAME"),
-                                            getenv("LIBMEMCACHED_TEST_SASL_SERVER")));
-
-  test_compare(MEMCACHED_AUTH_FAILURE, 
-               memcached_set(memc, "foo", 3, "bar", 3, (time_t)0, (uint32_t)0));
-  test_compare(MEMCACHED_SUCCESS, memcached_destroy_sasl_auth_data(memc));
-
-  memcached_quit(memc);
-  return TEST_SUCCESS;
-#else
-  (void)memc;
-  return TEST_FAILURE;
-#endif
-}
-
 /* Clean the server before beginning testing */
 test_st tests[] ={
   {"util_version", true, (test_callback_fn*)util_version_test },
@@ -6072,11 +6014,6 @@ test_st regression_tests[]= {
   {0, false, (test_callback_fn*)0}
 };
 
-test_st sasl_auth_tests[]= {
-  {"sasl_auth", true, (test_callback_fn*)sasl_auth_test },
-  {0, 0, (test_callback_fn*)0}
-};
-
 test_st ketama_compatibility[]= {
   {"libmemcached", true, (test_callback_fn*)ketama_compatibility_libmemcached },
   {"spymemcached", true, (test_callback_fn*)ketama_compatibility_spymemcached },
@@ -6237,8 +6174,6 @@ collection_st collection[] ={
   {"namespace(BINARY)", (test_callback_fn*)set_namespace_and_binary, 0, tests},
   {"specific namespace", 0, 0, namespace_tests},
   {"specific namespace(BINARY)", (test_callback_fn*)pre_binary, 0, namespace_tests},
-  {"sasl_auth", (test_callback_fn*)pre_sasl, 0, sasl_auth_tests },
-  {"sasl", (test_callback_fn*)pre_sasl, 0, tests },
   {"version_1_2_3", (test_callback_fn*)check_for_1_2_3, 0, version_1_2_3},
   {"result", 0, 0, result_tests},
   {"async", (test_callback_fn*)pre_nonblock, 0, async_tests},
@@ -6273,6 +6208,8 @@ collection_st collection[] ={
   {0, 0, 0, 0}
 };
 
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
+
 #include "tests/libmemcached_world.h"
 
 void get_world(Framework *world)
index 846d2bfdea9bbdba3facd0a8dc4be2a0e7b315f4..a53db785d1bdb8913fec75ad1fa5e849849a0f2f 100644 (file)
@@ -491,6 +491,7 @@ collection_st collection[] ={
 
 #define SERVERS_TO_CREATE 5
 
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
 #include "libmemcached_world.h"
 
 void get_world(Framework *world)
index aed34a4960f4079c03416e99f37f64efcae46a1f..3bc85bc1a8632526e08e77ea873bd419afbec377 100644 (file)
@@ -258,6 +258,7 @@ collection_st collection[] ={
 
 #define SERVERS_TO_CREATE 5
 
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +10
 #include "libmemcached_world.h"
 
 void get_world(Framework *world)
diff --git a/tests/sasl.cc b/tests/sasl.cc
new file mode 100644 (file)
index 0000000..70b4298
--- /dev/null
@@ -0,0 +1,122 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+#include <libtest/test.hpp>
+
+using namespace libtest;
+
+/*
+  Test cases
+*/
+
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +20
+#include <libmemcached/memcached.h>
+
+static test_return_t pre_sasl(memcached_st *)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return TEST_SKIPPED;
+  }
+
+  return TEST_SUCCESS;
+}
+
+/*
+ * Test that the sasl authentication works. We cannot use the default
+ * pool of servers, because that would require that all servers we want
+ * to test supports SASL authentication, and that they use the default
+ * creds.
+ */
+static test_return_t sasl_auth_test(memcached_st *memc)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT)
+  {
+    test_compare(MEMCACHED_SUCCESS, memcached_set(memc, "foo", 3, "bar", 3, (time_t)0, (uint32_t)0));
+    test_compare(MEMCACHED_SUCCESS, memcached_delete(memc, "foo", 3, 0));
+    test_compare(MEMCACHED_SUCCESS, memcached_destroy_sasl_auth_data(memc));
+    test_compare(MEMCACHED_SUCCESS, memcached_destroy_sasl_auth_data(memc));
+    test_compare(MEMCACHED_INVALID_ARGUMENTS, memcached_destroy_sasl_auth_data(NULL));
+    memcached_quit(memc);
+
+    test_compare(MEMCACHED_AUTH_FAILURE, 
+                 memcached_set(memc, "foo", 3, "bar", 3, (time_t)0, (uint32_t)0));
+    test_compare(MEMCACHED_SUCCESS, memcached_destroy_sasl_auth_data(memc));
+
+    memcached_quit(memc);
+    return TEST_SUCCESS;
+  }
+
+  return TEST_SKIPPED;
+}
+
+
+test_st sasl_auth_tests[]= {
+  {"sasl_auth", true, (test_callback_fn*)sasl_auth_test },
+  {0, 0, (test_callback_fn*)0}
+};
+
+collection_st collection[] ={
+  {"sasl_auth", (test_callback_fn*)pre_sasl, 0, sasl_auth_tests },
+#if 0
+  {"sasl", (test_callback_fn*)pre_sasl, 0, tests },
+#endif
+  {0, 0, 0, 0}
+};
+
+#include "tests/libmemcached_world.h"
+
+void get_world(Framework *world)
+{
+  world->collections= collection;
+
+  world->_create= (test_callback_create_fn*)world_create;
+  world->_destroy= (test_callback_destroy_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_flush((test_callback_fn*)world_flush);
+  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->set_runner(&defualt_libmemcached_runner);
+
+  world->set_sasl("memcached", "memcached");
+}
index 9eed1999fb7324bf6a0b2f45e0e4015f37acf53c..5c00525d5d25ad16d0cb4f91616a34da147b7d6b 100644 (file)
@@ -14,5 +14,6 @@ noinst_HEADERS+= \
                 util/daemon.hpp \
                 util/instance.hpp \
                 util/operation.hpp \
+                util/signal.hpp \
                 util/string.hpp \
                 util/pidfile.hpp
index f9a5afbb3a5b03de89d65b31178dc3a50472bec5..c44b90817023101fd88e45adca25f2bc99a7d75b 100644 (file)
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
-#include <errno.h>
+#include <cerrno>
 #include <fcntl.h>
 #include <iostream>
+#include <sstream>
 #include <sys/stat.h>
 #include <sys/types.h>
 
+extern "C" {
+
+  char pid_file[1024 * 4]= { 0 };
+
+  static void remove_pidfile(void)
+  {
+    if (pid_file[0])
+    {
+      if (unlink(pid_file) == -1)
+      {
+        std::cerr << "Could not remove pidfile: " << pid_file << "(" << strerror(errno) << ")" << std::endl;
+      }
+
+      pid_file[0]= 0;
+    }
+  }
+
+}
+
 namespace datadifferential {
 namespace util {
 
@@ -60,35 +80,61 @@ Pidfile::Pidfile(const std::string &arg) :
 
 Pidfile::~Pidfile()
 {
-  if (not _filename.empty() and (unlink(_filename.c_str()) == -1))
+  if (not _filename.empty())
   {
-    _error_message+= "Could not remove the pid file: ";
-    _error_message+= _filename;
+    if (access(_filename.c_str(), F_OK) == -1)
+    {
+      std::stringstream error_stream;
+      error_stream << "Could not access the pid file: " << _filename << "(" << strerror(errno) << ")";
+      _error_message= error_stream.str();
+    }
+    else if (unlink(_filename.c_str()) == -1)
+    {
+      std::stringstream error_stream;
+      error_stream << "Could not remove the pid file: " << _filename << "(" << strerror(errno) << ")";
+      _error_message= error_stream.str();
+    }
   }
+  pid_file[0]= 0;
 }
 
 bool Pidfile::create()
 {
   if (_filename.empty())
+  {
     return true;
+  }
+
+  if (access(_filename.c_str(), F_OK) == 0)
+  {
+    if (unlink(_filename.c_str()) == -1)
+    {
+      std::stringstream error_stream;
+      error_stream << "Unable to remove exisiting file:" << _filename << "(" << strerror(errno) << ")";
+      _error_message= error_stream.str();
+
+      return false;
+    }
+  }
 
   int file;
   if ((file = open(_filename.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU|S_IRGRP|S_IROTH)) < 0)
   {
-    _error_message+= "Could not open pid file for writing: "; 
-    _error_message+= _filename;
+    std::stringstream error_stream;
+    error_stream << "Could not open pid file for writing: " << _filename << "(" << strerror(errno) << ")";
+    _error_message= error_stream.str();
+    
     return false;
   }
 
   char buffer[BUFSIZ];
-
   unsigned long temp= static_cast<unsigned long>(getpid());
   int length= snprintf(buffer, sizeof(buffer), "%lu\n", temp);
-
   if (write(file, buffer, length) != length)
   { 
-    _error_message+= "Could not write pid to file: "; 
-    _error_message+= _filename;
+    std::stringstream error_stream;
+    error_stream << "Could not write pid to file: " << _filename << "(" << strerror(errno) << ")";
+    _error_message= error_stream.str();
     close(file);
 
     return false;
@@ -100,6 +146,8 @@ bool Pidfile::create()
     _error_message+= _filename;
     return false;
   }
+  snprintf(pid_file, sizeof(pid_file), "%s", _filename.c_str());
+  atexit(remove_pidfile);
 
   return true;
 }
index 71d89e1170a4cd92e40ebc6b7ec5dea23e35475c..73ba49ce2b19fe4f564c8bb600d78342828c63c0 100644 (file)
@@ -37,7 +37,6 @@
 
 #pragma once
 
-
 #include <string>
 
 namespace datadifferential {
@@ -59,7 +58,7 @@ public:
 
 private:
   int _last_errno;
-  std::string _filename;
+  const std::string _filename;
   std::string _error_message;
 };
 
diff --git a/util/signal.cc b/util/signal.cc
new file mode 100644 (file)
index 0000000..551803a
--- /dev/null
@@ -0,0 +1,199 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DD Util
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+#include <config.h>
+
+#include <cassert>
+#include <cerrno>
+#include <csignal>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include <util/signal.hpp>
+
+namespace datadifferential {
+namespace util {
+
+#define MAGIC_MEMORY 123569
+
+bool SignalThread::is_shutdown()
+{
+  bool ret;
+  pthread_mutex_lock(&shutdown_mutex);
+  ret= bool(__shutdown != SHUTDOWN_RUNNING);
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return ret;
+}
+
+void SignalThread::set_shutdown(shutdown_t arg)
+{
+  pthread_mutex_lock(&shutdown_mutex);
+  __shutdown= arg;
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  if (arg == SHUTDOWN_GRACEFUL)
+  {
+    if (pthread_kill(thread, SIGUSR2) == 0)
+    {
+      void *retval;
+      pthread_join(thread, &retval);
+    }
+  }
+}
+
+shutdown_t SignalThread::get_shutdown()
+{
+  shutdown_t local;
+  pthread_mutex_lock(&shutdown_mutex);
+  local= __shutdown;
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return local;
+}
+
+void SignalThread::post()
+{
+  sem_post(&lock);
+}
+
+void SignalThread::test()
+{
+  assert(magic_memory == MAGIC_MEMORY);
+  assert(sigismember(&set, SIGABRT));
+  assert(sigismember(&set, SIGINT));
+  assert(sigismember(&set, SIGQUIT));
+  assert(sigismember(&set, SIGTERM));
+  assert(sigismember(&set, SIGUSR2));
+}
+
+SignalThread::~SignalThread()
+{
+  if (not is_shutdown())
+  {
+    set_shutdown(SHUTDOWN_GRACEFUL);
+  }
+
+#if 0
+  if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true)
+  {
+    void *retval;
+    pthread_join(thread, &retval);
+  }
+#endif
+  sem_destroy(&lock);
+}
+
+extern "C" {
+
+static void *sig_thread(void *arg)
+{   
+  SignalThread *context= (SignalThread*)arg;
+
+  context->test();
+  context->post();
+
+  while (context->get_shutdown() == SHUTDOWN_RUNNING)
+  {
+    int sig;
+
+    if (context->wait(sig) == -1)
+    {
+      std::cerr << "sigwait() returned errno:" << strerror(errno) << std::endl;
+      continue;
+    }
+
+    switch (sig)
+    {
+    case SIGUSR2:
+      break;
+
+    case SIGABRT:
+    case SIGINT:
+    case SIGQUIT:
+    case SIGTERM:
+      if (context->is_shutdown() == false)
+      {
+        context->set_shutdown(SHUTDOWN_FORCED);
+      }
+
+      if (context->exit_on_signal())
+      {
+        exit(EXIT_SUCCESS);
+      }
+
+      break;
+
+    default:
+      std::cerr << "Signal handling thread got unexpected signal " <<  strsignal(sig) << std::endl;
+      break;
+    }
+  }
+
+  return NULL;
+}
+
+}
+
+SignalThread::SignalThread(bool exit_on_signal_arg) :
+  _exit_on_signal(exit_on_signal_arg),
+  magic_memory(MAGIC_MEMORY),
+  thread(pthread_self())
+{
+  pthread_mutex_init(&shutdown_mutex, NULL);
+  sigemptyset(&set);
+
+  sigaddset(&set, SIGABRT);
+  sigaddset(&set, SIGINT);
+  sigaddset(&set, SIGQUIT);
+  sigaddset(&set, SIGTERM);
+  sigaddset(&set, SIGUSR2);
+
+  sem_init(&lock, 0, 0);
+}
+
+
+bool SignalThread::setup()
+{
+  set_shutdown(SHUTDOWN_RUNNING);
+
+  int error;
+  if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
+  {
+    std::cerr << "pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")" << std::endl;
+    return false;
+  }
+
+  if ((error= pthread_create(&thread, NULL, &sig_thread, this)) != 0)
+  {
+    std::cerr << "pthread_create() died during pthread_create(" << strerror(error) << ")" << std::endl;
+    return false;
+  }
+
+  sem_wait(&lock);
+
+  return true;
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/util/signal.hpp b/util/signal.hpp
new file mode 100644 (file)
index 0000000..7573fe6
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+
+
+#pragma once 
+
+#include <pthread.h>
+#include <semaphore.h>
+
+namespace datadifferential {
+namespace util {
+
+enum shutdown_t {
+  SHUTDOWN_RUNNING,
+  SHUTDOWN_GRACEFUL,
+  SHUTDOWN_FORCED
+};
+
+class SignalThread {
+  bool _exit_on_signal;
+  sigset_t set;
+  sem_t lock;
+  uint64_t magic_memory;
+  volatile shutdown_t __shutdown;
+  pthread_mutex_t shutdown_mutex;
+  pthread_t thread;
+
+public:
+
+  SignalThread(bool exit_on_signal_arg= false);
+
+  void test();
+  void post();
+  bool setup();
+
+  bool exit_on_signal()
+  {
+    return _exit_on_signal;
+  }
+
+  int wait(int& sig)
+  {
+    return sigwait(&set, &sig);
+  }
+
+  ~SignalThread();
+
+  void set_shutdown(shutdown_t arg);
+  bool is_shutdown();
+  shutdown_t get_shutdown();
+};
+
+} /* namespace util */
+} /* namespace datadifferential */