MXS-1625 Remove need for RWS session from handle_multi_temp_and_load()

This commit is contained in:
Johan Wikman
2018-04-05 14:59:41 +03:00
parent 05a6aa2dea
commit 36bea39b63
2 changed files with 74 additions and 34 deletions

View File

@ -39,6 +39,13 @@ public:
TARGET_ALL = 0x08 TARGET_ALL = 0x08
}; };
enum current_target_t
{
CURRENT_TARGET_UNDEFINED, /**< Current target has not been set. */
CURRENT_TARGET_MASTER, /**< Current target is master */
CURRENT_TARGET_SLAVE /**< Current target is a slave */
};
/** States of a LOAD DATA LOCAL INFILE */ /** States of a LOAD DATA LOCAL INFILE */
enum load_data_state_t enum load_data_state_t
{ {

View File

@ -434,70 +434,69 @@ bool check_for_multi_stmt(const QueryClassifier& qc, GWBUF *buf, uint8_t packet_
* *
* One of the possible types of handling required when a request is routed * One of the possible types of handling required when a request is routed
* *
* @param ses Router session * @param qc The query classifier
* @param querybuf Buffer containing query to be routed * @param current_target The current target
* @param packet_type Type of packet (database specific) * @param querybuf Buffer containing query to be routed
* @param qtype Query type * @param packet_type Type of packet (database specific)
* @param qtype Query type
*
* @return QueryClassifier::CURRENT_TARGET_MASTER if the session should be fixed
* to the master, QueryClassifier::CURRENT_TARGET_UNDEFINED otherwise.
*/ */
void QueryClassifier::current_target_t
handle_multi_temp_and_load(RWSplitSession *rses, GWBUF *querybuf, handle_multi_temp_and_load(QueryClassifier& qc,
uint8_t packet_type, uint32_t *qtype) QueryClassifier::current_target_t current_target,
GWBUF *querybuf,
uint8_t packet_type,
uint32_t *qtype)
{ {
QueryClassifier::current_target_t rv = QueryClassifier::CURRENT_TARGET_UNDEFINED;
/** Check for multi-statement queries. If no master server is available /** Check for multi-statement queries. If no master server is available
* and a multi-statement is issued, an error is returned to the client * and a multi-statement is issued, an error is returned to the client
* when the query is routed. * when the query is routed. */
* if ((current_target != QueryClassifier::CURRENT_TARGET_MASTER) &&
* If we do not have a master node, assigning the forced node is not (check_for_multi_stmt(qc, querybuf, packet_type) ||
* effective since we don't have a node to force queries to. In this
* situation, assigning QUERY_TYPE_WRITE for the query will trigger
* the error processing. */
if ((rses->m_target_node == NULL || rses->m_target_node != rses->m_current_master) &&
(check_for_multi_stmt(rses->qc(), querybuf, packet_type) ||
check_for_sp_call(querybuf, packet_type))) check_for_sp_call(querybuf, packet_type)))
{ {
if (rses->m_current_master && rses->m_current_master->in_use()) MXS_INFO("Multi-statement query or stored procedure call, routing "
{ "all future queries to master.");
rses->m_target_node = rses->m_current_master; rv = QueryClassifier::CURRENT_TARGET_MASTER;
MXS_INFO("Multi-statement query or stored procedure call, routing "
"all future queries to master.");
}
else
{
*qtype |= QUERY_TYPE_WRITE;
}
} }
/** /**
* Check if the query has anything to do with temporary tables. * Check if the query has anything to do with temporary tables.
*/ */
if (rses->qc().have_tmp_tables() && is_packet_a_query(packet_type)) if (qc.have_tmp_tables() && is_packet_a_query(packet_type))
{ {
check_drop_tmp_table(rses->qc(), querybuf); check_drop_tmp_table(qc, querybuf);
if (is_read_tmp_table(rses->qc(), querybuf, *qtype)) if (is_read_tmp_table(qc, querybuf, *qtype))
{ {
*qtype |= QUERY_TYPE_MASTER_READ; *qtype |= QUERY_TYPE_MASTER_READ;
} }
} }
check_create_tmp_table(rses->qc(), querybuf, *qtype); check_create_tmp_table(qc, querybuf, *qtype);
/** /**
* Check if this is a LOAD DATA LOCAL INFILE query. If so, send all queries * Check if this is a LOAD DATA LOCAL INFILE query. If so, send all queries
* to the master until the last, empty packet arrives. * to the master until the last, empty packet arrives.
*/ */
if (rses->qc().load_data_state() == QueryClassifier::LOAD_DATA_ACTIVE) if (qc.load_data_state() == QueryClassifier::LOAD_DATA_ACTIVE)
{ {
rses->qc().append_load_data_sent(querybuf); qc.append_load_data_sent(querybuf);
} }
else if (is_packet_a_query(packet_type)) else if (is_packet_a_query(packet_type))
{ {
qc_query_op_t queryop = qc_get_operation(querybuf); qc_query_op_t queryop = qc_get_operation(querybuf);
if (queryop == QUERY_OP_LOAD) if (queryop == QUERY_OP_LOAD)
{ {
rses->qc().set_load_data_state(QueryClassifier::LOAD_DATA_START); qc.set_load_data_state(QueryClassifier::LOAD_DATA_START);
rses->qc().reset_load_data_sent(); qc.reset_load_data_sent();
} }
} }
return rv;
} }
/** /**
@ -533,7 +532,41 @@ route_target_t get_target_type(RWSplitSession *rses, GWBUF *buffer,
else else
{ {
*type = determine_query_type(buffer, *command); *type = determine_query_type(buffer, *command);
handle_multi_temp_and_load(rses, buffer, *command, type);
QueryClassifier::current_target_t current_target;
if (rses->m_target_node == NULL)
{
current_target = QueryClassifier::CURRENT_TARGET_UNDEFINED;
}
else if (rses->m_target_node == rses->m_current_master)
{
current_target = QueryClassifier::CURRENT_TARGET_MASTER;
}
else
{
current_target = QueryClassifier::CURRENT_TARGET_SLAVE;
}
current_target = handle_multi_temp_and_load(rses->qc(),
current_target,
buffer, *command, type);
if (current_target == QueryClassifier::CURRENT_TARGET_MASTER)
{
/* If we do not have a master node, assigning the forced node is not
* effective since we don't have a node to force queries to. In this
* situation, assigning QUERY_TYPE_WRITE for the query will trigger
* the error processing. */
if (rses->m_current_master && rses->m_current_master->in_use())
{
rses->m_target_node = rses->m_current_master;
}
else
{
*type |= QUERY_TYPE_WRITE;
}
}
} }
if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO)) if (MXS_LOG_PRIORITY_IS_ENABLED(LOG_INFO))