From 5f4aa465522a5c4546f8aef405d9a8e3a3a79cee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 28 Aug 2018 14:19:06 +0300 Subject: [PATCH] MXS-2027: Store LOAD DATA state inside MXS_SESSION By storing the data gathere by readwritesplit inside the session, the protocol will be aware of the state of the LOAD DATA LOCAL INFILE execution. This prevents misinterpretation of the data which previously led to closed connections, effectively rendering LOAD DATA LOCAL INFILE unusable. This change is a temporary solution to a problem that needs to be solved at the protocol level. The changes required to implement this are too big to add into a bug fix release. --- include/maxscale/session.h | 11 +++++++++++ server/core/session.cc | 1 + .../protocol/MySQL/mariadbclient/mysql_client.cc | 5 +++-- .../modules/routing/readwritesplit/readwritesplit.cc | 1 + .../routing/readwritesplit/rwsplit_route_stmt.cc | 2 ++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/maxscale/session.h b/include/maxscale/session.h index 24255d42a..1f2e48628 100644 --- a/include/maxscale/session.h +++ b/include/maxscale/session.h @@ -181,6 +181,7 @@ typedef struct session bool qualifies_for_pooling; /**< Whether this session qualifies for the connection pool */ SessionStmtQueue* last_statements; /*< The N last statements by the client */ session_close_t close_reason; /**< Reason why the session was closed */ + bool load_active; /**< Data streaming state (for LOAD DATA LOCAL INFILE) */ skygw_chk_t ses_chk_tail; } MXS_SESSION; @@ -557,4 +558,14 @@ session_dump_statements_t session_get_dump_statements(); */ const char* session_get_close_reason(const MXS_SESSION* session); +static inline void session_set_load_active(MXS_SESSION* session, bool value) +{ + session->load_active = value; +} + +static inline bool session_is_load_active(const MXS_SESSION* session) +{ + return session->load_active; +} + MXS_END_DECLS diff --git a/server/core/session.cc b/server/core/session.cc index f546d2f1c..9ea030cc2 100644 --- a/server/core/session.cc +++ b/server/core/session.cc @@ -130,6 +130,7 @@ static MXS_SESSION* session_alloc_body(SERVICE* service, DCB* client_dcb, session->stmt.target = NULL; session->qualifies_for_pooling = false; session->close_reason = SESSION_CLOSE_NONE; + session->load_active = false; MXS_CONFIG *config = config_get_global_options(); // If MaxScale is running in Oracle mode, then autocommit needs to diff --git a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc index 136eb4ac8..12d81dbd0 100644 --- a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc +++ b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc @@ -1622,7 +1622,7 @@ static int route_by_statement(MXS_SESSION* session, uint64_t capabilities, GWBUF /** * Update the currently command being executed. */ - if (!proto->changing_user) + if (!proto->changing_user && !session_is_load_active(session)) { update_current_command(session->client_dcb, packetbuf); } @@ -1631,7 +1631,8 @@ static int route_by_statement(MXS_SESSION* session, uint64_t capabilities, GWBUF { ss_dassert(GWBUF_IS_CONTIGUOUS(packetbuf)); - if (rcap_type_required(capabilities, RCAP_TYPE_TRANSACTION_TRACKING)) + if (rcap_type_required(capabilities, RCAP_TYPE_TRANSACTION_TRACKING) && + !session_is_load_active(session)) { if (session_trx_is_ending(session)) { diff --git a/server/modules/routing/readwritesplit/readwritesplit.cc b/server/modules/routing/readwritesplit/readwritesplit.cc index cb5de21bb..4d518f9a0 100644 --- a/server/modules/routing/readwritesplit/readwritesplit.cc +++ b/server/modules/routing/readwritesplit/readwritesplit.cc @@ -1204,6 +1204,7 @@ static void clientReply(MXS_ROUTER *instance, { // Server responded with an error to the LOAD DATA LOCAL INFILE rses->load_data_state = LOAD_DATA_INACTIVE; + session_set_load_active(backend_dcb->session, true); } if (backend->get_reply_state() == REPLY_STATE_DONE) diff --git a/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc b/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc index 496318251..cc5ed2e19 100644 --- a/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc +++ b/server/modules/routing/readwritesplit/rwsplit_route_stmt.cc @@ -1220,6 +1220,7 @@ bool handle_got_target(RWSplit *inst, RWSplitSession *rses, /** The first packet contains the actual query and the server * will respond to it */ rses->load_data_state = LOAD_DATA_ACTIVE; + session_set_load_active(rses->client_dcb->session, true); } else if (rses->load_data_state == LOAD_DATA_END) { @@ -1227,6 +1228,7 @@ bool handle_got_target(RWSplit *inst, RWSplitSession *rses, * to which the server responds with an OK or an ERR packet */ ss_dassert(gwbuf_length(querybuf) == 4); rses->load_data_state = LOAD_DATA_INACTIVE; + session_set_load_active(rses->client_dcb->session, false); } }