From: Pavan Deolasee Date: Wed, 9 Mar 2016 12:18:23 +0000 (+0530) Subject: Send down SYNC message to a failed remote session that was running extended X-Git-Tag: XL9_5_R1BETA2~36 X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=e1d06bdacf69954f1b81eeb84a42fe13b51fe44c;p=postgres-xl.git 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 --- diff --git a/src/backend/pgxc/pool/execRemote.c b/src/backend/pgxc/pool/execRemote.c index 61bee42736..c0d418a3c7 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 */ @@ -2637,6 +2646,16 @@ pgxc_node_remote_abort(void) if (conn->state != DN_CONNECTION_STATE_IDLE) 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;