Merge branch '2.3' into develop

This commit is contained in:
Markus Mäkelä
2019-02-01 13:55:54 +02:00
31 changed files with 743 additions and 175 deletions

View File

@ -81,6 +81,10 @@ if (HAVE_LIBDL)
target_link_libraries(maxscale-common dl)
endif()
# Using initial-exec instead of the default global-dynamic tls-model
# reduces the cost of using thread-local variables in dynamic libraries.
target_compile_options(maxscale-common PUBLIC "-ftls-model=initial-exec")
add_dependencies(maxscale-common pcre2 connector-c libmicrohttpd jansson maxbase)
set_target_properties(maxscale-common PROPERTIES VERSION "1.0.0")
install_module(maxscale-common core)

View File

@ -17,12 +17,15 @@
#include <maxbase/atomic.hh>
#include <maxscale/alloc.h>
#include <maxscale/protocol/mysql.hh>
using namespace maxscale;
Backend::Backend(SERVER_REF* ref)
: m_closed(false)
, m_closed_at(0)
, m_opened_at(0)
, m_backend(ref)
, m_dcb(NULL)
, m_state(0)
@ -49,6 +52,7 @@ void Backend::close(close_type type)
if (!m_closed)
{
m_closed = true;
m_closed_at = time(NULL);
if (in_use())
{
@ -182,6 +186,8 @@ bool Backend::connect(MXS_SESSION* session, SessionCommandList* sescmd)
if ((m_dcb = dcb_connect(m_backend->server, session, m_backend->server->protocol().c_str())))
{
m_closed = false;
m_closed_at = 0;
m_opened_at = time(NULL);
m_state = IN_USE;
mxb::atomic::add(&m_backend->connections, 1, mxb::atomic::RELAXED);
rval = true;
@ -285,3 +291,73 @@ int64_t Backend::num_selects() const
{
return m_num_selects;
}
void Backend::set_close_reason(const std::string& reason)
{
m_close_reason = reason;
}
std::string Backend::get_verbose_status() const
{
std::stringstream ss;
char closed_at[30] = "not closed";
char opened_at[30] = "not opened";
if (m_closed_at)
{
mxb_assert(m_closed);
ctime_r(&m_closed_at, closed_at);
char* nl = strrchr(closed_at, '\n');
mxb_assert(nl);
*nl = '\0';
}
if (m_opened_at)
{
ctime_r(&m_opened_at, opened_at);
char* nl = strrchr(opened_at, '\n');
mxb_assert(nl);
*nl = '\0';
}
ss << "name: [" << name() << "] "
<< "status: [" << m_backend->server->status_string() << "] "
<< "state: [" << to_string((backend_state)m_state) << "] "
<< "last opened at: [" << opened_at << "] "
<< "last closed at: [" << closed_at << "] "
<< "last close reason: [" << m_close_reason << "] "
<< "num sescmd: [" << m_session_commands.size() << "]";
return ss.str();
}
std::string Backend::to_string(backend_state state)
{
std::string rval;
if (state == 0)
{
rval = "NOT_IN_USE";
}
else
{
if (state & IN_USE)
{
rval += "IN_USE";
}
if (state & WAITING_RESULT)
{
rval += rval.empty() ? "" : "|";
rval += "WAITING_RESULT";
}
if (state & FATAL_FAILURE)
{
rval += rval.empty() ? "" : "|";
rval += "FATAL_FAILURE";
}
}
return rval;
}

View File

@ -1217,6 +1217,10 @@ bool config_load_global(const char* filename)
"cache. To enable it, add '%s' to the configuration file.",
CN_QUERY_CLASSIFIER_CACHE_SIZE);
}
else if (gateway.qc_cache_properties.max_size == 0)
{
MXS_NOTICE("Query classifier cache is disabled");
}
else
{
MXS_NOTICE("Using up to %s of memory for query classifier cache",
@ -1275,6 +1279,34 @@ const MXS_MODULE* get_module(CONFIG_CONTEXT* obj, const char* param_name, const
return module ? get_module(module, module_type) : NULL;
}
const char* get_missing_module_parameter_name(const CONFIG_CONTEXT* obj)
{
std::string type = config_get_string(obj->parameters, CN_TYPE);
if (type == CN_SERVICE && !config_get_param(obj->parameters, CN_ROUTER))
{
return CN_ROUTER;
}
else if (type == CN_LISTENER && !config_get_param(obj->parameters, CN_PROTOCOL))
{
return CN_PROTOCOL;
}
else if (type == CN_SERVER && !config_get_param(obj->parameters, CN_PROTOCOL))
{
return CN_PROTOCOL;
}
else if (type == CN_MONITOR && !config_get_param(obj->parameters, CN_MODULE))
{
return CN_MODULE;
}
else if (type == CN_FILTER && !config_get_param(obj->parameters, CN_MODULE))
{
return CN_MODULE;
}
return nullptr;
}
std::pair<const MXS_MODULE_PARAM*, const MXS_MODULE*> get_module_details(const CONFIG_CONTEXT* obj)
{
std::string type = config_get_string(obj->parameters, CN_TYPE);
@ -3038,6 +3070,15 @@ static bool check_config_objects(CONFIG_CONTEXT* context)
continue;
}
const char* no_module_defined = get_missing_module_parameter_name(obj);
if (no_module_defined)
{
MXS_ERROR("'%s' is missing the required parameter '%s'", obj->object, no_module_defined);
rval = false;
continue;
}
const MXS_MODULE_PARAM* param_set = nullptr;
const MXS_MODULE* mod = nullptr;
std::tie(param_set, mod) = get_module_details(obj);

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))
{