Fix RWBackend state tracking with multi-result queries

If a query returned multiple resultsets and the connection was broken
between the resultsets, the backend would not know that parts of the
response were already sent. This is caused by the cyclic nature of the
state machine when multi-result responses are being processed.

To fix the problem, the result size is tracked to know how many bytes have
been sent to the client. This is a backport of the
MySQLProtocol::Result::size from 2.5(develop).
This commit is contained in:
Markus Mäkelä 2019-07-27 11:42:05 +03:00
parent ed84f29fca
commit 45aa40c10a
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
2 changed files with 6 additions and 1 deletions

View File

@ -240,7 +240,7 @@ public:
*/
bool reply_has_started() const
{
return m_reply_state != REPLY_STATE_START && m_reply_state != REPLY_STATE_DONE;
return m_size > 0 && m_reply_state != REPLY_STATE_DONE;
}
void process_packets(GWBUF* buffer);
@ -269,6 +269,7 @@ private:
bool m_large_query = false;
bool m_skip_next = false;
Error m_error;
uint64_t m_size = 0;/**< Size of the response */
/**
* @param it Iterator pointing to the command byte of an error packet.

View File

@ -45,6 +45,7 @@ bool RWBackend::execute_session_command()
if (rval && expect_response)
{
set_reply_state(REPLY_STATE_START);
m_size = 0;
}
return rval;
@ -88,6 +89,7 @@ bool RWBackend::write(GWBUF* buffer, response_type type)
{
/** The server will reply to this command */
set_reply_state(REPLY_STATE_START);
m_size = 0;
}
uint8_t cmd = mxs_mysql_get_command(buffer);
@ -320,6 +322,8 @@ void RWBackend::process_packets(GWBUF* result)
end.advance(len);
uint8_t cmd = *it;
m_size += len;
// Ignore the tail end of a large packet large packet. Only resultsets can generate packets this large
// and we don't care what the contents are and thus it is safe to ignore it.
bool skip_next = m_skip_next;