# define FD_CLOEXEC 0
#endif
+#ifndef SO_NOSIGPIPE
+# define SO_NOSIGPIPE 0
+#endif
+
+#ifndef TCP_NODELAY
+# define TCP_NODELAY 0
+#endif
+
+#ifndef TCP_KEEPIDLE
+# define TCP_KEEPIDLE 0
+#endif
+
static memcached_return_t connect_poll(org::libmemcached::Instance* server)
{
struct pollfd fds[1];
#endif
}
-static void set_socket_options(org::libmemcached::Instance* server)
+static bool set_socket_options(org::libmemcached::Instance* server)
{
assert_msg(server->fd != INVALID_SOCKET, "invalid socket was passed to set_socket_options()");
+#ifdef HAVE_FCNTL
+ // If SOCK_CLOEXEC exists then we don't need to call the following
+ if (SOCK_CLOEXEC == 0)
+ {
+ if (FD_CLOEXEC)
+ {
+ int flags;
+ do
+ {
+ flags= fcntl(server->fd, F_GETFD, 0);
+ } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
+
+ if (flags != -1)
+ {
+ int rval;
+ do
+ {
+ rval= fcntl (server->fd, F_SETFD, flags | FD_CLOEXEC);
+ } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
+ // we currently ignore the case where rval is -1
+ }
+ }
+ }
+#endif
+
if (memcached_is_udp(server->root))
{
- return;
+ return true;
}
#ifdef HAVE_SNDTIMEO
#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)
+ if (SO_NOSIGPIPE)
{
int set= 1;
int error= setsockopt(server->fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
assert(error == 0);
}
- if (server->root->flags.tcp_nodelay)
+ if (TCP_NODELAY)
{
- int flag= 1;
+ if (server->root->flags.tcp_nodelay)
+ {
+ int flag= 1;
- int error= setsockopt(server->fd, IPPROTO_TCP, TCP_NODELAY,
- (char*)&flag, (socklen_t)sizeof(int));
- (void)(error);
- assert(error == 0);
+ int error= setsockopt(server->fd, IPPROTO_TCP, TCP_NODELAY,
+ (char*)&flag, (socklen_t)sizeof(int));
+ (void)(error);
+ assert(error == 0);
+ }
}
if (server->root->flags.tcp_keepalive)
assert(error == 0);
}
-#ifdef TCP_KEEPIDLE
- if (server->root->tcp_keepidle > 0)
+ if (TCP_KEEPIDLE)
{
- int error= setsockopt(server->fd, IPPROTO_TCP, TCP_KEEPIDLE,
- (char*)&server->root->tcp_keepidle, (socklen_t)sizeof(int));
- (void)(error);
- assert(error == 0);
+ if (server->root->tcp_keepidle > 0)
+ {
+ int error= setsockopt(server->fd, IPPROTO_TCP, TCP_KEEPIDLE,
+ (char*)&server->root->tcp_keepidle, (socklen_t)sizeof(int));
+ (void)(error);
+ assert(error == 0);
+ }
}
-#endif
if (server->root->send_size > 0)
{
/* libmemcached will always use nonblocking IO to avoid write deadlocks */
set_socket_nonblocking(server);
+
+ return true;
}
static memcached_return_t unix_socket_connect(org::libmemcached::Instance* server)
return memcached_set_errno(*server, get_socket_errno(), NULL);
}
-#ifdef HAVE_FCNTL
- // If SOCK_CLOEXEC exists then we don't need to call the following
- if (SOCK_CLOEXEC == 0)
+ if (set_socket_options(server) == false)
{
- if (FD_CLOEXEC)
- {
- int rval;
- do
- {
- rval= fcntl (server->fd, F_SETFD, FD_CLOEXEC);
- } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
- }
+ (void)closesocket(server->fd);
+ return MEMCACHED_CONNECTION_FAILURE;
}
-#endif
-
- set_socket_options(server);
/* connect to server */
if ((connect(server->fd, server->address_info_next->ai_addr, server->address_info_next->ai_addrlen) != SOCKET_ERROR))
do {
/* Just try a single read to grab what's available */
ssize_t nr;
- if ((nr= recv(ptr->fd,
+ if ((nr= ::recv(ptr->fd,
ptr->read_ptr + ptr->read_data_length,
MEMCACHED_MAX_BUFFER - ptr->read_data_length,
- MSG_DONTWAIT)) <= 0)
+ MSG_DONTWAIT|MSG_NOSIGNAL)) <= 0)
{
if (nr == 0)
{
ssize_t data_read;
do
{
- data_read= ::recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT);
+ data_read= ::recv(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER, MSG_DONTWAIT|MSG_NOSIGNAL);
if (data_read == SOCKET_ERROR)
{
switch (get_socket_errno())
char buffer[MEMCACHED_MAX_BUFFER];
do
{
- data_read= recv(ptr->fd, ptr->read_buffer, sizeof(buffer), MSG_DONTWAIT);
+ data_read= ::recv(ptr->fd, ptr->read_buffer, sizeof(buffer), MSG_DONTWAIT|MSG_NOSIGNAL);
if (data_read == SOCKET_ERROR)
{
switch (get_socket_errno())
#define memcached_has_replicas(__object) ((__object)->root->number_of_replicas)
#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
-#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized(= (__value))
+#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized= (__value))
#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated= (__value))
#define memcached_set_weighted_ketama(__object, __value) ((__object)->ketama.weighted_= (__value))
noinst_HEADERS+= tests/libmemcached_test_container.h
noinst_HEADERS+= tests/libmemcached_world.h
noinst_HEADERS+= tests/libmemcached_world_socket.h
-noinst_HEADERS+= tests/memc.h
+noinst_HEADERS+= tests/memc.hpp
noinst_HEADERS+= tests/runner.h
# Cycle should always run first
#endif
test_st ketama_auto_eject_hosts[] ={
+ {"basic ketama test", true, (test_callback_fn*)ketama_TEST },
{"auto_eject_hosts", true, (test_callback_fn*)auto_eject_hosts },
{"output_ketama_weighted_keys", true, (test_callback_fn*)output_ketama_weighted_keys },
{0, 0, (test_callback_fn*)0}
#include "tests/libmemcached-1.0/setup_and_teardowns.h"
#include "tests/print.h"
#include "tests/debug.h"
+#include "tests/memc.hpp"
#define UUID_STRING_MAXLENGTH 36
return TEST_SUCCESS;
}
+test_return_t ketama_TEST(memcached_st *)
+{
+ test::Memc memc("--server=10.0.1.1:11211 --server=10.0.1.2:11211");
+
+ test_compare(MEMCACHED_SUCCESS,
+ memcached_behavior_set(&memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED, true));
+
+ test_compare(memcached_behavior_get(&memc, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED), uint64_t(1));
+
+ test_compare(memcached_behavior_set(&memc, MEMCACHED_BEHAVIOR_KETAMA_HASH, MEMCACHED_HASH_MD5), MEMCACHED_SUCCESS);
+
+ test_compare(memcached_behavior_get(&memc, MEMCACHED_BEHAVIOR_KETAMA_HASH), MEMCACHED_HASH_MD5);
+
+ test_compare(memcached_behavior_set_distribution(&memc, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY), MEMCACHED_SUCCESS);
+
+
+ return TEST_SUCCESS;
+}
+
test_return_t output_ketama_weighted_keys(memcached_st *)
{
memcached_st *memc= memcached_create(NULL);
test_return_t murmur3_TEST(hashkit_st *);
test_return_t noreply_test(memcached_st *memc);
test_return_t one_at_a_time_run (memcached_st *);
+test_return_t ketama_TEST(memcached_st *);
test_return_t output_ketama_weighted_keys(memcached_st *);
test_return_t libmemcached_util_ping_TEST(memcached_st*);
test_return_t prepend_test(memcached_st *memc);
return NULL;
}
- if ((servers.sasl()) and ((LIBMEMCACHED_WITH_SASL_SUPPORT == 0)))
+ if (servers.sasl())
{
- error= TEST_SKIPPED;
- return NULL;
- }
-
- if (HAVE_MEMCACHED_SASL_BINARY == 0)
- {
- error= TEST_SKIPPED;
- return NULL;
- }
+ if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+ {
+ error= TEST_SKIPPED;
+ return NULL;
+ }
- // Assume we are running under valgrind, and bail
- if (servers.sasl() and getenv("TESTS_ENVIRONMENT"))
- {
- error= TEST_SKIPPED;
- return NULL;
+ if (HAVE_MEMCACHED_SASL_BINARY == 0)
+ {
+ error= TEST_SKIPPED;
+ return NULL;
+ }
+
+ // Assume we are running under valgrind, and bail
+ if (getenv("TESTS_ENVIRONMENT"))
+ {
+ error= TEST_SKIPPED;
+ return NULL;
+ }
}
for (uint32_t x= 0; x < servers.servers_to_run(); x++)
if (server_startup(servers, "memcached-sasl", port, 0, NULL) == false)
{
error= TEST_SKIPPED;
-#if 0
- fatal_message("Could not start memcached-sasl");
-#endif
return NULL;
}
}
if (server_startup(servers, "memcached", port, 0, NULL) == false)
{
error= TEST_SKIPPED;
-#if 0
- fatal_message("Could not start memcached");
-#endif
return NULL;
}
}
+++ /dev/null
-/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- * Gearmand client and server library.
- *
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * 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.
- *
- */
-
-#pragma once
-
-class Memc {
-public:
- Memc()
- {
- _memc= memcached_create(NULL);
-
- if (_memc == NULL)
- {
- throw "memcached_create() failed";
- }
- }
-
- Memc(memcached_st* arg)
- {
- _memc= memcached_clone(NULL, arg);
-
- if (_memc == NULL)
- {
- throw "memcached_clone() failed";
- }
- }
-
- memcached_st* operator&() const
- {
- return _memc;
- }
-
- memcached_st* operator->() const
- {
- return _memc;
- }
-
- ~Memc()
- {
- memcached_free(_memc);
- }
-
-private:
- memcached_st *_memc;
-
-};
--- /dev/null
+/* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ * 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.
+ *
+ */
+
+#pragma once
+
+namespace test {
+
+class Memc {
+public:
+ Memc()
+ {
+ _memc= memcached_create(NULL);
+
+ if (_memc == NULL)
+ {
+ throw "memcached_create() failed";
+ }
+ }
+
+ Memc(const memcached_st* arg)
+ {
+ _memc= memcached_clone(NULL, arg);
+
+ if (_memc == NULL)
+ {
+ throw "memcached_clone() failed";
+ }
+ }
+
+ Memc(const std::string& arg)
+ {
+ _memc= memcached(arg.c_str(), arg.size());
+ if (_memc == NULL)
+ {
+ throw "memcached() failed";
+ }
+ }
+
+ Memc(in_port_t arg)
+ {
+ _memc= memcached_create(NULL);
+
+ if (_memc == NULL)
+ {
+ throw "memcached_create() failed";
+ }
+ memcached_server_add(_memc, "localhost", arg);
+ }
+
+ memcached_st* operator&() const
+ {
+ return _memc;
+ }
+
+ memcached_st* operator->() const
+ {
+ return _memc;
+ }
+
+ ~Memc()
+ {
+ memcached_free(_memc);
+ }
+
+private:
+ memcached_st *_memc;
+
+};
+
+} // namespace test
#pragma once
#include "tests/libmemcached-1.0/generate.h"
-#include "tests/memc.h"
+#include "tests/memc.hpp"
#include "tests/print.h"
class LibmemcachedRunner : public libtest::Runner {
test_return_t flush(libmemcached_test_container_st *container)
{
- Memc memc(container->parent());
+ test::Memc memc(container->parent());
memcached_flush(&memc, 0);
memcached_quit(&memc);
{
test_true(container);
test_true(container->parent());
- Memc memc(container->parent());
+ test::Memc memc(container->parent());
test_compare(true, check());