pgpool2.git / summary / log / commit / refs

commit    39e07ea13a7f318f2c50a8aec7baa93e13a347d3
Author:   Tatsuo Ishii <ishii@postgresql.org>
Date:     Tue Mar 29 11:05:06 2016 +0000

    Fix extended query hangs
    
    Deal with bug 167. The problem is in the following sequence:
    
    Parse(BEGIN)
    Bind
    :
    Execute
    Parse(SELECT)
    Bind
    :
    
    (Notice that no Sync message between Execute and Parse)
    BEGIN is sent to all db nodes while select is sent to one of db
    nodes. So pgpool is confused which DB node to read the response. To
    fix this, after each Execute, send flash message to backend to get
    response. This will ensure that the responses of BEGIN etc. are read
    from all DB nodes while the responses of SELECT etc. are read from
    only one of DB node.


src/protocol/CommandComplete.c | 3 +++ src/protocol/pool_proto_modules.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/protocol/CommandComplete.c b/src/protocol/CommandComplete.c index e72b9066e..f18f3db11 100644 --- a/src/protocol/CommandComplete.c +++ b/src/protocol/CommandComplete.c @@ -150,6 +150,9 @@ POOL_STATUS CommandComplete(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *bac pool_set_query_state(session_context->query_context, POOL_EXECUTE_COMPLETE); } + if (STREAM && pool_is_doing_extended_query_message()) + pool_unset_query_in_progress(); + return POOL_CONTINUE; } diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index 5e871233e..15aa00bcc 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -760,7 +760,30 @@ POOL_STATUS Execute(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, { pool_extended_send_and_wait(query_context, "E", len, contents, 1, MASTER_NODE_ID, true); pool_extended_send_and_wait(query_context, "E", len, contents, -1, MASTER_NODE_ID, true); + + /* + * Send flush message to backend to make sure that we get any response + * from backend. + */ + pool_write(MASTER(session_context->backend), "H", 1); + len = htonl(sizeof(len)); + pool_write_and_flush(MASTER(session_context->backend), &len, sizeof(len)); + if (MASTER(session_context->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)); + } + /* + * Remeber that we send flush or sync message to backend. + */ + pool_unset_pending_response(); +#ifdef NOT_USED pool_unset_query_in_progress(); +#endif } return POOL_CONTINUE; @@ -1087,6 +1110,7 @@ POOL_STATUS Parse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, { /* XXX fix me:even with streaming replication mode, couldn't we have a deadlock */ pool_set_query_in_progress(); + pool_clear_sync_map(); pool_extended_send_and_wait(query_context, "P", len, contents, 1, MASTER_NODE_ID, true); pool_extended_send_and_wait(query_context, "P", len, contents, -1, MASTER_NODE_ID, true); pool_add_sent_message(session_context->uncompleted_message); @@ -1216,6 +1240,7 @@ POOL_STATUS Bind(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, nowait = (STREAM? true: false); + pool_clear_sync_map(); pool_extended_send_and_wait(query_context, "B", len, contents, 1, MASTER_NODE_ID, nowait); pool_extended_send_and_wait(query_context, "B", len, contents, -1, MASTER_NODE_ID, nowait); @@ -1367,6 +1392,7 @@ POOL_STATUS Close(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, { POOL_PENDING_MESSAGE *pmsg; + pool_clear_sync_map(); pool_extended_send_and_wait(query_context, "C", len, contents, 1, MASTER_NODE_ID, true); pool_extended_send_and_wait(query_context, "C", len, contents, -1, MASTER_NODE_ID, true); [parent: 37767d0910b9]