pgpool2.git / summary / log / commit / refs
commit 28bdbfa516a8e66750734fb66e63de419ca29155
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Thu Aug 05 08:08:44 2010 +0000
Implement pcp_detatch_node gracefull mode.
i.e. wait until all clients disconnected.
doc/pgpool-en.html | 6 ++++--
doc/pgpool-ja.html | 6 ++++--
pcp/pcp.c | 30 ++++++++++++++++++++++++--
pcp/pcp.h | 1 +
pcp/pcp_detach_node.c | 21 ++++++++++++++----
pcp_child.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++-
pool.h | 1 +
recovery.c | 3 +--
8 files changed, 115 insertions(+), 13 deletions(-)
diff --git a/doc/pgpool-en.html b/doc/pgpool-en.html
index a55b50b99..3018e3a51 100644
--- a/doc/pgpool-en.html
+++ b/doc/pgpool-en.html
@@ -7,7 +7,7 @@
</head>
<!-- hhmts start -->
-Last modified: Thu Aug 5 12:08:51 JST 2010
+Last modified: Thu Aug 5 16:59:08 JST 2010
<!-- hhmts end -->
<body bgcolor="#ffffff">
@@ -2383,10 +2383,12 @@ BackendError will be displayed.</p>
<h3>pcp_detach_node</h3>
<pre>
Format:
-pcp_detach_node _timeout_ _host_ _port_ _userid_ _passwd_ _nodeid_
+pcp_detach_node [-g] _timeout_ _host_ _port_ _userid_ _passwd_ _nodeid_
</pre>
<p>
Detaches the given node from pgpool-II.
+If -g is given, wait until all clients are disconnected (unless
+client_idle_limit_in_recovery is -1 or recovery_timeout is expired).
</p>
diff --git a/doc/pgpool-ja.html b/doc/pgpool-ja.html
index 691f16306..b3153815a 100644
--- a/doc/pgpool-ja.html
+++ b/doc/pgpool-ja.html
@@ -8,7 +8,7 @@
<body>
<!-- hhmts start -->
-Last modified: Thu Aug 5 11:40:10 JST 2010
+Last modified: Thu Aug 5 16:59:41 JST 2010
<!-- hhmts end -->
<body bgcolor="#ffffff">
@@ -3085,9 +3085,11 @@ configure $B$K<:GT$7$^$9!#I,$:(B libpq 3.0 (PostgreSQL 7.4) $B$r%j%s%/$9$k$h
<p>
<pre>
$B=q<0!'(B
- pcp_detach_node _timeout_ _host_ _port_ _userid_ _passwd_ _nodeid_
+ pcp_detach_node [-g] _timeout_ _host_ _port_ _userid_ _passwd_ _nodeid_
pgpool-II$B$N%N!<%I$r@Z$jN%$7$^$9!#(B
+-g$B$r;XDj$9$k$H!"$9$Y$F$N%/%i%$%"%s%H$,@\B3$r=*N;$9$k$^$G%N!<%I$rI|5"$7$^$;$s!#(B
+($B$?$@$7!"(Bclient_idle_limit_in_recovery $B$,(B -1 $B$"$k$$$O!"(Brecovery_timeout $B$,@_Dj$5$l$F$$$k>l9g$r=|$/(B)
</pre>
</p>
diff --git a/pcp/pcp.c b/pcp/pcp.c
index 49bbb845d..1955155b3 100644
--- a/pcp/pcp.c
+++ b/pcp/pcp.c
@@ -8,7 +8,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2008 PgPool Global Development Group
+ * Copyright (c) 2003-2010 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -49,6 +49,8 @@ static int debug = 0;
#endif
static int pcp_authorize(char *username, char *password);
+static int _pcp_detach_node(int nid, bool gracefully);
+
/* --------------------------------
* pcp_connect - open connection to pgpool using given arguments
*
@@ -1078,12 +1080,31 @@ free_systemdb_info(SystemDBInfo * si)
*/
int
pcp_detach_node(int nid)
+{
+ return _pcp_detach_node(nid, FALSE);
+}
+
+/* --------------------------------
+
+ * and dettach a node given by the argument from pgpool's control
+ *
+ * return 0 on success, -1 otherwise
+ * --------------------------------
+ */
+int
+pcp_detach_node_gracefully(int nid)
+{
+ return _pcp_detach_node(nid, TRUE);
+}
+
+static int _pcp_detach_node(int nid, bool gracefully)
{
int wsize;
char node_id[16];
char tos;
char *buf = NULL;
int rsize;
+ char *sendchar;
if (pc == NULL)
{
@@ -1094,7 +1115,12 @@ pcp_detach_node(int nid)
snprintf(node_id, sizeof(node_id), "%d", nid);
- pcp_write(pc, "D", 1);
+ if (gracefully)
+ sendchar = "d";
+ else
+ sendchar = "D";
+
+ pcp_write(pc, sendchar, 1);
wsize = htonl(strlen(node_id)+1 + sizeof(int));
pcp_write(pc, &wsize, sizeof(int));
pcp_write(pc, node_id, strlen(node_id)+1);
diff --git a/pcp/pcp.h b/pcp/pcp.h
index 71d25d3ad..e18f08383 100644
--- a/pcp/pcp.h
+++ b/pcp/pcp.h
@@ -59,6 +59,7 @@ extern ProcessInfo *pcp_process_info(int pid, int *array_size);
extern SystemDBInfo *pcp_systemdb_info(void);
extern void free_systemdb_info(SystemDBInfo * si);
extern int pcp_detach_node(int nid);
+extern int pcp_detach_node_gracefully(int nid);
extern int pcp_attach_node(int nid);
extern void pcp_set_timeout(long sec);
extern int pcp_recovery_node(int nid);
diff --git a/pcp/pcp_detach_node.c b/pcp/pcp_detach_node.c
index 3be3c1bc8..b8d56d54c 100644
--- a/pcp/pcp_detach_node.c
+++ b/pcp/pcp_detach_node.c
@@ -4,7 +4,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2008 PgPool Global Development Group
+ * Copyright (c) 2003-2010 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -42,19 +42,26 @@ main(int argc, char **argv)
int nodeID;
int ch;
int optindex;
+ bool gracefully = false;
+ int sts;
static struct option long_options[] = {
{"debug", no_argument, NULL, 'd'},
+ {"gracefully", no_argument, NULL, 'g'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
- while ((ch = getopt_long(argc, argv, "hd", long_options, &optindex)) != -1) {
+ while ((ch = getopt_long(argc, argv, "hdg", long_options, &optindex)) != -1) {
switch (ch) {
case 'd':
pcp_enable_debug();
break;
+ case 'g':
+ gracefully = true;
+ break;
+
case 'h':
case '?':
default:
@@ -127,7 +134,12 @@ main(int argc, char **argv)
myexit(errorcode);
}
- if (pcp_detach_node(nodeID))
+ if (gracefully)
+ sts = pcp_detach_node_gracefully(nodeID);
+ else
+ sts = pcp_detach_node(nodeID);
+
+ if (sts)
{
pcp_errorstr(errorcode);
pcp_disconnect();
@@ -143,9 +155,10 @@ static void
usage(void)
{
fprintf(stderr, "pcp_detach_node - detach a node from pgpool-II\n\n");
- fprintf(stderr, "Usage: pcp_detach_node [-d] timeout hostname port# username password nodeID\n");
+ fprintf(stderr, "Usage: pcp_detach_node [-d][-g] timeout hostname port# username password nodeID\n");
fprintf(stderr, "Usage: pcp_detach_node -h\n\n");
fprintf(stderr, " -d - enable debug message (optional)\n");
+ fprintf(stderr, " -g - detach gracefully(optional)\n");
fprintf(stderr, " timeout - connection timeout value in seconds. command exits on timeout\n");
fprintf(stderr, " hostname - pgpool-II hostname\n");
fprintf(stderr, " port# - PCP port number\n");
diff --git a/pcp_child.c b/pcp_child.c
index 8c4291733..1b0d4fd9f 100644
--- a/pcp_child.c
+++ b/pcp_child.c
@@ -68,6 +68,7 @@ static void unset_nonblock(int fd);
static int user_authenticate(char *buf, char *passwd_file, char *salt, int salt_len);
static RETSIGTYPE wakeup_handler(int sig);
static RETSIGTYPE reload_config_handler(int sig);
+static int pool_detach_node(int node_id, bool gracefully);
extern int myargc;
extern char **myargv;
@@ -683,14 +684,21 @@ pcp_do_child(int unix_fd, int inet_fd, char *pcp_conf_file)
}
case 'D': /* detach node */
+ case 'd': /* detach node gracefully */
{
int node_id;
int wsize;
char code[] = "CommandComplete";
+ bool gracefully;
+
+ if (tos == 'D')
+ gracefully = false;
+ else
+ gracefully = true;
node_id = atoi(buf);
pool_debug("pcp_child: detaching Node ID %d", node_id);
- notice_backend_error(node_id);
+ pool_detach_node(node_id, gracefully);
pcp_write(frontend, "d", 1);
wsize = htonl(sizeof(code) + sizeof(int));
@@ -1087,3 +1095,53 @@ static RETSIGTYPE reload_config_handler(int sig)
{
pcp_got_sighup = 1;
}
+
+/* Dedatch a node */
+static int pool_detach_node(int node_id, bool gracefully)
+{
+ pool_log("gracefully: %d", gracefully);
+
+ if (!gracefully)
+ {
+ notice_backend_error(node_id); /* send failover request */
+ return 0;
+ }
+
+ /*
+ * Wait until all frontends exit
+ */
+ *InRecovery = 1; /* This wiil ensure that new incoming
+ * connection requests are blocked */
+
+ if (wait_connection_closed())
+ {
+ /* wait timed out */
+ finish_recovery();
+ return -1;
+ }
+
+ /*
+ * Now all frontends have gone. Let's do failover.
+ */
+ notice_backend_error(node_id); /* send failover request */
+
+ /*
+ * Wait for failover completed.
+ */
+ pcp_wakeup_request = 0;
+
+ while (!pcp_wakeup_request)
+ {
+ struct timeval t = {1, 0};
+ select(0, NULL, NULL, NULL, &t);
+ }
+ pcp_wakeup_request = 0;
+
+ /*
+ * Start to accept incoming connections and send SIGUSR2 to pgpool
+ * parent to distribute SIGUSR2 all pgpool children.
+ */
+ finish_recovery();
+
+ return 0;
+}
diff --git a/pool.h b/pool.h
index 61c914b78..5e7dfa70f 100644
--- a/pool.h
+++ b/pool.h
@@ -551,6 +551,7 @@ extern const char *get_ps_display(int *displen);
/* recovery.c */
extern int start_recovery(int recovery_node);
extern void finish_recovery(void);
+extern int wait_connection_closed(void);
/* child.c */
extern void cancel_request(CancelPacket *sp);
diff --git a/recovery.c b/recovery.c
index f5af4920d..5eb41da93 100644
--- a/recovery.c
+++ b/recovery.c
@@ -41,7 +41,6 @@ static int exec_checkpoint(PGconn *conn);
static int exec_recovery(PGconn *conn, BackendInfo *backend, char stage);
static int exec_remote_start(PGconn *conn, BackendInfo *backend);
static PGconn *connect_backend_libpq(BackendInfo *backend);
-static int wait_connection_closed(void);
static int check_postmaster_started(BackendInfo *backend);
static char recovery_command[1024];
@@ -347,7 +346,7 @@ static PGconn *connect_backend_libpq(BackendInfo *backend)
/*
* Wait all connections are closed.
*/
-static int wait_connection_closed(void)
+int wait_connection_closed(void)
{
int i = 0;
[parent: 33dcc931a3aa]