Merge branch '2.1' into develop
This commit is contained in:
@ -53,9 +53,29 @@ GWBUF* modutil_create_mysql_err_msg(int packet_number,
|
||||
int merrno,
|
||||
const char *statemsg,
|
||||
const char *msg);
|
||||
|
||||
int modutil_count_signal_packets(GWBUF*, int, int, int*);
|
||||
mxs_pcre2_result_t modutil_mysql_wildcard_match(const char* pattern, const char* string);
|
||||
|
||||
/**
|
||||
* Given a buffer containing a MySQL statement, this function will return
|
||||
* a pointer to the first character that is not whitespace. In this context,
|
||||
* comments are also counted as whitespace. For instance:
|
||||
*
|
||||
* "SELECT" => "SELECT"
|
||||
* " SELECT => "SELECT"
|
||||
* " / * A comment * / SELECT" => "SELECT"
|
||||
* "-- comment\nSELECT" => "SELECT"
|
||||
*
|
||||
* @param sql Pointer to buffer containing a MySQL statement
|
||||
* @param len Length of sql.
|
||||
*
|
||||
* @return The first non whitespace (including comments) character. If the
|
||||
* entire buffer is only whitespace, the returned pointer will point
|
||||
* to the character following the buffer (i.e. sql + len).
|
||||
*/
|
||||
char* modutil_MySQL_bypass_whitespace(char* sql, size_t len);
|
||||
|
||||
/** Character and token searching functions */
|
||||
char* strnchr_esc(char* ptr, char c, int len);
|
||||
char* strnchr_esc_mysql(char* ptr, char c, int len);
|
||||
|
@ -31,6 +31,7 @@ MXS_BEGIN_DECLS
|
||||
#define MXS_DEFAULT_CONFIG_SUBPATH "@DEFAULT_CONFIG_SUBPATH@"
|
||||
#define MXS_DEFAULT_CONFIG_PERSIST_SUBPATH "@DEFAULT_CONFIG_PERSIST_SUBPATH@"
|
||||
#define MXS_DEFAULT_MODULE_CONFIG_SUBPATH "@DEFAULT_MODULE_CONFIG_SUBPATH@"
|
||||
#define MXS_DEFAULT_CONNECTOR_PLUGIN_SUBPATH "@DEFAULT_CONNECTOR_PLUGIN_SUBPATH@"
|
||||
|
||||
/** Default file locations, configured by CMake */
|
||||
#define MXS_DEFAULT_CONFIGDIR "@DEFAULT_CONFIGDIR@"
|
||||
@ -43,6 +44,7 @@ MXS_BEGIN_DECLS
|
||||
#define MXS_DEFAULT_EXECDIR "@DEFAULT_EXECDIR@"
|
||||
#define MXS_DEFAULT_CONFIG_PERSISTDIR "@DEFAULT_CONFIG_PERSISTDIR@"
|
||||
#define MXS_DEFAULT_MODULE_CONFIGDIR "@DEFAULT_MODULE_CONFIGDIR@"
|
||||
#define MXS_DEFAULT_CONNECTOR_PLUGINDIR "@DEFAULT_CONNECTOR_PLUGINDIR@"
|
||||
|
||||
static const char* default_cnf_fname = "maxscale.cnf";
|
||||
static const char* default_configdir = MXS_DEFAULT_CONFIGDIR;
|
||||
@ -59,6 +61,7 @@ static const char* default_langdir = MXS_DEFAULT_LANGDIR;
|
||||
static const char* default_execdir = MXS_DEFAULT_EXECDIR;
|
||||
static const char* default_config_persistdir = MXS_DEFAULT_CONFIG_PERSISTDIR;
|
||||
static const char* default_module_configdir = MXS_DEFAULT_MODULE_CONFIGDIR;
|
||||
static const char* default_connector_plugindir = MXS_DEFAULT_CONNECTOR_PLUGINDIR;
|
||||
|
||||
static char* configdir = NULL; /*< Where the config file is found e.g. /etc/ */
|
||||
static char* config_persistdir = NULL;/*< Persisted configs e.g. /var/lib/maxscale/maxscale.cnf.d/ */
|
||||
@ -71,6 +74,7 @@ static char* processdatadir = NULL; /*< Process specific data directory */
|
||||
static char* langdir = NULL;
|
||||
static char* piddir = NULL;
|
||||
static char* execdir = NULL;
|
||||
static char* connector_plugindir = NULL;
|
||||
|
||||
void set_libdir(char* param);
|
||||
void set_datadir(char* param);
|
||||
@ -83,6 +87,7 @@ void set_logdir(char* param);
|
||||
void set_langdir(char* param);
|
||||
void set_piddir(char* param);
|
||||
void set_execdir(char* param);
|
||||
void set_connector_plugindir(char* param);
|
||||
char* get_libdir();
|
||||
char* get_datadir();
|
||||
char* get_process_datadir();
|
||||
@ -94,5 +99,6 @@ char* get_piddir();
|
||||
char* get_logdir();
|
||||
char* get_langdir();
|
||||
char* get_execdir();
|
||||
char* get_connector_plugindir();
|
||||
|
||||
MXS_END_DECLS
|
||||
|
@ -19,6 +19,29 @@ MXS_BEGIN_DECLS
|
||||
|
||||
#define QUERY_CLASSIFIER_VERSION {1, 1, 0}
|
||||
|
||||
/**
|
||||
* qc_init_kind_t specifies what kind of initialization should be performed.
|
||||
*/
|
||||
typedef enum qc_init_kind
|
||||
{
|
||||
QC_INIT_SELF = 0x01, /*< Initialize/finalize the query classifier itself. */
|
||||
QC_INIT_PLUGIN = 0x02, /*< Initialize/finalize the plugin. */
|
||||
QC_INIT_BOTH = 0x03
|
||||
} qc_init_kind_t;
|
||||
|
||||
/**
|
||||
* @c qc_collect_info_t specifies what information should be collected during parsing.
|
||||
*/
|
||||
typedef enum qc_collect_info
|
||||
{
|
||||
QC_COLLECT_ESSENTIALS = 0x00, /*< Collect only the base minimum. */
|
||||
QC_COLLECT_TABLES = 0x01, /*< Collect table names. */
|
||||
QC_COLLECT_DATABASES = 0x02, /*< Collect database names. */
|
||||
QC_COLLECT_FIELDS = 0x04, /*< Collect field information. */
|
||||
QC_COLLECT_FUNCTIONS = 0x08, /*< Collect function information. */
|
||||
|
||||
QC_COLLECT_ALL = (QC_COLLECT_TABLES|QC_COLLECT_DATABASES|QC_COLLECT_FIELDS|QC_COLLECT_FUNCTIONS)
|
||||
} qc_collect_info_t;
|
||||
/**
|
||||
* qc_query_type_t defines bits that provide information about a
|
||||
* particular statement.
|
||||
@ -186,13 +209,16 @@ typedef struct query_classifier
|
||||
/**
|
||||
* Called to explicitly parse a statement.
|
||||
*
|
||||
* @param stmt The statement to be parsed.
|
||||
* @param result On return, the parse result, if @c QC_RESULT_OK is returned.
|
||||
* @param stmt The statement to be parsed.
|
||||
* @param collect A bitmask of @c qc_collect_info_t values. Specifies what information
|
||||
* should be collected. Only a hint and must not restrict what information
|
||||
* later can be queried.
|
||||
* @param result On return, the parse result, if @c QC_RESULT_OK is returned.
|
||||
*
|
||||
* @return QC_RESULT_OK, if the parsing was not aborted due to resource
|
||||
* exhaustion or equivalent.
|
||||
*/
|
||||
int32_t (*qc_parse)(GWBUF* stmt, int32_t* result);
|
||||
int32_t (*qc_parse)(GWBUF* stmt, uint32_t collect, int32_t* result);
|
||||
|
||||
/**
|
||||
* Reports the type of the statement.
|
||||
@ -377,11 +403,14 @@ bool qc_setup(const char* plugin_name, const char* plugin_args);
|
||||
*
|
||||
* MaxScale calls this functions, so plugins should not do that.
|
||||
*
|
||||
* @param kind What kind of initialization should be performed.
|
||||
* Combination of qc_init_kind_t.
|
||||
*
|
||||
* @return True, if the process wide initialization could be performed.
|
||||
*
|
||||
* @see qc_process_end qc_thread_init
|
||||
*/
|
||||
bool qc_process_init(void);
|
||||
bool qc_process_init(uint32_t kind);
|
||||
|
||||
/**
|
||||
* Finalizes the query classifier.
|
||||
@ -390,9 +419,12 @@ bool qc_process_init(void);
|
||||
* by a call to this function. MaxScale calls this function, so plugins
|
||||
* should not do that.
|
||||
*
|
||||
* @param kind What kind of finalization should be performed.
|
||||
* Combination of qc_init_kind_t.
|
||||
*
|
||||
* @see qc_process_init qc_thread_end
|
||||
*/
|
||||
void qc_process_end(void);
|
||||
void qc_process_end(uint32_t kind);
|
||||
|
||||
/**
|
||||
* Loads a particular query classifier.
|
||||
@ -426,11 +458,14 @@ void qc_unload(QUERY_CLASSIFIER* classifier);
|
||||
*
|
||||
* MaxScale calls this function, so plugins should not do that.
|
||||
*
|
||||
* @param kind What kind of initialization should be performed.
|
||||
* Combination of qc_init_kind_t.
|
||||
*
|
||||
* @return True if the initialization succeeded, false otherwise.
|
||||
*
|
||||
* @see qc_thread_end
|
||||
*/
|
||||
bool qc_thread_init(void);
|
||||
bool qc_thread_init(uint32_t kind);
|
||||
|
||||
/**
|
||||
* Performs thread finalization needed by the query classifier.
|
||||
@ -439,9 +474,12 @@ bool qc_thread_init(void);
|
||||
*
|
||||
* MaxScale calls this function, so plugins should not do that.
|
||||
*
|
||||
* @param kind What kind of finalization should be performed.
|
||||
* Combination of qc_init_kind_t.
|
||||
*
|
||||
* @see qc_thread_init
|
||||
*/
|
||||
void qc_thread_end(void);
|
||||
void qc_thread_end(uint32_t kind);
|
||||
|
||||
/**
|
||||
* Parses the statement in the provided buffer and returns a value specifying
|
||||
@ -454,11 +492,17 @@ void qc_thread_end(void);
|
||||
* already then this function will only return the result of that parsing;
|
||||
* the statement will not be parsed again.
|
||||
*
|
||||
* @param stmt A buffer containing an COM_QUERY or COM_STMT_PREPARE packet.
|
||||
* @param stmt A buffer containing an COM_QUERY or COM_STMT_PREPARE packet.
|
||||
* @param collect A bitmask of @c qc_collect_info_t values. Specifies what information
|
||||
* should be collected.
|
||||
*
|
||||
* Note that this is merely a hint and does not restrict what
|
||||
* information can be queried for. If necessary, the statement
|
||||
* will transparently be reparsed.
|
||||
*
|
||||
* @return To what extent the statement could be parsed.
|
||||
*/
|
||||
qc_parse_result_t qc_parse(GWBUF* stmt);
|
||||
qc_parse_result_t qc_parse(GWBUF* stmt, uint32_t collect);
|
||||
|
||||
/**
|
||||
* Convert a qc_field_usage_t enum to corresponding string.
|
||||
@ -623,6 +667,30 @@ char** qc_get_table_names(GWBUF* stmt, int* size, bool fullnames);
|
||||
*/
|
||||
uint32_t qc_get_type_mask(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Returns the type bitmask of transaction related statements.
|
||||
*
|
||||
* If the statement starts a transaction, ends a transaction or
|
||||
* changes the autocommit state, the returned bitmap will be a
|
||||
* combination of:
|
||||
*
|
||||
* QUERY_TYPE_BEGIN_TRX
|
||||
* QUERY_TYPE_COMMIT
|
||||
* QUERY_TYPE_ROLLBACK
|
||||
* QUERY_TYPE_ENABLE_AUTOCOMMIT
|
||||
* QUERY_TYPE_DISABLE_AUTOCOMMIT
|
||||
* QUERY_TYPE_READ (explicitly read only transaction)
|
||||
* QUERY_TYPE_WRITE (explicitly read write transaction)
|
||||
*
|
||||
* Otherwise the result will be 0.
|
||||
*
|
||||
* @param stmt A COM_QUERY or COM_STMT_PREPARE packet.
|
||||
*
|
||||
* @return The relevant type bits if the statement is transaction
|
||||
* related, otherwise 0.
|
||||
*/
|
||||
uint32_t qc_get_trx_type_mask(GWBUF* stmt);
|
||||
|
||||
/**
|
||||
* Returns whether the statement is a DROP TABLE statement.
|
||||
*
|
||||
|
@ -79,21 +79,123 @@ typedef enum error_action
|
||||
*/
|
||||
typedef struct mxs_router_object
|
||||
{
|
||||
/**
|
||||
* @brief Create a new instance of the router
|
||||
*
|
||||
* This function is called when a new router instance is created. The return
|
||||
* value of this function will be passed as the first parameter to the
|
||||
* other API functions.
|
||||
*
|
||||
* @param service The service where the instance is created
|
||||
* @param options Router options
|
||||
*
|
||||
* @return New router instance on NULL on error
|
||||
*/
|
||||
MXS_ROUTER *(*createInstance)(SERVICE *service, char **options);
|
||||
|
||||
/**
|
||||
* Called to create a new user session within the router
|
||||
*
|
||||
* This function is called when a new router session is created for a client.
|
||||
* The return value of this function will be passed as the second parameter
|
||||
* to the @c routeQuery, @c clientReply, @c closeSession, @c freeSession,
|
||||
* and @c handleError functions.
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param session Client MXS_SESSION object
|
||||
*
|
||||
* @return New router session or NULL on error
|
||||
*/
|
||||
MXS_ROUTER_SESSION *(*newSession)(MXS_ROUTER *instance, MXS_SESSION *session);
|
||||
|
||||
/**
|
||||
* @brief Called when a session is closed
|
||||
*
|
||||
* The router should close all objects (including backend DCBs) but not free any memory.
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param router_session Router session
|
||||
*/
|
||||
void (*closeSession)(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session);
|
||||
|
||||
/**
|
||||
* @brief Called when a session is freed
|
||||
*
|
||||
* The session should free all allocated memory in this function.
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param router_session Router session
|
||||
*/
|
||||
void (*freeSession)(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session);
|
||||
|
||||
/**
|
||||
* @brief Called on each query that requires routing
|
||||
*
|
||||
* TODO: Document how routeQuery should be used
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param router_session Router session
|
||||
* @param queue Request from the client
|
||||
*
|
||||
* @return If successful, the function returns 1. If an error occurs
|
||||
* and the session should be closed, the function returns 0.
|
||||
*/
|
||||
int32_t (*routeQuery)(MXS_ROUTER *instance, MXS_ROUTER_SESSION *router_session, GWBUF *queue);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Called for diagnostic output
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param dcb DCB where the diagnostic information should be written
|
||||
*/
|
||||
void (*diagnostics)(MXS_ROUTER *instance, DCB *dcb);
|
||||
void (*clientReply)(MXS_ROUTER* instance, MXS_ROUTER_SESSION *router_session, GWBUF *queue,
|
||||
DCB *backend_dcb);
|
||||
|
||||
/**
|
||||
* @brief Called for each reply packet
|
||||
*
|
||||
* TODO: Document how clientReply should be used
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param router_session Router session
|
||||
* @param queue Response from the server
|
||||
* @param backend_dcb The backend DCB which responded to the query
|
||||
*/
|
||||
void (*clientReply)(MXS_ROUTER* instance, MXS_ROUTER_SESSION *router_session,
|
||||
GWBUF *queue, DCB *backend_dcb);
|
||||
|
||||
/**
|
||||
* @brief Called when a backend DCB has failed
|
||||
*
|
||||
* @param instance Router instance
|
||||
* @param router_session Router session
|
||||
* @param errmsgbuf Error message buffer
|
||||
* @param backend_dcb The backend DCB that has failed
|
||||
* @param action The type of the action (TODO: Remove this parameter)
|
||||
*
|
||||
* @param succp Pointer to a `bool` which should be set to true for success or false for error
|
||||
*/
|
||||
void (*handleError)(MXS_ROUTER *instance,
|
||||
MXS_ROUTER_SESSION *router_session,
|
||||
GWBUF *errmsgbuf,
|
||||
DCB *backend_dcb,
|
||||
mxs_error_action_t action,
|
||||
bool* succp);
|
||||
|
||||
/**
|
||||
* @brief Called to obtain the capabilities of the router
|
||||
*
|
||||
* @return Zero or more bitwise-or'd values from the mxs_routing_capability_t enum
|
||||
*
|
||||
* @see routing.h
|
||||
*/
|
||||
uint64_t (*getCapabilities)(MXS_ROUTER *instance);
|
||||
|
||||
/**
|
||||
* @brief Called for destroying a router instance
|
||||
*
|
||||
* @param instance Router instance
|
||||
*/
|
||||
void (*destroyInstance)(MXS_ROUTER *instance);
|
||||
} MXS_ROUTER_OBJECT;
|
||||
|
||||
|
@ -254,6 +254,14 @@ void server_add_parameter(SERVER *server, const char *name, const char *value);
|
||||
*/
|
||||
bool server_remove_parameter(SERVER *server, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Check if a server points to a local MaxScale service
|
||||
*
|
||||
* @param server Server to check
|
||||
* @return True if the server points to a local MaxScale service
|
||||
*/
|
||||
bool server_is_mxs_service(const SERVER *server);
|
||||
|
||||
extern int server_free(SERVER *server);
|
||||
extern SERVER *server_find_by_unique_name(const char *name);
|
||||
extern int server_find_by_unique_names(char **server_names, int size, SERVER*** output);
|
||||
|
@ -241,6 +241,14 @@ bool serviceHasBackend(SERVICE *service, SERVER *server);
|
||||
bool serviceHasListener(SERVICE *service, const char *protocol,
|
||||
const char* address, unsigned short port);
|
||||
|
||||
/**
|
||||
* @brief Check if a MaxScale service listens on a port
|
||||
*
|
||||
* @param port The port to check
|
||||
* @return True if a MaxScale service uses the port
|
||||
*/
|
||||
bool service_port_is_used(unsigned short port);
|
||||
|
||||
int serviceGetUser(SERVICE *service, char **user, char **auth);
|
||||
int serviceSetUser(SERVICE *service, char *user, char *auth);
|
||||
bool serviceSetFilters(SERVICE *service, char *filters);
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
#include <maxscale/cdefs.h>
|
||||
#include <stdbool.h>
|
||||
#include <maxscale/debug.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
@ -42,37 +43,73 @@ MXS_BEGIN_DECLS
|
||||
*/
|
||||
typedef struct spinlock
|
||||
{
|
||||
volatile int lock;/*< Is the lock held? */
|
||||
int lock; /*< Is the lock held? */
|
||||
#if SPINLOCK_PROFILE
|
||||
int spins; /*< Number of spins on this lock */
|
||||
int maxspins; /*< Max no of spins to acquire lock */
|
||||
int acquired; /*< No. of times lock was acquired */
|
||||
int waiting; /*< No. of threads acquiring this lock */
|
||||
int max_waiting; /*< Max no of threads waiting for lock */
|
||||
int contended; /*< No. of times acquire was contended */
|
||||
THREAD owner; /*< Last owner of this lock */
|
||||
uint64_t spins; /*< Number of spins on this lock */
|
||||
uint64_t maxspins; /*< Max no of spins to acquire lock */
|
||||
uint64_t acquired; /*< No. of times lock was acquired */
|
||||
uint64_t waiting; /*< No. of threads acquiring this lock */
|
||||
uint64_t max_waiting; /*< Max no of threads waiting for lock */
|
||||
uint64_t contended; /*< No. of times acquire was contended */
|
||||
THREAD owner; /*< Last owner of this lock */
|
||||
#endif
|
||||
} SPINLOCK;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE true
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE false
|
||||
#endif
|
||||
|
||||
#if SPINLOCK_PROFILE
|
||||
#define SPINLOCK_INIT { 0, 0, 0, 0, 0, 0, 0, 0 }
|
||||
#else
|
||||
#define SPINLOCK_INIT { 0 }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Debugging macro for testing the state of a spinlock.
|
||||
*
|
||||
* @attention ONLY to be used in debugging context.
|
||||
*/
|
||||
#define SPINLOCK_IS_LOCKED(l) ((l)->lock != 0 ? true : false)
|
||||
|
||||
/**
|
||||
* Initialise a spinlock.
|
||||
*
|
||||
* @param lock The spinlock to initialise.
|
||||
*/
|
||||
extern void spinlock_init(SPINLOCK *lock);
|
||||
|
||||
/**
|
||||
* Acquire a spinlock.
|
||||
*
|
||||
* @param lock The spinlock to acquire
|
||||
*/
|
||||
extern void spinlock_acquire(const SPINLOCK *lock);
|
||||
extern int spinlock_acquire_nowait(const SPINLOCK *lock);
|
||||
|
||||
/**
|
||||
* Acquire a spinlock if it is not already locked.
|
||||
*
|
||||
* @param lock The spinlock to acquire
|
||||
* @return True if the spinlock was acquired, otherwise false
|
||||
*/
|
||||
extern bool spinlock_acquire_nowait(const SPINLOCK *lock);
|
||||
|
||||
/*
|
||||
* Release a spinlock.
|
||||
*
|
||||
* @param lock The spinlock to release
|
||||
*/
|
||||
extern void spinlock_release(const SPINLOCK *lock);
|
||||
|
||||
/**
|
||||
* Report statistics on a spinlock. This only has an effect if the
|
||||
* spinlock code has been compiled with the SPINLOCK_PROFILE option set.
|
||||
*
|
||||
* NB A callback function is used to return the data rather than
|
||||
* merely printing to a DCB in order to avoid a dependency on the DCB
|
||||
* form the spinlock code and also to facilitate other uses of the
|
||||
* statistics reporting.
|
||||
*
|
||||
* @param lock The spinlock to report on
|
||||
* @param reporter The callback function to pass the statistics to
|
||||
* @param hdl A handle that is passed to the reporter function
|
||||
*/
|
||||
extern void spinlock_stats(const SPINLOCK *lock, void (*reporter)(void *, char *, int), void *hdl);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
Reference in New Issue
Block a user