Fix bug #303.
authorTatsuo Ishii <ishii@postgresql.org>
Thu, 3 Aug 2017 02:52:24 +0000 (11:52 +0900)
committerTatsuo Ishii <ishii@postgresql.org>
Thu, 3 Aug 2017 05:14:02 +0000 (14:14 +0900)
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.

child.c
main.c
pool.h
pool_stream.c
pool_stream.h
pool_worker_child.c

diff --git a/child.c b/child.c
index 0a7b097cfe96649618950729514550f23744976e..6421a58e2aee77b477fe3fab6fcf5ed9a9606d43 100644 (file)
--- a/child.c
+++ b/child.c
@@ -1235,7 +1235,7 @@ static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION
                if (VALID_BACKEND(i))
                {
                        /* 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;
@@ -1484,7 +1484,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;
@@ -1542,6 +1542,7 @@ POOL_CONNECTION_POOL_SLOT *make_persistent_db_connection(
        cp->con = pool_open(fd);
        cp->closetime = 0;
        cp->con->isbackend = 1;
+       pool_set_db_node_id(cp->con, db_node_id);
        pool_ssl_negotiate_clientserver(cp->con);
 
        /*
@@ -2082,7 +2083,7 @@ static void init_system_db_connection(void)
                        pool_error("Could not make persistent libpq system DB connection");
                }
 
-               system_db_info->connection = make_persistent_db_connection(pool_config->system_db_hostname,
+               system_db_info->connection = make_persistent_db_connection(-1, pool_config->system_db_hostname,
                                                                                                                                   pool_config->system_db_port,
                                                                                                                                   pool_config->system_db_dbname,
                                                                                                                                   pool_config->system_db_user,
diff --git a/main.c b/main.c
index 534e8682b9d7e527956718013147538a20d79edf..8dc01bf5bd9d5ce12f92d676b254ba5568ebf773 100644 (file)
--- a/main.c
+++ b/main.c
@@ -2543,7 +2543,7 @@ static int health_check(void)
                        bkinfo->backend_status == CON_DOWN)
                        continue;
 
-               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,
@@ -3142,7 +3142,7 @@ static int find_primary_node(void)
                is_standby = false;
 
                bkinfo = pool_get_node_info(i);
-               s = make_persistent_db_connection(bkinfo->backend_hostname,
+               s = make_persistent_db_connection(i, bkinfo->backend_hostname,
                                                                                  bkinfo->backend_port,
                                                                                  "postgres",
                                                                                  pool_config->sr_check_user,
diff --git a/pool.h b/pool.h
index fabfb0a46ac52ab55eaf7a97eb91febd75d9250b..3887fb3ef424ec5a5463db16df8f419c200759df 100644 (file)
--- a/pool.h
+++ b/pool.h
@@ -565,7 +565,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, 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 */
index d5a0a00e12295a6c7aae1bbe3051943a0a25a387..de86bad70d18c419c17fb543638c87b54d935eea 100644 (file)
@@ -719,6 +719,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.
index d7e15ea8af48852eac65ea3125c31f0164c32762..46002d0c1653ce9bf52a2cc2c2e0909232718528 100644 (file)
@@ -6,7 +6,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL 
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2013     PgPool Global Development Group
+ * Copyright (c) 2003-2017     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -57,5 +57,6 @@ extern void pool_pop(POOL_CONNECTION *cp, int *len);
 extern int pool_stacklen(POOL_CONNECTION *cp);
 extern void pool_set_nonblock(int fd);
 extern void pool_unset_nonblock(int fd);
+extern void pool_set_db_node_id(POOL_CONNECTION *con, int db_node_id);
 
 #endif /* POOL_STREAM_H */
index b2e2ebc825691f0a5fba1125eb7ad356e3a33753..694af8b2da04eb88dd8697f8d755a2be8a18acd2 100644 (file)
@@ -163,7 +163,7 @@ static void establish_persistent_connection(void)
                if (slots[i] == NULL)
                {
                        bkinfo = pool_get_node_info(i);
-                       s = make_persistent_db_connection(bkinfo->backend_hostname, 
+                       s = make_persistent_db_connection(i, bkinfo->backend_hostname, 
                                                                                          bkinfo->backend_port,
                                                                                          "postgres",
                                                                                          pool_config->sr_check_user,