MXS-2299: Hints always take precedence

Hints should override all statement level routing decisions that would
otherwise be done based on the query type.
This commit is contained in:
Markus Mäkelä
2019-01-28 18:23:38 +02:00
parent 6d88afbf55
commit 16fc920d33
2 changed files with 72 additions and 67 deletions

View File

@ -348,7 +348,8 @@ private:
*/
bool query_type_is_read_only(uint32_t qtype) const;
uint32_t get_route_target(uint8_t command, uint32_t qtype, HINT* pHints);
void process_routing_hints(HINT* pHints, uint32_t* target);
uint32_t get_route_target(uint8_t command, uint32_t qtype);
MXS_SESSION* session() const
{

View File

@ -433,7 +433,73 @@ bool QueryClassifier::query_type_is_read_only(uint32_t qtype) const
return rval;
}
uint32_t QueryClassifier::get_route_target(uint8_t command, uint32_t qtype, HINT* pHints)
void QueryClassifier::process_routing_hints(HINT* pHints, uint32_t* target)
{
HINT* pHint = pHints;
while (pHint)
{
if (m_pHandler->supports_hint(pHint->type))
{
switch (pHint->type)
{
case HINT_ROUTE_TO_MASTER:
// This means override, so we bail out immediately.
*target = TARGET_MASTER;
MXS_DEBUG("Hint: route to master");
pHint = NULL;
break;
case HINT_ROUTE_TO_NAMED_SERVER:
// The router is expected to look up the named server.
*target |= TARGET_NAMED_SERVER;
MXS_DEBUG("Hint: route to named server: %s", (char*)pHint->data);
break;
case HINT_ROUTE_TO_UPTODATE_SERVER:
// TODO: Add generic target type, never to be seem by RWS.
mxb_assert(false);
break;
case HINT_ROUTE_TO_ALL:
// TODO: Add generic target type, never to be seem by RWS.
mxb_assert(false);
break;
case HINT_ROUTE_TO_LAST_USED:
MXS_DEBUG("Hint: route to last used");
*target = TARGET_LAST_USED;
break;
case HINT_PARAMETER:
if (strncasecmp((char*)pHint->data,
"max_slave_replication_lag",
strlen("max_slave_replication_lag")) == 0)
{
*target |= TARGET_RLAG_MAX;
}
else
{
MXS_ERROR("Unknown hint parameter '%s' when "
"'max_slave_replication_lag' was expected.",
(char*)pHint->data);
}
break;
case HINT_ROUTE_TO_SLAVE:
*target = TARGET_SLAVE;
MXS_DEBUG("Hint: route to slave.");
}
}
if (pHint)
{
pHint = pHint->next;
}
}
}
uint32_t QueryClassifier::get_route_target(uint8_t command, uint32_t qtype)
{
bool trx_active = session_trx_is_active(m_pSession);
uint32_t target = TARGET_UNDEFINED;
@ -533,70 +599,6 @@ uint32_t QueryClassifier::get_route_target(uint8_t command, uint32_t qtype, HINT
target = TARGET_MASTER;
}
/** Process routing hints */
HINT* pHint = pHints;
while (pHint)
{
if (m_pHandler->supports_hint(pHint->type))
{
switch (pHint->type)
{
case HINT_ROUTE_TO_MASTER:
// This means override, so we bail out immediately.
target = TARGET_MASTER;
MXS_DEBUG("Hint: route to master");
pHint = NULL;
break;
case HINT_ROUTE_TO_NAMED_SERVER:
// The router is expected to look up the named server.
target |= TARGET_NAMED_SERVER;
MXS_DEBUG("Hint: route to named server: %s", (char*)pHint->data);
break;
case HINT_ROUTE_TO_UPTODATE_SERVER:
// TODO: Add generic target type, never to be seem by RWS.
mxb_assert(false);
break;
case HINT_ROUTE_TO_ALL:
// TODO: Add generic target type, never to be seem by RWS.
mxb_assert(false);
break;
case HINT_ROUTE_TO_LAST_USED:
MXS_DEBUG("Hint: route to last used");
target = TARGET_LAST_USED;
break;
case HINT_PARAMETER:
if (strncasecmp((char*)pHint->data,
"max_slave_replication_lag",
strlen("max_slave_replication_lag")) == 0)
{
target |= TARGET_RLAG_MAX;
}
else
{
MXS_ERROR("Unknown hint parameter '%s' when "
"'max_slave_replication_lag' was expected.",
(char*)pHint->data);
}
break;
case HINT_ROUTE_TO_SLAVE:
target = TARGET_SLAVE;
MXS_DEBUG("Hint: route to slave.");
}
}
if (pHint)
{
pHint = pHint->next;
}
}
return target;
}
@ -999,9 +1001,11 @@ QueryClassifier::RouteInfo QueryClassifier::update_route_info(
type_mask = ps_get_type(stmt_id);
}
route_target = get_route_target(command, type_mask, pBuffer->hint);
route_target = get_route_target(command, type_mask);
}
process_routing_hints(pBuffer->hint, &route_target);
if (session_trx_is_ending(m_pSession)
|| qc_query_is_type(type_mask, QUERY_TYPE_BEGIN_TRX))
{