MXS-2025 RWBackends as a vector of unique_ptr:s

For lifetime management keep RWBackends in a vector of unique_ptrs.
RWSplitSession keeps the unique_ptrs very private, and provides a vector
of plain pointers for all other interfaces.
This commit is contained in:
Niclas Antti 2018-11-29 11:57:28 +02:00
parent 91f6f374a8
commit 0d09b56f58
9 changed files with 52 additions and 35 deletions

View File

@ -14,6 +14,7 @@
#include <map>
#include <memory>
#include <algorithm>
#include <maxscale/backend.hh>
#include <maxscale/modutil.hh>
@ -22,6 +23,17 @@
namespace maxscale
{
/** Move this somewhere else */
template<typename Smart>
std::vector<typename Smart::pointer> sptr_vec_to_ptr_vec(const std::vector<Smart>& sVec)
{
std::vector<typename Smart::pointer> pVec;
std::for_each(sVec.begin(), sVec.end(), [&pVec](const Smart& smart) {
pVec.push_back(smart.get());
});
return pVec;
}
/** Enum for tracking client reply state */
enum reply_state_t
{
@ -38,7 +50,7 @@ class RWBackend;
// All interfacing is now handled via RWBackend*.
using PRWBackends = std::vector<RWBackend*>;
// Internal storage for a class containing RWBackend:s. Not used yet.
// Internal storage for a class containing RWBackend:s.
using SRWBackends = std::vector<std::unique_ptr<RWBackend>>;
class RWBackend : public mxs::Backend
@ -48,7 +60,7 @@ class RWBackend : public mxs::Backend
public:
static PRWBackends from_servers(SERVER_REF* servers);
static SRWBackends from_servers(SERVER_REF* servers);
RWBackend(SERVER_REF* ref);
virtual ~RWBackend();

View File

@ -253,15 +253,15 @@ ResponseStat& RWBackend::response_stat()
return m_response_stat;
}
PRWBackends RWBackend::from_servers(SERVER_REF* servers)
mxs::SRWBackends RWBackend::from_servers(SERVER_REF* servers)
{
PRWBackends backends;
SRWBackends backends;
for (SERVER_REF* ref = servers; ref; ref = ref->next)
{
if (ref->active)
{
backends.push_back(new mxs::RWBackend(ref));
backends.emplace_back(new mxs::RWBackend(ref));
}
}

View File

@ -43,7 +43,7 @@ CatSession* Cat::newSession(MXS_SESSION* pSession)
}
}
return connected ? new CatSession(pSession, this, backends) : NULL;
return connected ? new CatSession(pSession, this, std::move(backends)) : NULL;
}
void Cat::diagnostics(DCB* dcb)

View File

@ -18,10 +18,10 @@
using namespace maxscale;
CatSession::CatSession(MXS_SESSION* session, Cat* router, PRWBackends& backends)
CatSession::CatSession(MXS_SESSION* session, Cat* router, mxs::SRWBackends backends)
: RouterSession(session)
, m_session(session)
, m_backends(backends)
, m_backends(std::move(backends))
, m_completed(0)
, m_packet_num(0)
, m_query(NULL)
@ -68,7 +68,7 @@ int32_t CatSession::routeQuery(GWBUF* pPacket)
void CatSession::clientReply(GWBUF* pPacket, DCB* pDcb)
{
auto backend = *m_current;
auto& backend = *m_current;
mxb_assert(backend->dcb() == pDcb);
bool send = false;

View File

@ -27,7 +27,7 @@ class CatSession : public mxs::RouterSession
CatSession& operator=(const CatSession&) = delete;
public:
CatSession(MXS_SESSION* session, Cat* router, mxs::PRWBackends& backends);
CatSession(MXS_SESSION* session, Cat* router, mxs::SRWBackends backends);
/**
* The RouterSession instance will be deleted when a client session
@ -71,10 +71,10 @@ public:
private:
MXS_SESSION* m_session;
mxs::PRWBackends m_backends;
mxs::SRWBackends m_backends;
uint64_t m_completed;
uint8_t m_packet_num;
mxs::PRWBackends::iterator m_current;
mxs::SRWBackends::iterator m_current;
GWBUF* m_query;
/**

View File

@ -43,7 +43,7 @@ void RWSplitSession::handle_connection_keepalive(RWBackend* target)
/** Each heartbeat is 1/10th of a second */
int keepalive = m_config.connection_keepalive * 10;
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
for (auto it = m_raw_backends.begin(); it != m_raw_backends.end(); it++)
{
RWBackend* backend = *it;
@ -126,7 +126,7 @@ uint32_t extract_binary_ps_id(GWBUF* buffer)
bool RWSplitSession::have_connected_slaves() const
{
for (const auto& b : m_backends)
for (const auto& b : m_raw_backends)
{
if (b->is_slave() && b->in_use())
{
@ -378,7 +378,7 @@ void RWSplitSession::compress_history(mxs::SSessionCommand& sescmd)
void RWSplitSession::continue_large_session_write(GWBUF* querybuf, uint32_t type)
{
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
for (auto it = m_raw_backends.begin(); it != m_raw_backends.end(); it++)
{
RWBackend* backend = *it;
@ -446,7 +446,7 @@ bool RWSplitSession::route_session_write(GWBUF* querybuf, uint8_t command, uint3
MXS_INFO("Session write, routing to all servers.");
bool attempted_write = false;
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
for (auto it = m_raw_backends.begin(); it != m_raw_backends.end(); it++)
{
RWBackend* backend = *it;
@ -558,7 +558,7 @@ RWBackend* RWSplitSession::get_hinted_backend(char* name)
{
RWBackend* rval;
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
for (auto it = m_raw_backends.begin(); it != m_raw_backends.end(); it++)
{
auto& backend = *it;
@ -579,9 +579,9 @@ RWBackend* RWSplitSession::get_slave_backend(int max_rlag)
// create a list of useable backends (includes masters, function name is a bit off),
// then feed that list to compare.
PRWBackends candidates;
auto counts = get_slave_counts(m_backends, m_current_master);
auto counts = get_slave_counts(m_raw_backends, m_current_master);
for (auto& backend : m_backends)
for (auto& backend : m_raw_backends)
{
bool can_take_slave_into_use = backend->is_slave()
&& !backend->in_use()
@ -612,7 +612,7 @@ RWBackend* RWSplitSession::get_master_backend()
{
RWBackend* rval;
/** get root master from available servers */
RWBackend* master = get_root_master(m_backends);
RWBackend* master = get_root_master(m_raw_backends);
if (master)
{

View File

@ -373,8 +373,8 @@ std::pair<int, int> get_slave_counts(PRWBackends& backends, RWBackend* master)
* @return True if session can continue
*/
bool RWSplit::select_connect_backend_servers(MXS_SESSION* session,
PRWBackends& backends,
mxs::RWBackend** current_master,
mxs::PRWBackends& backends,
mxs::RWBackend** current_master,
SessionCommandList* sescmd_list,
int* expected_responses,
connection_type type)

View File

@ -22,10 +22,11 @@ using namespace maxscale;
RWSplitSession::RWSplitSession(RWSplit* instance,
MXS_SESSION* session,
PRWBackends backends,
RWBackend* master)
mxs::SRWBackends backends,
mxs::RWBackend* master)
: mxs::RouterSession(session)
, m_backends(backends)
, m_backends(std::move(backends))
, m_raw_backends(sptr_vec_to_ptr_vec(m_backends))
, m_current_master(master)
, m_config(instance->config())
, m_nbackends(instance->service()->n_dbref)
@ -60,7 +61,7 @@ RWSplitSession* RWSplitSession::create(RWSplit* router, MXS_SESSION* session)
if (router->have_enough_servers())
{
PRWBackends backends = RWBackend::from_servers(router->service()->dbref);
SRWBackends backends = RWBackend::from_servers(router->service()->dbref);
/**
* At least the master must be found if the router is in the strict mode.
@ -69,14 +70,16 @@ RWSplitSession* RWSplitSession::create(RWSplit* router, MXS_SESSION* session)
RWBackend* master;
auto backend_ptrs = sptr_vec_to_ptr_vec(backends);
if (router->select_connect_backend_servers(session,
backends,
backend_ptrs,
&master,
NULL,
NULL,
connection_type::ALL))
{
if ((rses = new RWSplitSession(router, session, backends, master)))
if ((rses = new RWSplitSession(router, session, std::move(backends), master)))
{
router->stats().n_sessions += 1;
}
@ -106,10 +109,10 @@ void close_all_connections(PRWBackends& backends)
void RWSplitSession::close()
{
close_all_connections(m_backends);
close_all_connections(m_raw_backends);
m_current_query.reset();
for (auto& backend : m_backends)
for (auto& backend : m_raw_backends)
{
ResponseStat& stat = backend->response_stat();
@ -310,7 +313,7 @@ RWBackend* RWSplitSession::get_backend_from_dcb(DCB* dcb)
{
mxb_assert(dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER);
for (auto it = m_backends.begin(); it != m_backends.end(); it++)
for (auto it = m_raw_backends.begin(); it != m_raw_backends.end(); it++)
{
RWBackend* backend = *it;
@ -1076,7 +1079,7 @@ bool RWSplitSession::handle_error_new_connection(DCB* backend_dcb, GWBUF* errmsg
*/
if (m_recv_sescmd > 0 && m_config.disable_sescmd_history)
{
for (const auto& a : m_backends)
for (const auto& a : m_raw_backends)
{
if (a->in_use())
{
@ -1093,8 +1096,9 @@ bool RWSplitSession::handle_error_new_connection(DCB* backend_dcb, GWBUF* errmsg
}
else
{
succp = m_router->select_connect_backend_servers(ses,
m_backends,
m_raw_backends,
&m_current_master,
&m_sescmd_list,
&m_expected_responses,

View File

@ -131,7 +131,8 @@ public:
}
// TODO: Make member variables private
mxs::PRWBackends m_backends; /**< List of backend servers */
mxs::SRWBackends m_backends; /**< Mem. management, not for use outside RWSplitSession */
mxs::PRWBackends m_raw_backends; /**< Backend pointers for use in interfaces . */
mxs::RWBackend* m_current_master; /**< Current master server */
mxs::RWBackend* m_target_node; /**< The currently locked target node */
mxs::RWBackend* m_prev_target; /**< The previous target where a query was sent */
@ -172,7 +173,7 @@ public:
private:
RWSplitSession(RWSplit* instance,
MXS_SESSION* session,
mxs::PRWBackends backends,
mxs::SRWBackends backends,
mxs::RWBackend* master);
void process_sescmd_response(mxs::RWBackend* backend, GWBUF** ppPacket);