Send down SYNC message to a failed remote session that was running extended
authorPavan Deolasee <[email protected]>
Wed, 9 Mar 2016 12:18:23 +0000 (17:48 +0530)
committerPavan Deolasee <[email protected]>
Wed, 9 Mar 2016 12:18:23 +0000 (17:48 +0530)
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

src/backend/pgxc/pool/execRemote.c
src/backend/pgxc/pool/pgxcnode.c
src/include/pgxc/pgxcnode.h

index 61bee4273665abdbf7fb83e40435b777cdaa2157..c0d418a3c7222d6d02e4e881075598f87567131a 100644 (file)
@@ -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;
index 87a2f6167fb96e56ec01ba88b71da514868bcbc5..579cb4b30ac4c5b405bca7ab0afc12b601ed6ae4 100644 (file)
@@ -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);
 }
 
index 64cf432ee895f1220d7d0ad8480f1546f860a2eb..93cc925c70c418b2487710f4d718d685373301eb 100644 (file)
@@ -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;