Merge branch '2.1' into develop

This commit is contained in:
Markus Mäkelä
2017-03-22 15:20:21 +02:00
107 changed files with 3365 additions and 3638 deletions

View File

@ -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);

View File

@ -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

View File

@ -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.
*

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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