pgpool2.git / summary / log / commit / refs

commit    f305fbe0355529d4142d3b76e08f7d08dc2c3cf9
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Mon Mar 28 01:40:35 2016 +0000

    Fix pgpool hang bug (deal with bug 167)
    
    pgpool-II 3.5 or after in streaming replication mode does not wait for
    response from each phase such parse, bind anymore.  However, if
    do_query is called, it sends flush message to retrieve the result of
    system catalog look up. This is only sent to primary node which may
    results in retrieving previous message results, for example parse
    complete. If standby is assigned to load balance node, the node does
    not return parse complete message, which will cause a problem in
    bug167 case, because parse message for "BEGIN" was sent to both the
    primary and the standby. Fix is, send flush message in do_query if the
    load balance node is one of standbys.


src/context/pool_session_context.c | 22 +++++++++++++++++++++- src/protocol/pool_process_query.c | 24 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/context/pool_session_context.c b/src/context/pool_session_context.c index 8fd95a884..6e6c5578d 100644 --- a/src/context/pool_session_context.c +++ b/src/context/pool_session_context.c @@ -37,6 +37,7 @@ static void GetTranIsolationErrorCb(void *arg); static void init_sent_message_list(void); static POOL_PENDING_MESSAGE *copy_pending_message(POOL_PENDING_MESSAGE *messag); static void dump_sent_message(char *caller, POOL_SENT_MESSAGE *m); +static char *dump_sync_map(void); /* * Initialize per session context @@ -947,16 +948,35 @@ bool pool_use_sync_map(void) if (pool_is_set_sync_map(i)) { ereport(DEBUG1, - (errmsg("pool_use_sync_map: set use sync map: %d", i))); + (errmsg("pool_use_sync_map: we can use sync map: %s", dump_sync_map()))); return POOL_SYNC_MAP_IS_VALID; /* yes, we can use sync map */ } } + ereport(DEBUG1, + (errmsg("pool_use_sync_map: we cannot use sync map because all map entries are false"))); return POOL_SYNC_MAP_EMPTY; /* no, we cannot use sync map */ } + ereport(DEBUG1, + (errmsg("pool_use_sync_map: we cannot use sync map because STREAM: %d query in progress: %d doing extended query: %d", STREAM, pool_is_query_in_progress(), pool_is_doing_extended_query_message()))); + return POOL_IGNORE_SYNC_MAP; } +static char *dump_sync_map(void) +{ + static char mapstr[MAX_NUM_BACKENDS+1]; + int i; + + memset(mapstr, 0, sizeof(mapstr)); + + for (i=0;i<NUM_BACKENDS;i++) + { + mapstr[i] = session_context->sync_map[i]?'1':'0'; + } + return mapstr; +} + /* * Set pending response */ diff --git a/src/protocol/pool_process_query.c b/src/protocol/pool_process_query.c index fd3b76ffa..5236e6ea5 100644 --- a/src/protocol/pool_process_query.c +++ b/src/protocol/pool_process_query.c @@ -1926,6 +1926,7 @@ void do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result int num_close_complete; int state; bool data_pushed; + POOL_SESSION_CONTEXT *session_context; data_pushed = false; @@ -1970,6 +1971,29 @@ void do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result pool_write(backend, "H", 1); len = htonl(sizeof(len)); pool_write_and_flush(backend, &len, sizeof(len)); + ereport(DEBUG1, + (errmsg("do_query: send flush message to %d", backend->db_node_id))); + + /* + * If we have not send the flush message to load balance node yet, + * send a flush message to the load balance node. Otherwise only + * the non load balance node (usually the master node) produces + * response if we do not send sync message to it yet. + */ + session_context = pool_get_session_context(false); + + if (backend->db_node_id != session_context->load_balance_node_id) + { + POOL_CONNECTION *con; + + con = session_context->backend->slots[session_context->load_balance_node_id]->con; + pool_write(con, "H", 1); + len = htonl(sizeof(len)); + pool_write_and_flush(con, &len, sizeof(len)); + ereport(DEBUG1, + (errmsg("do_query: send flush message to %d", con->db_node_id))); + + } for(;;) { [parent: 95f4f2982300]