From a1c7ee438d9246a23dea06f934f5d53850770a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Sun, 2 Apr 2017 11:11:43 +0300 Subject: [PATCH] MXS-1203: Fix current command tracking with statement routing When statement based routing was used, it was possible that the current statement being executed wasn't properly updated. Readwritesplit requires it to track whether a command will create a response. --- .../protocol/MySQL/MySQLClient/mysql_client.c | 4 ++ .../readwritesplit/rwsplit_route_stmt.c | 37 ++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/server/modules/protocol/MySQL/MySQLClient/mysql_client.c b/server/modules/protocol/MySQL/MySQLClient/mysql_client.c index 4cab7131d..d18e20a7e 100644 --- a/server/modules/protocol/MySQL/MySQLClient/mysql_client.c +++ b/server/modules/protocol/MySQL/MySQLClient/mysql_client.c @@ -1399,6 +1399,10 @@ static int route_by_statement(MXS_SESSION* session, uint64_t capabilities, GWBUF if (packetbuf != NULL) { CHK_GWBUF(packetbuf); + + MySQLProtocol* proto = session->client_dcb->protocol; + proto->current_command = (mysql_server_cmd_t)GWBUF_DATA(packetbuf)[4]; + /** * This means that buffer includes exactly one MySQL * statement. diff --git a/server/modules/routing/readwritesplit/rwsplit_route_stmt.c b/server/modules/routing/readwritesplit/rwsplit_route_stmt.c index 894e8e6f0..91ba4f90c 100644 --- a/server/modules/routing/readwritesplit/rwsplit_route_stmt.c +++ b/server/modules/routing/readwritesplit/rwsplit_route_stmt.c @@ -1230,6 +1230,13 @@ bool handle_master_is_target(ROUTER_INSTANCE *inst, ROUTER_CLIENT_SES *rses, return succp; } +static inline bool query_creates_reply(mysql_server_cmd_t cmd) +{ + return cmd != MYSQL_COM_QUIT && + cmd != MYSQL_COM_STMT_SEND_LONG_DATA && + cmd != MYSQL_COM_STMT_CLOSE; +} + /** * @brief Handle got a target * @@ -1279,22 +1286,26 @@ handle_got_target(ROUTER_INSTANCE *inst, ROUTER_CLIENT_SES *rses, MXS_ERROR("Failed to store current statement, it won't be retried if it fails."); } - backend_ref_t *bref; - atomic_add_uint64(&inst->stats.n_queries, 1); - /** - * Add one query response waiter to backend reference - */ - bref = get_bref_from_dcb(rses, target_dcb); - bref_set_state(bref, BREF_QUERY_ACTIVE); - bref_set_state(bref, BREF_WAITING_RESULT); - ss_dassert(bref->reply_state == REPLY_STATE_DONE); - LOG_RS(bref, REPLY_STATE_START); - bref->reply_state = REPLY_STATE_START; - rses->expected_responses++; + mysql_server_cmd_t cmd = mxs_mysql_current_command(rses->client_dcb->session); + + if (query_creates_reply(cmd)) + { + /** The server will reply to this command */ + ss_dassert(bref->reply_state == REPLY_STATE_DONE); + + bref = get_bref_from_dcb(rses, target_dcb); + bref_set_state(bref, BREF_QUERY_ACTIVE); + bref_set_state(bref, BREF_WAITING_RESULT); + + LOG_RS(bref, REPLY_STATE_START); + bref->reply_state = REPLY_STATE_START; + rses->expected_responses++; + } + /** - * If a READ ONLYtransaction is ending set forced_node to NULL + * If a READ ONLY transaction is ending set forced_node to NULL */ if (rses->forced_node && session_trx_is_read_only(rses->client_dcb->session) &&