From b0a1eddb6ca723b1c5cbaac7bc237e4fdf533791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Tue, 17 Dec 2019 07:49:58 +0200 Subject: [PATCH] Store ignored error information The errors that are ignored by readwritesplit are now stored as the current close reason in the Backend. This allows the information about the error to be retained and it can be used later in the error handler to display the true reason why the connection was closed. --- include/maxscale/backend.hh | 10 ++++++++++ server/core/backend.cc | 1 + .../modules/routing/readwritesplit/rwsplitsession.cc | 8 ++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/maxscale/backend.hh b/include/maxscale/backend.hh index a60f828ed..d220164a9 100644 --- a/include/maxscale/backend.hh +++ b/include/maxscale/backend.hh @@ -357,6 +357,16 @@ public: */ void set_close_reason(const std::string& reason); + /** + * Get latest close reason + * + * @return A human-readable reason why the connection was closed + */ + const std::string& close_reason() const + { + return m_close_reason; + } + private: /** * Internal state of the backend diff --git a/server/core/backend.cc b/server/core/backend.cc index e7c71c52f..8a0cd1cc6 100644 --- a/server/core/backend.cc +++ b/server/core/backend.cc @@ -197,6 +197,7 @@ bool Backend::connect(MXS_SESSION* session, SessionCommandList* sescmd) m_closed_at = 0; m_opened_at = time(NULL); m_state = IN_USE; + m_close_reason.clear(); mxb::atomic::add(&m_backend->connections, 1, mxb::atomic::RELAXED); rval = true; m_history_size = 0; diff --git a/server/modules/routing/readwritesplit/rwsplitsession.cc b/server/modules/routing/readwritesplit/rwsplitsession.cc index f82f2a897..e5099b6fa 100644 --- a/server/modules/routing/readwritesplit/rwsplitsession.cc +++ b/server/modules/routing/readwritesplit/rwsplitsession.cc @@ -589,6 +589,7 @@ void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb) // The connection was killed, we can safely ignore it. When the TCP connection is // closed, the router's error handling will sort it out. gwbuf_free(writebuf); + backend->set_close_reason("Connection was killed"); } else { @@ -604,6 +605,7 @@ void RWSplitSession::clientReply(GWBUF* writebuf, DCB* backend_dcb) { // The server is shutting down, ignore this error and wait for the TCP connection to die. // This allows the query to be retried on another server without the client noticing it. + backend->set_close_reason(std::string("Server '") + backend->name() + "' is shutting down"); gwbuf_free(writebuf); return; } @@ -1039,9 +1041,11 @@ void RWSplitSession::handleError(GWBUF* errmsgbuf, { int64_t idle = mxs_clock() - backend->dcb()->last_read; MXS_ERROR("Lost connection to the master server '%s', closing session.%s " - "Connection has been idle for %.1f seconds. Error caused by: %s", + "Connection has been idle for %.1f seconds. Error caused by: %s. " + "Last close reason: %s", backend->name(), errmsg.c_str(), (float)idle / 10.f, - extract_error(errmsgbuf).c_str()); + extract_error(errmsgbuf).c_str(), + backend->close_reason().empty() ? "" : backend->close_reason().c_str()); } // Decrement the expected response count only if we know we can continue the sesssion.