Uncrustify maxscale
See script directory for method. The script to run in the top level MaxScale directory is called maxscale-uncrustify.sh, which uses another script, list-src, from the same directory (so you need to set your PATH). The uncrustify version was 0.66.
This commit is contained in:
@ -18,13 +18,13 @@
|
||||
namespace schemarouter
|
||||
{
|
||||
|
||||
Config::Config(MXS_CONFIG_PARAMETER* conf):
|
||||
refresh_min_interval(config_get_integer(conf, "refresh_interval")),
|
||||
refresh_databases(config_get_bool(conf, "refresh_databases")),
|
||||
debug(config_get_bool(conf, "debug")),
|
||||
ignore_regex(config_get_compiled_regex(conf, "ignore_databases_regex", 0, NULL)),
|
||||
ignore_match_data(ignore_regex ? pcre2_match_data_create_from_pattern(ignore_regex, NULL) : NULL),
|
||||
preferred_server(config_get_server(conf, "preferred_server"))
|
||||
Config::Config(MXS_CONFIG_PARAMETER* conf)
|
||||
: refresh_min_interval(config_get_integer(conf, "refresh_interval"))
|
||||
, refresh_databases(config_get_bool(conf, "refresh_databases"))
|
||||
, debug(config_get_bool(conf, "debug"))
|
||||
, ignore_regex(config_get_compiled_regex(conf, "ignore_databases_regex", 0, NULL))
|
||||
, ignore_match_data(ignore_regex ? pcre2_match_data_create_from_pattern(ignore_regex, NULL) : NULL)
|
||||
, preferred_server(config_get_server(conf, "preferred_server"))
|
||||
{
|
||||
ignored_dbs.insert("mysql");
|
||||
ignored_dbs.insert("information_schema");
|
||||
@ -33,7 +33,7 @@ Config::Config(MXS_CONFIG_PARAMETER* conf):
|
||||
// TODO: Don't process this in the router
|
||||
if (MXS_CONFIG_PARAMETER* p = config_get_param(conf, "ignore_databases"))
|
||||
{
|
||||
for (const auto& a: mxs::strtok(p->value, ", \t"))
|
||||
for (const auto& a : mxs::strtok(p->value, ", \t"))
|
||||
{
|
||||
ignored_dbs.insert(a);
|
||||
}
|
||||
@ -49,5 +49,4 @@ bool SRBackend::is_mapped() const
|
||||
{
|
||||
return m_mapped;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @file schemarouter.hh - Common schemarouter definitions
|
||||
@ -38,15 +38,15 @@ namespace schemarouter
|
||||
*/
|
||||
struct Config
|
||||
{
|
||||
double refresh_min_interval; /**< Minimum required interval between
|
||||
double refresh_min_interval; /**< Minimum required interval between
|
||||
* refreshes of databases */
|
||||
bool refresh_databases; /**< Are databases refreshed when
|
||||
bool refresh_databases; /**< Are databases refreshed when
|
||||
* they are not found in the hashtable */
|
||||
bool debug; /**< Enable verbose debug messages to clients */
|
||||
pcre2_code* ignore_regex; /**< Regular expression used to ignore databases */
|
||||
pcre2_match_data* ignore_match_data; /**< Match data for @c ignore_regex */
|
||||
bool debug; /**< Enable verbose debug messages to clients */
|
||||
pcre2_code* ignore_regex; /**< Regular expression used to ignore databases */
|
||||
pcre2_match_data* ignore_match_data;/**< Match data for @c ignore_regex */
|
||||
std::set<std::string> ignored_dbs; /**< Set of ignored databases */
|
||||
SERVER* preferred_server; /**< Server to prefer in conflict situations */
|
||||
SERVER* preferred_server; /**< Server to prefer in conflict situations */
|
||||
|
||||
Config(MXS_CONFIG_PARAMETER* conf);
|
||||
|
||||
@ -64,29 +64,29 @@ typedef std::shared_ptr<Config> SConfig;
|
||||
*/
|
||||
struct Stats
|
||||
{
|
||||
int n_queries; /*< Number of queries forwarded */
|
||||
int n_sescmd; /*< Number of session commands */
|
||||
int longest_sescmd; /*< Longest chain of stored session commands */
|
||||
int n_hist_exceeded; /*< Number of sessions that exceeded session
|
||||
* command history limit */
|
||||
int sessions; /*< Number of sessions */
|
||||
int shmap_cache_hit; /*< Shard map was found from the cache */
|
||||
int shmap_cache_miss; /*< No shard map found from the cache */
|
||||
double ses_longest; /*< Longest session */
|
||||
double ses_shortest; /*< Shortest session */
|
||||
double ses_average; /*< Average session length */
|
||||
int n_queries; /*< Number of queries forwarded */
|
||||
int n_sescmd; /*< Number of session commands */
|
||||
int longest_sescmd; /*< Longest chain of stored session commands */
|
||||
int n_hist_exceeded; /*< Number of sessions that exceeded session
|
||||
* command history limit */
|
||||
int sessions; /*< Number of sessions */
|
||||
int shmap_cache_hit; /*< Shard map was found from the cache */
|
||||
int shmap_cache_miss;/*< No shard map found from the cache */
|
||||
double ses_longest; /*< Longest session */
|
||||
double ses_shortest; /*< Shortest session */
|
||||
double ses_average; /*< Average session length */
|
||||
|
||||
Stats():
|
||||
n_queries(0),
|
||||
n_sescmd(0),
|
||||
longest_sescmd(0),
|
||||
n_hist_exceeded(0),
|
||||
sessions(0),
|
||||
shmap_cache_hit(0),
|
||||
shmap_cache_miss(0),
|
||||
ses_longest(0.0),
|
||||
ses_shortest(std::numeric_limits<double>::max()),
|
||||
ses_average(0.0)
|
||||
Stats()
|
||||
: n_queries(0)
|
||||
, n_sescmd(0)
|
||||
, longest_sescmd(0)
|
||||
, n_hist_exceeded(0)
|
||||
, sessions(0)
|
||||
, shmap_cache_hit(0)
|
||||
, shmap_cache_miss(0)
|
||||
, ses_longest(0.0)
|
||||
, ses_shortest(std::numeric_limits<double>::max())
|
||||
, ses_average(0.0)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -96,13 +96,13 @@ struct Stats
|
||||
*
|
||||
* Owned by router client session.
|
||||
*/
|
||||
class SRBackend: public mxs::Backend
|
||||
class SRBackend : public mxs::Backend
|
||||
{
|
||||
public:
|
||||
|
||||
SRBackend(SERVER_REF *ref):
|
||||
mxs::Backend(ref),
|
||||
m_mapped(false)
|
||||
SRBackend(SERVER_REF* ref)
|
||||
: mxs::Backend(ref)
|
||||
, m_mapped(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -125,10 +125,9 @@ public:
|
||||
bool is_mapped() const;
|
||||
|
||||
private:
|
||||
bool m_mapped; /**< Whether the backend has been mapped */
|
||||
bool m_mapped; /**< Whether the backend has been mapped */
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<SRBackend> SSRBackend;
|
||||
typedef std::list<SSRBackend> SSRBackendList;
|
||||
|
||||
typedef std::list<SSRBackend> SSRBackendList;
|
||||
}
|
||||
|
||||
@ -42,10 +42,10 @@ namespace schemarouter
|
||||
* @file schemarouter.c The entry points for the simple sharding router module.
|
||||
*/
|
||||
|
||||
SchemaRouter::SchemaRouter(SERVICE *service, SConfig config):
|
||||
mxs::Router<SchemaRouter, SchemaRouterSession>(service),
|
||||
m_config(config),
|
||||
m_service(service)
|
||||
SchemaRouter::SchemaRouter(SERVICE* service, SConfig config)
|
||||
: mxs::Router<SchemaRouter, SchemaRouterSession>(service)
|
||||
, m_config(config)
|
||||
, m_service(service)
|
||||
{
|
||||
spinlock_init(&m_lock);
|
||||
}
|
||||
@ -188,7 +188,7 @@ SchemaRouterSession* SchemaRouter::newSession(MXS_SESSION* pSession)
|
||||
{
|
||||
SSRBackendList backends;
|
||||
|
||||
for (SERVER_REF *ref = m_service->dbref; ref; ref = ref->next)
|
||||
for (SERVER_REF* ref = m_service->dbref; ref; ref = ref->next)
|
||||
{
|
||||
if (ref->active)
|
||||
{
|
||||
@ -208,19 +208,23 @@ SchemaRouterSession* SchemaRouter::newSession(MXS_SESSION* pSession)
|
||||
|
||||
void SchemaRouter::diagnostics(DCB* dcb)
|
||||
{
|
||||
double sescmd_pct = m_stats.n_sescmd != 0 ?
|
||||
100.0 * ((double)m_stats.n_sescmd / (double)m_stats.n_queries) :
|
||||
0.0;
|
||||
double sescmd_pct = m_stats.n_sescmd != 0
|
||||
? 100.0 * ((double)m_stats.n_sescmd / (double)m_stats.n_queries)
|
||||
: 0.0;
|
||||
|
||||
/** Session command statistics */
|
||||
dcb_printf(dcb, "\n\33[1;4mSession Commands\33[0m\n");
|
||||
dcb_printf(dcb, "Total number of queries: %d\n",
|
||||
dcb_printf(dcb,
|
||||
"Total number of queries: %d\n",
|
||||
m_stats.n_queries);
|
||||
dcb_printf(dcb, "Percentage of session commands: %.2f\n",
|
||||
dcb_printf(dcb,
|
||||
"Percentage of session commands: %.2f\n",
|
||||
sescmd_pct);
|
||||
dcb_printf(dcb, "Longest chain of stored session commands: %d\n",
|
||||
dcb_printf(dcb,
|
||||
"Longest chain of stored session commands: %d\n",
|
||||
m_stats.longest_sescmd);
|
||||
dcb_printf(dcb, "Session command history limit exceeded: %d times\n",
|
||||
dcb_printf(dcb,
|
||||
"Session command history limit exceeded: %d times\n",
|
||||
m_stats.n_hist_exceeded);
|
||||
|
||||
/** Session time statistics */
|
||||
@ -239,9 +243,9 @@ void SchemaRouter::diagnostics(DCB* dcb)
|
||||
|
||||
json_t* SchemaRouter::diagnostics_json() const
|
||||
{
|
||||
double sescmd_pct = m_stats.n_sescmd != 0 ?
|
||||
100.0 * ((double)m_stats.n_sescmd / (double)m_stats.n_queries) :
|
||||
0.0;
|
||||
double sescmd_pct = m_stats.n_sescmd != 0
|
||||
? 100.0 * ((double)m_stats.n_sescmd / (double)m_stats.n_queries)
|
||||
: 0.0;
|
||||
|
||||
json_t* rval = json_object();
|
||||
json_object_set_new(rval, "queries", json_integer(m_stats.n_queries));
|
||||
@ -267,7 +271,6 @@ uint64_t SchemaRouter::getCapabilities()
|
||||
{
|
||||
return RCAP_TYPE_CONTIGUOUS_INPUT | RCAP_TYPE_RUNTIME_CONFIG;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -289,19 +292,19 @@ extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
||||
"V1.0.0",
|
||||
RCAP_TYPE_CONTIGUOUS_INPUT | RCAP_TYPE_RUNTIME_CONFIG,
|
||||
&schemarouter::SchemaRouter::s_object,
|
||||
NULL, /* Process init. */
|
||||
NULL, /* Process finish. */
|
||||
NULL, /* Thread init. */
|
||||
NULL, /* Thread finish. */
|
||||
NULL, /* Process init. */
|
||||
NULL, /* Process finish. */
|
||||
NULL, /* Thread init. */
|
||||
NULL, /* Thread finish. */
|
||||
{
|
||||
{"ignore_databases", MXS_MODULE_PARAM_STRING},
|
||||
{"ignore_databases_regex", MXS_MODULE_PARAM_STRING},
|
||||
{"max_sescmd_history", MXS_MODULE_PARAM_COUNT, "0"},
|
||||
{"disable_sescmd_history", MXS_MODULE_PARAM_BOOL, "false"},
|
||||
{"refresh_databases", MXS_MODULE_PARAM_BOOL, "true"},
|
||||
{"refresh_interval", MXS_MODULE_PARAM_COUNT, DEFAULT_REFRESH_INTERVAL},
|
||||
{"debug", MXS_MODULE_PARAM_BOOL, "false"},
|
||||
{"preferred_server", MXS_MODULE_PARAM_SERVER},
|
||||
{"ignore_databases", MXS_MODULE_PARAM_STRING },
|
||||
{"ignore_databases_regex", MXS_MODULE_PARAM_STRING },
|
||||
{"max_sescmd_history", MXS_MODULE_PARAM_COUNT, "0"},
|
||||
{"disable_sescmd_history", MXS_MODULE_PARAM_BOOL, "false"},
|
||||
{"refresh_databases", MXS_MODULE_PARAM_BOOL, "true"},
|
||||
{"refresh_interval", MXS_MODULE_PARAM_COUNT, DEFAULT_REFRESH_INTERVAL},
|
||||
{"debug", MXS_MODULE_PARAM_BOOL, "false"},
|
||||
{"preferred_server", MXS_MODULE_PARAM_SERVER },
|
||||
{MXS_END_MODULE_PARAMS}
|
||||
}
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "schemarouter.hh"
|
||||
|
||||
@ -30,29 +30,28 @@ class SchemaRouterSession;
|
||||
/**
|
||||
* The per instance data for the router.
|
||||
*/
|
||||
class SchemaRouter: public mxs::Router<SchemaRouter, SchemaRouterSession>
|
||||
class SchemaRouter : public mxs::Router<SchemaRouter, SchemaRouterSession>
|
||||
{
|
||||
public:
|
||||
~SchemaRouter();
|
||||
static SchemaRouter* create(SERVICE* pService, MXS_CONFIG_PARAMETER* params);
|
||||
SchemaRouterSession* newSession(MXS_SESSION* pSession);
|
||||
void diagnostics(DCB* pDcb);
|
||||
json_t* diagnostics_json() const;
|
||||
uint64_t getCapabilities();
|
||||
bool configure(MXS_CONFIG_PARAMETER* param);
|
||||
void diagnostics(DCB* pDcb);
|
||||
json_t* diagnostics_json() const;
|
||||
uint64_t getCapabilities();
|
||||
bool configure(MXS_CONFIG_PARAMETER* param);
|
||||
|
||||
private:
|
||||
friend class SchemaRouterSession;
|
||||
|
||||
/** Internal functions */
|
||||
SchemaRouter(SERVICE *service, SConfig config);
|
||||
SchemaRouter(SERVICE* service, SConfig config);
|
||||
|
||||
/** Member variables */
|
||||
SConfig m_config; /*< expanded config info from SERVICE */
|
||||
ShardManager m_shard_manager; /*< Shard maps hashed by user name */
|
||||
SERVICE* m_service; /*< Pointer to service */
|
||||
SPINLOCK m_lock; /*< Lock for the instance data */
|
||||
Stats m_stats; /*< Statistics for this router */
|
||||
SConfig m_config; /*< expanded config info from SERVICE */
|
||||
ShardManager m_shard_manager; /*< Shard maps hashed by user name */
|
||||
SERVICE* m_service; /*< Pointer to service */
|
||||
SPINLOCK m_lock; /*< Lock for the instance data */
|
||||
Stats m_stats; /*< Statistics for this router */
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,25 +29,26 @@ namespace schemarouter
|
||||
bool connect_backend_servers(SSRBackendList& backends, MXS_SESSION* session);
|
||||
|
||||
enum route_target get_shard_route_target(uint32_t qtype);
|
||||
bool change_current_db(std::string& dest, Shard& shard, GWBUF* buf);
|
||||
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);
|
||||
bool change_current_db(std::string& dest, Shard& shard, GWBUF* buf);
|
||||
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);
|
||||
|
||||
SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session, SchemaRouter* router,
|
||||
SSRBackendList& backends):
|
||||
mxs::RouterSession(session),
|
||||
m_closed(false),
|
||||
m_client(session->client_dcb),
|
||||
m_mysql_session((MYSQL_session*)session->client_dcb->data),
|
||||
m_backends(backends),
|
||||
m_config(router->m_config),
|
||||
m_router(router),
|
||||
m_shard(m_router->m_shard_manager.get_shard(m_client->user, m_config->refresh_min_interval)),
|
||||
m_state(0),
|
||||
m_sent_sescmd(0),
|
||||
m_replied_sescmd(0),
|
||||
m_load_target(NULL)
|
||||
SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session,
|
||||
SchemaRouter* router,
|
||||
SSRBackendList& backends)
|
||||
: mxs::RouterSession(session)
|
||||
, m_closed(false)
|
||||
, m_client(session->client_dcb)
|
||||
, m_mysql_session((MYSQL_session*)session->client_dcb->data)
|
||||
, m_backends(backends)
|
||||
, m_config(router->m_config)
|
||||
, m_router(router)
|
||||
, m_shard(m_router->m_shard_manager.get_shard(m_client->user, m_config->refresh_min_interval))
|
||||
, m_state(0)
|
||||
, m_sent_sescmd(0)
|
||||
, m_replied_sescmd(0)
|
||||
, m_load_target(NULL)
|
||||
{
|
||||
char db[MYSQL_DATABASE_MAXLEN + 1] = "";
|
||||
MySQLProtocol* protocol = (MySQLProtocol*)session->client_dcb->protocol;
|
||||
@ -57,15 +58,16 @@ SchemaRouterSession::SchemaRouterSession(MXS_SESSION* session, SchemaRouter* rou
|
||||
|
||||
/* To enable connecting directly to a sharded database we first need
|
||||
* to disable it for the client DCB's protocol so that we can connect to them*/
|
||||
if (protocol->client_capabilities & GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB &&
|
||||
(have_db = *current_db))
|
||||
if (protocol->client_capabilities & GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB
|
||||
&& (have_db = *current_db))
|
||||
{
|
||||
protocol->client_capabilities &= ~GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB;
|
||||
strcpy(db, current_db);
|
||||
mxs_mysql_set_current_db(session, "");
|
||||
using_db = true;
|
||||
MXS_INFO("Client logging in directly to a database '%s', "
|
||||
"postponing until databases have been mapped.", db);
|
||||
"postponing until databases have been mapped.",
|
||||
db);
|
||||
}
|
||||
|
||||
if (using_db)
|
||||
@ -123,9 +125,9 @@ void SchemaRouterSession::close()
|
||||
m_router->m_stats.ses_shortest = ses_time;
|
||||
}
|
||||
|
||||
m_router->m_stats.ses_average =
|
||||
(ses_time + ((m_router->m_stats.sessions - 1) * m_router->m_stats.ses_average)) /
|
||||
(m_router->m_stats.sessions);
|
||||
m_router->m_stats.ses_average
|
||||
= (ses_time + ((m_router->m_stats.sessions - 1) * m_router->m_stats.ses_average))
|
||||
/ (m_router->m_stats.sessions);
|
||||
|
||||
spinlock_release(&m_router->m_lock);
|
||||
}
|
||||
@ -138,20 +140,20 @@ static void inspect_query(GWBUF* pPacket, uint32_t* type, qc_query_op_t* op, uin
|
||||
|
||||
switch (*command)
|
||||
{
|
||||
case MXS_COM_QUIT: /*< 1 QUIT will close all sessions */
|
||||
case MXS_COM_INIT_DB: /*< 2 DDL must go to the master */
|
||||
case MXS_COM_REFRESH: /*< 7 - I guess this is session but not sure */
|
||||
case MXS_COM_DEBUG: /*< 0d all servers dump debug info to stdout */
|
||||
case MXS_COM_PING: /*< 0e all servers are pinged */
|
||||
case MXS_COM_CHANGE_USER: /*< 11 all servers change it accordingly */
|
||||
//case MXS_COM_STMT_CLOSE: /*< free prepared statement */
|
||||
//case MXS_COM_STMT_SEND_LONG_DATA: /*< send data to column */
|
||||
//case MXS_COM_STMT_RESET: /*< resets the data of a prepared statement */
|
||||
case MXS_COM_QUIT: /*< 1 QUIT will close all sessions */
|
||||
case MXS_COM_INIT_DB: /*< 2 DDL must go to the master */
|
||||
case MXS_COM_REFRESH: /*< 7 - I guess this is session but not sure */
|
||||
case MXS_COM_DEBUG: /*< 0d all servers dump debug info to stdout */
|
||||
case MXS_COM_PING: /*< 0e all servers are pinged */
|
||||
case MXS_COM_CHANGE_USER: /*< 11 all servers change it accordingly */
|
||||
// case MXS_COM_STMT_CLOSE: /*< free prepared statement */
|
||||
// case MXS_COM_STMT_SEND_LONG_DATA: /*< send data to column */
|
||||
// case MXS_COM_STMT_RESET: /*< resets the data of a prepared statement */
|
||||
*type = QUERY_TYPE_SESSION_WRITE;
|
||||
break;
|
||||
|
||||
case MXS_COM_CREATE_DB: /**< 5 DDL must go to the master */
|
||||
case MXS_COM_DROP_DB: /**< 6 DDL must go to the master */
|
||||
case MXS_COM_DROP_DB: /**< 6 DDL must go to the master */
|
||||
*type = QUERY_TYPE_WRITE;
|
||||
break;
|
||||
|
||||
@ -170,27 +172,29 @@ static void inspect_query(GWBUF* pPacket, uint32_t* type, qc_query_op_t* op, uin
|
||||
*type = QUERY_TYPE_EXEC_STMT;
|
||||
break;
|
||||
|
||||
case MXS_COM_SHUTDOWN: /**< 8 where should shutdown be routed ? */
|
||||
case MXS_COM_STATISTICS: /**< 9 ? */
|
||||
case MXS_COM_PROCESS_INFO: /**< 0a ? */
|
||||
case MXS_COM_CONNECT: /**< 0b ? */
|
||||
case MXS_COM_PROCESS_KILL: /**< 0c ? */
|
||||
case MXS_COM_TIME: /**< 0f should this be run in gateway ? */
|
||||
case MXS_COM_DELAYED_INSERT: /**< 10 ? */
|
||||
case MXS_COM_DAEMON: /**< 1d ? */
|
||||
case MXS_COM_SHUTDOWN: /**< 8 where should shutdown be routed ? */
|
||||
case MXS_COM_STATISTICS: /**< 9 ? */
|
||||
case MXS_COM_PROCESS_INFO: /**< 0a ? */
|
||||
case MXS_COM_CONNECT: /**< 0b ? */
|
||||
case MXS_COM_PROCESS_KILL: /**< 0c ? */
|
||||
case MXS_COM_TIME: /**< 0f should this be run in gateway ? */
|
||||
case MXS_COM_DELAYED_INSERT:/**< 10 ? */
|
||||
case MXS_COM_DAEMON: /**< 1d ? */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (mxs_log_is_priority_enabled(LOG_INFO))
|
||||
{
|
||||
char *sql;
|
||||
char* sql;
|
||||
int sql_len;
|
||||
char* qtypestr = qc_typemask_to_string(*type);
|
||||
int rc = modutil_extract_SQL(pPacket, &sql, &sql_len);
|
||||
|
||||
MXS_INFO("> Command: %s, stmt: %.*s %s%s",
|
||||
STRPACKETTYPE(*command), rc ? sql_len : 0, rc ? sql : "",
|
||||
STRPACKETTYPE(*command),
|
||||
rc ? sql_len : 0,
|
||||
rc ? sql : "",
|
||||
(pPacket->hint == NULL ? "" : ", Hint:"),
|
||||
(pPacket->hint == NULL ? "" : STRHINTTYPE(pPacket->hint->type)));
|
||||
|
||||
@ -200,7 +204,7 @@ static void inspect_query(GWBUF* pPacket, uint32_t* type, qc_query_op_t* op, uin
|
||||
|
||||
SERVER* SchemaRouterSession::resolve_query_target(GWBUF* pPacket,
|
||||
uint32_t type,
|
||||
uint8_t command,
|
||||
uint8_t command,
|
||||
enum route_target& route_target)
|
||||
{
|
||||
SERVER* target = NULL;
|
||||
@ -222,9 +226,9 @@ SERVER* SchemaRouterSession::resolve_query_target(GWBUF* pPacket,
|
||||
* the current default database or to the first available server. */
|
||||
target = get_shard_target(pPacket, type);
|
||||
|
||||
if ((target == NULL && command != MXS_COM_INIT_DB && m_current_db.length() == 0) ||
|
||||
command == MXS_COM_FIELD_LIST ||
|
||||
m_current_db.length() == 0)
|
||||
if ((target == NULL && command != MXS_COM_INIT_DB && m_current_db.length() == 0)
|
||||
|| command == MXS_COM_FIELD_LIST
|
||||
|| m_current_db.length() == 0)
|
||||
{
|
||||
/** No current database and no databases in query or the database is
|
||||
* ignored, route to first available backend. */
|
||||
@ -236,7 +240,7 @@ SERVER* SchemaRouterSession::resolve_query_target(GWBUF* pPacket,
|
||||
{
|
||||
for (SSRBackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
|
||||
{
|
||||
SERVER *server = (*it)->backend()->server;
|
||||
SERVER* server = (*it)->backend()->server;
|
||||
if (server_is_usable(server))
|
||||
{
|
||||
route_target = TARGET_NAMED_SERVER;
|
||||
@ -260,9 +264,9 @@ static bool is_empty_packet(GWBUF* pPacket)
|
||||
bool rval = false;
|
||||
uint8_t len[3];
|
||||
|
||||
if (gwbuf_length(pPacket) == 4 &&
|
||||
gwbuf_copy_data(pPacket, 0, 3, len) == 3 &&
|
||||
gw_mysql_get_byte3(len) == 0)
|
||||
if (gwbuf_length(pPacket) == 4
|
||||
&& gwbuf_copy_data(pPacket, 0, 3, len) == 3
|
||||
&& gw_mysql_get_byte3(len) == 0)
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
@ -296,7 +300,7 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
|
||||
m_queue.push_back(pPacket);
|
||||
ret = 1;
|
||||
|
||||
if (m_state == (INIT_READY | INIT_USE_DB))
|
||||
if (m_state == (INIT_READY | INIT_USE_DB))
|
||||
{
|
||||
/**
|
||||
* This state is possible if a client connects with a default database
|
||||
@ -366,7 +370,7 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
|
||||
gwbuf_free(pPacket);
|
||||
|
||||
char errbuf[128 + MYSQL_DATABASE_MAXLEN];
|
||||
snprintf(errbuf, sizeof (errbuf), "Unknown database: %s", db);
|
||||
snprintf(errbuf, sizeof(errbuf), "Unknown database: %s", db);
|
||||
|
||||
if (m_config->debug)
|
||||
{
|
||||
@ -388,7 +392,8 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
|
||||
if (target)
|
||||
{
|
||||
MXS_INFO("INIT_DB for database '%s' on server '%s'",
|
||||
m_current_db.c_str(), target->name);
|
||||
m_current_db.c_str(),
|
||||
target->name);
|
||||
route_target = TARGET_NAMED_SERVER;
|
||||
}
|
||||
else
|
||||
@ -423,8 +428,8 @@ int32_t SchemaRouterSession::routeQuery(GWBUF* pPacket)
|
||||
|
||||
DCB* target_dcb = NULL;
|
||||
|
||||
if (TARGET_IS_NAMED_SERVER(route_target) && target &&
|
||||
get_shard_dcb(&target_dcb, target->name))
|
||||
if (TARGET_IS_NAMED_SERVER(route_target) && target
|
||||
&& get_shard_dcb(&target_dcb, target->name))
|
||||
{
|
||||
/** We know where to route this query */
|
||||
SSRBackend bref = get_bref_from_dcb(target_dcb);
|
||||
@ -541,7 +546,7 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
|
||||
{
|
||||
SSRBackend bref = get_bref_from_dcb(pDcb);
|
||||
|
||||
if (m_closed || bref.get() == NULL) // The bref should always be valid
|
||||
if (m_closed || bref.get() == NULL) // The bref should always be valid
|
||||
{
|
||||
gwbuf_free(pPacket);
|
||||
return;
|
||||
@ -552,8 +557,8 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
|
||||
bref->backend()->server->name,
|
||||
m_client->session,
|
||||
m_state & INIT_MAPPING ? "true" : "false",
|
||||
m_queue.size() == 0 ? "none" :
|
||||
m_queue.size() > 0 ? "multiple" : "one");
|
||||
m_queue.size() == 0 ? "none"
|
||||
: m_queue.size() > 0 ? "multiple" : "one");
|
||||
|
||||
if (m_state & INIT_MAPPING)
|
||||
{
|
||||
@ -562,7 +567,8 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
|
||||
else if (m_state & INIT_USE_DB)
|
||||
{
|
||||
MXS_DEBUG("Reply to USE '%s' received for session %p",
|
||||
m_connect_db.c_str(), m_client->session);
|
||||
m_connect_db.c_str(),
|
||||
m_client->session);
|
||||
m_state &= ~INIT_USE_DB;
|
||||
m_current_db = m_connect_db;
|
||||
mxb_assert(m_state == INIT_READY);
|
||||
@ -597,7 +603,8 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
|
||||
if (bref->execute_session_command())
|
||||
{
|
||||
MXS_INFO("Backend %s:%d processed reply and starts to execute active cursor.",
|
||||
bref->backend()->server->address, bref->backend()->server->port);
|
||||
bref->backend()->server->address,
|
||||
bref->backend()->server->port);
|
||||
}
|
||||
else if (bref->write_stored_command())
|
||||
{
|
||||
@ -609,14 +616,14 @@ void SchemaRouterSession::clientReply(GWBUF* pPacket, DCB* pDcb)
|
||||
}
|
||||
|
||||
void SchemaRouterSession::handleError(GWBUF* pMessage,
|
||||
DCB* pProblem,
|
||||
DCB* pProblem,
|
||||
mxs_error_action_t action,
|
||||
bool* pSuccess)
|
||||
{
|
||||
mxb_assert(pProblem->dcb_role == DCB_ROLE_BACKEND_HANDLER);
|
||||
SSRBackend bref = get_bref_from_dcb(pProblem);
|
||||
|
||||
if (bref.get() == NULL) // Should never happen
|
||||
if (bref.get() == NULL) // Should never happen
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -639,7 +646,7 @@ void SchemaRouterSession::handleError(GWBUF* pMessage,
|
||||
m_client->func.write(m_client, gwbuf_clone(pMessage));
|
||||
}
|
||||
|
||||
*pSuccess = false; /*< no new backend servers were made available */
|
||||
*pSuccess = false; /*< no new backend servers were made available */
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -681,7 +688,7 @@ void SchemaRouterSession::synchronize_shards()
|
||||
bool extract_database(GWBUF* buf, char* str)
|
||||
{
|
||||
uint8_t* packet;
|
||||
char *saved, *tok, *query = NULL;
|
||||
char* saved, * tok, * query = NULL;
|
||||
bool succp = true;
|
||||
unsigned int plen;
|
||||
|
||||
@ -689,10 +696,10 @@ bool extract_database(GWBUF* buf, char* str)
|
||||
plen = gw_mysql_get_byte3(packet) - 1;
|
||||
|
||||
/** Copy database name from MySQL packet to session */
|
||||
if (mxs_mysql_get_command(buf) == MXS_COM_QUERY &&
|
||||
qc_get_operation(buf) == QUERY_OP_CHANGE_DB)
|
||||
if (mxs_mysql_get_command(buf) == MXS_COM_QUERY
|
||||
&& qc_get_operation(buf) == QUERY_OP_CHANGE_DB)
|
||||
{
|
||||
const char *delim = "` \n\t;";
|
||||
const char* delim = "` \n\t;";
|
||||
|
||||
query = modutil_get_SQL(buf);
|
||||
tok = strtok_r(query, delim, &saved);
|
||||
@ -751,7 +758,7 @@ bool SchemaRouterSession::route_session_write(GWBUF* querybuf, uint8_t command)
|
||||
{
|
||||
if ((*it)->in_use())
|
||||
{
|
||||
GWBUF *buffer = gwbuf_clone(querybuf);
|
||||
GWBUF* buffer = gwbuf_clone(querybuf);
|
||||
|
||||
(*it)->append_session_command(buffer, m_sent_sescmd);
|
||||
|
||||
@ -844,7 +851,7 @@ SSRBackend SchemaRouterSession::get_bref_from_dcb(DCB* dcb)
|
||||
bool detect_show_shards(GWBUF* query)
|
||||
{
|
||||
bool rval = false;
|
||||
char *querystr, *tok, *sptr;
|
||||
char* querystr, * tok, * sptr;
|
||||
|
||||
if (query == NULL)
|
||||
{
|
||||
@ -941,7 +948,7 @@ bool SchemaRouterSession::handle_default_db()
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
uint8_t *data = GWBUF_DATA(buffer);
|
||||
uint8_t* data = GWBUF_DATA(buffer);
|
||||
gw_mysql_set_byte3(data, qlen + 1);
|
||||
data[3] = 0x0;
|
||||
data[4] = 0x2;
|
||||
@ -949,8 +956,8 @@ bool SchemaRouterSession::handle_default_db()
|
||||
SSRBackend backend;
|
||||
DCB* dcb = NULL;
|
||||
|
||||
if (get_shard_dcb(&dcb, target->name) &&
|
||||
(backend = get_bref_from_dcb(dcb)))
|
||||
if (get_shard_dcb(&dcb, target->name)
|
||||
&& (backend = get_bref_from_dcb(dcb)))
|
||||
{
|
||||
backend->write(buffer);
|
||||
MXS_DEBUG("USE '%s' sent to %s for session %p",
|
||||
@ -977,7 +984,8 @@ bool SchemaRouterSession::handle_default_db()
|
||||
sprintf(errmsg, "Unknown database '%s'", m_connect_db.c_str());
|
||||
if (m_config->debug)
|
||||
{
|
||||
sprintf(errmsg + strlen(errmsg), " ([%" PRIu64 "]: DB not found on connect)",
|
||||
sprintf(errmsg + strlen(errmsg),
|
||||
" ([%" PRIu64 "]: DB not found on connect)",
|
||||
m_client->session->ses_id);
|
||||
}
|
||||
write_error_to_client(m_client,
|
||||
@ -1056,7 +1064,8 @@ int SchemaRouterSession::inspect_mapping_states(SSRBackend& bref,
|
||||
* if there is a queued query from the client. */
|
||||
if (m_queue.size())
|
||||
{
|
||||
GWBUF* error = modutil_create_mysql_err_msg(1, 0,
|
||||
GWBUF* error = modutil_create_mysql_err_msg(1,
|
||||
0,
|
||||
SCHEMA_ERR_DUPLICATEDB,
|
||||
SCHEMA_ERRSTR_DUPLICATEDB,
|
||||
"Error: duplicate tables "
|
||||
@ -1081,7 +1090,8 @@ int SchemaRouterSession::inspect_mapping_states(SSRBackend& bref,
|
||||
{
|
||||
mapped = false;
|
||||
MXS_DEBUG("Still waiting for reply to SHOW DATABASES from %s for session %p",
|
||||
(*it)->backend()->server->name, m_client->session);
|
||||
(*it)->backend()->server->name,
|
||||
m_client->session);
|
||||
}
|
||||
}
|
||||
*wbuf = writebuf;
|
||||
@ -1161,21 +1171,25 @@ char* get_lenenc_str(void* data)
|
||||
{
|
||||
case 0xfb:
|
||||
return NULL;
|
||||
|
||||
case 0xfc:
|
||||
size = *(ptr + 1) + (*(ptr + 2) << 8);
|
||||
offset = 2;
|
||||
break;
|
||||
|
||||
case 0xfd:
|
||||
size = *ptr + (*(ptr + 2) << 8) + (*(ptr + 3) << 16);
|
||||
offset = 3;
|
||||
break;
|
||||
|
||||
case 0xfe:
|
||||
size = *ptr + ((*(ptr + 2) << 8)) + (*(ptr + 3) << 16) +
|
||||
(*(ptr + 4) << 24) + ((uintptr_t) * (ptr + 5) << 32) +
|
||||
((uintptr_t) * (ptr + 6) << 40) +
|
||||
((uintptr_t) * (ptr + 7) << 48) + ((uintptr_t) * (ptr + 8) << 56);
|
||||
size = *ptr + ((*(ptr + 2) << 8)) + (*(ptr + 3) << 16)
|
||||
+ (*(ptr + 4) << 24) + ((uintptr_t) * (ptr + 5) << 32)
|
||||
+ ((uintptr_t) * (ptr + 6) << 40)
|
||||
+ ((uintptr_t) * (ptr + 7) << 48) + ((uintptr_t) * (ptr + 8) << 56);
|
||||
offset = 8;
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
@ -1186,7 +1200,6 @@ char* get_lenenc_str(void* data)
|
||||
{
|
||||
memcpy(rval, ptr + offset, size);
|
||||
memset(rval + size, 0, 1);
|
||||
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
@ -1201,15 +1214,20 @@ bool SchemaRouterSession::ignore_duplicate_database(const char* data)
|
||||
}
|
||||
else if (m_config->ignore_regex)
|
||||
{
|
||||
pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(m_config->ignore_regex, NULL);
|
||||
pcre2_match_data* match_data = pcre2_match_data_create_from_pattern(m_config->ignore_regex, NULL);
|
||||
|
||||
if (match_data == NULL)
|
||||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
|
||||
if (pcre2_match(m_config->ignore_regex, (PCRE2_SPTR) data,
|
||||
PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL) >= 0)
|
||||
if (pcre2_match(m_config->ignore_regex,
|
||||
(PCRE2_SPTR) data,
|
||||
PCRE2_ZERO_TERMINATED,
|
||||
0,
|
||||
0,
|
||||
match_data,
|
||||
NULL) >= 0)
|
||||
{
|
||||
rval = true;
|
||||
}
|
||||
@ -1299,17 +1317,21 @@ enum showdb_response SchemaRouterSession::parse_mapping_response(SSRBackend& bre
|
||||
if (!ignore_duplicate_database(data) && strchr(data, '.') != NULL)
|
||||
{
|
||||
duplicate_found = true;
|
||||
SERVER *duplicate = m_shard.get_location(data);
|
||||
SERVER* duplicate = m_shard.get_location(data);
|
||||
|
||||
MXS_ERROR("Table '%s' found on servers '%s' and '%s' for user %s@%s.",
|
||||
data, target->name, duplicate->name,
|
||||
m_client->user, m_client->remote);
|
||||
data,
|
||||
target->name,
|
||||
duplicate->name,
|
||||
m_client->user,
|
||||
m_client->remote);
|
||||
}
|
||||
else if (m_config->preferred_server == target)
|
||||
{
|
||||
/** In conflict situations, use the preferred server */
|
||||
MXS_INFO("Forcing location of '%s' from '%s' to '%s'",
|
||||
data, m_shard.get_location(data)->name,
|
||||
data,
|
||||
m_shard.get_location(data)->name,
|
||||
target->name);
|
||||
m_shard.replace_location(data, target);
|
||||
}
|
||||
@ -1365,19 +1387,18 @@ void SchemaRouterSession::query_databases()
|
||||
m_state |= INIT_MAPPING;
|
||||
m_state &= ~INIT_UNINT;
|
||||
|
||||
GWBUF *buffer = modutil_create_query
|
||||
("SELECT schema_name FROM information_schema.schemata AS s "
|
||||
"LEFT JOIN information_schema.tables AS t ON s.schema_name = t.table_schema "
|
||||
"WHERE t.table_name IS NULL "
|
||||
"UNION "
|
||||
"SELECT CONCAT (table_schema, '.', table_name) FROM information_schema.tables "
|
||||
"WHERE table_schema NOT IN ('information_schema', 'performance_schema', 'mysql');");
|
||||
GWBUF* buffer = modutil_create_query("SELECT schema_name FROM information_schema.schemata AS s "
|
||||
"LEFT JOIN information_schema.tables AS t ON s.schema_name = t.table_schema "
|
||||
"WHERE t.table_name IS NULL "
|
||||
"UNION "
|
||||
"SELECT CONCAT (table_schema, '.', table_name) FROM information_schema.tables "
|
||||
"WHERE table_schema NOT IN ('information_schema', 'performance_schema', 'mysql');");
|
||||
gwbuf_set_type(buffer, GWBUF_TYPE_COLLECT_RESULT);
|
||||
|
||||
for (SSRBackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
|
||||
{
|
||||
if ((*it)->in_use() && !(*it)->is_closed() &
|
||||
server_is_usable((*it)->backend()->server))
|
||||
if ((*it)->in_use() && !(*it)->is_closed()
|
||||
& server_is_usable((*it)->backend()->server))
|
||||
{
|
||||
GWBUF* clone = gwbuf_clone(buffer);
|
||||
MXS_ABORT_IF_NULL(clone);
|
||||
@ -1401,7 +1422,7 @@ void SchemaRouterSession::query_databases()
|
||||
*/
|
||||
SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype)
|
||||
{
|
||||
SERVER *rval = NULL;
|
||||
SERVER* rval = NULL;
|
||||
qc_query_op_t op = QUERY_OP_UNDEFINED;
|
||||
uint8_t command = mxs_mysql_get_command(buffer);
|
||||
|
||||
@ -1411,11 +1432,11 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype)
|
||||
rval = get_query_target(buffer);
|
||||
}
|
||||
|
||||
if (mxs_mysql_is_ps_command(command) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_PREPARE_NAMED_STMT) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_DEALLOC_PREPARE) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_PREPARE_STMT) ||
|
||||
op == QUERY_OP_EXECUTE)
|
||||
if (mxs_mysql_is_ps_command(command)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_PREPARE_NAMED_STMT)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_DEALLOC_PREPARE)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_PREPARE_STMT)
|
||||
|| op == QUERY_OP_EXECUTE)
|
||||
{
|
||||
rval = get_ps_target(buffer, qtype, op);
|
||||
}
|
||||
@ -1424,7 +1445,7 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype)
|
||||
{
|
||||
for (SSRBackendList::iterator it = m_backends.begin(); it != m_backends.end(); it++)
|
||||
{
|
||||
char *srvnm = (*it)->backend()->server->name;
|
||||
char* srvnm = (*it)->backend()->server->name;
|
||||
|
||||
if (strcmp(srvnm, (char*)buffer->hint->data) == 0)
|
||||
{
|
||||
@ -1445,7 +1466,8 @@ SERVER* SchemaRouterSession::get_shard_target(GWBUF* buffer, uint32_t qtype)
|
||||
if (rval)
|
||||
{
|
||||
MXS_INFO("Using active database '%s' on '%s'",
|
||||
m_current_db.c_str(), rval->name);
|
||||
m_current_db.c_str(),
|
||||
rval->name);
|
||||
}
|
||||
}
|
||||
return rval;
|
||||
@ -1477,9 +1499,9 @@ bool SchemaRouterSession::get_shard_dcb(DCB** p_dcb, char* name)
|
||||
* backend must be in use, name must match, and
|
||||
* the backend state must be RUNNING
|
||||
*/
|
||||
if ((*it)->in_use() &&
|
||||
(strncasecmp(name, b->server->name, PATH_MAX) == 0) &&
|
||||
server_is_usable(b->server))
|
||||
if ((*it)->in_use()
|
||||
&& (strncasecmp(name, b->server->name, PATH_MAX) == 0)
|
||||
&& server_is_usable(b->server))
|
||||
{
|
||||
*p_dcb = (*it)->dcb();
|
||||
succp = true;
|
||||
@ -1509,17 +1531,17 @@ enum route_target get_shard_route_target(uint32_t qtype)
|
||||
/**
|
||||
* These queries are not affected by hints
|
||||
*/
|
||||
if (qc_query_is_type(qtype, QUERY_TYPE_SESSION_WRITE) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_WRITE) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_USERVAR_WRITE) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_ENABLE_AUTOCOMMIT) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_DISABLE_AUTOCOMMIT))
|
||||
if (qc_query_is_type(qtype, QUERY_TYPE_SESSION_WRITE)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_WRITE)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_USERVAR_WRITE)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_ENABLE_AUTOCOMMIT)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_DISABLE_AUTOCOMMIT))
|
||||
{
|
||||
/** hints don't affect on routing */
|
||||
target = TARGET_ALL;
|
||||
}
|
||||
else if (qc_query_is_type(qtype, QUERY_TYPE_SYSVAR_READ) ||
|
||||
qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_READ))
|
||||
else if (qc_query_is_type(qtype, QUERY_TYPE_SYSVAR_READ)
|
||||
|| qc_query_is_type(qtype, QUERY_TYPE_GSYSVAR_READ))
|
||||
{
|
||||
target = TARGET_ANY;
|
||||
}
|
||||
@ -1561,14 +1583,14 @@ void SchemaRouterSession::send_databases()
|
||||
|
||||
bool SchemaRouterSession::send_tables(GWBUF* pPacket)
|
||||
{
|
||||
char *query = modutil_get_SQL(pPacket);
|
||||
char *tmp;
|
||||
char* query = modutil_get_SQL(pPacket);
|
||||
char* tmp;
|
||||
std::string database;
|
||||
|
||||
if ((tmp = strcasestr(query, "from")))
|
||||
{
|
||||
const char *delim = "` \n\t;";
|
||||
char *saved, *tok = strtok_r(tmp, delim, &saved);
|
||||
const char* delim = "` \n\t;";
|
||||
char* saved, * tok = strtok_r(tmp, delim, &saved);
|
||||
tok = strtok_r(NULL, delim, &saved);
|
||||
database = tok;
|
||||
}
|
||||
@ -1624,7 +1646,7 @@ bool SchemaRouterSession::handle_statement(GWBUF* querybuf, SSRBackend& bref, ui
|
||||
|
||||
if (bref->in_use())
|
||||
{
|
||||
GWBUF *buffer = gwbuf_clone(querybuf);
|
||||
GWBUF* buffer = gwbuf_clone(querybuf);
|
||||
bref->append_session_command(buffer, m_sent_sescmd);
|
||||
|
||||
if (bref->session_command_count() == 1)
|
||||
@ -1636,20 +1658,20 @@ bool SchemaRouterSession::handle_statement(GWBUF* querybuf, SSRBackend& bref, ui
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Failed to execute session "
|
||||
"command in %s:%d",
|
||||
bref->backend()->server->address,
|
||||
bref->backend()->server->port);
|
||||
MXS_ERROR("Failed to execute session "
|
||||
"command in %s:%d",
|
||||
bref->backend()->server->address,
|
||||
bref->backend()->server->port);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mxb_assert(bref->session_command_count() > 1);
|
||||
/** The server is already executing a session command */
|
||||
MXS_INFO("Backend %s:%d already executing sescmd.",
|
||||
bref->backend()->server->address,
|
||||
bref->backend()->server->port);
|
||||
succp = true;
|
||||
mxb_assert(bref->session_command_count() > 1);
|
||||
/** The server is already executing a session command */
|
||||
MXS_INFO("Backend %s:%d already executing sescmd.",
|
||||
bref->backend()->server->address,
|
||||
bref->backend()->server->port);
|
||||
succp = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1688,27 +1710,29 @@ SERVER* SchemaRouterSession::get_query_target(GWBUF* buffer)
|
||||
{
|
||||
MXS_ERROR("Query targets tables on servers '%s' and '%s'. "
|
||||
"Cross server queries are not supported.",
|
||||
rval->name, target->name);
|
||||
rval->name,
|
||||
target->name);
|
||||
}
|
||||
else if (rval == NULL)
|
||||
{
|
||||
rval = target;
|
||||
MXS_INFO("Query targets table '%s' on server '%s'",
|
||||
tables[j], rval->name);
|
||||
tables[j],
|
||||
rval->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MXS_FREE(databases[i]);
|
||||
}
|
||||
MXS_FREE(databases[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_tables; i++)
|
||||
{
|
||||
MXS_FREE(tables[i]);
|
||||
}
|
||||
MXS_FREE(tables);
|
||||
MXS_FREE(databases);
|
||||
return rval;
|
||||
for (int i = 0; i < n_tables; i++)
|
||||
{
|
||||
MXS_FREE(tables[i]);
|
||||
}
|
||||
MXS_FREE(tables);
|
||||
MXS_FREE(databases);
|
||||
return rval;
|
||||
}
|
||||
|
||||
SERVER* SchemaRouterSession::get_ps_target(GWBUF* buffer, uint32_t qtype, qc_query_op_t op)
|
||||
@ -1734,7 +1758,8 @@ SERVER* SchemaRouterSession::get_ps_target(GWBUF* buffer, uint32_t qtype, qc_que
|
||||
{
|
||||
MXS_ERROR("Statement targets tables on servers '%s' and '%s'. "
|
||||
"Cross server queries are not supported.",
|
||||
rval->name, target->name);
|
||||
rval->name,
|
||||
target->name);
|
||||
}
|
||||
else if (rval == NULL)
|
||||
{
|
||||
@ -1780,8 +1805,8 @@ SERVER* SchemaRouterSession::get_ps_target(GWBUF* buffer, uint32_t qtype, qc_que
|
||||
rval = m_shard.get_location(tables[0]);
|
||||
MXS_FREE(tables[i]);
|
||||
}
|
||||
rval ? MXS_INFO("Prepare statement on server %s", rval->name) :
|
||||
MXS_INFO("Prepared statement targets no mapped tables");
|
||||
rval ? MXS_INFO("Prepare statement on server %s", rval->name)
|
||||
: MXS_INFO("Prepared statement targets no mapped tables");
|
||||
MXS_FREE(tables);
|
||||
}
|
||||
else if (mxs_mysql_is_ps_command(command))
|
||||
@ -1800,5 +1825,4 @@ SERVER* SchemaRouterSession::get_ps_target(GWBUF* buffer, uint32_t qtype, qc_que
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include "schemarouter.hh"
|
||||
|
||||
@ -46,10 +46,10 @@ enum showdb_response
|
||||
SHOWDB_FATAL_ERROR
|
||||
};
|
||||
|
||||
#define SCHEMA_ERR_DUPLICATEDB 5000
|
||||
#define SCHEMA_ERR_DUPLICATEDB 5000
|
||||
#define SCHEMA_ERRSTR_DUPLICATEDB "DUPDB"
|
||||
#define SCHEMA_ERR_DBNOTFOUND 1049
|
||||
#define SCHEMA_ERRSTR_DBNOTFOUND "42000"
|
||||
#define SCHEMA_ERR_DBNOTFOUND 1049
|
||||
#define SCHEMA_ERRSTR_DBNOTFOUND "42000"
|
||||
|
||||
/**
|
||||
* Route target types
|
||||
@ -73,7 +73,7 @@ class SchemaRouter;
|
||||
/**
|
||||
* The client session structure used within this router.
|
||||
*/
|
||||
class SchemaRouterSession: public mxs::RouterSession
|
||||
class SchemaRouterSession : public mxs::RouterSession
|
||||
{
|
||||
public:
|
||||
|
||||
@ -114,29 +114,31 @@ public:
|
||||
* @param action The context.
|
||||
* @param pSuccess On output, if false, the session will be terminated.
|
||||
*/
|
||||
void handleError(GWBUF* pMessage,
|
||||
DCB* pProblem,
|
||||
void handleError(GWBUF* pMessage,
|
||||
DCB* pProblem,
|
||||
mxs_error_action_t action,
|
||||
bool* pSuccess);
|
||||
bool* pSuccess);
|
||||
private:
|
||||
/**
|
||||
* Internal functions
|
||||
*/
|
||||
|
||||
/** Helper functions */
|
||||
SERVER* get_shard_target(GWBUF* buffer, uint32_t qtype);
|
||||
SERVER* get_shard_target(GWBUF* buffer, uint32_t qtype);
|
||||
SSRBackend get_bref_from_dcb(DCB* dcb);
|
||||
bool get_shard_dcb(DCB** dcb, char* name);
|
||||
bool have_servers();
|
||||
bool handle_default_db();
|
||||
bool ignore_duplicate_database(const char* data);
|
||||
SERVER* get_query_target(GWBUF* buffer);
|
||||
SERVER* get_ps_target(GWBUF* buffer, uint32_t qtype, qc_query_op_t op);
|
||||
bool get_shard_dcb(DCB** dcb, char* name);
|
||||
bool have_servers();
|
||||
bool handle_default_db();
|
||||
bool ignore_duplicate_database(const char* data);
|
||||
SERVER* get_query_target(GWBUF* buffer);
|
||||
SERVER* get_ps_target(GWBUF* buffer, uint32_t qtype, qc_query_op_t op);
|
||||
|
||||
/** Routing functions */
|
||||
bool route_session_write(GWBUF* querybuf, uint8_t command);
|
||||
void process_sescmd_response(SSRBackend& bref, GWBUF** ppPacket);
|
||||
SERVER* resolve_query_target(GWBUF* pPacket, uint32_t type, uint8_t command,
|
||||
SERVER* resolve_query_target(GWBUF* pPacket,
|
||||
uint32_t type,
|
||||
uint8_t command,
|
||||
enum route_target& route_target);
|
||||
|
||||
/** Shard mapping functions */
|
||||
@ -152,20 +154,20 @@ private:
|
||||
bool handle_statement(GWBUF* querybuf, SSRBackend& bref, uint8_t command, uint32_t type);
|
||||
|
||||
/** Member variables */
|
||||
bool m_closed; /**< True if session closed */
|
||||
DCB* m_client; /**< The client DCB */
|
||||
MYSQL_session* m_mysql_session; /**< Session client data (username, password, SHA1). */
|
||||
SSRBackendList m_backends; /**< Backend references */
|
||||
SConfig m_config; /**< Session specific configuration */
|
||||
SchemaRouter* m_router; /**< The router instance */
|
||||
Shard m_shard; /**< Database to server mapping */
|
||||
std::string m_connect_db; /**< Database the user was trying to connect to */
|
||||
std::string m_current_db; /**< Current active database */
|
||||
int m_state; /**< Initialization state bitmask */
|
||||
std::list<mxs::Buffer> m_queue; /**< Query that was received before the session was ready */
|
||||
Stats m_stats; /**< Statistics for this router */
|
||||
uint64_t m_sent_sescmd; /**< The latest session command being executed */
|
||||
uint64_t m_replied_sescmd; /**< The last session command reply that was sent to the client */
|
||||
SERVER* m_load_target; /**< Target for LOAD DATA LOCAL INFILE */
|
||||
bool m_closed; /**< True if session closed */
|
||||
DCB* m_client; /**< The client DCB */
|
||||
MYSQL_session* m_mysql_session; /**< Session client data (username, password, SHA1). */
|
||||
SSRBackendList m_backends; /**< Backend references */
|
||||
SConfig m_config; /**< Session specific configuration */
|
||||
SchemaRouter* m_router; /**< The router instance */
|
||||
Shard m_shard; /**< Database to server mapping */
|
||||
std::string m_connect_db; /**< Database the user was trying to connect to */
|
||||
std::string m_current_db; /**< Current active database */
|
||||
int m_state; /**< Initialization state bitmask */
|
||||
std::list<mxs::Buffer> m_queue; /**< Query that was received before the session was ready */
|
||||
Stats m_stats; /**< Statistics for this router */
|
||||
uint64_t m_sent_sescmd; /**< The latest session command being executed */
|
||||
uint64_t m_replied_sescmd;/**< The last session command reply that was sent to the client */
|
||||
SERVER* m_load_target; /**< Target for LOAD DATA LOCAL INFILE */
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,8 +17,8 @@
|
||||
|
||||
#include <maxscale/alloc.h>
|
||||
|
||||
Shard::Shard():
|
||||
m_last_updated(time(NULL))
|
||||
Shard::Shard()
|
||||
: m_last_updated(time(NULL))
|
||||
{
|
||||
}
|
||||
|
||||
@ -83,7 +83,10 @@ SERVER* Shard::get_location(std::string table)
|
||||
if ((rval && rval != it->second))
|
||||
{
|
||||
MXS_DEBUG("There are 2 databases with same name on a different servers: '%s' and '%s'. Connecting to '%s'"
|
||||
, rval->name,it->second->name, rval->name);
|
||||
,
|
||||
rval->name,
|
||||
it->second->name,
|
||||
rval->name);
|
||||
break;
|
||||
}
|
||||
else
|
||||
@ -114,7 +117,7 @@ SERVER* Shard::get_statement(std::string stmt)
|
||||
{
|
||||
SERVER* rval = NULL;
|
||||
ServerMap::iterator iter = stmt_map.find(stmt);
|
||||
if(iter != stmt_map.end())
|
||||
if (iter != stmt_map.end())
|
||||
{
|
||||
rval = iter->second;
|
||||
}
|
||||
@ -125,7 +128,7 @@ SERVER* Shard::get_statement(uint32_t id)
|
||||
{
|
||||
SERVER* rval = NULL;
|
||||
BinaryPSMap::iterator iter = m_binary_map.find(id);
|
||||
if(iter != m_binary_map.end())
|
||||
if (iter != m_binary_map.end())
|
||||
{
|
||||
rval = iter->second;
|
||||
}
|
||||
@ -207,4 +210,4 @@ void ShardManager::update_shard(Shard& shard, std::string user)
|
||||
{
|
||||
m_maps[user] = shard;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
#include <maxscale/ccdefs.hh>
|
||||
|
||||
@ -25,8 +25,8 @@ using namespace maxscale;
|
||||
|
||||
/** This contains the database to server mapping */
|
||||
typedef std::unordered_map<std::string, SERVER*> ServerMap;
|
||||
typedef std::unordered_map<uint64_t, SERVER*> BinaryPSMap;
|
||||
typedef std::unordered_map<uint32_t, uint32_t> PSHandleMap;
|
||||
typedef std::unordered_map<uint64_t, SERVER*> BinaryPSMap;
|
||||
typedef std::unordered_map<uint32_t, uint32_t> PSHandleMap;
|
||||
|
||||
class Shard
|
||||
{
|
||||
@ -53,15 +53,15 @@ public:
|
||||
*/
|
||||
SERVER* get_location(std::string db);
|
||||
|
||||
void add_statement(std::string stmt, SERVER* target);
|
||||
void add_statement(uint32_t id, SERVER* target);
|
||||
void add_ps_handle(uint32_t id, uint32_t handle);
|
||||
void add_statement(std::string stmt, SERVER* target);
|
||||
void add_statement(uint32_t id, SERVER* target);
|
||||
void add_ps_handle(uint32_t id, uint32_t handle);
|
||||
uint32_t get_ps_handle(uint32_t id);
|
||||
bool remove_ps_handle(uint32_t id);
|
||||
SERVER* get_statement(std::string stmt);
|
||||
SERVER* get_statement(uint32_t id);
|
||||
bool remove_statement(std::string stmt);
|
||||
bool remove_statement(uint32_t id);
|
||||
bool remove_ps_handle(uint32_t id);
|
||||
SERVER* get_statement(std::string stmt);
|
||||
SERVER* get_statement(uint32_t id);
|
||||
bool remove_statement(std::string stmt);
|
||||
bool remove_statement(uint32_t id);
|
||||
|
||||
/**
|
||||
* @brief Change the location of a database
|
||||
@ -104,11 +104,11 @@ public:
|
||||
bool newer_than(const Shard& shard) const;
|
||||
|
||||
private:
|
||||
ServerMap m_map;
|
||||
ServerMap stmt_map;
|
||||
ServerMap m_map;
|
||||
ServerMap stmt_map;
|
||||
BinaryPSMap m_binary_map;
|
||||
PSHandleMap m_ps_handles;
|
||||
time_t m_last_updated;
|
||||
time_t m_last_updated;
|
||||
};
|
||||
|
||||
typedef std::unordered_map<std::string, Shard> ShardMap;
|
||||
|
||||
Reference in New Issue
Block a user