From 88325a9d36f7a6416ebcd3fd79e9eab34f65ca76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 10 Oct 2017 22:31:41 +0300 Subject: [PATCH] Fix resultset handling with binary data When binary data was processed, it was possible that the values were misinterpreted as OK packets which caused debug assertions to trigger. In addition to this, readwritesplit did not handle the case when all packets were routed individually. --- server/core/modutil.cc | 7 ++++++- .../modules/routing/readwritesplit/readwritesplit.cc | 12 +++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/server/core/modutil.cc b/server/core/modutil.cc index 2ee5ff595..7618edf40 100644 --- a/server/core/modutil.cc +++ b/server/core/modutil.cc @@ -649,10 +649,12 @@ int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_out, modu if (payloadlen == GW_MYSQL_MAX_PACKET_LEN) { + only_ok = false; skip_next = true; } else if (skip_next) { + only_ok = false; skip_next = false; } else @@ -670,9 +672,12 @@ int modutil_count_signal_packets(GWBUF *reply, int n_found, bool* more_out, modu else if (command == MYSQL_REPLY_EOF && pktlen == MYSQL_EOF_PACKET_LEN) { eof++; + only_ok = false; } - else if (command == MYSQL_REPLY_OK && pktlen >= MYSQL_OK_PACKET_MIN_LEN) + else if (command == MYSQL_REPLY_OK && pktlen >= MYSQL_OK_PACKET_MIN_LEN && + (eof + n_found) % 2 == 0) { + // An OK packet that is not in the middle of a resultset stream uint8_t data[payloadlen - 1]; gwbuf_copy_data(reply, offset + MYSQL_HEADER_LEN + 1, sizeof(data), data); diff --git a/server/modules/routing/readwritesplit/readwritesplit.cc b/server/modules/routing/readwritesplit/readwritesplit.cc index e9eda014b..50cc8a8e4 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.cc +++ b/server/modules/routing/readwritesplit/readwritesplit.cc @@ -515,6 +515,12 @@ static bool route_stored_query(RWSplitSession *rses) return rval; } +static inline bool have_next_packet(GWBUF* buffer) +{ + uint32_t len = MYSQL_GET_PAYLOAD_LEN(GWBUF_DATA(buffer)) + MYSQL_HEADER_LEN; + return gwbuf_length(buffer) > len; +} + /** * @brief Check if we have received a complete reply from the backend * @@ -545,7 +551,11 @@ bool reply_is_complete(SRWBackend& backend, GWBUF *buffer) LOG_RS(backend, REPLY_STATE_RSET_COLDEF); backend->set_reply_state(REPLY_STATE_RSET_COLDEF); - return reply_is_complete(backend, buffer); + + if (have_next_packet(buffer)) + { + return reply_is_complete(backend, buffer); + } } } else