pgpool2.git / summary / log / commit / refs
commit 2c54c4b6f3fc4f36ceda528ec8ab00ad723030d4
Author: Tatsuo Ishii <ishii@postgresql.org>
Date: Thu Aug 03 02:52:24 2017 +0000
Fix bug #303.
When failover is triggered by worker process, it is possible that
wrong DB node could failover. This is due to the db_node_id member in
the POLL_CONNECTION structure is not initialized in the process (in
child process the member is properly initialized). To solve the
problem, add new function pool_set_db_node_id() to set the structure
member variable and call it inside
make_persistent_db_connection(). For this purpose also the new
parameter "db_node_id" is added to make_persistent_db_connection and
friends.
src/include/pool.h | 4 ++--
src/include/utils/pool_stream.h | 2 ++
src/main/health_check.c | 2 +-
src/main/pgpool_main.c | 4 ++--
src/protocol/child.c | 21 +++++++++++++--------
src/streaming_replication/pool_worker_child.c | 2 +-
src/utils/pool_stream.c | 10 ++++++++++
7 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/src/include/pool.h b/src/include/pool.h
index d5dd63aa8..ac282ba72 100644
--- a/src/include/pool.h
+++ b/src/include/pool.h
@@ -622,9 +622,9 @@ 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, bool retry);
+ int db_node_id, char *hostname, int port, char *dbname, char *user, char *password, bool retry);
extern POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection_noerror(
- char *hostname, int port, char *dbname, char *user, char *password, bool retry);
+ int db_node_id, 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/src/include/utils/pool_stream.h b/src/include/utils/pool_stream.h
index 5db83728d..c79f5dfbe 100644
--- a/src/include/utils/pool_stream.h
+++ b/src/include/utils/pool_stream.h
@@ -67,4 +67,6 @@ extern void pool_unset_nonblock(int fd);
extern int socket_read(int sock, void* buf, size_t len, int timeout);
extern int socket_write(int fd, void* buf, size_t len);
+extern void pool_set_db_node_id(POOL_CONNECTION *con, int db_node_id);
+
#endif /* POOL_STREAM_H */
diff --git a/src/main/health_check.c b/src/main/health_check.c
index 92ad28006..14468f242 100644
--- a/src/main/health_check.c
+++ b/src/main/health_check.c
@@ -246,7 +246,7 @@ static bool establish_persistent_connection(int node)
health_check_timer_expired = 0;
}
- slot = make_persistent_db_connection_noerror(bkinfo->backend_hostname,
+ slot = make_persistent_db_connection_noerror(node, bkinfo->backend_hostname,
bkinfo->backend_port,
pool_config->health_check_database,
pool_config->health_check_user,
diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c
index c71ddaedf..f029be4ab 100644
--- a/src/main/pgpool_main.c
+++ b/src/main/pgpool_main.c
@@ -2133,7 +2133,7 @@ do_health_check(bool use_template_db, volatile int *health_check_node_id)
ereport(DEBUG1,
(errmsg("Trying to make persistent DB connection to backend node %d having status %d", i, bkinfo->backend_status)));
- slot = make_persistent_db_connection(bkinfo->backend_hostname,
+ slot = make_persistent_db_connection(i, bkinfo->backend_hostname,
bkinfo->backend_port,
dbname,
pool_config->health_check_user,
@@ -2748,7 +2748,7 @@ static bool
*is_standby = false;
- s = make_persistent_db_connection_noerror(bkinfo->backend_hostname,
+ s = make_persistent_db_connection_noerror(backend_no, bkinfo->backend_hostname,
bkinfo->backend_port,
pool_config->sr_check_database,
pool_config->sr_check_user,
diff --git a/src/protocol/child.c b/src/protocol/child.c
index a0f8c171c..0f66e7dac 100644
--- a/src/protocol/child.c
+++ b/src/protocol/child.c
@@ -797,6 +797,8 @@ void cancel_request(CancelPacket *sp)
if (con == NULL)
return;
+ pool_set_db_node_id(con, i);
+
len = htonl(sizeof(len) + sizeof(CancelPacket));
pool_write(con, &len, sizeof(len));
@@ -880,7 +882,7 @@ static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION
{
/* set DB node id */
- CONNECTION(backend, i)->db_node_id = i;
+ pool_set_db_node_id(CONNECTION(backend, i), i);
/* mark this is a backend connection */
CONNECTION(backend, i)->isbackend = 1;
@@ -1177,7 +1179,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, bool retry)
+ int db_node_id, char *hostname, int port, char *dbname, char *user, char *password, bool retry)
{
POOL_CONNECTION_POOL_SLOT *cp;
int fd;
@@ -1221,6 +1223,8 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
cp->con = pool_open(fd,true);
cp->closetime = 0;
cp->con->isbackend = 1;
+ pool_set_db_node_id(cp->con, db_node_id);
+
pool_ssl_negotiate_clientserver(cp->con);
/*
@@ -1297,17 +1301,18 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
* make_persistent_db_connection() which does not ereports in case of an error
*/
POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection_noerror(
- char *hostname, int port, char *dbname, char *user, char *password, bool retry)
+ int db_node_id, char *hostname, int port, char *dbname, char *user, char *password, bool retry)
{
POOL_CONNECTION_POOL_SLOT *slot = NULL;
MemoryContext oldContext = CurrentMemoryContext;
PG_TRY();
{
- slot = make_persistent_db_connection(hostname,
- port,
- dbname,
- user,
- password, retry);
+ slot = make_persistent_db_connection(db_node_id,
+ hostname,
+ port,
+ dbname,
+ user,
+ password, retry);
}
PG_CATCH();
{
diff --git a/src/streaming_replication/pool_worker_child.c b/src/streaming_replication/pool_worker_child.c
index c0faa840b..3c11fa69e 100644
--- a/src/streaming_replication/pool_worker_child.c
+++ b/src/streaming_replication/pool_worker_child.c
@@ -203,7 +203,7 @@ static void establish_persistent_connection(void)
if (slots[i] == NULL)
{
bkinfo = pool_get_node_info(i);
- slots[i] = make_persistent_db_connection_noerror(bkinfo->backend_hostname,
+ slots[i] = make_persistent_db_connection_noerror(i, bkinfo->backend_hostname,
bkinfo->backend_port,
pool_config->sr_check_database,
pool_config->sr_check_user,
diff --git a/src/utils/pool_stream.c b/src/utils/pool_stream.c
index 30d9da40f..2f8d2f273 100644
--- a/src/utils/pool_stream.c
+++ b/src/utils/pool_stream.c
@@ -881,6 +881,16 @@ char *pool_read_string(POOL_CONNECTION *cp, int *len, int line)
return cp->sbuf;
}
+/*
+ * Set db node id to connection.
+ */
+void pool_set_db_node_id(POOL_CONNECTION *con, int db_node_id)
+{
+ if (!con)
+ return;
+ con->db_node_id = db_node_id;
+}
+
/*
* returns the byte length of str, including \0, no more than upper.
* if encountered \0, flag is set to non 0.
[parent: 8e984d1a78e9]