diff options
author | Ruediger Pluem <rpluem@apache.org> | 2023-05-03 07:47:15 +0000 |
---|---|---|
committer | Ruediger Pluem <rpluem@apache.org> | 2023-05-03 07:47:15 +0000 |
commit | 4b0778590349e2ff2b07073615f1b82ad83d35de (patch) | |
tree | 078f1c5994a5c8410ebbe85828e0f6b7fd74be00 /test/testmemcache.c | |
parent | 572ffea6a5b1aae06333385cbbec0069c6140ba2 (diff) | |
download | apr-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.c | 69 |
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; } |