pgpool2.git / summary / log / commit / refs
commit 3d3fe8611b8a87e8787fc50272c59e40b28daff4
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Sun Feb 19 12:23:45 2012 +0000
Allow health check retry while connect(). It is reported that
connect() blocks sigalarm under some conditions, for example:
> When system is configured for security reasons not to return destination
> host unreachable messages ([pgpool-general: 131])
To enable this, following changes have been made. Part of changes are
contributed by Stevo Slavic.
- Make health_check_timer_expired to be global variable. This is set
when alarm is timed out in health checking process. The variable is
refered to by lower level functions such as
connect_inet_domain_socket_by_port().
- Modify connect_inet_domain_socket_by_port() so that it calls
connect(2) with non block socket. This allows to detect
health_check_timer_expired flag be set while retrying.
- Add retry parameter to make_persistent_db_connection(). The flag is
passed to connect_inet_domain_socket_by_port(). Retry = false is
used by health_check().
- Change pool_read2 etc. not to trigger failover if reading from
socket fails when fail_over_on_backend_error = off. Before
fail_over_on_backend_error is only refered to by socket writing
functions. But treating reading functions so is more consistent.
child.c | 8 ++++----
doc/pgpool-en.html | 9 ++++-----
main.c | 28 ++++++++++++++++++++++------
pgpool.conf.sample | 4 +---
pgpool.conf.sample-master-slave | 4 +---
pgpool.conf.sample-replication | 4 +---
pgpool.conf.sample-stream | 4 +---
pool.h | 6 ++----
pool_connection_pool.c | 20 ++++++++++++++++++--
pool_stream.c | 24 +++++++++++++++++-------
pool_worker_child.c | 2 +-
11 files changed, 72 insertions(+), 41 deletions(-)
diff --git a/child.c b/child.c
index 3dfa460ce..335f6fb6b 100644
--- a/child.c
+++ b/child.c
@@ -1415,7 +1415,7 @@ void child_exit(int code)
* create a persistent connection
*/
POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
- char *hostname, int port, char *dbname, char *user, char *password)
+ char *hostname, int port, char *dbname, char *user, char *password, bool retry)
{
POOL_CONNECTION_POOL_SLOT *cp;
int fd;
@@ -1454,11 +1454,11 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
*/
if (*hostname == '/')
{
- fd = connect_unix_domain_socket_by_port(port, hostname, TRUE);
+ fd = connect_unix_domain_socket_by_port(port, hostname, retry);
}
else
{
- fd = connect_inet_domain_socket_by_port(hostname, port, TRUE);
+ fd = connect_inet_domain_socket_by_port(hostname, port, retry);
}
if (fd < 0)
@@ -1951,7 +1951,7 @@ static void init_system_db_connection(void)
pool_config->system_db_port,
pool_config->system_db_dbname,
pool_config->system_db_user,
- pool_config->system_db_password);
+ pool_config->system_db_password, false);
if (system_db_info->connection == NULL)
{
pool_error("Could not make persistent system DB connection");
diff --git a/doc/pgpool-en.html b/doc/pgpool-en.html
index d6587f1c3..99cdb1f13 100644
--- a/doc/pgpool-en.html
+++ b/doc/pgpool-en.html
@@ -7,7 +7,7 @@
</head>
<!-- hhmts start -->
-Last modified: Sun Nov 20 15:33:45 JST 2011
+Last modified: Sun Feb 19 20:58:54 JST 2012
<!-- hhmts end -->
<body bgcolor="#ffffff">
@@ -778,10 +778,9 @@ pcp_recovery_node command for example.
<dt><a name="FAIL_OVER_ON_BACKEND_ERROR"></a>fail_over_on_backend_error</dt>
<dd>
<p>
-If true, and an error occurs when writing to the backend communication,
-pgpool-II will trigger the fail over procedure . This is the same behavior as of
-pgpool-II 2.2.x or earlier. If set to false, pgpool will report an error and
-disconnect the session.
+If true, and an error occurs when reading/writing to the backend communication,
+pgpool-II will trigger the fail over procedure.
+If set to false, pgpool will report an error and disconnect the session.
If you set this parameter to off, it is recommended that you turn on health checking.
Please note that even if this parameter is set to off, however, pgpool will also do the fail over when
pgpool detects the administrative shutdown of
diff --git a/main.c b/main.c
index 6c0ff21a8..de3c2b43f 100644
--- a/main.c
+++ b/main.c
@@ -116,6 +116,9 @@ static RETSIGTYPE reload_config_handler(int sig);
static RETSIGTYPE health_check_timer_handler(int sig);
static RETSIGTYPE wakeup_handler(int sig);
+static int health_check(void);
+static int system_db_health_check(void);
+
static void usage(void);
static void show_version(void);
static void stop_me(void);
@@ -162,8 +165,6 @@ static int not_detach = 0; /* non 0 if non detach option (-n) is given */
static int stop_sig = SIGTERM; /* stopping signal default value */
-static volatile sig_atomic_t health_check_timer_expired; /* non 0 if health check timer expired */
-
POOL_REQUEST_INFO *Req_info; /* request info area in shared memory */
volatile sig_atomic_t *InRecovery; /* non 0 if recovery is started */
volatile sig_atomic_t reload_config_request = 0;
@@ -714,6 +715,7 @@ int main(int argc, char **argv)
pool_log("set %d th backend down status", sts);
Req_info->kind = NODE_DOWN_REQUEST;
Req_info->node_id[0] = sts;
+ health_check_timer_expired = 0;
failover();
/* need to distribute this info to children */
retrying = false;
@@ -727,8 +729,10 @@ int main(int argc, char **argv)
pool_log("set %d th backend down status", sts);
Req_info->kind = NODE_DOWN_REQUEST;
Req_info->node_id[0] = sts;
+ health_check_timer_expired = 0;
failover();
retrycnt = 0;
+ retrying = false;
}
else
{
@@ -1941,7 +1945,7 @@ static RETSIGTYPE health_check_timer_handler(int sig)
* Check if we can connect to the backend
* returns 0 for ok. otherwise returns backend id + 1
*/
-int health_check(void)
+static int health_check(void)
{
POOL_CONNECTION_POOL_SLOT *slot;
BackendInfo *bkinfo;
@@ -1962,6 +1966,18 @@ int health_check(void)
for (i=0;i<pool_config->backend_desc->num_backends;i++)
{
+ /*
+ * Make sure that health check timer has not been expired.
+ * Before called health_check(), health_check_timer_expired is
+ * set to 0. However it is possible that while processing DB
+ * nodes health check timer expired.
+ */
+ if (health_check_timer_expired)
+ {
+ pool_log("health_check: health check timer has been already expired before attempting to connect to %d th backend", i);
+ return i+1;
+ }
+
bkinfo = pool_get_node_info(i);
pool_debug("health_check: %d th DB node status: %d", i, bkinfo->backend_status);
@@ -1974,7 +1990,7 @@ int health_check(void)
bkinfo->backend_port,
dbname,
pool_config->health_check_user,
- pool_config->health_check_password);
+ pool_config->health_check_password, false);
if (is_first)
is_first = false;
@@ -2011,7 +2027,7 @@ int health_check(void)
* check if we can connect to the SystemDB
* returns 0 for ok. otherwise returns -1
*/
-int
+static int
system_db_health_check(void)
{
int fd;
@@ -2543,7 +2559,7 @@ static int find_primary_node(void)
bkinfo->backend_port,
"postgres",
pool_config->sr_check_user,
- pool_config->sr_check_password);
+ pool_config->sr_check_password, true);
if (!s)
{
pool_error("find_primary_node: make_persistent_connection failed");
diff --git a/pgpool.conf.sample b/pgpool.conf.sample
index d777a09d7..fb600ae2e 100644
--- a/pgpool.conf.sample
+++ b/pgpool.conf.sample
@@ -386,10 +386,8 @@ failback_command = ''
# %% = '%' character
fail_over_on_backend_error = on
- # Initiates failover when writing to the
+ # Initiates failover when reading/writing to the
# backend communication socket fails
- # This is the same behaviour of pgpool-II
- # 2.2.x and previous releases
# If set to off, pgpool will report an
# error and disconnect the session.
diff --git a/pgpool.conf.sample-master-slave b/pgpool.conf.sample-master-slave
index a8e1714d7..a4436e9d6 100644
--- a/pgpool.conf.sample-master-slave
+++ b/pgpool.conf.sample-master-slave
@@ -381,10 +381,8 @@ failback_command = ''
# %% = '%' character
fail_over_on_backend_error = on
- # Initiates failover when writing to the
+ # Initiates failover when reading/writing to the
# backend communication socket fails
- # This is the same behaviour of pgpool-II
- # 2.2.x and previous releases
# If set to off, pgpool will report an
# error and disconnect the session.
diff --git a/pgpool.conf.sample-replication b/pgpool.conf.sample-replication
index ad52a5512..0e1a43671 100644
--- a/pgpool.conf.sample-replication
+++ b/pgpool.conf.sample-replication
@@ -381,10 +381,8 @@ failback_command = ''
# %% = '%' character
fail_over_on_backend_error = on
- # Initiates failover when writing to the
+ # Initiates failover when reading/writing to the
# backend communication socket fails
- # This is the same behaviour of pgpool-II
- # 2.2.x and previous releases
# If set to off, pgpool will report an
# error and disconnect the session.
diff --git a/pgpool.conf.sample-stream b/pgpool.conf.sample-stream
index 194ac585f..2c92b090f 100644
--- a/pgpool.conf.sample-stream
+++ b/pgpool.conf.sample-stream
@@ -381,10 +381,8 @@ failback_command = ''
# %% = '%' character
fail_over_on_backend_error = on
- # Initiates failover when writing to the
+ # Initiates failover when reading/writing to the
# backend communication socket fails
- # This is the same behaviour of pgpool-II
- # 2.2.x and previous releases
# If set to off, pgpool will report an
# error and disconnect the session.
diff --git a/pool.h b/pool.h
index 449b0901a..5f85230f5 100644
--- a/pool.h
+++ b/pool.h
@@ -403,6 +403,7 @@ extern bool run_as_pcp_child;
extern POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */
extern volatile sig_atomic_t backend_timer_expired; /* flag for connection closed timer is expired */
+extern volatile sig_atomic_t health_check_timer_expired; /* non 0 if health check timer expired */
extern long int weight_master; /* normalized weight of master (0-RAND_MAX range) */
extern int my_proc_id; /* process table id (!= UNIX's PID) */
extern POOL_SYSTEMDB_CONNECTION_POOL *system_db_info; /* systemdb */
@@ -518,9 +519,6 @@ extern int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp);
extern void pool_free_startup_packet(StartupPacket *sp);
extern void child_exit(int code);
-extern int health_check(void);
-extern int system_db_health_check(void);
-
extern void init_prepared_list(void);
extern void *pool_shared_memory_create(size_t size);
@@ -539,7 +537,7 @@ extern POOL_STATUS OneNode_do_command(POOL_CONNECTION *frontend, POOL_CONNECTION
/* child.c */
extern POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
- char *hostname, int port, char *dbname, char *user, char *password);
+ char *hostname, int port, char *dbname, char *user, char *password, bool retry);
extern void discard_persistent_db_connection(POOL_CONNECTION_POOL_SLOT *cp);
/* define pool_system.c */
diff --git a/pool_connection_pool.c b/pool_connection_pool.c
index fa6f62800..05cf496f0 100644
--- a/pool_connection_pool.c
+++ b/pool_connection_pool.c
@@ -5,7 +5,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
- * Copyright (c) 2003-2011 PgPool Global Development Group
+ * Copyright (c) 2003-2012 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -50,7 +50,7 @@
static int pool_index; /* Active pool index */
POOL_CONNECTION_POOL *pool_connection_pool; /* connection pool */
volatile sig_atomic_t backend_timer_expired = 0; /* flag for connection closed timer is expired */
-
+volatile sig_atomic_t health_check_timer_expired; /* non 0 if health check timer expired */
static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot);
static POOL_CONNECTION_POOL *new_connection(POOL_CONNECTION_POOL *p);
static int check_socket_status(int fd);
@@ -481,6 +481,7 @@ int connect_unix_domain_socket_by_port(int port, char *socket_dir, bool retry)
if (exit_request) /* exit request already sent */
{
pool_log("connect_unix_domain_socket_by_port: exit request has been sent");
+ close(fd);
return -1;
}
@@ -545,11 +546,21 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry)
(char *) hp->h_addr,
hp->h_length);
+ pool_set_nonblock(fd);
+
for (;;)
{
if (exit_request) /* exit request already sent */
{
pool_log("connect_inet_domain_socket_by_port: exit request has been sent");
+ close(fd);
+ return -1;
+ }
+
+ if (health_check_timer_expired) /* has health check timer expired */
+ {
+ pool_log("connect_inet_domain_socket_by_port: health check timer expired");
+ close(fd);
return -1;
}
@@ -558,6 +569,10 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry)
if ((errno == EINTR && retry) || errno == EAGAIN)
continue;
+ /* Non block fd could return these */
+ if (errno == EINPROGRESS || errno == EALREADY)
+ continue;
+
pool_error("connect_inet_domain_socket: connect() failed: %s",strerror(errno));
close(fd);
return -1;
@@ -565,6 +580,7 @@ int connect_inet_domain_socket_by_port(char *host, int port, bool retry)
break;
}
+ pool_unset_nonblock(fd);
return fd;
}
diff --git a/pool_stream.c b/pool_stream.c
index 053f34883..804a3836d 100644
--- a/pool_stream.c
+++ b/pool_stream.c
@@ -5,7 +5,7 @@
* pgpool: a language independent connection pool server for PostgreSQL
* written by Tatsuo Ishii
*
-* Copyright (c) 2003-2010 PgPool Global Development Group
+* Copyright (c) 2003-2012 PgPool Global Development Group
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby
@@ -168,9 +168,14 @@ int pool_read(POOL_CONNECTION *cp, void *buf, int len)
if (cp->isbackend)
{
- /* fatal error, notice to parent and exit */
- notice_backend_error(cp->db_node_id);
- child_exit(1);
+ /* if fail_over_on_backend_erro is true, then trigger failover */
+ if (pool_config->fail_over_on_backend_error)
+ {
+ notice_backend_error(cp->db_node_id);
+ child_exit(1);
+ }
+ else
+ return -1;
}
else
{
@@ -283,9 +288,14 @@ char *pool_read2(POOL_CONNECTION *cp, int len)
if (cp->isbackend)
{
- /* fatal error, notice to parent and exit */
- notice_backend_error(cp->db_node_id);
- child_exit(1);
+ /* if fail_over_on_backend_erro is true, then trigger failover */
+ if (pool_config->fail_over_on_backend_error)
+ {
+ notice_backend_error(cp->db_node_id);
+ child_exit(1);
+ }
+ else
+ return NULL;
}
else
{
diff --git a/pool_worker_child.c b/pool_worker_child.c
index 9fcd3d824..df2b65a49 100644
--- a/pool_worker_child.c
+++ b/pool_worker_child.c
@@ -164,7 +164,7 @@ static void establish_persistent_connection(void)
bkinfo->backend_port,
"postgres",
pool_config->sr_check_user,
- pool_config->sr_check_password);
+ pool_config->sr_check_password, true);
if (s)
slots[i] = s;
else
[parent: 49a36559ea71]