Subject: | disconnect_all implementation |
As the POD says, disconnect_all() is still to be implemented.
Unfortunately, it is necessary to call it in a mod_perl environment. The
Cache::Memcached::Managed wrapper module already tries to detect forking
and calls it when appropriate, but the documented workaround (ie.
undefining the object to trigger its destruction) cannot be used with
Cache::Memcached::Managed (without overwriting its reset method, and
that's better to avoid).
Please check the attached patch for a preliminary implementation of
disconnect_all. Please let me know what I should change.
Subject: | Cache-Memcached-Fast-disconnect_all.diff |
diff -Naur Cache-Memcached-Fast-0.13/Fast.xs Cache-Memcached-Fast-0.13-fixed/Fast.xs
--- Cache-Memcached-Fast-0.13/Fast.xs 2008-10-13 17:41:49.000000000 +0200
+++ Cache-Memcached-Fast-0.13-fixed/Fast.xs 2008-11-20 00:35:18.000000000 +0100
@@ -1255,3 +1255,11 @@
}
OUTPUT:
RETVAL
+
+
+void
+disconnect_all(memd)
+ Cache_Memcached_Fast * memd
+ PROTOTYPE: $
+ CODE:
+ client_reinit(memd->c);
diff -Naur Cache-Memcached-Fast-0.13/lib/Cache/Memcached/Fast.pm Cache-Memcached-Fast-0.13-fixed/lib/Cache/Memcached/Fast.pm
--- Cache-Memcached-Fast-0.13/lib/Cache/Memcached/Fast.pm 2008-10-13 17:41:49.000000000 +0200
+++ Cache-Memcached-Fast-0.13-fixed/lib/Cache/Memcached/Fast.pm 2008-11-20 00:35:18.000000000 +0100
@@ -1185,6 +1185,22 @@
# See Fast.xs.
+=item C<disconnect_all>
+
+ $memd->disconnect_all;
+
+Closes all open sockets to memcached servers. Must be called after
+L<perlfunc/fork> if the parent process has open sockets to memcacheds (as the
+child process inherits the socket and thus two processes end up using the same
+socket which leads to protocol errors.)
+
+I<Return:> The C<$memd> object.
+
+=cut
+
+# See Fast.xs.
+
+
1;
__END__
@@ -1285,17 +1301,6 @@
Not supported. Perhaps will appear in the future releases.
-=item C<disconnect_all>
-
-Not supported. Easy to add. Meanwhile to disconnect from all servers
-you may do
-
- undef $memd;
-
-or
-
- $memd = undef;
-
=back
diff -Naur Cache-Memcached-Fast-0.13/src/client.c Cache-Memcached-Fast-0.13-fixed/src/client.c
--- Cache-Memcached-Fast-0.13/src/client.c 2008-10-13 17:41:49.000000000 +0200
+++ Cache-Memcached-Fast-0.13-fixed/src/client.c 2008-11-20 00:36:35.000000000 +0100
@@ -181,6 +181,27 @@
}
+static inline
+int
+command_state_reinit(struct command_state *state)
+{
+ if (state->fd != -1)
+ close(state->fd);
+
+ state->fd = -1;
+ state->last_cmd_noreply = 0;
+
+ array_clear(state->iov_buf);
+
+ state->generation = 0;
+ state->nowait_count = 0;
+
+ state->pos = state->end = state->eol = state->buf;
+
+ return 0;
+}
+
+
struct server
{
char *host;
@@ -240,6 +261,20 @@
}
+static inline
+int
+server_reinit(struct server *s)
+{
+ s->failure_count = 0;
+ s->failure_expires = 0;
+
+ if (command_state_reinit(&s->cmd_state) != 0)
+ return MEMCACHED_FAILURE;
+
+ return MEMCACHED_SUCCESS;
+}
+
+
struct index_node
{
int index;
@@ -412,6 +447,19 @@
}
+inline
+void
+client_reinit(struct client *c)
+{
+ struct server *s;
+
+ for (array_each(c->servers, struct server, s))
+ server_reinit(s);
+
+ array_clear(c->str_buf);
+}
+
+
int
client_set_ketama_points(struct client *c, int ketama_points)
{
diff -Naur Cache-Memcached-Fast-0.13/src/client.h Cache-Memcached-Fast-0.13-fixed/src/client.h
--- Cache-Memcached-Fast-0.13/src/client.h 2008-10-13 17:41:49.000000000 +0200
+++ Cache-Memcached-Fast-0.13-fixed/src/client.h 2008-11-20 00:35:18.000000000 +0100
@@ -96,6 +96,10 @@
void
client_destroy(struct client *c);
+extern
+void
+client_reinit(struct client *);
+
/*
client_set_ketama_points() should be called before adding any server.
*/
diff -Naur Cache-Memcached-Fast-0.13/t/01-connect.t Cache-Memcached-Fast-0.13-fixed/t/01-connect.t
--- Cache-Memcached-Fast-0.13/t/01-connect.t 2008-10-13 17:41:49.000000000 +0200
+++ Cache-Memcached-Fast-0.13-fixed/t/01-connect.t 2008-11-20 00:35:18.000000000 +0100
@@ -11,8 +11,12 @@
if ($Memd::memd) {
diag("Connected to " . scalar @Memd::addr
. " memcached servers, lowest version $Memd::version_str");
- plan tests => 1;
+ plan tests => 2;
pass('connected');
+
+ my $server_versions = $Memd::memd->server_versions;
+ $Memd::memd->disconnect_all;
+ is_deeply($Memd::memd->server_versions, $server_versions, "server_versions still works after disconnect_all");
} else {
plan skip_all => $Memd::error;
}