Use a list of backends instead of an array

Changed the backend_ref_t struct into a Backend class. Replaced static
arrays with lists. Altered functions to make the code compile.

Further refactoring is needed, a part of the functions should be moved
into this new class.
This commit is contained in:
Markus Mäkelä
2017-03-27 19:41:50 +03:00
parent c4638666cf
commit d1aa2a4b8a
2 changed files with 159 additions and 201 deletions

View File

@ -20,13 +20,11 @@
#include "schemaroutersession.hh"
#include "schemarouterinstance.hh"
bool connect_backend_servers(backend_ref_t* backend_ref,
int router_nservers,
MXS_SESSION* session);
bool connect_backend_servers(BackendList& backends, MXS_SESSION* session);
bool execute_sescmd_in_backend(backend_ref_t* backend_ref);
void bref_clear_state(backend_ref_t* bref, enum bref_state state);
void bref_set_state(backend_ref_t* bref, enum bref_state state);
bool execute_sescmd_in_backend(Backend* backend_ref);
void bref_clear_state(Backend& bref, enum bref_state state);
void bref_set_state(Backend& bref, enum bref_state state);
enum route_target get_shard_route_target(uint32_t qtype);
bool change_current_db(string& dest, Shard& shard, GWBUF* buf);
@ -34,15 +32,30 @@ bool extract_database(GWBUF* buf, char* str);
bool detect_show_shards(GWBUF* query);
void write_error_to_client(DCB* dcb, int errnum, const char* mysqlstate, const char* errmsg);
Backend::Backend(SERVER_REF *ref):
backend(ref),
dcb(NULL),
map_queue(NULL),
mapped(false),
n_mapping_eof(0),
num_result_wait(0),
pending_cmd(NULL),
state(0)
{
}
Backend::~Backend()
{
gwbuf_free(map_queue);
gwbuf_free(pending_cmd);
}
SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session, SchemaRouter* router):
mxs::RouterSession(session),
m_closed(false),
m_client(session->client_dcb),
m_mysql_session((MYSQL_session*)session->client_dcb->data),
m_backends(NULL),
m_config(&m_router->m_config),
m_backend_count(0),
m_router(router),
m_shard(m_router->m_shard_manager.get_shard(m_client->user, m_config->refresh_min_interval)),
m_state(0),
@ -78,33 +91,15 @@ SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session, SchemaRouter* rou
m_state |= INIT_USE_DB;
}
int router_nservers = m_router->m_service->n_dbref;
backend_ref_t* backend_ref = new backend_ref_t[router_nservers];
int i = 0;
for (SERVER_REF *ref = m_router->m_service->dbref; ref && i < router_nservers; ref = ref->next)
for (SERVER_REF *ref = m_router->m_service->dbref; ref; ref = ref->next)
{
if (ref->active)
{
backend_ref[i].state = 0;
backend_ref[i].n_mapping_eof = 0;
backend_ref[i].map_queue = NULL;
backend_ref[i].backend = ref;
backend_ref[i].pending_cmd = NULL;
i++;
m_backends.push_back(Backend(ref));
}
}
if (i < router_nservers)
{
/** Service had less than the reported number of servers */
router_nservers = i;
}
m_backends = backend_ref;
m_backend_count = router_nservers;
if (!connect_backend_servers(backend_ref, router_nservers, session))
if (!connect_backend_servers(m_backends, session))
{
// TODO: Figure out how to avoid this throw
throw std::runtime_error("Failed to connect to backend servers");
@ -121,12 +116,6 @@ SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session, SchemaRouter* rou
SchemaRouterSession::~SchemaRouterSession()
{
for (int i = 0; i < m_backend_count; i++)
{
gwbuf_free(m_backends[i].pending_cmd);
}
delete[] m_backends;
}
void SchemaRouterSession::close()
@ -140,28 +129,27 @@ void SchemaRouterSession::close()
{
m_closed = true;
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
backend_ref_t* bref = &m_backends[i];
DCB* dcb = bref->dcb;
DCB* dcb = it->dcb;
/** Close those which had been connected */
if (BREF_IS_IN_USE(bref))
if (BREF_IS_IN_USE(it))
{
CHK_DCB(dcb);
/** Clean operation counter in bref and in SERVER */
while (BREF_IS_WAITING_RESULT(bref))
while (BREF_IS_WAITING_RESULT(it))
{
bref_clear_state(bref, BREF_WAITING_RESULT);
bref_clear_state(*it, BREF_WAITING_RESULT);
}
bref_clear_state(bref, BREF_IN_USE);
bref_set_state(bref, BREF_CLOSED);
bref_clear_state(*it, BREF_IN_USE);
bref_set_state(*it, BREF_CLOSED);
/**
* closes protocol and dcb
*/
dcb_close(dcb);
/** decrease server current connection counters */
atomic_add(&bref->backend->connections, -1);
atomic_add(&it->backend->connections, -1);
}
}
@ -291,9 +279,9 @@ SERVER* SchemaRouterSession::resolve_query_target(GWBUF* pPacket,
if (TARGET_IS_ANY(route_target))
{
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
SERVER *server = m_backends[i].backend->server;
SERVER *server = it->backend->server;
if (SERVER_IS_RUNNING(server))
{
route_target = TARGET_NAMED_SERVER;
@ -453,7 +441,7 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
get_shard_dcb(&target_dcb, target->unique_name))
{
/** We know where to route this query */
backend_ref_t *bref = get_bref_from_dcb(target_dcb);
Backend *bref = get_bref_from_dcb(target_dcb);
MXS_INFO("Route query to \t%s:%d <", bref->backend->server->name, bref->backend->server->port);
@ -467,7 +455,7 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
}
else if ((ret = target_dcb->func.write(target_dcb, gwbuf_clone(pPacket))) == 1)
{
backend_ref_t* bref;
Backend* bref;
atomic_add(&m_router->m_stats.n_queries, 1);
@ -475,8 +463,8 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
* Add one query response waiter to backend reference
*/
bref = get_bref_from_dcb(target_dcb);
bref_set_state(bref, BREF_QUERY_ACTIVE);
bref_set_state(bref, BREF_WAITING_RESULT);
bref_set_state(*bref, BREF_QUERY_ACTIVE);
bref_set_state(*bref, BREF_WAITING_RESULT);
}
else
{
@ -487,7 +475,7 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
gwbuf_free(pPacket);
return ret;
}
void SchemaRouterSession::handle_mapping_reply(backend_ref_t* bref, GWBUF* pPacket)
void SchemaRouterSession::handle_mapping_reply(Backend* bref, GWBUF* pPacket)
{
int rc = inspect_backend_mapping_states(bref, &pPacket);
@ -521,7 +509,7 @@ void SchemaRouterSession::handle_mapping_reply(backend_ref_t* bref, GWBUF* pPack
}
}
void SchemaRouterSession::process_response(backend_ref_t* bref, GWBUF** ppPacket)
void SchemaRouterSession::process_response(Backend* bref, GWBUF** ppPacket)
{
if (bref->session_commands.size() > 0)
{
@ -547,20 +535,20 @@ void SchemaRouterSession::process_response(backend_ref_t* bref, GWBUF** ppPacket
if (*ppPacket)
{
bref_clear_state(bref, BREF_WAITING_RESULT);
bref_clear_state(*bref, BREF_WAITING_RESULT);
}
}
else if (BREF_IS_QUERY_ACTIVE(bref))
{
bref_clear_state(bref, BREF_QUERY_ACTIVE);
bref_clear_state(*bref, BREF_QUERY_ACTIVE);
/** Set response status as replied */
bref_clear_state(bref, BREF_WAITING_RESULT);
bref_clear_state(*bref, BREF_WAITING_RESULT);
}
}
void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
{
backend_ref_t* bref = get_bref_from_dcb(pDcb);
Backend* bref = get_bref_from_dcb(pDcb);
if (m_closed || bref == NULL)
{
@ -614,7 +602,7 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
/** There are pending session commands to be executed. */
MXS_INFO("Backend %s:%d processed reply and starts to execute active cursor.",
bref->backend->server->name, bref->backend->server->port);
execute_sescmd_in_backend(bref);
execute_sescmd_in_backend(*bref);
}
else if (bref->pending_cmd) /*< non-sescmd is waiting to be routed */
{
@ -625,8 +613,8 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
if (ret == 1)
{
atomic_add(&m_router->m_stats.n_queries, 1);
bref_set_state(bref, BREF_QUERY_ACTIVE);
bref_set_state(bref, BREF_WAITING_RESULT);
bref_set_state(*bref, BREF_QUERY_ACTIVE);
bref_set_state(*bref, BREF_WAITING_RESULT);
}
else
{
@ -753,27 +741,27 @@ retblock:
*
* Router session must be locked.
*/
bool SchemaRouterSession::execute_sescmd_in_backend(backend_ref_t* backend_ref)
bool SchemaRouterSession::execute_sescmd_in_backend(Backend& backend_ref)
{
if (BREF_IS_CLOSED(backend_ref))
if (BREF_IS_CLOSED(&backend_ref))
{
return false;
}
DCB *dcb = backend_ref->dcb;
DCB *dcb = backend_ref.dcb;
CHK_DCB(dcb);
int rc = 0;
/** Return if there are no pending ses commands */
if (backend_ref->session_commands.size() == 0)
if (backend_ref.session_commands.size() == 0)
{
MXS_INFO("Cursor had no pending session commands.");
return false;
}
SessionCommandList::iterator iter = backend_ref->session_commands.begin();
SessionCommandList::iterator iter = backend_ref.session_commands.begin();
GWBUF *buffer = iter->copy_buffer().release();
switch (iter->get_command())
@ -813,7 +801,6 @@ bool SchemaRouterSession::execute_sescmd_in_backend(backend_ref_t* backend_ref)
bool SchemaRouterSession::route_session_write(GWBUF* querybuf, uint8_t command)
{
bool succp = false;
backend_ref_t *backend_ref = m_backends;
MXS_INFO("Session write, routing to all servers.");
atomic_add(&m_stats.longest_sescmd, 1);
@ -821,24 +808,22 @@ bool SchemaRouterSession::route_session_write(GWBUF* querybuf, uint8_t command)
/** Increment the session command count */
++m_sent_sescmd;
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
if (BREF_IS_IN_USE((&backend_ref[i])))
if (BREF_IS_IN_USE(it))
{
GWBUF *buffer = gwbuf_clone(querybuf);
backend_ref[i].session_commands.push_back(SessionCommand(buffer, m_sent_sescmd));
it->session_commands.push_back(SessionCommand(buffer, m_sent_sescmd));
if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
MXS_INFO("Route query to %s\t%s:%d%s",
(SERVER_IS_MASTER(backend_ref[i].backend->server) ?
"master" : "slave"),
backend_ref[i].backend->server->name,
backend_ref[i].backend->server->port,
(i + 1 == m_backend_count ? " <" : ""));
MXS_INFO("Route query to %s\t%s:%d",
SERVER_IS_MASTER(it->backend->server) ? "master" : "slave",
it->backend->server->name,
it->backend->server->port);
}
if (backend_ref[i].session_commands.size() == 1)
if (it->session_commands.size() == 1)
{
/** Only one command, execute it */
switch (command)
@ -849,11 +834,11 @@ bool SchemaRouterSession::route_session_write(GWBUF* querybuf, uint8_t command)
break;
default:
bref_set_state(&backend_ref[i], BREF_WAITING_RESULT);
bref_set_state(*it, BREF_WAITING_RESULT);
break;
}
if (execute_sescmd_in_backend(&backend_ref[i]))
if (execute_sescmd_in_backend(*it))
{
succp = true;
}
@ -861,17 +846,17 @@ bool SchemaRouterSession::route_session_write(GWBUF* querybuf, uint8_t command)
{
MXS_ERROR("Failed to execute session "
"command in %s:%d",
backend_ref[i].backend->server->name,
backend_ref[i].backend->server->port);
it->backend->server->name,
it->backend->server->port);
}
}
else
{
ss_dassert(backend_ref[i].session_commands.size() > 1);
ss_dassert(it->session_commands.size() > 1);
/** The server is already executing a session command */
MXS_INFO("Backend %s:%d already executing sescmd.",
backend_ref[i].backend->server->name,
backend_ref[i].backend->server->port);
it->backend->server->name,
it->backend->server->port);
succp = true;
}
}
@ -882,13 +867,13 @@ bool SchemaRouterSession::route_session_write(GWBUF* querybuf, uint8_t command)
void SchemaRouterSession::handle_error_reply_client(DCB* dcb, GWBUF* errmsg)
{
backend_ref_t* bref = get_bref_from_dcb(dcb);
Backend* bref = get_bref_from_dcb(dcb);
if (bref)
{
bref_clear_state(bref, BREF_IN_USE);
bref_set_state(bref, BREF_CLOSED);
bref_clear_state(*bref, BREF_IN_USE);
bref_set_state(*bref, BREF_CLOSED);
}
if (dcb->session->state == SESSION_STATE_ROUTER_READY)
@ -905,10 +890,9 @@ void SchemaRouterSession::handle_error_reply_client(DCB* dcb, GWBUF* errmsg)
*/
bool SchemaRouterSession::have_servers()
{
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
if (BREF_IS_IN_USE(&m_backends[i]) &&
!BREF_IS_CLOSED(&m_backends[i]))
if (BREF_IS_IN_USE(it) && !BREF_IS_CLOSED(it))
{
return true;
}
@ -932,15 +916,12 @@ bool SchemaRouterSession::have_servers()
*/
bool SchemaRouterSession::handle_error_new_connection(DCB* backend_dcb, GWBUF* errmsg)
{
backend_ref_t* bref;
MXS_SESSION *ses = backend_dcb->session;
CHK_SESSION(ses);
/**
* If bref == NULL it has been replaced already with another one.
*/
if ((bref = get_bref_from_dcb(backend_dcb)) == NULL)
Backend* bref = get_bref_from_dcb(backend_dcb);
if (bref == NULL)
{
/** This should not happen */
ss_dassert(false);
@ -957,10 +938,10 @@ bool SchemaRouterSession::handle_error_new_connection(DCB* backend_dcb, GWBUF* e
DCB* client_dcb;
client_dcb = ses->client_dcb;
client_dcb->func.write(client_dcb, gwbuf_clone(errmsg));
bref_clear_state(bref, BREF_WAITING_RESULT);
bref_clear_state(*bref, BREF_WAITING_RESULT);
}
bref_clear_state(bref, BREF_IN_USE);
bref_set_state(bref, BREF_CLOSED);
bref_clear_state(*bref, BREF_IN_USE);
bref_set_state(*bref, BREF_CLOSED);
return have_servers();
}
@ -973,15 +954,15 @@ bool SchemaRouterSession::handle_error_new_connection(DCB* backend_dcb, GWBUF* e
*
* @return backend reference pointer if succeed or NULL
*/
backend_ref_t* SchemaRouterSession::get_bref_from_dcb(DCB* dcb)
Backend* SchemaRouterSession::get_bref_from_dcb(DCB* dcb)
{
CHK_DCB(dcb);
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
if (m_backends[i].dcb == dcb)
if (it->dcb == dcb)
{
return &m_backends[i];
return &(*it);
}
}
@ -1183,29 +1164,28 @@ void SchemaRouterSession::route_queued_query()
* @param router_cli_ses Router client session
* @return 1 if mapping is done, 0 if it is still ongoing and -1 on error
*/
int SchemaRouterSession::inspect_backend_mapping_states(backend_ref_t *bref,
int SchemaRouterSession::inspect_backend_mapping_states(Backend *bref,
GWBUF** wbuf)
{
bool mapped = true;
GWBUF* writebuf = *wbuf;
backend_ref_t* bkrf = m_backends;
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
if (bref->dcb == bkrf[i].dcb && !BREF_IS_MAPPED(&bkrf[i]))
if (bref->dcb == it->dcb && !BREF_IS_MAPPED(it))
{
if (bref->map_queue)
{
writebuf = gwbuf_append(bref->map_queue, writebuf);
bref->map_queue = NULL;
}
enum showdb_response rc = parse_showdb_response(&m_backends[i],
enum showdb_response rc = parse_showdb_response(&(*it),
&writebuf);
if (rc == SHOWDB_FULL_RESPONSE)
{
m_backends[i].mapped = true;
it->mapped = true;
MXS_DEBUG("Received SHOW DATABASES reply from %s for session %p",
m_backends[i].backend->server->unique_name,
it->backend->server->unique_name,
m_client->session);
}
else if (rc == SHOWDB_PARTIAL_RESPONSE)
@ -1213,7 +1193,7 @@ int SchemaRouterSession::inspect_backend_mapping_states(backend_ref_t *bref,
bref->map_queue = writebuf;
writebuf = NULL;
MXS_DEBUG("Received partial SHOW DATABASES reply from %s for session %p",
m_backends[i].backend->server->unique_name,
it->backend->server->unique_name,
m_client->session);
}
else
@ -1262,11 +1242,11 @@ int SchemaRouterSession::inspect_backend_mapping_states(backend_ref_t *bref,
}
}
if (BREF_IS_IN_USE(&bkrf[i]) && !BREF_IS_MAPPED(&bkrf[i]))
if (BREF_IS_IN_USE(it) && !BREF_IS_MAPPED(it))
{
mapped = false;
MXS_DEBUG("Still waiting for reply to SHOW DATABASES from %s for session %p",
bkrf[i].backend->server->unique_name,
it->backend->server->unique_name,
m_client->session);
}
}
@ -1411,7 +1391,7 @@ char* get_lenenc_str(void* data)
* @return 1 if a complete response was received, 0 if a partial response was received
* and -1 if a database was found on more than one server.
*/
enum showdb_response SchemaRouterSession::parse_showdb_response(backend_ref_t* bref, GWBUF** buffer)
enum showdb_response SchemaRouterSession::parse_showdb_response(Backend* bref, GWBUF** buffer)
{
unsigned char* ptr;
SERVER* target = bref->backend->server;
@ -1539,10 +1519,10 @@ int SchemaRouterSession::gen_databaselist()
int i, rval = 0;
unsigned int len;
for (i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
m_backends[i].mapped = false;
m_backends[i].n_mapping_eof = 0;
it->mapped = false;
it->n_mapping_eof = 0;
}
m_state |= INIT_MAPPING;
@ -1557,17 +1537,17 @@ int SchemaRouterSession::gen_databaselist()
*(data + 4) = 0x03;
memcpy(data + 5, query, strlen(query));
for (i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
if (BREF_IS_IN_USE(&m_backends[i]) &&
!BREF_IS_CLOSED(&m_backends[i]) &
SERVER_IS_RUNNING(m_backends[i].backend->server))
if (BREF_IS_IN_USE(it) &&
!BREF_IS_CLOSED(it) &
SERVER_IS_RUNNING(it->backend->server))
{
clone = gwbuf_clone(buffer);
dcb = m_backends[i].dcb;
dcb = it->dcb;
rval |= !dcb->func.write(dcb, clone);
MXS_DEBUG("Wrote SHOW DATABASES to %s for session %p: returned %d",
m_backends[i].backend->server->unique_name,
it->backend->server->unique_name,
m_client->session,
rval);
}
@ -1666,13 +1646,13 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype)
}
else if (buffer->hint && buffer->hint->type == HINT_ROUTE_TO_NAMED_SERVER)
{
for (int i = 0; i < m_backend_count; i++)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
char *srvnm = m_backends[i].backend->server->unique_name;
char *srvnm = it->backend->server->unique_name;
if (strcmp(srvnm, (char*)buffer->hint->data) == 0)
{
rval = m_backends[i].backend->server;
rval = it->backend->server;
MXS_INFO("Routing hint found (%s)", rval->unique_name);
}
}
@ -1712,39 +1692,28 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype)
*/
bool SchemaRouterSession::get_shard_dcb(DCB** p_dcb, char* name)
{
backend_ref_t* backend_ref;
int i;
bool succp = false;
ss_dassert(p_dcb != NULL && *(p_dcb) == NULL);
if (p_dcb == NULL || name == NULL)
for (BackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
{
goto return_succp;
}
backend_ref = m_backends;
for (i = 0; i < m_backend_count; i++)
{
SERVER_REF* b = backend_ref[i].backend;
SERVER_REF* b = it->backend;
/**
* To become chosen:
* backend must be in use, name must match, and
* the backend state must be RUNNING
*/
if (BREF_IS_IN_USE((&backend_ref[i])) &&
if (BREF_IS_IN_USE((&(*it))) &&
(strncasecmp(name, b->server->unique_name, PATH_MAX) == 0) &&
SERVER_IS_RUNNING(b->server))
{
*p_dcb = backend_ref[i].dcb;
*p_dcb = it->dcb;
succp = true;
ss_dassert(backend_ref[i].dcb->state != DCB_STATE_ZOMBIE);
goto return_succp;
ss_dassert(it->dcb->state != DCB_STATE_ZOMBIE);
break;
}
}
return_succp:
return succp;
}
@ -1843,56 +1812,46 @@ bool SchemaRouterSession::send_database_list()
return rval;
}
void bref_clear_state(backend_ref_t* bref, enum bref_state state)
void bref_clear_state(Backend& bref, enum bref_state state)
{
if (bref == NULL)
{
MXS_ERROR("[%s] Error: NULL parameter.", __FUNCTION__);
return;
}
if (state != BREF_WAITING_RESULT)
{
bref->state &= ~state;
bref.state &= ~state;
}
else
{
/** Decrease global operation count */
int prev2 = atomic_add(&bref->backend->server->stats.n_current_ops, -1);
int prev2 = atomic_add(&bref.backend->server->stats.n_current_ops, -1);
ss_dassert(prev2 > 0);
if (prev2 <= 0)
{
MXS_ERROR("[%s] Error: negative current operation count in backend %s:%u",
__FUNCTION__,
bref->backend->server->name,
bref->backend->server->port);
bref.backend->server->name,
bref.backend->server->port);
}
}
}
void bref_set_state(backend_ref_t* bref, enum bref_state state)
void bref_set_state(Backend& bref, enum bref_state state)
{
if (bref == NULL)
{
MXS_ERROR("[%s] Error: NULL parameter.", __FUNCTION__);
return;
}
if (state != BREF_WAITING_RESULT)
{
bref->state |= state;
bref.state |= state;
}
else
{
/** Increase global operation count */
int prev2 = atomic_add(&bref->backend->server->stats.n_current_ops, 1);
int prev2 = atomic_add(&bref.backend->server->stats.n_current_ops, 1);
ss_dassert(prev2 >= 0);
if (prev2 < 0)
{
MXS_ERROR("[%s] Error: negative current operation count in backend %s:%u",
__FUNCTION__,
bref->backend->server->name,
bref->backend->server->port);
bref.backend->server->name,
bref.backend->server->port);
}
}
}
@ -1922,9 +1881,7 @@ void bref_set_state(backend_ref_t* bref, enum bref_state state)
* connections because all servers are supposed to be operational. It is,
* however, possible that there are less available servers than expected.
*/
bool connect_backend_servers(backend_ref_t* backend_ref,
int router_nservers,
MXS_SESSION* session)
bool connect_backend_servers(BackendList& backends, MXS_SESSION* session)
{
bool succp = false;
int servers_found = 0;
@ -1935,9 +1892,9 @@ bool connect_backend_servers(backend_ref_t* backend_ref,
{
MXS_INFO("Servers and connection counts:");
for (int i = 0; i < router_nservers; i++)
for (BackendList::iterator it = backends.begin(); it != backends.end(); it++)
{
SERVER_REF* b = backend_ref[i].backend;
SERVER_REF* b = it->backend;
MXS_INFO("MaxScale connections : %d (%d) in \t%s:%d %s",
b->connections,
@ -1951,27 +1908,23 @@ bool connect_backend_servers(backend_ref_t* backend_ref,
* Scan server list and connect each of them. None should fail or session
* can't be established.
*/
for (int i = 0; i < router_nservers; i++)
for (BackendList::iterator it = backends.begin(); it != backends.end(); it++)
{
SERVER_REF* b = backend_ref[i].backend;
SERVER_REF* b = it->backend;
if (SERVER_IS_RUNNING(b->server))
{
servers_found += 1;
/** Server is already connected */
if (BREF_IS_IN_USE((&backend_ref[i])))
if (BREF_IS_IN_USE(it))
{
slaves_connected += 1;
}
/** New server connection */
else
{
backend_ref[i].dcb = dcb_connect(b->server,
session,
b->server->protocol);
if (backend_ref[i].dcb != NULL)
if ((it->dcb = dcb_connect(b->server, session, b->server->protocol)))
{
servers_connected += 1;
/**
@ -1982,8 +1935,8 @@ bool connect_backend_servers(backend_ref_t* backend_ref,
* table.
*/
backend_ref[i].state = 0;
bref_set_state(&backend_ref[i], BREF_IN_USE);
it->state = 0;
bref_set_state(*it, BREF_IN_USE);
/**
* Increase backend connection counter.
* Server's stats are _increased_ in
@ -2013,11 +1966,11 @@ bool connect_backend_servers(backend_ref_t* backend_ref,
if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))
{
for (int i = 0; i < router_nservers; i++)
for (BackendList::iterator it = backends.begin(); it != backends.end(); it++)
{
SERVER_REF* b = backend_ref[i].backend;
SERVER_REF* b = it->backend;
if (BREF_IS_IN_USE((&backend_ref[i])))
if (BREF_IS_IN_USE(it))
{
MXS_INFO("Connected %s in \t%s:%d",
STRSRVSTATUS(b->server),

View File

@ -61,13 +61,6 @@ enum bref_state
BREF_DB_MAPPED = 0x10
};
#define BREF_IS_NOT_USED(s) ((s)->state & ~BREF_IN_USE)
#define BREF_IS_IN_USE(s) ((s)->state & BREF_IN_USE)
#define BREF_IS_WAITING_RESULT(s) ((s)->num_result_wait > 0)
#define BREF_IS_QUERY_ACTIVE(s) ((s)->state & BREF_QUERY_ACTIVE)
#define BREF_IS_CLOSED(s) ((s)->state & BREF_CLOSED)
#define BREF_IS_MAPPED(s) ((s)->mapped)
#define SCHEMA_ERR_DUPLICATEDB 5000
#define SCHEMA_ERRSTR_DUPLICATEDB "DUPDB"
#define SCHEMA_ERR_DBNOTFOUND 1049
@ -95,20 +88,33 @@ enum route_target
*
* Owned by router client session.
*/
typedef struct backend_ref_st
class Backend
{
int n_mapping_eof;
GWBUF* map_queue;
public:
Backend(SERVER_REF *ref);
~Backend();
SERVER_REF* backend; /**< Backend server */
DCB* dcb; /**< Backend DCB */
int state; /**< State of the backend */
GWBUF* map_queue;
bool mapped; /**< Whether the backend has been mapped */
int n_mapping_eof;
int num_result_wait; /**< Number of not yet received results */
GWBUF* pending_cmd; /**< Pending commands */
int state; /**< State of the backend */
SessionCommandList session_commands; /**< List of session commands that are
* to be executed on this backend server */
} backend_ref_t;
};
typedef list<Backend> BackendList;
// TODO: Move these as member functions, currently they operate on iterators
#define BREF_IS_NOT_USED(s) ((s)->state & ~BREF_IN_USE)
#define BREF_IS_IN_USE(s) ((s)->state & BREF_IN_USE)
#define BREF_IS_WAITING_RESULT(s) ((s)->num_result_wait > 0)
#define BREF_IS_QUERY_ACTIVE(s) ((s)->state & BREF_QUERY_ACTIVE)
#define BREF_IS_CLOSED(s) ((s)->state & BREF_CLOSED)
#define BREF_IS_MAPPED(s) ((s)->mapped)
class SchemaRouter;
@ -163,8 +169,8 @@ public:
private:
/** Internal functions */
SERVER* get_shard_target(GWBUF* buffer, uint32_t qtype);
backend_ref_t* get_bref_from_dcb(DCB* dcb);
bool execute_sescmd_in_backend(backend_ref_t* backend_ref);
Backend* get_bref_from_dcb(DCB* dcb);
bool execute_sescmd_in_backend(Backend& backend_ref);
bool get_shard_dcb(DCB** dcb, char* name);
bool handle_default_db();
bool handle_error_new_connection(DCB* backend_dcb, GWBUF* errmsg);
@ -172,14 +178,14 @@ private:
bool route_session_write(GWBUF* querybuf, uint8_t command);
bool send_database_list();
int gen_databaselist();
int inspect_backend_mapping_states(backend_ref_t *bref, GWBUF** wbuf);
int inspect_backend_mapping_states(Backend *bref, GWBUF** wbuf);
bool process_show_shards();
enum showdb_response parse_showdb_response(backend_ref_t* bref, GWBUF** buffer);
enum showdb_response parse_showdb_response(Backend* bref, GWBUF** buffer);
void handle_error_reply_client(DCB* backend_dcb, GWBUF* errmsg);
void route_queued_query();
void synchronize_shard_map();
void handle_mapping_reply(backend_ref_t* bref, GWBUF* pPacket);
void process_response(backend_ref_t* bref, GWBUF** ppPacket);
void handle_mapping_reply(Backend* bref, GWBUF* pPacket);
void process_response(Backend* bref, GWBUF** ppPacket);
SERVER* resolve_query_target(GWBUF* pPacket, uint32_t type, uint8_t command,
enum route_target& route_target);
@ -187,9 +193,8 @@ private:
bool m_closed; /**< True if session closed */
DCB* m_client; /**< The client DCB */
MYSQL_session* m_mysql_session; /**< Session client data (username, password, SHA1). */
backend_ref_t* m_backends; /**< Pointer to backend reference array */
BackendList m_backends; /**< Backend references */
Config* m_config; /**< Pointer to router config */
int m_backend_count; /**< Number of backends */
SchemaRouter* m_router; /**< The router instance */
Shard m_shard; /**< Database to server mapping */
string m_connect_db; /**< Database the user was trying to connect to */