This patch creates a couple of tests around how autoeject works.
authorBrian Aker <brian@tangent.org>
Sat, 20 Aug 2011 07:01:20 +0000 (00:01 -0700)
committerBrian Aker <brian@tangent.org>
Sat, 20 Aug 2011 07:01:20 +0000 (00:01 -0700)
libmemcached/constants.h
libmemcached/server.cc
libmemcached/server.h
libmemcached/server.hpp
libtest/include.am
libtest/port.cc [new file with mode: 0644]
libtest/port.h [new file with mode: 0644]
libtest/server_container.cc
libtest/test.cc
libtest/test.hpp
tests/failure.cc

index 7a84b9a80abb0b81360c21a85accca29b2e652be..106aec496d5050f30c2d2c2da435810611e4350e 100644 (file)
@@ -54,7 +54,7 @@
 #define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
 #define MEMCACHED_VERSION_STRING_LENGTH 24
 #define MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH 20
-#define MEMCACHED_SERVER_FAILURE_LIMIT 2
+#define MEMCACHED_SERVER_FAILURE_LIMIT 5
 #define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
 
 
index 022dda4f70be04d891746275c6cbe6318c34b0e1..ed360ee31aaa2f14f560df9e5e92059dcc6562a1 100644 (file)
@@ -53,6 +53,7 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
   self->fd= -1;
   self->io_bytes_sent= 0;
   self->server_failure_counter= 0;
+  self->server_failure_counter_query_id= 0;
   self->weight= weight ? weight : 1; // 1 is the default weight value
   WATCHPOINT_SET(self->io_wait_count.read= 0);
   WATCHPOINT_SET(self->io_wait_count.write= 0);
index e6f3a30a2884a1820ee5a2cd6e89e811c30a8a9f..3afb5202f6eb95dcabf55cf0a73f688dd931ec13 100644 (file)
@@ -63,6 +63,7 @@ struct memcached_server_st {
   memcached_socket_t fd;
   uint32_t io_bytes_sent; /* # bytes sent since last read */
   uint32_t server_failure_counter;
+  uint64_t server_failure_counter_query_id;
   uint32_t weight;
   uint32_t version;
   enum memcached_server_state_t state;
index 320da1152fe0f07aea280dbfda3ad98e3a29c0cc..8cfcbdba229fa75112d9acd83a3953e8fa869ef8 100644 (file)
@@ -93,7 +93,11 @@ static inline void memcached_mark_server_for_timeout(memcached_server_write_inst
     }
 
     server->state= MEMCACHED_SERVER_STATE_IN_TIMEOUT;
-    server->server_failure_counter++;
+    if (server->server_failure_counter_query_id != server->root->query_id)
+    {
+      server->server_failure_counter++;
+      server->server_failure_counter_query_id= server->root->query_id;
+    }
     set_last_disconnected_host(server);
   }
 }
index d7394fd090c9e78ccabc092322acf611bcfe2250..044ca4f8e7bf9e2b8cbcda171936d8cba8c2ca54 100644 (file)
@@ -69,6 +69,7 @@ noinst_HEADERS+= \
                 libtest/libtool.hpp \
                 libtest/memcached.h \
                 libtest/runner.h \
+                libtest/port.h \
                 libtest/server.h \
                 libtest/server_container.h \
                 libtest/signal.h \
@@ -88,6 +89,7 @@ libtest_libtest_la_SOURCES= \
                            libtest/killpid.cc \
                            libtest/libtool.cc \
                            libtest/runner.cc \
+                           libtest/port.cc \
                            libtest/server.cc \
                            libtest/server_container.cc \
                            libtest/signal.cc \
diff --git a/libtest/port.cc b/libtest/port.cc
new file mode 100644 (file)
index 0000000..9bd7717
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 3 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#include <libtest/common.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <ctime>
+#include <fnmatch.h>
+#include <iostream>
+
+#include <signal.h>
+
+#include <libtest/stats.h>
+#include <libtest/signal.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+using namespace libtest;
+
+static in_port_t global_port= 0;
+static in_port_t global_max_port= 0;
+
+in_port_t default_port()
+{
+  return global_port;
+}
+void set_default_port(in_port_t port)
+{
+  global_port= port;
+}
+
+in_port_t max_port()
+{
+  return global_max_port;
+}
+void set_max_port(in_port_t port)
+{
+  if (port > global_max_port)
+  {
+    global_max_port= port;
+  }
+
+  global_max_port= port;
+}
diff --git a/libtest/port.h b/libtest/port.h
new file mode 100644 (file)
index 0000000..63b2992
--- /dev/null
@@ -0,0 +1,39 @@
+/*  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
+ */
+
+
+/*
+  Structures for generic tests.
+*/
+
+#pragma once
+
+LIBTEST_API
+in_port_t default_port();
+
+LIBTEST_API
+void set_default_port(in_port_t port);
+
+LIBTEST_API
+in_port_t max_port();
+
+LIBTEST_API
+void set_max_port(in_port_t port);
index bba1240cabc5019022c6e5f3250a55604776669d..684303a23934ef09e7a4e62352cc44219fc8a60d 100644 (file)
@@ -147,6 +147,8 @@ bool server_startup(server_startup_st& construct, const std::string& server_type
   Outn();
   (void)try_port;
 
+  set_max_port(try_port);
+
   // Look to see if we are being provided ports to use
   {
     char variable_buffer[1024];
index 5c43e40b35d9f0211d076c19d24c6864fe7dfa59..89e7c07112e674c6a8a2be1e9c40cbf5c2a9733b 100644 (file)
 
 using namespace libtest;
 
-static in_port_t global_port= 0;
 static char global_socket[1024];
 
-in_port_t default_port()
-{
-  return global_port;
-}
-void set_default_port(in_port_t port)
-{
-  global_port= port;
-}
-
 const char *default_socket()
 {
   assert(global_socket[0]);
index a10aa30dd2f927adc3a9ace9a1bdfe10eb4685f6..047dd8ce03390f245e5c6c71f95c0672786d154a 100644 (file)
@@ -41,6 +41,7 @@
 #include <libtest/strerror.h>
 #include <libtest/core.h>
 #include <libtest/runner.h>
+#include <libtest/port.h>
 #include <libtest/stats.h>
 #include <libtest/collection.h>
 #include <libtest/framework.h>
index 185f9c71d9647de0920c5672928bbfb20477853f..c616a262d794f52253e8779f875effb7afff3220 100644 (file)
@@ -71,6 +71,22 @@ static test_return_t shutdown_servers(memcached_st *memc)
   return TEST_SUCCESS;
 }
 
+static test_return_t add_shutdown_servers(memcached_st *memc)
+{
+  while (memcached_server_count(memc) < 2)
+  {
+    const char *argv[1]= { "add_shutdown_server" };
+    in_port_t port= max_port() +1;
+    test_true(global_framework->servers().start_socket_server("memcached", port, 1, argv));
+    test_compare(MEMCACHED_SUCCESS, memcached_server_add(memc, "localhost", port));
+  }
+
+  // Disable a single server, just the first
+  global_framework->servers().shutdown(0);
+
+  return TEST_SUCCESS;
+}
+
 static test_return_t restart_servers(memcached_st *)
 {
   // Restart the servers
@@ -142,6 +158,29 @@ static test_return_t MEMCACHED_SERVER_TEMPORARILY_DISABLED_to_success_TEST(memca
   return TEST_SUCCESS;
 }
 
+static test_return_t MEMCACHED_SERVER_MARKED_DEAD_TEST(memcached_st *memc)
+{
+  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, 30));
+  test_compare(MEMCACHED_SUCCESS, memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS, true));
+
+  memcached_return_t ret;
+  do {
+    ret= memcached_set(memc,
+                       test_literal_param("foo"),
+                       NULL, 0, time_t(0), uint32_t(0));
+  } while (ret == MEMCACHED_SUCCESS or ret == MEMCACHED_CONNECTION_FAILURE);
+  test_compare(MEMCACHED_SERVER_TEMPORARILY_DISABLED, ret);
+
+  do {
+    sleep(3);
+    ret= memcached_set(memc, test_literal_param("foo"), NULL, 0, time_t(0), uint32_t(0));
+  } while (ret == MEMCACHED_SERVER_TEMPORARILY_DISABLED or ret == MEMCACHED_SUCCESS);
+
+  test_compare_got(MEMCACHED_SERVER_MARKED_DEAD, ret, memcached_last_error_message(memc));
+
+  return TEST_SUCCESS;
+}
+
 test_st cull_TESTS[] ={
   { "cull servers", true, (test_callback_fn*)cull_TEST },
   { 0, 0, 0 }
@@ -153,9 +192,15 @@ test_st server_temporarily_disabled_TESTS[] ={
   { 0, 0, 0 }
 };
 
+test_st server_permanently_disabled_TESTS[] ={
+  { "memcached_set(MEMCACHED_SERVER_MARKED_DEAD)", true, (test_callback_fn*)MEMCACHED_SERVER_MARKED_DEAD_TEST },
+  { 0, 0, 0 }
+};
+
 collection_st collection[] ={
   { "cull", (test_callback_fn*)shutdown_servers, (test_callback_fn*)restart_servers, cull_TESTS },
   { "server failed", (test_callback_fn*)shutdown_servers, (test_callback_fn*)restart_servers, server_temporarily_disabled_TESTS },
+  { "server eject", (test_callback_fn*)add_shutdown_servers, (test_callback_fn*)restart_servers, server_permanently_disabled_TESTS },
   { 0, 0, 0, 0 }
 };