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]