
Using the same implementation of the Backend and SessionCommand classes in both schemarouter and readwritesplit will prevent duplication of code. This commit only splits the generic parts of the class to a Backend class which the schemarouter then extends. The session commands for both routers are similar so they require no special handling.
167 lines
5.5 KiB
C++
167 lines
5.5 KiB
C++
#pragma once
|
|
/*
|
|
* Copyright (c) 2016 MariaDB Corporation Ab
|
|
*
|
|
* Use of this software is governed by the Business Source License included
|
|
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
|
*
|
|
* Change Date: 2020-01-01
|
|
*
|
|
* On the date above, in accordance with the Business Source License, use
|
|
* of this software will be governed by version 2 or later of the General
|
|
* Public License.
|
|
*/
|
|
|
|
#include "schemarouter.hh"
|
|
|
|
#include <string>
|
|
#include <list>
|
|
|
|
#include <maxscale/protocol/mysql.h>
|
|
#include <maxscale/router.hh>
|
|
#include <maxscale/session_command.hh>
|
|
|
|
#include "shard_map.hh"
|
|
|
|
namespace schemarouter
|
|
{
|
|
/**
|
|
* Bitmask values for the router session's initialization. These values are used
|
|
* to prevent responses from internal commands being forwarded to the client.
|
|
*/
|
|
enum init_mask
|
|
{
|
|
INIT_READY = 0x00,
|
|
INIT_MAPPING = 0x01,
|
|
INIT_USE_DB = 0x02,
|
|
INIT_UNINT = 0x04,
|
|
INIT_FAILED = 0x08
|
|
};
|
|
|
|
enum showdb_response
|
|
{
|
|
SHOWDB_FULL_RESPONSE,
|
|
SHOWDB_PARTIAL_RESPONSE,
|
|
SHOWDB_DUPLICATE_DATABASES,
|
|
SHOWDB_FATAL_ERROR
|
|
};
|
|
|
|
#define SCHEMA_ERR_DUPLICATEDB 5000
|
|
#define SCHEMA_ERRSTR_DUPLICATEDB "DUPDB"
|
|
#define SCHEMA_ERR_DBNOTFOUND 1049
|
|
#define SCHEMA_ERRSTR_DBNOTFOUND "42000"
|
|
|
|
/**
|
|
* Route target types
|
|
*/
|
|
enum route_target
|
|
{
|
|
TARGET_UNDEFINED,
|
|
TARGET_NAMED_SERVER,
|
|
TARGET_ALL,
|
|
TARGET_ANY
|
|
};
|
|
|
|
/** Helper macros for route target type */
|
|
#define TARGET_IS_UNDEFINED(t) (t == TARGET_UNDEFINED)
|
|
#define TARGET_IS_NAMED_SERVER(t) (t == TARGET_NAMED_SERVER)
|
|
#define TARGET_IS_ALL(t) (t == TARGET_ALL)
|
|
#define TARGET_IS_ANY(t) (t == TARGET_ANY)
|
|
|
|
class SchemaRouter;
|
|
|
|
/**
|
|
* The client session structure used within this router.
|
|
*/
|
|
class SchemaRouterSession: public mxs::RouterSession
|
|
{
|
|
public:
|
|
|
|
SchemaRouterSession(MXS_SESSION* session, SchemaRouter* router, SSRBackendList& backends);
|
|
|
|
/**
|
|
* The RouterSession instance will be deleted when a client session
|
|
* has terminated. Will be called only after @c close() has been called.
|
|
*/
|
|
~SchemaRouterSession();
|
|
|
|
/**
|
|
* Called when a client session has been closed.
|
|
*/
|
|
void close();
|
|
|
|
/**
|
|
* Called when a packet being is routed to the backend. The router should
|
|
* forward the packet to the appropriate server(s).
|
|
*
|
|
* @param pPacket A client packet.
|
|
*/
|
|
int32_t routeQuery(GWBUF* pPacket);
|
|
|
|
/**
|
|
* Called when a packet is routed to the client. The router should
|
|
* forward the packet to the client using `MXS_SESSION_ROUTE_REPLY`.
|
|
*
|
|
* @param pPacket A client packet.
|
|
* @param pBackend The backend the packet is coming from.
|
|
*/
|
|
void clientReply(GWBUF* pPacket, DCB* pBackend);
|
|
|
|
/**
|
|
*
|
|
* @param pMessage The rror message.
|
|
* @param pProblem The DCB on which the error occurred.
|
|
* @param action The context.
|
|
* @param pSuccess On output, if false, the session will be terminated.
|
|
*/
|
|
void handleError(GWBUF* pMessage,
|
|
DCB* pProblem,
|
|
mxs_error_action_t action,
|
|
bool* pSuccess);
|
|
private:
|
|
/**
|
|
* Internal functions
|
|
*/
|
|
|
|
/** Helper functions */
|
|
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);
|
|
|
|
/** 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,
|
|
enum route_target& route_target);
|
|
|
|
/** Shard mapping functions */
|
|
bool send_databases();
|
|
bool send_shards();
|
|
void query_databases();
|
|
int inspect_mapping_states(SSRBackend& bref, GWBUF** wbuf);
|
|
enum showdb_response parse_mapping_response(SSRBackend& bref, GWBUF** buffer);
|
|
void route_queued_query();
|
|
void synchronize_shards();
|
|
void handle_mapping_reply(SSRBackend& bref, GWBUF** pPacket);
|
|
|
|
/** 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 */
|
|
Config* m_config; /**< Pointer to router config */
|
|
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 */
|
|
};
|
|
} |