Fix regression in handling of large packets

When large binary protocol packets were handled, a part of the data was
replaced with a non-existing PS ID.

The replacement of the client PS ID to the internal ID and the replacement
of the internal ID to the server specific ID must only be done if a large
packet is not being processed. This can be done on the router level
without adding knowledge of large packets to the RWBackend class.

A specific function, RWBackend::continue_write, was added to make it clear
that the buffer being written is a part of a larger query. The base class
Backend::write could be used but its usage is not self-explanatory.
This commit is contained in:
Markus Mäkelä 2018-05-21 23:58:21 +03:00
parent b59e6a4baf
commit 88380038c1
No known key found for this signature in database
GPG Key ID: 72D48FCE664F7B19
2 changed files with 41 additions and 2 deletions

View File

@ -65,7 +65,36 @@ public:
bool execute_session_command();
bool continue_session_command(GWBUF* buffer);
/**
* Write a query to the backend
*
* This function handles the replacement of the prepared statement IDs from
* the internal ID to the server specific one. Trailing parts of large
* packets should use RWBackend::continue_write.
*
* @param buffer Buffer to write
* @param type Whether a response is expected
*
* @return True if writing was successful
*/
bool write(GWBUF* buffer, response_type type = EXPECT_RESPONSE);
/**
* Continue a previously started write
*
* This should only be used when RWBackend::write has been called to start
* a new query.
*
* @param buffer Buffer to write
*
* @return True if writing was successful
*/
bool continue_write(GWBUF* buffer)
{
return mxs::Backend::write(buffer);
}
void close(close_type type = CLOSE_NORMAL);
// For COM_STMT_FETCH processing

View File

@ -148,7 +148,7 @@ bool RWSplitSession::route_single_stmt(GWBUF *querybuf)
route_target_t route_target = info.target();
bool not_locked_to_master = !is_locked_to_master();
if (not_locked_to_master && mxs_mysql_is_ps_command(command))
if (not_locked_to_master && mxs_mysql_is_ps_command(command) && !m_qc.large_query())
{
/** Replace the client statement ID with our internal one only if the
* target node is not the current master */
@ -967,7 +967,17 @@ bool RWSplitSession::handle_got_target(GWBUF* querybuf, SRWBackend& target, bool
bool large_query = is_large_query(querybuf);
if (target->write(send_buf, response))
/**
* If we are starting a new query, we use RWBackend::write, otherwise we use
* RWBackend::continue_write to continue an ongoing query. RWBackend::write
* will do the replacement of PS IDs which must not be done if we are
* continuing an ongoing query.
*/
bool success = !m_qc.large_query() ?
target->write(send_buf, response) :
target->continue_write(send_buf);
if (success)
{
if (store)
{