summaryrefslogtreecommitdiff
path: root/test/testmemcache.c
diff options
context:
space:
mode:
authorRuediger Pluem <rpluem@apache.org>2023-05-03 07:47:15 +0000
committerRuediger Pluem <rpluem@apache.org>2023-05-03 07:47:15 +0000
commit4b0778590349e2ff2b07073615f1b82ad83d35de (patch)
tree078f1c5994a5c8410ebbe85828e0f6b7fd74be00 /test/testmemcache.c
parent572ffea6a5b1aae06333385cbbec0069c6140ba2 (diff)
downloadapr-4b0778590349e2ff2b07073615f1b82ad83d35de.tar.gz
Check sockets from connection pool before using them and try to reconnect
them if they are not usable any longer. * memcache/apr_memcache.c::ms_find_conn: Check if the socket returned from the connection pool is still readable. If not then invalidate the connection in the pool and request a new one from the connection pool. Repeat this until a valid socket is returned or this was done the maximum number of connections in the pool plus one. This ensures that at least one new socket was created. If a new socket does not work this indicates a broken backend and not just a restart in the past. In this case return an error like previously. * test/testmemcache.c: Add new test for connection validation. * test/memcachedmock.c: For the new test we need a memcached mock server that we control and can restart. * test/testmemcache.h: Shared defines between test/testmemcache.c and test/memcachedmock.c. * test/Makefile.in: * test/Makefile.win: * test/NWGNUmakefile: * test/NWGNUmemcachedmock: Needed changes to build test/memcachedmock.c on different platforms. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1909585 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'test/testmemcache.c')
-rw-r--r--test/testmemcache.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/test/testmemcache.c b/test/testmemcache.c
index 33e0e7c45..20fad58d1 100644
--- a/test/testmemcache.c
+++ b/test/testmemcache.c
@@ -23,6 +23,8 @@
#include "apr_memcache.h"
#include "apr_network_io.h"
#include "apr_thread_proc.h"
+#include "apr_signal.h"
+#include "testmemcache.h"
#if APR_HAVE_STDLIB_H
#include <stdlib.h> /* for exit() */
@@ -662,6 +664,72 @@ static void test_memcache_setget(abts_case * tc, void *data)
}
}
+static void test_connection_validation(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+ apr_memcache_t *memcache;
+ apr_memcache_server_t *memserver;
+ char *result;
+ apr_procattr_t *procattr;
+ apr_proc_t proc;
+ const char *args[2];
+ int exitcode;
+ apr_exit_why_e why;
+#ifdef SIGPIPE
+ /*
+ * If SIGPIPE is present ignore it as we will write to a closed socket.
+ * Otherwise we would be terminated by the default handler for SIGPIPE.
+ */
+ apr_sigfunc_t *old_action;
+
+ old_action = apr_signal(SIGPIPE, SIG_IGN);
+#endif
+
+ rv = apr_procattr_create(&procattr, p);
+ ABTS_ASSERT(tc, "Couldn't create procattr", rv == APR_SUCCESS);
+
+ rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE,
+ APR_NO_PIPE);
+ ABTS_ASSERT(tc, "Couldn't set io in procattr", rv == APR_SUCCESS);
+
+ rv = apr_procattr_error_check_set(procattr, 1);
+ ABTS_ASSERT(tc, "Couldn't set error check in procattr", rv == APR_SUCCESS);
+
+ rv = apr_procattr_cmdtype_set(procattr, APR_PROGRAM_ENV);
+ ABTS_ASSERT(tc, "Couldn't set copy environment", rv == APR_SUCCESS);
+
+ args[0] = "memcachedmock" EXTENSION;
+ args[1] = NULL;
+ rv = apr_proc_create(&proc, TESTBINPATH "memcachedmock" EXTENSION, args, NULL,
+ procattr, p);
+ ABTS_ASSERT(tc, "Couldn't launch program", rv == APR_SUCCESS);
+
+ /* Wait for the mock memcached to start */
+ apr_sleep(apr_time_from_sec(2));
+
+ rv = apr_memcache_create(p, 1, 0, &memcache);
+ ABTS_ASSERT(tc, "memcache create failed", rv == APR_SUCCESS);
+
+ rv = apr_memcache_server_create(p, MOCK_HOST, MOCK_PORT, 0, 1, 1, 60000, &memserver);
+ ABTS_ASSERT(tc, "server create failed", rv == APR_SUCCESS);
+
+ rv = apr_memcache_add_server(memcache, memserver);
+ ABTS_ASSERT(tc, "server add failed", rv == APR_SUCCESS);
+
+ rv = apr_memcache_version(memserver, p, &result);
+ ABTS_ASSERT(tc, "Couldn't get initial version", rv == APR_SUCCESS);
+
+ rv = apr_memcache_version(memserver, p, &result);
+ ABTS_ASSERT(tc, "Couldn't get version after connection shutdown", rv == APR_SUCCESS);
+
+#ifdef SIGPIPE
+ /* Restore old SIGPIPE handler */
+ apr_signal(SIGPIPE, old_action);
+#endif
+
+ apr_proc_wait(&proc, &exitcode, &why, APR_WAIT);
+}
+
abts_suite *testmemcache(abts_suite * suite)
{
suite = ADD_SUITE(suite);
@@ -672,6 +740,7 @@ abts_suite *testmemcache(abts_suite * suite)
abts_run_test(suite, test_memcache_multiget, NULL);
abts_run_test(suite, test_memcache_addreplace, NULL);
abts_run_test(suite, test_memcache_incrdecr, NULL);
+ abts_run_test(suite, test_connection_validation, NULL);
return suite;
}