diff options
author | Pavan Deolasee | 2016-03-09 12:18:23 +0000 |
---|---|---|
committer | Pavan Deolasee | 2016-10-18 10:00:19 +0000 |
commit | fc88a9adc7a027c22e300bfc6bfc0f97128f97e1 (patch) | |
tree | 9056b9a70168233aab5e78c9969c13011e3e2766 | |
parent | 7aecc3a15b64df4da5dfa3d458f9dd0f959030bd (diff) |
Send down SYNC message to a failed remote session that was running extended
query protocol.
While running extended query protocol, a backend that has thrown an error will
keep ignoring all messages until it sees a SYNC message. We now carefully track
the messages that we are sending to the remote node and remember if we must
send a SYNC message even before sending a ROLLBACK command.
While the regression was running fine even without this patch, this issue was
noticed as part of some other work and hence fixed
-rw-r--r-- | src/backend/pgxc/pool/execRemote.c | 28 | ||||
-rw-r--r-- | src/backend/pgxc/pool/pgxcnode.c | 12 | ||||
-rw-r--r-- | src/include/pgxc/pgxcnode.h | 3 |
3 files changed, 43 insertions, 0 deletions
diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index eb3807c70e..ab0a96986c 100644 --- a/src/backend/pgxc/pool/execRemote.c +++ b/src/backend/pgxc/pool/execRemote.c @@ -1718,6 +1718,15 @@ handle_response(PGXCNodeHandle *conn, ResponseCombiner *combiner) case 'E': /* ErrorResponse */ HandleError(combiner, msg, msg_len, conn); add_error_message(conn, combiner->errorMessage); + /* + * In case the remote node was running an extended query + * protocol and reported an error, it will keep ignoring all + * subsequent commands until it sees a SYNC message. So make + * sure that we send down SYNC even before sending a ROLLBACK + * command + */ + if (conn->in_extended_query) + conn->needSync = true; return RESPONSE_ERROR; case 'A': /* NotificationResponse */ case 'N': /* NoticeResponse */ @@ -2638,6 +2647,16 @@ pgxc_node_remote_abort(void) BufferConnection(conn); /* + * If the remote session was running extended query protocol when + * it failed, it will expect a SYNC message before it accepts any + * other command + */ + if (conn->needSync) + { + pgxc_node_send_sync(conn); + pgxc_node_receive(1, &conn, NULL); + } + /* * Do not matter, is there committed or failed transaction, * just send down rollback to finish it. */ @@ -2664,6 +2683,12 @@ pgxc_node_remote_abort(void) if (conn->transaction_status != 'I') { + /* Send SYNC if the remote session is expecting one */ + if (conn->needSync) + { + pgxc_node_send_sync(conn); + pgxc_node_receive(1, &conn, NULL); + } /* * Do not matter, is there committed or failed transaction, * just send down rollback to finish it. @@ -2902,6 +2927,8 @@ DataNodeCopyIn(char *data_row, int len, int conn_count, PGXCNodeHandle** copy_co memcpy(handle->outBuffer + handle->outEnd, data_row, len); handle->outEnd += len; handle->outBuffer[handle->outEnd++] = '\n'; + + handle->in_extended_query = false; } else { @@ -3045,6 +3072,7 @@ DataNodeCopyEnd(PGXCNodeHandle *handle, bool is_error) memcpy(handle->outBuffer + handle->outEnd, &nLen, 4); handle->outEnd += 4; + handle->in_extended_query = false; /* We need response right away, so send immediately */ if (pgxc_node_flush(handle) < 0) return true; diff --git a/src/backend/pgxc/pool/pgxcnode.c b/src/backend/pgxc/pool/pgxcnode.c index 87a2f6167f..579cb4b30a 100644 --- a/src/backend/pgxc/pool/pgxcnode.c +++ b/src/backend/pgxc/pool/pgxcnode.c @@ -143,6 +143,7 @@ init_pgxc_handle(PGXCNodeHandle *pgxc_handle) pgxc_handle->inEnd = 0; pgxc_handle->inCursor = 0; pgxc_handle->outEnd = 0; + pgxc_handle->needSync = false; if (pgxc_handle->outBuffer == NULL || pgxc_handle->inBuffer == NULL) { @@ -415,6 +416,7 @@ pgxc_node_init(PGXCNodeHandle *handle, int sock, bool global_session, int pid) handle->inStart = 0; handle->inEnd = 0; handle->inCursor = 0; + handle->needSync = false; /* * We got a new connection, set on the remote node the session parameters * if defined. The transaction parameter should be sent after BEGIN @@ -1325,6 +1327,7 @@ pgxc_node_send_plan(PGXCNodeHandle * handle, const char *statement, } pfree(paramTypes); + handle->in_extended_query = true; return 0; } @@ -1405,6 +1408,7 @@ pgxc_node_send_bind(PGXCNodeHandle * handle, const char *portal, handle->outBuffer[handle->outEnd++] = 0; handle->outBuffer[handle->outEnd++] = 0; + handle->in_extended_query = true; return 0; } @@ -1452,6 +1456,7 @@ pgxc_node_send_describe(PGXCNodeHandle * handle, bool is_statement, else handle->outBuffer[handle->outEnd++] = '\0'; + handle->in_extended_query = true; return 0; } @@ -1492,6 +1497,7 @@ pgxc_node_send_close(PGXCNodeHandle * handle, bool is_statement, else handle->outBuffer[handle->outEnd++] = '\0'; + handle->in_extended_query = true; return 0; } @@ -1535,6 +1541,7 @@ pgxc_node_send_execute(PGXCNodeHandle * handle, const char *portal, int fetch) PGXCNodeSetConnectionState(handle, DN_CONNECTION_STATE_QUERY); + handle->in_extended_query = true; return 0; } @@ -1561,6 +1568,7 @@ pgxc_node_send_flush(PGXCNodeHandle * handle) memcpy(handle->outBuffer + handle->outEnd, &msgLen, 4); handle->outEnd += 4; + handle->in_extended_query = true; return pgxc_node_flush(handle); } @@ -1587,6 +1595,9 @@ pgxc_node_send_sync(PGXCNodeHandle * handle) memcpy(handle->outBuffer + handle->outEnd, &msgLen, 4); handle->outEnd += 4; + handle->in_extended_query = false; + handle->needSync = false; + return pgxc_node_flush(handle); } @@ -1721,6 +1732,7 @@ pgxc_node_send_query_internal(PGXCNodeHandle * handle, const char *query, PGXCNodeSetConnectionState(handle, DN_CONNECTION_STATE_QUERY); + handle->in_extended_query = false; return pgxc_node_flush(handle); } diff --git a/src/include/pgxc/pgxcnode.h b/src/include/pgxc/pgxcnode.h index 64cf432ee8..93cc925c70 100644 --- a/src/include/pgxc/pgxcnode.h +++ b/src/include/pgxc/pgxcnode.h @@ -92,6 +92,9 @@ struct pgxc_node_handle * For details see comments of RESP_ROLLBACK */ bool ck_resp_rollback; + + bool in_extended_query; + bool needSync; }; typedef struct pgxc_node_handle PGXCNodeHandle; |