From: Brian Aker Date: Mon, 15 Aug 2011 07:10:59 +0000 (-0700) Subject: Merge in sasl update X-Git-Tag: 1.0.2~23 X-Git-Url: https://git.m6w6.name/?a=commitdiff_plain;h=5d66b2f99bf7de6f54a3e463b01542b997f68ac8;hp=562eadf651a079c347ff2797069adbbf938fea96;p=m6w6%2Flibmemcached Merge in sasl update --- diff --git a/.bzrignore b/.bzrignore index 27188105..034514bb 100644 --- a/.bzrignore +++ b/.bzrignore @@ -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 diff --git a/Makefile.am b/Makefile.am index 5b600d5a..2ecc8f2c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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= diff --git a/clients/include.am b/clients/include.am index 98511366..8fc8c00b 100644 --- a/clients/include.am +++ b/clients/include.am @@ -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 \ diff --git a/clients/memcat.cc b/clients/memcat.cc index 12df3479..fdbcb67e 100644 --- a/clients/memcat.cc +++ b/clients/memcat.cc @@ -11,6 +11,7 @@ #include "config.h" +#include #include #include #include @@ -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; diff --git a/clients/memcp.cc b/clients/memcp.cc index 3869242b..2a73390b 100644 --- a/clients/memcp.cc +++ b/clients/memcp.cc @@ -11,6 +11,7 @@ #include "config.h" +#include #include #include #include @@ -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; } diff --git a/clients/memdump.cc b/clients/memdump.cc index 0e81dad4..6f3c3e53 100644 --- a/clients/memdump.cc +++ b/clients/memdump.cc @@ -11,18 +11,18 @@ #include "config.h" -#include -#include -#include -#include +#include +#include +#include +#include +#include #include -#include +#include +#include #include #include -#include -#include -#include -#include +#include +#include #include @@ -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; } diff --git a/clients/memflush.cc b/clients/memflush.cc index 848bc1e7..b19c2860 100644 --- a/clients/memflush.cc +++ b/clients/memflush.cc @@ -10,10 +10,12 @@ */ #include "config.h" -#include -#include -#include +#include +#include #include +#include +#include + #include #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 index 00000000..ee245cda --- /dev/null +++ b/clients/memping.cc @@ -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 +#include +#include +#include +#include +#include +#include "client_options.h" +#include "utilities.h" + +#include + +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(); + } + } +} diff --git a/clients/memrm.cc b/clients/memrm.cc index d4d93c2e..0551e326 100644 --- a/clients/memrm.cc +++ b/clients/memrm.cc @@ -10,11 +10,13 @@ */ #include "config.h" -#include -#include +#include +#include #include +#include +#include + #include -#include #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; } diff --git a/clients/utilities.cc b/clients/utilities.cc index ca109adc..8be59abb 100644 --- a/clients/utilities.cc +++ b/clients/utilities.cc @@ -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) { diff --git a/config/autorun.sh b/config/autorun.sh index 3b076d1a..79d6629e 100755 --- a/config/autorun.sh +++ b/config/autorun.sh @@ -1,2 +1,2 @@ #!/bin/sh -autoreconf -ivf +autoreconf -ivf -Wall diff --git a/configure.ac b/configure.ac index 153fdb1f..5fc2c6c7 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/libmemcached/connect.cc b/libmemcached/connect.cc index 07bb545b..3c12339c 100644 --- a/libmemcached/connect.cc +++ b/libmemcached/connect.cc @@ -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: diff --git a/libmemcached/include.am b/libmemcached/include.am index 4950f3ca..425cec0b 100644 --- a/libmemcached/include.am +++ b/libmemcached/include.am @@ -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 diff --git a/libmemcached/memcached.cc b/libmemcached/memcached.cc index 359a4403..ce3fb8e3 100644 --- a/libmemcached/memcached.cc +++ b/libmemcached/memcached.cc @@ -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); diff --git a/libmemcached/protocol/include.am b/libmemcached/protocol/include.am index 9c4c1bc2..d5bd9c46 100644 --- a/libmemcached/protocol/include.am +++ b/libmemcached/protocol/include.am @@ -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 index 434d2db6..00000000 --- a/libmemcached/sasl.c +++ /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 -#include - -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 index 00000000..4f18ca2a --- /dev/null +++ b/libmemcached/sasl.cc @@ -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 +#include + +#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT + +#include + +void memcached_set_sasl_callbacks(memcached_st *ptr, + const sasl_callback_t *callbacks) +{ + ptr->sasl.callbacks= const_cast(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 diff --git a/libmemcached/sasl.h b/libmemcached/sasl.h index 5a0236bf..8602246d 100644 --- a/libmemcached/sasl.h +++ b/libmemcached/sasl.h @@ -37,8 +37,11 @@ #pragma once -#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT +#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT #include +#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; }; diff --git a/libmemcached/util/include.am b/libmemcached/util/include.am index 2f446517..10f3b944 100644 --- a/libmemcached/util/include.am +++ b/libmemcached/util/include.am @@ -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 diff --git a/libmemcached/util/pid.cc b/libmemcached/util/pid.cc index 2d7a86dd..de009fbb 100644 --- a/libmemcached/util/pid.cc +++ b/libmemcached/util/pid.cc @@ -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; +} diff --git a/libmemcached/util/pid.h b/libmemcached/util/pid.h index f2fb7488..4101c11f 100644 --- a/libmemcached/util/pid.h +++ b/libmemcached/util/pid.h @@ -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 diff --git a/libmemcached/util/ping.cc b/libmemcached/util/ping.cc index 45f94b19..907f6dc0 100644 --- a/libmemcached/util/ping.cc +++ b/libmemcached/util/ping.cc @@ -40,7 +40,6 @@ #include #include - 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); +} diff --git a/libmemcached/util/ping.h b/libmemcached/util/ping.h index e9f3bc50..faea8b2b 100644 --- a/libmemcached/util/ping.h +++ b/libmemcached/util/ping.h @@ -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 diff --git a/libmemcachedinternal/util/include.am b/libmemcachedinternal/util/include.am index 64589255..7b5e8007 100644 --- a/libmemcachedinternal/util/include.am +++ b/libmemcachedinternal/util/include.am @@ -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 diff --git a/libtest/blobslap_worker.cc b/libtest/blobslap_worker.cc index c7ac0a02..378f8268 100644 --- a/libtest/blobslap_worker.cc +++ b/libtest/blobslap_worker.cc @@ -21,6 +21,7 @@ #include + #include #include @@ -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() diff --git a/libtest/cmdline.cc b/libtest/cmdline.cc index 6c71f9b0..421fa006 100644 --- a/libtest/cmdline.cc +++ b/libtest/cmdline.cc @@ -21,19 +21,19 @@ #include -#include - using namespace libtest; #include #include #include +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 diff --git a/libtest/cmdline.h b/libtest/cmdline.h index cfe29575..dcb4b0ab 100644 --- a/libtest/cmdline.h +++ b/libtest/cmdline.h @@ -21,4 +21,10 @@ #pragma once +namespace libtest { + bool exec_cmdline(const std::string& executable, const char *args[]); + +const char *gearmand_binary(); + +} diff --git a/libtest/common.h b/libtest/common.h index 7a7f1ff0..8f2c0108 100644 --- a/libtest/common.h +++ b/libtest/common.h @@ -20,7 +20,7 @@ */ /* - Common include file for libmemached + Common include file for libtest */ #pragma once @@ -53,4 +53,15 @@ #include #endif +static inline bool is_pid_valid(const pid_t pid) +{ + return (pid > 1) ? true : false; +} + +#include +#include +#include + +#include + #include diff --git a/libtest/comparison.hpp b/libtest/comparison.hpp index 8656e499..5c687fc3 100644 --- a/libtest/comparison.hpp +++ b/libtest/comparison.hpp @@ -23,7 +23,14 @@ #include #include + +#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED #include +#endif + +#if defined(HAVE_LIBGEARMAN) && HAVE_LIBGEARMAN +#include +#endif namespace libtest { @@ -40,24 +47,39 @@ bool _compare_true_hint(const char *file, int line, const char *func, T_comparab } template -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 << "\""; diff --git a/libtest/framework.h b/libtest/framework.h index 69941b1b..90908244 100644 --- a/libtest/framework.h +++ b/libtest/framework.h @@ -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 diff --git a/libtest/gearmand.cc b/libtest/gearmand.cc index 9a7649ef..deac09f3 100644 --- a/libtest/gearmand.cc +++ b/libtest/gearmand.cc @@ -21,6 +21,7 @@ #include + #include #include "util/instance.hpp" @@ -36,6 +37,7 @@ using namespace libtest; #include #include #include +#include #include #include #include @@ -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 - 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); } diff --git a/libtest/gearmand.h b/libtest/gearmand.h index 22aaa713..f6aa6c32 100644 --- a/libtest/gearmand.h +++ b/libtest/gearmand.h @@ -22,8 +22,12 @@ #pragma once +#include + +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); } diff --git a/libtest/include.am b/libtest/include.am index 2ed437c2..3ee7d3f9 100644 --- a/libtest/include.am +++ b/libtest/include.am @@ -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 - diff --git a/libtest/killpid.cc b/libtest/killpid.cc index 7bbdd636..8a1543f4 100644 --- a/libtest/killpid.cc +++ b/libtest/killpid.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -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; diff --git a/libtest/killpid.h b/libtest/killpid.h index 83c7bb0a..becfd0ed 100644 --- a/libtest/killpid.h +++ b/libtest/killpid.h @@ -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 index 00000000..c7aa29d7 --- /dev/null +++ b/libtest/libtool.cc @@ -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 +#include + +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 index 00000000..d523aa28 --- /dev/null +++ b/libtest/libtool.hpp @@ -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); + +} diff --git a/libtest/memcached.cc b/libtest/memcached.cc index 910ea809..3aba2543 100644 --- a/libtest/memcached.cc +++ b/libtest/memcached.cc @@ -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 @@ -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); } } diff --git a/libtest/memcached.h b/libtest/memcached.h index 575ba001..a0899614 100644 --- a/libtest/memcached.h +++ b/libtest/memcached.h @@ -23,11 +23,13 @@ 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); } diff --git a/libtest/server.cc b/libtest/server.cc index b8fb603e..603b3f45 100644 --- a/libtest/server.cc +++ b/libtest/server.cc @@ -42,15 +42,6 @@ static inline std::string &rtrim(std::string &s) #include #include -#ifdef HAVE_LIBGEARMAN -#include -#include -#endif - -#ifdef HAVE_LIBMEMCACHED -#include -#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 { diff --git a/libtest/server.h b/libtest/server.h index a38bf428..b4a48446 100644 --- a/libtest/server.h +++ b/libtest/server.h @@ -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 *); diff --git a/libtest/signal.cc b/libtest/signal.cc index 50234d8d..ed017b2b 100644 --- a/libtest/signal.cc +++ b/libtest/signal.cc @@ -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 index 00000000..784f3a8f --- /dev/null +++ b/libtest/skiptest.cc @@ -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 + +#include + +#include +#include + +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; +} diff --git a/libtest/test.cc b/libtest/test.cc index 1ed61578..5c43e40b 100644 --- a/libtest/test.cc +++ b/libtest/test.cc @@ -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; } diff --git a/libtest/test.hpp b/libtest/test.hpp index 3e834b02..1933ef4b 100644 --- a/libtest/test.hpp +++ b/libtest/test.hpp @@ -30,6 +30,7 @@ #include #include +#include #include #include diff --git a/libtest/unittest.cc b/libtest/unittest.cc index e3272783..d2c965ba 100644 --- a/libtest/unittest.cc +++ b/libtest/unittest.cc @@ -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 index 00000000..a670a2e1 --- /dev/null +++ b/libtest/version.h.in @@ -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 index 0a86dffe..00000000 --- a/m4/acx_pthread.m4 +++ /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 -# -# 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 . -# -# 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_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 ], [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 index 00000000..a6bf596c --- /dev/null +++ b/m4/ax_pthread.m4 @@ -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 +# Copyright (c) 2011 Daniel Richard G. +# +# 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 . +# +# 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 + 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 ], + [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 ]], [[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 index 00000000..f337c059 --- /dev/null +++ b/m4/ax_with_prog.m4 @@ -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 . +# +# LICENSE +# +# Copyright (c) 2008 Francesco Salvestrini +# Copyright (c) 2008 Dustin J. Mitchell +# +# 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]) +]) diff --git a/m4/enable_utillib.m4 b/m4/enable_utillib.m4 index d77922d3..e9730f1b 100644 --- a/m4/enable_utillib.m4 +++ b/m4/enable_utillib.m4 @@ -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 index c90d02f3..00000000 --- a/m4/libgearmand.m4 +++ /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]) ]) diff --git a/m4/memcached.m4 b/m4/memcached.m4 index 010fb429..0b8592fe 100644 --- a/m4/memcached.m4 +++ b/m4/memcached.m4 @@ -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 index 00000000..5983c112 --- /dev/null +++ b/m4/memcached_sasl.m4 @@ -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 index 47f4cd4a..00000000 --- a/m4/pandora_have_protobuf.m4 +++ /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::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 -#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 index a4111166..00000000 --- a/m4/pandora_pthread.m4 +++ /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_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_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 - ]], [[ -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_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 -#include ]], [[ 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 -#include - ]], [[ -#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 -#include - ]], [[ -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_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 -#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 -#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 index ca4a21dc..00000000 --- a/m4/pandora_sasl.m4 +++ /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 - #include - ],[ - sasl_server_init(NULL, NULL); - ]) - - AS_IF([test "x${ac_cv_libsasl}" != "xyes" ], - [ - AC_LIB_HAVE_LINKFLAGS(sasl2,,[ - #include - #include - ],[ - 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 - #include - ],[ - 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 - #include - ],[ - 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}])) -]) diff --git a/support/libmemcached.pc.in b/support/libmemcached.pc.in index 03031f92..d8012913 100644 --- a/support/libmemcached.pc.in +++ b/support/libmemcached.pc.in @@ -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} diff --git a/tests/atomsmasher.cc b/tests/atomsmasher.cc index 573e7f53..6949bcd6 100644 --- a/tests/atomsmasher.cc +++ b/tests/atomsmasher.cc @@ -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 index 00000000..18e3f422 --- /dev/null +++ b/tests/c_sasl_test.c @@ -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 + +#ifdef HAVE_SASL_SASL_H +#include +#endif + +#include + +int main(void) +{ + memcached_st *memc= memcached_create(NULL); + memcached_free(memc); + + return EXIT_SUCCESS; +} + diff --git a/tests/cycle.cc b/tests/cycle.cc index 957b52b0..5693b04d 100644 --- a/tests/cycle.cc +++ b/tests/cycle.cc @@ -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) diff --git a/tests/include.am b/tests/include.am index 18dbdb6b..b5f4fb0d 100644 --- a/tests/include.am +++ b/tests/include.am @@ -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 diff --git a/tests/libmemcached_world.h b/tests/libmemcached_world.h index 968c235e..17561838 100644 --- a/tests/libmemcached_world.h +++ b/tests/libmemcached_world.h @@ -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; diff --git a/tests/mem_functions.cc b/tests/mem_functions.cc index 7418cc21..6845074b 100644 --- a/tests/mem_functions.cc +++ b/tests/mem_functions.cc @@ -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) diff --git a/tests/mem_udp.cc b/tests/mem_udp.cc index 846d2bfd..a53db785 100644 --- a/tests/mem_udp.cc +++ b/tests/mem_udp.cc @@ -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) diff --git a/tests/plus.cpp b/tests/plus.cpp index aed34a49..3bc85bc1 100644 --- a/tests/plus.cpp +++ b/tests/plus.cpp @@ -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 index 00000000..70b42987 --- /dev/null +++ b/tests/sasl.cc @@ -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 +#include + +using namespace libtest; + +/* + Test cases +*/ + +#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT +20 +#include + +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"); +} diff --git a/util/include.am b/util/include.am index 9eed1999..5c00525d 100644 --- a/util/include.am +++ b/util/include.am @@ -14,5 +14,6 @@ noinst_HEADERS+= \ util/daemon.hpp \ util/instance.hpp \ util/operation.hpp \ + util/signal.hpp \ util/string.hpp \ util/pidfile.hpp diff --git a/util/pidfile.cc b/util/pidfile.cc index f9a5afbb..c44b9081 100644 --- a/util/pidfile.cc +++ b/util/pidfile.cc @@ -42,12 +42,32 @@ #include #include #include -#include +#include #include #include +#include #include #include +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(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; } diff --git a/util/pidfile.hpp b/util/pidfile.hpp index 71d89e11..73ba49ce 100644 --- a/util/pidfile.hpp +++ b/util/pidfile.hpp @@ -37,7 +37,6 @@ #pragma once - #include 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 index 00000000..551803ab --- /dev/null +++ b/util/signal.cc @@ -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 + +#include +#include +#include +#include +#include +#include + +#include + +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 index 00000000..7573fe65 --- /dev/null +++ b/util/signal.hpp @@ -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 +#include + +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 */