From: Tatsuo Ishii Date: Thu, 5 Aug 2010 08:08:44 +0000 (+0000) Subject: Implement pcp_detatch_node gracefull mode. X-Git-Tag: V3_0_0_BETA1~58 X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=28bdbfa516a8e66750734fb66e63de419ca29155;p=pgpool2.git Implement pcp_detatch_node gracefull mode. i.e. wait until all clients disconnected. --- 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 @@ -Last modified: Thu Aug 5 12:08:51 JST 2010 +Last modified: Thu Aug 5 16:59:08 JST 2010 @@ -2383,10 +2383,12 @@ BackendError will be displayed.

pcp_detach_node

 Format:
-pcp_detach_node  _timeout_  _host_  _port_  _userid_  _passwd_  _nodeid_
+pcp_detach_node  [-g] _timeout_  _host_  _port_  _userid_  _passwd_  _nodeid_
 

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).

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 @@ -Last modified: Thu Aug 5 11:40:10 JST 2010 +Last modified: Thu Aug 5 16:59:41 JST 2010 @@ -3085,9 +3085,11 @@ configure に失敗します。必ず libpq 3.0 (PostgreSQL 7.4) をリンクするよ

    $B書式:
-	pcp_detach_node  _timeout_  _host_  _port_  _userid_  _passwd_  _nodeid_
+	pcp_detach_node  [-g] _timeout_  _host_  _port_  _userid_  _passwd_  _nodeid_
 
    pgpool-IIのノードを切り離します。
+-gを指定すると、すべてのクライアントが接続を終了するまでノードを復帰しません。
+(ただし、client_idle_limit_in_recovery が -1 あるいは、recovery_timeout が設定されている場合を除く)
 

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;