Fix in-source builds
The internal header directory conflicted with in-source builds causing a build failure. This is fixed by renaming the internal header directory to something other than maxscale. The renaming pointed out a few problems in a couple of source files that appeared to include internal headers when the headers were in fact public headers. Fixed maxctrl in-source builds by making the copying of the sources optional.
This commit is contained in:
121
server/core/internal/admin.hh
Normal file
121
server/core/internal/admin.hh
Normal file
@ -0,0 +1,121 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
|
||||
#include <string>
|
||||
#include <microhttpd.h>
|
||||
|
||||
#include <maxscale/thread.h>
|
||||
|
||||
class Client
|
||||
{
|
||||
Client(const Client&);
|
||||
Client& operator=(const Client&);
|
||||
|
||||
public:
|
||||
|
||||
enum state
|
||||
{
|
||||
OK,
|
||||
FAILED,
|
||||
INIT,
|
||||
CLOSED
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Create a new client
|
||||
*
|
||||
* @param connection The connection handle for this client
|
||||
*/
|
||||
Client(MHD_Connection *connection):
|
||||
m_connection(connection),
|
||||
m_state(INIT)
|
||||
{
|
||||
}
|
||||
|
||||
~Client()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process a client request
|
||||
*
|
||||
* This function can be called multiple times if a PUT/POST/PATCH
|
||||
* uploads a large amount of data.
|
||||
*
|
||||
* @param url Requested URL
|
||||
* @param method Request method
|
||||
* @param data Pointer to request data
|
||||
* @param size Size of request data
|
||||
*
|
||||
* @return MHD_YES on success, MHD_NO on error
|
||||
*/
|
||||
int process(std::string url, std::string method, const char* data, size_t *size);
|
||||
|
||||
/**
|
||||
* @brief Authenticate the client
|
||||
*
|
||||
* @param connection The MHD connection object
|
||||
* @param url Requested URL
|
||||
* @param method The request method
|
||||
*
|
||||
* @return True if authentication was successful
|
||||
*/
|
||||
bool auth(MHD_Connection* connection, const char* url, const char* method);
|
||||
|
||||
/**
|
||||
* Get client state
|
||||
*
|
||||
* @return The client state
|
||||
*/
|
||||
state get_state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the client connection
|
||||
*
|
||||
* All further requests will be rejected immediately
|
||||
*/
|
||||
void close()
|
||||
{
|
||||
m_state = CLOSED;
|
||||
}
|
||||
|
||||
private:
|
||||
MHD_Connection* m_connection; /**< Connection handle */
|
||||
std::string m_data; /**< Uploaded data */
|
||||
state m_state; /**< Client state */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Start the administrative interface
|
||||
*
|
||||
* @return True if the interface was successfully started
|
||||
*/
|
||||
bool mxs_admin_init();
|
||||
|
||||
/**
|
||||
* @brief Shutdown the administrative interface
|
||||
*/
|
||||
void mxs_admin_shutdown();
|
||||
|
||||
/**
|
||||
* @brief Check if admin interface uses HTTPS protocol
|
||||
*
|
||||
* @return True if HTTPS is enabled
|
||||
*/
|
||||
bool mxs_admin_https_enabled();
|
||||
166
server/core/internal/config.h
Normal file
166
server/core/internal/config.h
Normal file
@ -0,0 +1,166 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/config.h - The private config interface
|
||||
*/
|
||||
|
||||
#include <maxscale/config.h>
|
||||
|
||||
#include <maxscale/ssl.h>
|
||||
#include <maxscale/jansson.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define DEFAULT_NBPOLLS 3 /**< Default number of non block polls before we block */
|
||||
#define DEFAULT_POLLSLEEP 1000 /**< Default poll wait time (milliseconds) */
|
||||
#define DEFAULT_NTHREADS 1 /**< Default number of polling threads */
|
||||
#define DEFAULT_QUERY_RETRIES 0 /**< Number of retries for interrupted queries */
|
||||
#define DEFAULT_QUERY_RETRY_TIMEOUT 5 /**< Timeout for query retries */
|
||||
|
||||
/**
|
||||
* Maximum length for configuration parameter value.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
MAX_PARAM_LEN = 256
|
||||
};
|
||||
|
||||
/** Object type specific parameter name lists */
|
||||
extern const char *config_service_params[];
|
||||
extern const char *config_listener_params[];
|
||||
extern const char *config_monitor_params[];
|
||||
extern const char *config_filter_params[];
|
||||
extern const char *config_server_params[];
|
||||
|
||||
/**
|
||||
* Set the defaults for the global configuration options
|
||||
*/
|
||||
void config_set_global_defaults();
|
||||
|
||||
/**
|
||||
* @brief Generate default module parameters
|
||||
*
|
||||
* Adds any default parameters to @c ctx that aren't already in it.
|
||||
*
|
||||
* @param ctx Configuration context where the parameters are added
|
||||
* @param params Module parameters
|
||||
*/
|
||||
void config_add_defaults(CONFIG_CONTEXT *ctx, const MXS_MODULE_PARAM *params);
|
||||
|
||||
char* config_clean_string_list(const char* str);
|
||||
MXS_CONFIG_PARAMETER* config_clone_param(const MXS_CONFIG_PARAMETER* param);
|
||||
bool config_load(const char *);
|
||||
void config_parameter_free(MXS_CONFIG_PARAMETER* p1);
|
||||
|
||||
/**
|
||||
* @brief Creates an empty configuration context
|
||||
*
|
||||
* @param section Context name
|
||||
* @return New context or NULL on memory allocation failure
|
||||
*/
|
||||
CONFIG_CONTEXT* config_context_create(const char *section);
|
||||
|
||||
/**
|
||||
* @brief Free a configuration context
|
||||
*
|
||||
* @param context The context to free
|
||||
*/
|
||||
void config_context_free(CONFIG_CONTEXT *context);
|
||||
|
||||
/**
|
||||
* @brief Add a parameter to a configuration context
|
||||
*
|
||||
* @param obj Context where the parameter should be added
|
||||
* @param key Key to add
|
||||
* @param value Value for the key
|
||||
* @return True on success, false on memory allocation error
|
||||
*/
|
||||
bool config_add_param(CONFIG_CONTEXT* obj, const char* key, const char* value);
|
||||
|
||||
/**
|
||||
* @brief Append to an existing parameter
|
||||
*
|
||||
* @param obj Configuration context
|
||||
* @param key Parameter name
|
||||
* @param value Value to append to the parameter
|
||||
* @return True on success, false on memory allocation error
|
||||
*/
|
||||
bool config_append_param(CONFIG_CONTEXT* obj, const char* key, const char* value);
|
||||
|
||||
/**
|
||||
* @brief Replace an existing parameter
|
||||
*
|
||||
* @param obj Configuration context
|
||||
* @param key Parameter name
|
||||
* @param value Parameter value
|
||||
* @return True on success, false on memory allocation error
|
||||
*/
|
||||
bool config_replace_param(CONFIG_CONTEXT* obj, const char* key, const char* value);
|
||||
|
||||
/**
|
||||
* @brief Construct an SSL structure
|
||||
*
|
||||
* The SSL structure is used by both listeners and servers.
|
||||
*
|
||||
* TODO: Rename to something like @c config_construct_ssl
|
||||
*
|
||||
* @param obj Configuration context
|
||||
* @param require_cert Whether certificates are required
|
||||
* @param error_count Pointer to an int which is incremented for each error
|
||||
* @return New SSL_LISTENER structure or NULL on error
|
||||
*/
|
||||
SSL_LISTENER *make_ssl_structure(CONFIG_CONTEXT *obj, bool require_cert, int *error_count);
|
||||
|
||||
/**
|
||||
* @brief Check if all SSL parameters are defined
|
||||
*
|
||||
* Helper function to check whether all of the required SSL parameters are defined
|
||||
* in the configuration context. The checked parameters are 'ssl', 'ssl_key',
|
||||
* 'ssl_cert' and 'ssl_ca_cert'. The 'ssl' parameter must also have a value of
|
||||
* 'required'.
|
||||
*
|
||||
* @param obj Configuration context
|
||||
* @return True if all required parameters are present
|
||||
*/
|
||||
bool config_have_required_ssl_params(CONFIG_CONTEXT *obj);
|
||||
|
||||
/**
|
||||
* @brief Add non-standard module type parameters to a JSON object
|
||||
*
|
||||
* @param mod Module whose parameters are inspected
|
||||
* @param parameters List of configuration parameters for the module
|
||||
* @param type_params NULL terminated list of default module type parameters
|
||||
* @param output Output JSON object where the parameters are added
|
||||
*/
|
||||
void config_add_module_params_json(const MXS_MODULE* mod,
|
||||
MXS_CONFIG_PARAMETER* parameters,
|
||||
const char** type_params,
|
||||
json_t* output);
|
||||
|
||||
/**
|
||||
* @brief Convert section names to new format
|
||||
*
|
||||
* @param section Section name to fix
|
||||
*/
|
||||
void fix_section_name(char *section);
|
||||
|
||||
/**
|
||||
* @brief Serialize global options
|
||||
*
|
||||
* @return True if options were serialized successfully
|
||||
*/
|
||||
bool config_global_serialize();
|
||||
|
||||
MXS_END_DECLS
|
||||
337
server/core/internal/config_runtime.h
Normal file
337
server/core/internal/config_runtime.h
Normal file
@ -0,0 +1,337 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file config_runtime.h - Functions for runtime configuration modifications
|
||||
*/
|
||||
|
||||
#include <maxscale/cdefs.h>
|
||||
|
||||
#include <maxscale/adminusers.h>
|
||||
#include <maxscale/monitor.h>
|
||||
#include <maxscale/server.h>
|
||||
#include <maxscale/service.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Create a new server
|
||||
*
|
||||
* This function creates a new, persistent server by first allocating a new
|
||||
* server and then storing the resulting configuration file on disk. This
|
||||
* function should be used only from administrative interface modules and internal
|
||||
* modules should use server_alloc() instead.
|
||||
*
|
||||
* @param name Server name
|
||||
* @param address Network address
|
||||
* @param port Network port
|
||||
* @param protocol Protocol module name
|
||||
* @param authenticator Authenticator module name
|
||||
* @param options Options for the authenticator module
|
||||
* @return True on success, false if an error occurred
|
||||
*/
|
||||
bool runtime_create_server(const char *name, const char *address,
|
||||
const char *port, const char *protocol,
|
||||
const char *authenticator, const char *options);
|
||||
|
||||
/**
|
||||
* @brief Destroy a server
|
||||
*
|
||||
* This removes any created server configuration files and marks the server removed
|
||||
* If the server is not in use.
|
||||
*
|
||||
* @param server Server to destroy
|
||||
* @return True if server was destroyed
|
||||
*/
|
||||
bool runtime_destroy_server(SERVER *server);
|
||||
|
||||
/**
|
||||
* @brief Link a server to an object
|
||||
*
|
||||
* This function links the server to another object. The target can be either
|
||||
* a monitor or a service.
|
||||
*
|
||||
* @param server Server to link
|
||||
* @param target The monitor or service where the server is added
|
||||
* @return True if the object was found and the server was linked to it, false
|
||||
* if no object matching @c target was found
|
||||
*/
|
||||
bool runtime_link_server(SERVER *server, const char *target);
|
||||
|
||||
/**
|
||||
* @brief Unlink a server from an object
|
||||
*
|
||||
* This function unlinks the server from another object. The target can be either
|
||||
* a monitor or a service.
|
||||
*
|
||||
* @param server Server to unlink
|
||||
* @param target The monitor or service from which the server is removed
|
||||
* @return True if the object was found and the server was unlinked from it, false
|
||||
* if no object matching @c target was found
|
||||
*/
|
||||
bool runtime_unlink_server(SERVER *server, const char *target);
|
||||
|
||||
/**
|
||||
* @brief Alter server parameters
|
||||
*
|
||||
* @param server Server to alter
|
||||
* @param key Key to modify
|
||||
* @param value New value
|
||||
* @return True if @c key was one of the supported parameters
|
||||
*/
|
||||
bool runtime_alter_server(SERVER *server, const char *key, const char *value);
|
||||
|
||||
/**
|
||||
* @brief Enable SSL for a server
|
||||
*
|
||||
* The @c key , @c cert and @c ca parameters are required. @c version and @c depth
|
||||
* are optional.
|
||||
*
|
||||
* @note SSL cannot be disabled at runtime.
|
||||
*
|
||||
* @param server Server to configure
|
||||
* @param key Path to SSL private key
|
||||
* @param cert Path to SSL public certificate
|
||||
* @param ca Path to certificate authority
|
||||
* @param version Required SSL Version
|
||||
* @param depth Certificate verification depth
|
||||
* @return True if SSL was successfully enabled
|
||||
*/
|
||||
bool runtime_enable_server_ssl(SERVER *server, const char *key, const char *cert,
|
||||
const char *ca, const char *version, const char *depth);
|
||||
|
||||
/**
|
||||
* @brief Alter monitor parameters
|
||||
*
|
||||
* @param monitor Monitor to alter
|
||||
* @param key Key to modify
|
||||
* @param value New value
|
||||
* @return True if @c key was one of the supported parameters
|
||||
*/
|
||||
bool runtime_alter_monitor(MXS_MONITOR *monitor, const char *key, const char *value);
|
||||
|
||||
/**
|
||||
* @brief Alter service parameters
|
||||
*
|
||||
* @param monitor Service to alter
|
||||
* @param key Key to modify
|
||||
* @param value New value
|
||||
*
|
||||
* @return True if @c key was one of the supported parameters
|
||||
*/
|
||||
bool runtime_alter_service(SERVICE *service, const char* zKey, const char* zValue);
|
||||
|
||||
/**
|
||||
* @brief Alter MaxScale parameters
|
||||
*
|
||||
* @param name Key to modify
|
||||
* @param value New value
|
||||
*
|
||||
* @return True if @c key was one of the supported parameters
|
||||
*/
|
||||
bool runtime_alter_maxscale(const char* name, const char* value);
|
||||
|
||||
/**
|
||||
* @brief Create a new listener for a service
|
||||
*
|
||||
* This function adds a new listener to a service and starts it.
|
||||
*
|
||||
* @param service Service where the listener is added
|
||||
* @param name Name of the listener
|
||||
* @param addr Listening address, NULL for default of ::
|
||||
* @param port Listening port, NULL for default of 3306
|
||||
* @param proto Listener protocol, NULL for default of "MySQLClient"
|
||||
* @param auth Listener authenticator, NULL for protocol default authenticator
|
||||
* @param auth_opt Options for the authenticator, NULL for no options
|
||||
* @param ssl_key SSL key, NULL for no key
|
||||
* @param ssl_cert SSL cert, NULL for no cert
|
||||
* @param ssl_ca SSL CA cert, NULL for no CA cert
|
||||
* @param ssl_version SSL version, NULL for default of "MAX"
|
||||
* @param ssl_depth SSL cert verification depth, NULL for default
|
||||
*
|
||||
* @return True if the listener was successfully created and started
|
||||
*/
|
||||
bool runtime_create_listener(SERVICE *service, const char *name, const char *addr,
|
||||
const char *port, const char *proto, const char *auth,
|
||||
const char *auth_opt, const char *ssl_key,
|
||||
const char *ssl_cert, const char *ssl_ca,
|
||||
const char *ssl_version, const char *ssl_depth);
|
||||
|
||||
/**
|
||||
* @brief Destroy a listener
|
||||
*
|
||||
* This disables the listener by removing it from the polling system. It also
|
||||
* removes any generated configurations for this listener.
|
||||
*
|
||||
* @param service Service where the listener exists
|
||||
* @param name Name of the listener
|
||||
*
|
||||
* @return True if the listener was successfully destroyed
|
||||
*/
|
||||
bool runtime_destroy_listener(SERVICE *service, const char *name);
|
||||
|
||||
/**
|
||||
* @brief Create a new monitor
|
||||
*
|
||||
* @param name Name of the monitor
|
||||
* @param module Monitor module
|
||||
* @return True if new monitor was created and persisted
|
||||
*/
|
||||
bool runtime_create_monitor(const char *name, const char *module);
|
||||
|
||||
/**
|
||||
* @brief Destroy a monitor
|
||||
*
|
||||
* Monitors are not removed from the runtime configuration but they are stopped.
|
||||
* Destroyed monitor are removed after a restart.
|
||||
*
|
||||
* @param monitor Monitor to destroy
|
||||
* @return True if monitor was destroyed
|
||||
*/
|
||||
bool runtime_destroy_monitor(MXS_MONITOR *monitor);
|
||||
|
||||
/**
|
||||
* @brief Create a new server from JSON
|
||||
*
|
||||
* @param json JSON defining the server
|
||||
*
|
||||
* @return Created server or NULL on error
|
||||
*/
|
||||
SERVER* runtime_create_server_from_json(json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Alter a server using JSON
|
||||
*
|
||||
* @param server Server to alter
|
||||
* @param new_json JSON definition of the updated server
|
||||
*
|
||||
* @return True if the server was successfully modified to represent @c new_json
|
||||
*/
|
||||
bool runtime_alter_server_from_json(SERVER* server, json_t* new_json);
|
||||
|
||||
/**
|
||||
* @brief Alter server relationships
|
||||
*
|
||||
* @param server Server to alter
|
||||
* @param type Type of the relation, either @c services or @c monitors
|
||||
* @param json JSON that defines the relationship data
|
||||
*
|
||||
* @return True if the relationships were successfully modified
|
||||
*/
|
||||
bool runtime_alter_server_relationships_from_json(SERVER* server, const char* type, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Create a new monitor from JSON
|
||||
*
|
||||
* @param json JSON defining the monitor
|
||||
*
|
||||
* @return Created monitor or NULL on error
|
||||
*/
|
||||
MXS_MONITOR* runtime_create_monitor_from_json(json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Alter a monitor using JSON
|
||||
*
|
||||
* @param monitor Monitor to alter
|
||||
* @param new_json JSON definition of the updated monitor
|
||||
*
|
||||
* @return True if the monitor was successfully modified to represent @c new_json
|
||||
*/
|
||||
bool runtime_alter_monitor_from_json(MXS_MONITOR* monitor, json_t* new_json);
|
||||
|
||||
/**
|
||||
* @brief Alter monitor relationships
|
||||
*
|
||||
* @param monitor Monitor to alter
|
||||
* @param json JSON that defines the new relationships
|
||||
*
|
||||
* @return True if the relationships were successfully modified
|
||||
*/
|
||||
bool runtime_alter_monitor_relationships_from_json(MXS_MONITOR* monitor, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Alter a service using JSON
|
||||
*
|
||||
* @param service Service to alter
|
||||
* @param new_json JSON definition of the updated service
|
||||
*
|
||||
* @return True if the service was successfully modified to represent @c new_json
|
||||
*/
|
||||
bool runtime_alter_service_from_json(SERVICE* service, json_t* new_json);
|
||||
|
||||
/**
|
||||
* @brief Alter service relationships
|
||||
*
|
||||
* @param service Service to alter
|
||||
* @param json JSON that defines the new relationships
|
||||
*
|
||||
* @return True if the relationships were successfully modified
|
||||
*/
|
||||
bool runtime_alter_service_relationships_from_json(SERVICE* service, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Create a listener from JSON
|
||||
*
|
||||
* @param service Service where the listener is created
|
||||
* @param json JSON definition of the new listener
|
||||
*
|
||||
* @return True if the listener was successfully created and started
|
||||
*/
|
||||
bool runtime_create_listener_from_json(SERVICE* service, json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Alter logging options using JSON
|
||||
*
|
||||
* @param json JSON definition of the updated logging options
|
||||
*
|
||||
* @return True if the modifications were successful
|
||||
*/
|
||||
bool runtime_alter_logs_from_json(json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Get current runtime error in JSON format
|
||||
*
|
||||
* @return The latest runtime error in JSON format or NULL if no error has occurred
|
||||
*/
|
||||
json_t* runtime_get_json_error();
|
||||
|
||||
/**
|
||||
* @brief Create a new user account
|
||||
*
|
||||
* @param json JSON defining the user
|
||||
*
|
||||
* @return True if the user was successfully created
|
||||
*/
|
||||
bool runtime_create_user_from_json(json_t* json);
|
||||
|
||||
/**
|
||||
* @brief Remove admin user
|
||||
*
|
||||
* @param id Username of the network user
|
||||
* @param type USER_TYPE_INET for network user and USER_TYPE_UNIX for enabled accounts
|
||||
*
|
||||
* @return True if user was successfully removed
|
||||
*/
|
||||
bool runtime_remove_user(const char* id, enum user_type type);
|
||||
|
||||
/**
|
||||
* @brief Alter core MaxScale parameters from JSON
|
||||
*
|
||||
* @param new_json JSON defining the new core parameters
|
||||
*
|
||||
* @return True if the core parameters are valid and were successfully applied
|
||||
*/
|
||||
bool runtime_alter_maxscale_from_json(json_t* new_json);
|
||||
|
||||
MXS_END_DECLS
|
||||
22
server/core/internal/dcb.h
Normal file
22
server/core/internal/dcb.h
Normal file
@ -0,0 +1,22 @@
|
||||
#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 <maxscale/dcb.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
void dcb_free_all_memory(DCB *dcb);
|
||||
void dcb_final_close(DCB *dcb);
|
||||
|
||||
MXS_END_DECLS
|
||||
99
server/core/internal/externcmd.h
Normal file
99
server/core/internal/externcmd.h
Normal file
@ -0,0 +1,99 @@
|
||||
#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 <maxscale/cdefs.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define MAXSCALE_EXTCMD_ARG_MAX 256
|
||||
|
||||
typedef struct extern_cmd_t
|
||||
{
|
||||
char** argv; /**< Argument vector for the command, first being the
|
||||
* actual command being executed */
|
||||
int n_exec; /**< Number of times executed */
|
||||
pid_t child; /**< PID of the child process */
|
||||
uint32_t timeout; /**< Command timeout in seconds */
|
||||
} EXTERNCMD;
|
||||
|
||||
char* externcmd_extract_command(const char* argstr);
|
||||
|
||||
/**
|
||||
* Allocate a new external command.
|
||||
*
|
||||
* The name and parameters are copied into the external command structure so
|
||||
* the original memory can be freed if needed.
|
||||
*
|
||||
* @param command Command to execute with the parameters
|
||||
* @param timeout Command timeout in seconds
|
||||
*
|
||||
* @return Pointer to new external command struct or NULL if an error occurred
|
||||
*/
|
||||
EXTERNCMD* externcmd_allocate(const char* argstr, uint32_t timeout);
|
||||
|
||||
|
||||
/**
|
||||
* Free a previously allocated external command
|
||||
*
|
||||
* @param cmd Command to free
|
||||
*/
|
||||
void externcmd_free(EXTERNCMD* cmd);
|
||||
|
||||
/**
|
||||
* Execute a command
|
||||
*
|
||||
* The output of the command must be freed by the caller by calling MXS_FREE.
|
||||
*
|
||||
* @param cmd Command to execute
|
||||
*
|
||||
* @return The return value of the executed command or -1 on error
|
||||
*/
|
||||
int externcmd_execute(EXTERNCMD* cmd);
|
||||
|
||||
/**
|
||||
* Substitute all occurrences of @c match with @c replace in the arguments for @c cmd
|
||||
*
|
||||
* @param cmd External command
|
||||
* @param match Match string
|
||||
* @param replace Replacement string
|
||||
*
|
||||
* @return True if replacement was successful, false on error
|
||||
*/
|
||||
bool externcmd_substitute_arg(EXTERNCMD* cmd, const char* re, const char* replace);
|
||||
|
||||
/**
|
||||
* Check if a command can be executed
|
||||
*
|
||||
* Checks if the file being executed exists and if the current user has execution
|
||||
* permissions on the file.
|
||||
*
|
||||
* @param argstr Command to check, can contain arguments for the command
|
||||
*
|
||||
* @return True if the file was found and the use has execution permissions to it
|
||||
*/
|
||||
bool externcmd_can_execute(const char* argstr);
|
||||
|
||||
/**
|
||||
* Simple matching of string and command
|
||||
*
|
||||
* @param cmd Command where the match is searched from
|
||||
* @param match String to search for
|
||||
*
|
||||
* @return True if the string matched
|
||||
*/
|
||||
bool externcmd_matches(const EXTERNCMD* cmd, const char* match);
|
||||
|
||||
MXS_END_DECLS
|
||||
51
server/core/internal/filter.h
Normal file
51
server/core/internal/filter.h
Normal file
@ -0,0 +1,51 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/filter.h - The private filter interface
|
||||
*/
|
||||
|
||||
#include <maxscale/filter.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* The definition of a filter from the configuration file.
|
||||
* This is basically the link between a plugin to load and the
|
||||
* options to pass to that plugin.
|
||||
*/
|
||||
struct mxs_filter_def
|
||||
{
|
||||
char *name; /**< The Filter name */
|
||||
char *module; /**< The module to load */
|
||||
char **options; /**< The options set for this filter */
|
||||
MXS_CONFIG_PARAMETER *parameters; /**< The filter parameters */
|
||||
MXS_FILTER* filter; /**< The runtime filter */
|
||||
MXS_FILTER_OBJECT *obj; /**< The "MODULE_OBJECT" for the filter */
|
||||
SPINLOCK spin; /**< Spinlock to protect the filter definition */
|
||||
struct mxs_filter_def *next; /**< Next filter in the chain of all filters */
|
||||
};
|
||||
|
||||
void filter_add_option(MXS_FILTER_DEF *filter_def, const char *option);
|
||||
void filter_add_parameter(MXS_FILTER_DEF *filter_def, const char *name, const char *value);
|
||||
MXS_FILTER_DEF *filter_alloc(const char *name, const char *module_name);
|
||||
MXS_DOWNSTREAM *filter_apply(MXS_FILTER_DEF *filter_def, MXS_SESSION *session, MXS_DOWNSTREAM *downstream);
|
||||
void filter_free(MXS_FILTER_DEF *filter_def);
|
||||
bool filter_load(MXS_FILTER_DEF *filter_def);
|
||||
int filter_standard_parameter(const char *name);
|
||||
MXS_UPSTREAM *filter_upstream(MXS_FILTER_DEF *filter_def,
|
||||
MXS_FILTER_SESSION *fsession,
|
||||
MXS_UPSTREAM *upstream);
|
||||
|
||||
MXS_END_DECLS
|
||||
296
server/core/internal/httprequest.hh
Normal file
296
server/core/internal/httprequest.hh
Normal file
@ -0,0 +1,296 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tr1/memory>
|
||||
#include <cstdint>
|
||||
#include <microhttpd.h>
|
||||
|
||||
#include <maxscale/jansson.hh>
|
||||
#include <maxscale/utils.hh>
|
||||
#include <maxscale/http.hh>
|
||||
|
||||
// The API version part of the URL
|
||||
#define MXS_REST_API_VERSION "v1"
|
||||
|
||||
static int value_iterator(void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
std::pair<std::string, std::string>* cmp = (std::pair<std::string, std::string>*)cls;
|
||||
|
||||
if (strcasecmp(cmp->first.c_str(), key) == 0 && value)
|
||||
{
|
||||
cmp->second = value;
|
||||
return MHD_NO;
|
||||
}
|
||||
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
static int value_sum_iterator(void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
size_t& count = *(size_t*)cls;
|
||||
count++;
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
static int value_copy_iterator(void *cls,
|
||||
enum MHD_ValueKind kind,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
std::string k = key;
|
||||
if (value)
|
||||
{
|
||||
k += "=";
|
||||
k += value;
|
||||
}
|
||||
|
||||
char**& dest = *(char***) cls;
|
||||
*dest = MXS_STRDUP_A(k.c_str());
|
||||
dest++;
|
||||
|
||||
return MHD_YES;
|
||||
}
|
||||
|
||||
class HttpRequest
|
||||
{
|
||||
HttpRequest(const HttpRequest&);
|
||||
HttpRequest& operator = (const HttpRequest);
|
||||
public:
|
||||
/**
|
||||
* @brief Parse a request
|
||||
*
|
||||
* @param request Request to parse
|
||||
*
|
||||
* @return Parsed statement or NULL if request is not valid
|
||||
*/
|
||||
HttpRequest(struct MHD_Connection *connection, std::string url, std::string method, json_t* data);
|
||||
|
||||
~HttpRequest();
|
||||
|
||||
/**
|
||||
* @brief Return request verb type
|
||||
*
|
||||
* @return One of the HTTP verb values
|
||||
*/
|
||||
const std::string& get_verb() const
|
||||
{
|
||||
return m_verb;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get header value
|
||||
*
|
||||
* @param header Header to get
|
||||
*
|
||||
* @return Header value or empty string if the header was not found
|
||||
*/
|
||||
std::string get_header(const std::string& header) const
|
||||
{
|
||||
std::pair<std::string, std::string> p;
|
||||
p.first = header;
|
||||
|
||||
MHD_get_connection_values(m_connection, MHD_HEADER_KIND,
|
||||
value_iterator, &p);
|
||||
|
||||
return p.second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get option value
|
||||
*
|
||||
* @param header Option to get
|
||||
*
|
||||
* @return Option value or empty string if the option was not found
|
||||
*/
|
||||
std::string get_option(const std::string& option) const
|
||||
{
|
||||
std::pair<std::string, std::string> p;
|
||||
p.first = option;
|
||||
|
||||
MHD_get_connection_values(m_connection, MHD_GET_ARGUMENT_KIND,
|
||||
value_iterator, &p);
|
||||
|
||||
return p.second;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get request option count
|
||||
*
|
||||
* @return Number of options in the request
|
||||
*/
|
||||
size_t get_option_count() const
|
||||
{
|
||||
size_t rval = 0;
|
||||
MHD_get_connection_values(m_connection, MHD_GET_ARGUMENT_KIND,
|
||||
value_sum_iterator, &rval);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy options to an array
|
||||
*
|
||||
* The @c dest parameter must be able to hold at least get_option_count()
|
||||
* pointers. The values stored need to be freed by the caller.
|
||||
*
|
||||
* @param dest Destination where options are copied
|
||||
*/
|
||||
void copy_options(char** dest) const
|
||||
{
|
||||
MHD_get_connection_values(m_connection, MHD_GET_ARGUMENT_KIND,
|
||||
value_copy_iterator, &dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return request body
|
||||
*
|
||||
* @return Request body or empty string if no body is defined
|
||||
*/
|
||||
const std::string& get_json_str() const
|
||||
{
|
||||
return m_json_string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return raw JSON body
|
||||
*
|
||||
* @return Raw JSON body or NULL if no body is defined
|
||||
*/
|
||||
json_t* get_json() const
|
||||
{
|
||||
return m_json.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get complete request URI
|
||||
*
|
||||
* @return The complete request URI
|
||||
*/
|
||||
std::string get_uri() const
|
||||
{
|
||||
return m_resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get URI part
|
||||
*
|
||||
* @param idx Zero indexed part number in URI
|
||||
*
|
||||
* @return The request URI part or empty string if no part was found
|
||||
*/
|
||||
std::string uri_part(uint32_t idx) const
|
||||
{
|
||||
return m_resource_parts.size() > idx ? m_resource_parts[idx] : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a segment of the URI
|
||||
*
|
||||
* Combines a range of parts into a segment of the URI. Each part is
|
||||
* separated by a forward slash.
|
||||
*
|
||||
* @param start Start of range
|
||||
* @param end End of range, not inclusive
|
||||
*
|
||||
* @return The URI segment that matches this range
|
||||
*/
|
||||
std::string uri_segment(uint32_t start, uint32_t end) const
|
||||
{
|
||||
std::string rval;
|
||||
|
||||
for (uint32_t i = start; i < end && i < m_resource_parts.size(); i++)
|
||||
{
|
||||
if (i > start)
|
||||
{
|
||||
rval += "/";
|
||||
}
|
||||
|
||||
rval += m_resource_parts[i];
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return how many parts are in the URI
|
||||
*
|
||||
* @return Number of URI parts
|
||||
*/
|
||||
size_t uri_part_count() const
|
||||
{
|
||||
return m_resource_parts.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the last part of the URI
|
||||
*
|
||||
* @return The last URI part
|
||||
*/
|
||||
std::string last_uri_part() const
|
||||
{
|
||||
return m_resource_parts.size() > 0 ? m_resource_parts[m_resource_parts.size() - 1] : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the value of the Host header
|
||||
*
|
||||
* @return The value of the Host header
|
||||
*/
|
||||
const char* host() const
|
||||
{
|
||||
return m_hostname.c_str();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert request to string format
|
||||
*
|
||||
* The returned string should be logically equivalent to the original request.
|
||||
*
|
||||
* @return The request in string format
|
||||
*/
|
||||
std::string to_string() const;
|
||||
|
||||
/**
|
||||
* @brief Drop the API version prefix
|
||||
*
|
||||
* @return True if prefix is present and was successfully removed
|
||||
*/
|
||||
bool validate_api_version();
|
||||
|
||||
private:
|
||||
|
||||
/** Constants */
|
||||
static const std::string HTTP_PREFIX;
|
||||
static const std::string HTTPS_PREFIX;
|
||||
|
||||
std::map<std::string, std::string> m_options; /**< Request options */
|
||||
mxs::Closer<json_t*> m_json; /**< Request body */
|
||||
std::string m_json_string; /**< String version of @c m_json */
|
||||
std::string m_resource; /**< Requested resource */
|
||||
std::deque<std::string> m_resource_parts; /**< @c m_resource split into parts */
|
||||
std::string m_verb; /**< Request method */
|
||||
std::string m_hostname; /**< The value of the Host header */
|
||||
struct MHD_Connection* m_connection;
|
||||
};
|
||||
91
server/core/internal/httpresponse.hh
Normal file
91
server/core/internal/httpresponse.hh
Normal file
@ -0,0 +1,91 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <tr1/memory>
|
||||
#include <microhttpd.h>
|
||||
|
||||
#include <maxscale/jansson.hh>
|
||||
#include <maxscale/http.hh>
|
||||
|
||||
/**
|
||||
* A list of default headers that are generated with each response
|
||||
*/
|
||||
#define HTTP_RESPONSE_HEADER_DATE "Date"
|
||||
#define HTTP_RESPONSE_HEADER_LAST_MODIFIED "Last-Modified"
|
||||
#define HTTP_RESPONSE_HEADER_ETAG "ETag"
|
||||
#define HTTP_RESPONSE_HEADER_ACCEPT "Accept"
|
||||
#define HTTP_RESPONSE_HEADER_CONTENT_TYPE "Content-Type"
|
||||
|
||||
typedef std::map<std::string, std::string> Headers;
|
||||
|
||||
class HttpResponse
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Create new HTTP response
|
||||
*
|
||||
* @param response Response body
|
||||
* @param code HTTP return code
|
||||
*/
|
||||
HttpResponse(int code = MHD_HTTP_OK, json_t* response = NULL);
|
||||
HttpResponse(const HttpResponse& response);
|
||||
HttpResponse& operator = (const HttpResponse& response);
|
||||
|
||||
~HttpResponse();
|
||||
|
||||
/**
|
||||
* @brief Get the response body
|
||||
*
|
||||
* @return The response body
|
||||
*/
|
||||
json_t* get_response() const;
|
||||
|
||||
/**
|
||||
* @brief Drop response body
|
||||
*
|
||||
* This discards the message body.
|
||||
*/
|
||||
void drop_response();
|
||||
|
||||
/**
|
||||
* @brief Get the HTTP response code
|
||||
*
|
||||
* @return The HTTP response code
|
||||
*/
|
||||
int get_code() const;
|
||||
|
||||
/**
|
||||
* @brief Add an extra header to this response
|
||||
*
|
||||
* @param key Header name
|
||||
* @param value Header value
|
||||
*/
|
||||
void add_header(const std::string& key, const std::string& value);
|
||||
|
||||
/**
|
||||
* @brief Get request headers
|
||||
*
|
||||
* @return Headers of this request
|
||||
*/
|
||||
const Headers& get_headers() const;
|
||||
|
||||
private:
|
||||
json_t* m_body; /**< Message body */
|
||||
int m_code; /**< The HTTP code for the response */
|
||||
Headers m_headers; /**< Extra headers */
|
||||
};
|
||||
38
server/core/internal/maxscale.h
Normal file
38
server/core/internal/maxscale.h
Normal file
@ -0,0 +1,38 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/maxscale.h - The private maxscale general definitions
|
||||
*/
|
||||
|
||||
#include <maxscale/maxscale.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* Initiate shutdown of MaxScale.
|
||||
*
|
||||
* This functions informs all threads that they should stop the
|
||||
* processing and exit.
|
||||
*
|
||||
* @return How many times maxscale_shutdown() has been called.
|
||||
*/
|
||||
int maxscale_shutdown(void);
|
||||
|
||||
/**
|
||||
* Reset the start time from which the uptime is calculated.
|
||||
*/
|
||||
void maxscale_reset_starttime(void);
|
||||
|
||||
MXS_END_DECLS
|
||||
207
server/core/internal/messagequeue.hh
Normal file
207
server/core/internal/messagequeue.hh
Normal file
@ -0,0 +1,207 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
#include <maxscale/poll_core.hh>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
class MessageQueue;
|
||||
class Worker;
|
||||
|
||||
/**
|
||||
* An instance of @c MessageQueueMessage can be sent over a @c MessageQueue from
|
||||
* one context to another. The instance will be copied verbatim without any
|
||||
* interpretation, so if the same message is sent to multiple recipients it is
|
||||
* the caller's and recipient's responsibility to manage the lifetime and
|
||||
* concurrent access of anything possibly pointed to from the message.
|
||||
*/
|
||||
class MessageQueueMessage /* final */
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param id The id of the message. The meaning is an affair between the sender
|
||||
* and the recipient.
|
||||
* @param arg1 First argument.
|
||||
* @param arg2 Second argument.
|
||||
*/
|
||||
explicit MessageQueueMessage(uint64_t id = 0, intptr_t arg1 = 0, intptr_t arg2 = 0)
|
||||
: m_id(id)
|
||||
, m_arg1(arg1)
|
||||
, m_arg2(arg2)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
intptr_t arg1() const
|
||||
{
|
||||
return m_arg1;
|
||||
}
|
||||
|
||||
intptr_t arg2() const
|
||||
{
|
||||
return m_arg2;
|
||||
}
|
||||
|
||||
MessageQueueMessage& set_id(uint64_t id)
|
||||
{
|
||||
m_id = id;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageQueueMessage& set_arg1(intptr_t arg1)
|
||||
{
|
||||
m_arg1 = arg1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
MessageQueueMessage& set_arg2(intptr_t arg2)
|
||||
{
|
||||
m_arg2 = arg2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t m_id;
|
||||
intptr_t m_arg1;
|
||||
intptr_t m_arg2;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A @c MessageQueueHandler will be delivered messages received over a
|
||||
* @c MessageQueue.
|
||||
*/
|
||||
class MessageQueueHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Message delivery.
|
||||
*
|
||||
* @param queue The queue over which the message was received.
|
||||
* @param message The message.
|
||||
*/
|
||||
virtual void handle_message(MessageQueue& queue, const MessageQueueMessage& message) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The class @c MessageQueue provides a cross thread message queue implemented
|
||||
* on top of a pipe.
|
||||
*/
|
||||
class MessageQueue : private MxsPollData
|
||||
{
|
||||
MessageQueue(const MessageQueue&);
|
||||
MessageQueue& operator = (const MessageQueue&);
|
||||
|
||||
public:
|
||||
typedef MessageQueueHandler Handler;
|
||||
typedef MessageQueueMessage Message;
|
||||
|
||||
/**
|
||||
* Initializes the message queue mechanism. To be called once at
|
||||
* process startup.
|
||||
*
|
||||
* @return True if the initialization succeeded, false otherwise.
|
||||
*/
|
||||
static bool init();
|
||||
|
||||
|
||||
/**
|
||||
* Finalizes the message queue mechanism. To be called once at
|
||||
* process shutdown, if the initialization succeeded.
|
||||
*/
|
||||
static void finish();
|
||||
|
||||
/**
|
||||
* Creates a @c MessageQueue with the provided handler.
|
||||
*
|
||||
* @param pHandler The handler that will receive the messages sent over the
|
||||
* message queue. Note that the handler *must* remain valid
|
||||
* for the lifetime of the @c MessageQueue.
|
||||
*
|
||||
* @return A pointer to a new @c MessageQueue or NULL if an error occurred.
|
||||
*
|
||||
* @attention Before the message queue can be used, it must be added to
|
||||
* a worker.
|
||||
*/
|
||||
static MessageQueue* create(Handler* pHandler);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*
|
||||
* Removes itself If still added to a worker and closes the pipe.
|
||||
*/
|
||||
~MessageQueue();
|
||||
|
||||
/**
|
||||
* Posts a message over the queue to the handler provided when the
|
||||
* @c MessageQueue was created.
|
||||
*
|
||||
* @param message The message to be posted. A bitwise copy of the message
|
||||
* will be delivered to the handler, after an unspecified time.
|
||||
*
|
||||
* @return True if the message could be posted, false otherwise. Note that
|
||||
* a return value of true only means that the message could successfully
|
||||
* be posted, not that it has reached the handler.
|
||||
*
|
||||
* @attention Note that the message queue must have been added to a worker
|
||||
* before a message can be posted.
|
||||
*/
|
||||
bool post(const Message& message) const;
|
||||
|
||||
/**
|
||||
* Adds the message queue to a particular worker.
|
||||
*
|
||||
* @param pWorker The worker the message queue should be added to.
|
||||
* Must remain valid until the message queue is removed
|
||||
* from it.
|
||||
*
|
||||
* @return True if the message queue could be added, otherwise false.
|
||||
*
|
||||
* @attention If the message queue is currently added to a worker, it
|
||||
* will first be removed from that worker.
|
||||
*/
|
||||
bool add_to_worker(Worker* pWorker);
|
||||
|
||||
/**
|
||||
* Removes the message queue from the worker it is currently added to.
|
||||
*
|
||||
* @return The worker the message queue was associated with, or NULL
|
||||
* if it was not associated with any.
|
||||
*/
|
||||
Worker* remove_from_worker();
|
||||
|
||||
private:
|
||||
MessageQueue(Handler* pHandler, int read_fd, int write_fd);
|
||||
|
||||
uint32_t handle_poll_events(int thread_id, uint32_t events);
|
||||
|
||||
static uint32_t poll_handler(MXS_POLL_DATA* pData, int thread_id, uint32_t events);
|
||||
|
||||
private:
|
||||
Handler& m_handler;
|
||||
int m_read_fd;
|
||||
int m_write_fd;
|
||||
Worker* m_pWorker;
|
||||
};
|
||||
|
||||
}
|
||||
81
server/core/internal/mlist.h
Normal file
81
server/core/internal/mlist.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
#ifndef _MAXSCALE_MLIST_H
|
||||
#define _MAXSCALE_MLIST_H
|
||||
/*
|
||||
* 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 <maxscale/cdefs.h>
|
||||
#include "skygw_utils.h"
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
typedef struct mlist_node_st mlist_node_t;
|
||||
|
||||
typedef struct mlist_st
|
||||
{
|
||||
skygw_chk_t mlist_chk_top;
|
||||
char* mlist_name;
|
||||
void (*mlist_datadel)(void *); /**< clean-up function for data */
|
||||
simple_mutex_t mlist_mutex; /**< protect node updates and clean-up */
|
||||
bool mlist_uselock;
|
||||
bool mlist_islocked;
|
||||
bool mlist_deleted;
|
||||
size_t mlist_nodecount;
|
||||
size_t mlist_nodecount_max; /**< size limit. 0 == no limit */
|
||||
size_t mlist_versno;
|
||||
bool mlist_flat;
|
||||
mlist_node_t* mlist_first;
|
||||
mlist_node_t* mlist_last;
|
||||
skygw_chk_t mlist_chk_tail;
|
||||
} mlist_t;
|
||||
|
||||
typedef struct mlist_cursor_st
|
||||
{
|
||||
skygw_chk_t mlcursor_chk_top;
|
||||
mlist_t* mlcursor_list;
|
||||
mlist_node_t* mlcursor_pos;
|
||||
pthread_t* mlcursor_owner_thr;
|
||||
skygw_chk_t mlcursor_chk_tail;
|
||||
} mlist_cursor_t;
|
||||
|
||||
struct mlist_node_st
|
||||
{
|
||||
skygw_chk_t mlnode_chk_top;
|
||||
mlist_t* mlnode_list;
|
||||
mlist_node_t* mlnode_next;
|
||||
void* mlnode_data;
|
||||
bool mlnode_deleted;
|
||||
skygw_chk_t mlnode_chk_tail;
|
||||
};
|
||||
|
||||
|
||||
mlist_t* mlist_init(mlist_t* mlist,
|
||||
mlist_cursor_t** cursor,
|
||||
char* name,
|
||||
void (*datadel)(void*),
|
||||
int maxnodes);
|
||||
void mlist_done(mlist_t* list);
|
||||
bool mlist_add_data_nomutex(mlist_t* list, void* data);
|
||||
bool mlist_add_node_nomutex(mlist_t* list, mlist_node_t* newnode);
|
||||
mlist_node_t* mlist_detach_first(mlist_t* ml);
|
||||
mlist_node_t* mlist_detach_nodes(mlist_t* ml);
|
||||
void* mlist_node_get_data(mlist_node_t* node);
|
||||
void mlist_node_done(mlist_node_t* n);
|
||||
|
||||
mlist_cursor_t* mlist_cursor_init(mlist_t* ml);
|
||||
void* mlist_cursor_get_data_nomutex(mlist_cursor_t* c);
|
||||
bool mlist_cursor_move_to_first(mlist_cursor_t* c);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
||||
#endif
|
||||
154
server/core/internal/modules.h
Normal file
154
server/core/internal/modules.h
Normal file
@ -0,0 +1,154 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file modules.h Utilities for loading modules
|
||||
*/
|
||||
|
||||
#include <maxscale/cdefs.h>
|
||||
#include <maxscale/dcb.h>
|
||||
#include <maxscale/modinfo.h>
|
||||
#include <maxscale/resultset.h>
|
||||
#include <maxscale/debug.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* Module types
|
||||
*/
|
||||
#define MODULE_PROTOCOL "Protocol" /**< A protocol module type */
|
||||
#define MODULE_AUTHENTICATOR "Authenticator" /**< An authenticator module type */
|
||||
#define MODULE_ROUTER "Router" /**< A router module type */
|
||||
#define MODULE_MONITOR "Monitor" /**< A database monitor module type */
|
||||
#define MODULE_FILTER "Filter" /**< A filter module type */
|
||||
#define MODULE_QUERY_CLASSIFIER "QueryClassifier" /**< A query classifier module type */
|
||||
|
||||
|
||||
/**
|
||||
*@brief Load a module
|
||||
*
|
||||
* @param module Name of the module to load
|
||||
* @param type Type of module, used purely for registration
|
||||
* @return The module specific entry point structure or NULL
|
||||
*/
|
||||
void *load_module(const char *module, const char *type);
|
||||
|
||||
/**
|
||||
* @brief Get a module
|
||||
*
|
||||
* @param name Name of the module
|
||||
* @param type The module type or NULL for any type
|
||||
* @return The loaded module or NULL if the module is not loaded
|
||||
*/
|
||||
const MXS_MODULE *get_module(const char *name, const char *type);
|
||||
|
||||
/**
|
||||
* @brief Unload a module.
|
||||
*
|
||||
* No errors are returned since it is not clear that much can be done
|
||||
* to fix issues relating to unloading modules.
|
||||
*
|
||||
* @param module The name of the module
|
||||
*/
|
||||
void unload_module(const char *module);
|
||||
|
||||
/**
|
||||
* @brief Unload all modules
|
||||
*
|
||||
* Remove all the modules from the system, called during shutdown
|
||||
* to allow termination hooks to be called.
|
||||
*/
|
||||
void unload_all_modules();
|
||||
|
||||
/**
|
||||
* @brief Print Modules
|
||||
*
|
||||
* Diagnostic routine to display all the loaded modules
|
||||
*/
|
||||
void printModules();
|
||||
|
||||
/**
|
||||
* @brief Print Modules to a DCB
|
||||
*
|
||||
* Diagnostic routine to display all the loaded modules
|
||||
*/
|
||||
void dprintAllModules(DCB *);
|
||||
|
||||
/**
|
||||
* @brief Return a resultset that has the current set of modules in it
|
||||
*
|
||||
* @return A Result set
|
||||
*/
|
||||
RESULTSET *moduleGetList();
|
||||
|
||||
typedef struct mxs_module_iterator
|
||||
{
|
||||
const char* type;
|
||||
void* position;
|
||||
} MXS_MODULE_ITERATOR;
|
||||
|
||||
/**
|
||||
* @brief Returns an iterator to modules.
|
||||
*
|
||||
* @attention It is unspecified whether a module loaded after the iterator
|
||||
* was created, will be returned by the iterator. The behaviour
|
||||
* is undefined if a module is unloaded while an iteration is
|
||||
* being performed.
|
||||
*
|
||||
* @param type The type of modules that should be returned. If NULL,
|
||||
* then all modules are returned.
|
||||
*
|
||||
* @return An iterator.
|
||||
*/
|
||||
MXS_MODULE_ITERATOR mxs_module_iterator_get(const char* type);
|
||||
|
||||
/**
|
||||
* @brief Indicates whether the iterator has a module to return.
|
||||
*
|
||||
* @param iterator An iterator
|
||||
*
|
||||
* @return True if a subsequent call to @c mxs_module_iterator_get
|
||||
* will return a module.
|
||||
*/
|
||||
bool mxs_module_iterator_has_next(const MXS_MODULE_ITERATOR* iterator);
|
||||
|
||||
/**
|
||||
* @brief Returns the next module and advances the iterator.
|
||||
*
|
||||
* @param iterator An iterator.
|
||||
*
|
||||
* @return A module if there was a module to return, NULL otherwise.
|
||||
*/
|
||||
MXS_MODULE* mxs_module_iterator_get_next(MXS_MODULE_ITERATOR* iterator);
|
||||
|
||||
/**
|
||||
* @brief Convert module to JSON
|
||||
*
|
||||
* @param module Module to convert
|
||||
* @param host Hostname of this server
|
||||
*
|
||||
* @return The module in JSON format
|
||||
*/
|
||||
json_t* module_to_json(const MXS_MODULE* module, const char* host);
|
||||
|
||||
/**
|
||||
* @brief Convert all modules to JSON
|
||||
*
|
||||
* @param host The hostname of this server
|
||||
*
|
||||
* @return Array of modules in JSON format
|
||||
*/
|
||||
json_t* module_list_to_json(const char* host);
|
||||
|
||||
MXS_END_DECLS
|
||||
121
server/core/internal/monitor.h
Normal file
121
server/core/internal/monitor.h
Normal file
@ -0,0 +1,121 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/monitor.h - The private monitor interface
|
||||
*/
|
||||
|
||||
#include <maxscale/monitor.h>
|
||||
#include "externcmd.h"
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define MON_ARG_MAX 8192
|
||||
|
||||
#define DEFAULT_CONNECT_TIMEOUT 3
|
||||
#define DEFAULT_READ_TIMEOUT 1
|
||||
#define DEFAULT_WRITE_TIMEOUT 2
|
||||
#define DEFAULT_CONNECTION_ATTEMPTS 1
|
||||
|
||||
#define DEFAULT_MONITOR_INTERVAL 2000 // in milliseconds
|
||||
|
||||
/** Default maximum journal age in seconds */
|
||||
#define DEFAULT_JOURNAL_MAX_AGE 28800
|
||||
|
||||
/** Default script execution timeout in seconds */
|
||||
#define DEFAULT_SCRIPT_TIMEOUT 90
|
||||
|
||||
/**
|
||||
* Monitor network timeout types
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
MONITOR_CONNECT_TIMEOUT = 0,
|
||||
MONITOR_READ_TIMEOUT = 1,
|
||||
MONITOR_WRITE_TIMEOUT = 2,
|
||||
MONITOR_CONNECT_ATTEMPTS = 3
|
||||
} monitor_timeouts_t;
|
||||
|
||||
MXS_MONITOR *monitor_alloc(const char *, const char *);
|
||||
void monitor_free(MXS_MONITOR *);
|
||||
|
||||
void monitorStart(MXS_MONITOR *, const MXS_CONFIG_PARAMETER*);
|
||||
void monitorStop(MXS_MONITOR *);
|
||||
void monitorDestroy(MXS_MONITOR* monitor);
|
||||
void monitorStopAll();
|
||||
void monitorStartAll();
|
||||
|
||||
MXS_MONITOR *monitor_find(const char *);
|
||||
MXS_MONITOR* monitor_repurpose_destroyed(const char* name, const char* module);
|
||||
|
||||
void monitorShow(DCB *, MXS_MONITOR *);
|
||||
void monitorShowAll(DCB *);
|
||||
|
||||
void monitorList(DCB *);
|
||||
RESULTSET *monitorGetList();
|
||||
|
||||
bool monitorAddServer(MXS_MONITOR *mon, SERVER *server);
|
||||
void monitorRemoveServer(MXS_MONITOR *mon, SERVER *server);
|
||||
void monitorAddUser(MXS_MONITOR *, const char *, const char *);
|
||||
void monitorAddParameters(MXS_MONITOR *monitor, MXS_CONFIG_PARAMETER *params);
|
||||
bool monitorRemoveParameter(MXS_MONITOR *monitor, const char *key);
|
||||
|
||||
void monitorSetInterval (MXS_MONITOR *, unsigned long);
|
||||
bool monitorSetNetworkTimeout(MXS_MONITOR *, int, int, const char*);
|
||||
void monitorSetJournalMaxAge(MXS_MONITOR *mon, time_t value);
|
||||
void monitorSetScriptTimeout(MXS_MONITOR *mon, uint32_t value);
|
||||
|
||||
/**
|
||||
* @brief Serialize a monitor to a file
|
||||
*
|
||||
* This converts the static configuration of the monitor into an INI format file.
|
||||
*
|
||||
* @param monitor Monitor to serialize
|
||||
* @return True if serialization was successful
|
||||
*/
|
||||
bool monitor_serialize(const MXS_MONITOR *monitor);
|
||||
|
||||
/**
|
||||
* Check if a server is being monitored and return the monitor.
|
||||
* @param server Server that is queried
|
||||
* @return The monitor watching this server, or NULL if not monitored
|
||||
*/
|
||||
MXS_MONITOR* monitor_server_in_use(const SERVER *server);
|
||||
|
||||
/**
|
||||
* Launch a script
|
||||
*
|
||||
* @param mon Owning monitor
|
||||
* @param ptr The server which has changed state
|
||||
* @param script Script to execute
|
||||
* @param timeout Timeout in seconds for the script
|
||||
*
|
||||
* @return Return value of the executed script or -1 on error
|
||||
*/
|
||||
int monitor_launch_script(MXS_MONITOR* mon, MXS_MONITORED_SERVER* ptr, const char* script, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* Launch a command
|
||||
*
|
||||
* @param mon Owning monitor
|
||||
* @param ptr The server which has changed state
|
||||
* @param cmd The command to execute.
|
||||
*
|
||||
* @note All default script variables will be replaced.
|
||||
*
|
||||
* @return Return value of the executed script or -1 on error.
|
||||
*/
|
||||
int monitor_launch_command(MXS_MONITOR* mon, MXS_MONITORED_SERVER* ptr, EXTERNCMD* cmd);
|
||||
|
||||
MXS_END_DECLS
|
||||
64
server/core/internal/poll.h
Normal file
64
server/core/internal/poll.h
Normal file
@ -0,0 +1,64 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/poll.h - The private poll interface
|
||||
*/
|
||||
|
||||
#include <maxscale/poll.h>
|
||||
|
||||
#include <maxscale/resultset.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
struct mxs_worker;
|
||||
|
||||
#define MAX_EVENTS 1000
|
||||
|
||||
/**
|
||||
* A statistic identifier that can be returned by poll_get_stat
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
POLL_STAT_READ,
|
||||
POLL_STAT_WRITE,
|
||||
POLL_STAT_ERROR,
|
||||
POLL_STAT_HANGUP,
|
||||
POLL_STAT_ACCEPT,
|
||||
POLL_STAT_EVQ_LEN,
|
||||
POLL_STAT_EVQ_MAX,
|
||||
POLL_STAT_MAX_QTIME,
|
||||
POLL_STAT_MAX_EXECTIME
|
||||
} POLL_STAT;
|
||||
|
||||
enum poll_message
|
||||
{
|
||||
POLL_MSG_CLEAN_PERSISTENT = 0x01
|
||||
};
|
||||
|
||||
void poll_init();
|
||||
//void poll_finish(); // TODO: Add this.
|
||||
|
||||
void poll_set_maxwait(unsigned int);
|
||||
void poll_set_nonblocking_polls(unsigned int);
|
||||
|
||||
void dprintPollStats(DCB *);
|
||||
void dShowThreads(DCB *dcb);
|
||||
void dShowEventQ(DCB *dcb);
|
||||
void dShowEventStats(DCB *dcb);
|
||||
|
||||
int64_t poll_get_stat(POLL_STAT stat);
|
||||
RESULTSET *eventTimesGetList();
|
||||
|
||||
MXS_END_DECLS
|
||||
39
server/core/internal/query_classifier.h
Normal file
39
server/core/internal/query_classifier.h
Normal file
@ -0,0 +1,39 @@
|
||||
#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 <maxscale/cdefs.h>
|
||||
#include <maxscale/query_classifier.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
typedef enum qc_trx_parse_using
|
||||
{
|
||||
QC_TRX_PARSE_USING_QC, /**< Use the query classifier. */
|
||||
QC_TRX_PARSE_USING_PARSER, /**< Use custom parser. */
|
||||
} qc_trx_parse_using_t;
|
||||
|
||||
/**
|
||||
* Returns the type bitmask of transaction related statements.
|
||||
*
|
||||
* @param stmt A COM_QUERY or COM_STMT_PREPARE packet.
|
||||
* @param use What method should be used.
|
||||
*
|
||||
* @return The relevant type bits if the statement is transaction
|
||||
* related, otherwise 0.
|
||||
*
|
||||
* @see qc_get_trx_type_mask
|
||||
*/
|
||||
uint32_t qc_get_trx_type_mask_using(GWBUF* stmt, qc_trx_parse_using_t use);
|
||||
|
||||
MXS_END_DECLS
|
||||
98
server/core/internal/resource.hh
Normal file
98
server/core/internal/resource.hh
Normal file
@ -0,0 +1,98 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/** @file REST API resources */
|
||||
|
||||
#include <maxscale/cppdefs.hh>
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
#include <maxscale/server.h>
|
||||
#include <maxscale/http.hh>
|
||||
|
||||
#include "httprequest.hh"
|
||||
#include "httpresponse.hh"
|
||||
#include "monitor.h"
|
||||
#include "service.h"
|
||||
#include "filter.h"
|
||||
#include "session.h"
|
||||
|
||||
typedef HttpResponse (*ResourceCallback)(const HttpRequest& request);
|
||||
|
||||
class Resource
|
||||
{
|
||||
Resource(const Resource&);
|
||||
Resource& operator = (const Resource&);
|
||||
public:
|
||||
|
||||
enum resource_constraint
|
||||
{
|
||||
NONE = 0,
|
||||
REQUIRE_BODY = (1 << 0)
|
||||
};
|
||||
|
||||
Resource(ResourceCallback cb, int components, ...);
|
||||
~Resource();
|
||||
|
||||
/**
|
||||
* @brief Check if a request matches this resource
|
||||
*
|
||||
* @param request Request to match
|
||||
*
|
||||
* @return True if this request matches this resource
|
||||
*/
|
||||
bool match(const HttpRequest& request) const;
|
||||
|
||||
/**
|
||||
* @brief Handle a HTTP request
|
||||
*
|
||||
* @param request Request to handle
|
||||
*
|
||||
* @return Response to the request
|
||||
*/
|
||||
HttpResponse call(const HttpRequest& request) const;
|
||||
|
||||
/**
|
||||
* Add a resource constraint
|
||||
*
|
||||
* @param type Constraint to add
|
||||
*/
|
||||
void add_constraint(resource_constraint type);
|
||||
|
||||
/**
|
||||
* Whether resource requires a request body
|
||||
*
|
||||
* @return True if resource requires a request body
|
||||
*/
|
||||
bool requires_body() const;
|
||||
|
||||
private:
|
||||
|
||||
bool matching_variable_path(const std::string& path, const std::string& target) const;
|
||||
|
||||
ResourceCallback m_cb; /**< Resource handler callback */
|
||||
std::deque<std::string> m_path; /**< Path components */
|
||||
bool m_is_glob; /**< Does this path glob? */
|
||||
uint32_t m_constraints; /**< Resource constraints */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Handle a HTTP request
|
||||
*
|
||||
* @param request Request to handle
|
||||
*
|
||||
* @return Response to request
|
||||
*/
|
||||
HttpResponse resource_handle_request(const HttpRequest& request);
|
||||
43
server/core/internal/secrets.h
Normal file
43
server/core/internal/secrets.h
Normal file
@ -0,0 +1,43 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/secrets.h - MaxScale config file password encryption/decryption
|
||||
*/
|
||||
|
||||
#include <maxscale/secrets.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define MAXSCALE_KEYLEN 32
|
||||
#define MAXSCALE_IV_LEN 16
|
||||
|
||||
/**
|
||||
* The key structure held in the secrets file
|
||||
*/
|
||||
typedef struct maxkeys
|
||||
{
|
||||
unsigned char enckey[MAXSCALE_KEYLEN];
|
||||
unsigned char initvector[MAXSCALE_IV_LEN];
|
||||
} MAXKEYS;
|
||||
|
||||
enum
|
||||
{
|
||||
MXS_PASSWORD_MAXLEN = 79
|
||||
};
|
||||
|
||||
int secrets_write_keys(const char *directory);
|
||||
char *encrypt_password(const char*, const char *);
|
||||
|
||||
MXS_END_DECLS
|
||||
143
server/core/internal/service.h
Normal file
143
server/core/internal/service.h
Normal file
@ -0,0 +1,143 @@
|
||||
#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 <maxscale/service.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @file service.h - MaxScale internal service functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service life cycle management
|
||||
*
|
||||
* These functions should only be called by the MaxScale core.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Allocate a new service
|
||||
*
|
||||
* @param name The service name
|
||||
* @param router The router module this service uses
|
||||
*
|
||||
* @return The newly created service or NULL if an error occurred
|
||||
*/
|
||||
SERVICE* service_alloc(const char *name, const char *router);
|
||||
|
||||
/**
|
||||
* @brief Free the specified service
|
||||
*
|
||||
* @param service The service to free
|
||||
*/
|
||||
void service_free(SERVICE *service);
|
||||
|
||||
/**
|
||||
* @brief Shut all services down
|
||||
*
|
||||
* Turns on the shutdown flag in each service. This should be done as
|
||||
* part of the MaxScale shutdown.
|
||||
*/
|
||||
void service_shutdown(void);
|
||||
|
||||
/**
|
||||
* @brief Destroy all service router and filter instances
|
||||
*
|
||||
* Calls the @c destroyInstance entry point of each service' router and
|
||||
* filters. This should be done after all worker threads have exited.
|
||||
*/
|
||||
void service_destroy_instances(void);
|
||||
|
||||
/**
|
||||
* @brief Launch all services
|
||||
*
|
||||
* Initialize and start all services. This should only be called once by the
|
||||
* main initialization code.
|
||||
*
|
||||
* @return Number of successfully started services
|
||||
*/
|
||||
int service_launch_all(void);
|
||||
|
||||
/**
|
||||
* Creating and adding new components to services
|
||||
*/
|
||||
SERV_LISTENER* serviceCreateListener(SERVICE *service, const char *name,
|
||||
const char *protocol, const char *address,
|
||||
unsigned short port, const char *authenticator,
|
||||
const char *options, SSL_LISTENER *ssl);
|
||||
|
||||
void serviceRemoveBackend(SERVICE *service, const SERVER *server);
|
||||
|
||||
/**
|
||||
* @brief Serialize a service to a file
|
||||
*
|
||||
* This converts @c service into an INI format file.
|
||||
*
|
||||
* NOTE: This does not persist the complete service configuration and requires
|
||||
* that an existing service configuration is in the main configuration file.
|
||||
*
|
||||
* @param service Service to serialize
|
||||
* @return False if the serialization of the service fails, true if it was successful
|
||||
*/
|
||||
bool service_serialize(const SERVICE *service);
|
||||
|
||||
/**
|
||||
* Internal utility functions
|
||||
*/
|
||||
char* service_get_name(SERVICE* service);
|
||||
bool service_all_services_have_listeners(void);
|
||||
int service_isvalid(SERVICE *service);
|
||||
|
||||
/**
|
||||
* Check if a service uses @c servers
|
||||
* @param server Server that is queried
|
||||
* @return True if server is used by at least one service
|
||||
*/
|
||||
bool service_server_in_use(const SERVER *server);
|
||||
|
||||
/** Update the server weights used by services */
|
||||
void service_update_weights();
|
||||
|
||||
/**
|
||||
* Alteration of the service configuration
|
||||
*/
|
||||
void serviceAddRouterOption(SERVICE *service, char *option);
|
||||
void serviceClearRouterOptions(SERVICE *service);
|
||||
void service_update(SERVICE *service, char *router, char *user, char *auth);
|
||||
|
||||
/**
|
||||
* @brief Add parameters to a service
|
||||
*
|
||||
* A copy of @c param is added to @c service.
|
||||
*
|
||||
* @param service Service where the parameters are added
|
||||
* @param param Parameters to add
|
||||
*/
|
||||
void service_add_parameters(SERVICE *service, const MXS_CONFIG_PARAMETER *param);
|
||||
|
||||
/**
|
||||
* @brief Set listener rebinding interval
|
||||
*
|
||||
* @param service Service to configure
|
||||
* @param value String value o
|
||||
*/
|
||||
void service_set_retry_interval(SERVICE *service, int value);
|
||||
|
||||
/**
|
||||
* Internal debugging diagnostics
|
||||
*/
|
||||
void printService(SERVICE *service);
|
||||
void printAllServices(void);
|
||||
|
||||
MXS_END_DECLS
|
||||
77
server/core/internal/session.h
Normal file
77
server/core/internal/session.h
Normal file
@ -0,0 +1,77 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file core/maxscale/session.h - The private session interface
|
||||
*/
|
||||
|
||||
#include <maxscale/session.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define SESSION_STATS_INIT {0}
|
||||
#define MXS_DOWNSTREAM_INIT {0}
|
||||
#define MXS_UPSTREAM_INIT {0}
|
||||
#define SESSION_FILTER_INIT {0}
|
||||
|
||||
#define SESSION_INIT {.ses_chk_top = CHK_NUM_SESSION, \
|
||||
.stats = SESSION_STATS_INIT, .head = MXS_DOWNSTREAM_INIT, .tail = MXS_UPSTREAM_INIT, \
|
||||
.state = SESSION_STATE_ALLOC, .client_protocol_data = 0, .ses_chk_tail = CHK_NUM_SESSION}
|
||||
|
||||
#define SESSION_PROTOCOL(x, type) DCB_PROTOCOL((x)->client_dcb, type)
|
||||
|
||||
/**
|
||||
* Filter type for the sessionGetList call
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
SESSION_LIST_ALL,
|
||||
SESSION_LIST_CONNECTION
|
||||
} SESSIONLISTFILTER;
|
||||
|
||||
int session_isvalid(MXS_SESSION *);
|
||||
const char *session_state(mxs_session_state_t);
|
||||
|
||||
/**
|
||||
* Link a session to a backend DCB.
|
||||
*
|
||||
* @param session The session to link with the dcb
|
||||
* @param dcb The backend DCB to be linked
|
||||
*/
|
||||
void session_link_backend_dcb(MXS_SESSION *session, struct dcb *dcb);
|
||||
|
||||
RESULTSET *sessionGetList(SESSIONLISTFILTER);
|
||||
|
||||
void printAllSessions();
|
||||
void printSession(MXS_SESSION *);
|
||||
|
||||
void dprintSessionList(DCB *pdcb);
|
||||
void dprintAllSessions(struct dcb *);
|
||||
void dprintSession(struct dcb *, MXS_SESSION *);
|
||||
void dListSessions(struct dcb *);
|
||||
|
||||
/**
|
||||
* @brief Get a session reference
|
||||
*
|
||||
* This creates an additional reference to a session which allows it to live
|
||||
* as long as it is needed.
|
||||
*
|
||||
* @param session Session reference to get
|
||||
* @return Reference to a MXS_SESSION
|
||||
*
|
||||
* @note The caller must free the session reference by calling session_put_ref
|
||||
*/
|
||||
MXS_SESSION* session_get_ref(MXS_SESSION *sessoin);
|
||||
|
||||
MXS_END_DECLS
|
||||
39
server/core/internal/session.hh
Normal file
39
server/core/internal/session.hh
Normal file
@ -0,0 +1,39 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
#include <maxscale/session.h>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
/**
|
||||
* Specialization of RegistryTraits for the session registry.
|
||||
*/
|
||||
template<>
|
||||
struct RegistryTraits<MXS_SESSION>
|
||||
{
|
||||
typedef uint64_t id_type;
|
||||
typedef MXS_SESSION* entry_type;
|
||||
|
||||
static id_type get_id(entry_type entry)
|
||||
{
|
||||
return entry->ses_id;
|
||||
}
|
||||
static entry_type null_entry()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
170
server/core/internal/skygw_utils.h
Normal file
170
server/core/internal/skygw_utils.h
Normal file
@ -0,0 +1,170 @@
|
||||
#pragma once
|
||||
#ifndef _MAXSCALE_SKYGW_UTILS_H
|
||||
#define _MAXSCALE_SKYGW_UTILS_H
|
||||
/*
|
||||
* 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 <maxscale/cdefs.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
#define FSYNCLIMIT 10
|
||||
|
||||
#include <maxscale/debug.h>
|
||||
|
||||
#define DISKWRITE_LATENCY (5*MSEC_USEC)
|
||||
|
||||
typedef struct skygw_file_st skygw_file_t;
|
||||
typedef struct skygw_thread_st skygw_thread_t;
|
||||
typedef struct skygw_message_st skygw_message_t;
|
||||
|
||||
typedef struct simple_mutex_st
|
||||
{
|
||||
skygw_chk_t sm_chk_top;
|
||||
pthread_mutex_t sm_mutex;
|
||||
pthread_t sm_lock_thr;
|
||||
bool sm_locked;
|
||||
int sm_enabled; /**< defined as in to minimize mutexing */
|
||||
bool sm_flat;
|
||||
char* sm_name;
|
||||
skygw_chk_t sm_chk_tail;
|
||||
} simple_mutex_t;
|
||||
|
||||
typedef struct skygw_rwlock_st
|
||||
{
|
||||
skygw_chk_t srw_chk_top;
|
||||
pthread_rwlock_t* srw_rwlock;
|
||||
pthread_t srw_rwlock_thr;
|
||||
skygw_chk_t srw_chk_tail;
|
||||
} skygw_rwlock_t;
|
||||
|
||||
|
||||
typedef enum { THR_INIT, THR_RUNNING, THR_STOPPED, THR_DONE } skygw_thr_state_t;
|
||||
typedef enum { MES_RC_FAIL, MES_RC_SUCCESS, MES_RC_TIMEOUT } skygw_mes_rc_t;
|
||||
|
||||
|
||||
static const char* timestamp_formatstr = "%04d-%02d-%02d %02d:%02d:%02d ";
|
||||
/** One for terminating '\0' */
|
||||
static const size_t timestamp_len = (4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 3 + 1) * sizeof(char);
|
||||
|
||||
static const char* timestamp_formatstr_hp = "%04d-%02d-%02d %02d:%02d:%02d.%03d ";
|
||||
/** One for terminating '\0' */
|
||||
static const size_t timestamp_len_hp = (4 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 3 + 3 + 1) * sizeof(
|
||||
char);
|
||||
|
||||
struct skygw_thread_st
|
||||
{
|
||||
skygw_chk_t sth_chk_top;
|
||||
bool sth_must_exit;
|
||||
simple_mutex_t* sth_mutex;
|
||||
pthread_t sth_parent;
|
||||
pthread_t sth_thr;
|
||||
int sth_errno;
|
||||
#if defined(SS_DEBUG)
|
||||
skygw_thr_state_t sth_state;
|
||||
#endif
|
||||
char* sth_name;
|
||||
void* (*sth_thrfun)(void* data);
|
||||
void* sth_data;
|
||||
skygw_chk_t sth_chk_tail;
|
||||
};
|
||||
|
||||
struct skygw_message_st
|
||||
{
|
||||
skygw_chk_t mes_chk_top;
|
||||
bool mes_sent;
|
||||
pthread_mutex_t mes_mutex;
|
||||
pthread_cond_t mes_cond;
|
||||
skygw_chk_t mes_chk_tail;
|
||||
};
|
||||
|
||||
struct skygw_file_st
|
||||
{
|
||||
skygw_chk_t sf_chk_top;
|
||||
char* sf_fname;
|
||||
FILE* sf_file;
|
||||
int sf_fd;
|
||||
skygw_chk_t sf_chk_tail;
|
||||
};
|
||||
|
||||
/** Skygw thread routines */
|
||||
skygw_thread_t* skygw_thread_init(const char* name,
|
||||
void* (*sth_thrfun)(void* data),
|
||||
void* data);
|
||||
void skygw_thread_done(skygw_thread_t* th);
|
||||
int skygw_thread_start(skygw_thread_t* thr);
|
||||
skygw_thr_state_t skygw_thread_get_state(skygw_thread_t* thr);
|
||||
pthread_t skygw_thread_gettid(skygw_thread_t* thr);
|
||||
|
||||
size_t get_timestamp_len(void);
|
||||
size_t get_timestamp_len_hp(void);
|
||||
size_t snprint_timestamp(char* p_ts, size_t tslen);
|
||||
size_t snprint_timestamp_hp(char* p_ts, size_t tslen);
|
||||
|
||||
void skygw_thread_set_state(skygw_thread_t* thr,
|
||||
skygw_thr_state_t state);
|
||||
void* skygw_thread_get_data(skygw_thread_t* thr);
|
||||
bool skygw_thread_must_exit(skygw_thread_t* thr);
|
||||
bool skygw_thread_set_exitflag(skygw_thread_t* thr,
|
||||
skygw_message_t* sendmes,
|
||||
skygw_message_t* recmes);
|
||||
|
||||
/** Skygw thread routines */
|
||||
|
||||
/** Skygw file routines */
|
||||
typedef enum skygw_open_mode
|
||||
{
|
||||
SKYGW_OPEN_APPEND,
|
||||
SKYGW_OPEN_TRUNCATE,
|
||||
} skygw_open_mode_t;
|
||||
|
||||
skygw_file_t* skygw_file_alloc(const char* fname);
|
||||
void skygw_file_free(skygw_file_t* file);
|
||||
skygw_file_t* skygw_file_init(const char* fname,
|
||||
const char* symlinkname,
|
||||
skygw_open_mode_t mode);
|
||||
void skygw_file_close(skygw_file_t* file);
|
||||
int skygw_file_write(skygw_file_t* file,
|
||||
void* data,
|
||||
size_t nbytes,
|
||||
bool flush);
|
||||
/** Skygw file routines */
|
||||
|
||||
void acquire_lock(int* l);
|
||||
void release_lock(int* l);
|
||||
|
||||
simple_mutex_t* simple_mutex_init(simple_mutex_t* mutexptr, const char* name);
|
||||
int simple_mutex_done(simple_mutex_t* sm);
|
||||
int simple_mutex_lock(simple_mutex_t* sm, bool block);
|
||||
int simple_mutex_unlock(simple_mutex_t* sm);
|
||||
|
||||
/** Skygw message routines */
|
||||
skygw_message_t* skygw_message_init(void);
|
||||
void skygw_message_done(skygw_message_t* mes);
|
||||
skygw_mes_rc_t skygw_message_send(skygw_message_t* mes);
|
||||
void skygw_message_wait(skygw_message_t* mes);
|
||||
skygw_mes_rc_t skygw_message_request(skygw_message_t* mes);
|
||||
void skygw_message_reset(skygw_message_t* mes);
|
||||
|
||||
/** Skygw message routines */
|
||||
|
||||
int skygw_rwlock_wrlock(skygw_rwlock_t* rwlock);
|
||||
int skygw_rwlock_rdlock(skygw_rwlock_t* rwlock);
|
||||
int skygw_rwlock_unlock(skygw_rwlock_t* rwlock);
|
||||
int skygw_rwlock_init(skygw_rwlock_t** rwlock);
|
||||
|
||||
size_t get_decimal_len(size_t s);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
||||
#endif /* SKYGW_UTILS_H */
|
||||
37
server/core/internal/statistics.h
Normal file
37
server/core/internal/statistics.h
Normal file
@ -0,0 +1,37 @@
|
||||
#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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Internal code for the statistics system.
|
||||
*/
|
||||
|
||||
#include <maxscale/statistics.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @brief Initialize statistics system
|
||||
*
|
||||
* This function should only be called once by the MaxScale core.
|
||||
*/
|
||||
void ts_stats_init();
|
||||
|
||||
/**
|
||||
* @brief Terminate statistics system
|
||||
*/
|
||||
void ts_stats_end();
|
||||
|
||||
MXS_END_DECLS
|
||||
806
server/core/internal/trxboundaryparser.hh
Normal file
806
server/core/internal/trxboundaryparser.hh
Normal file
@ -0,0 +1,806 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
#include <ctype.h>
|
||||
#include <maxscale/customparser.hh>
|
||||
#include <maxscale/query_classifier.h>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
#define TBP_EXPECT_TOKEN(string_literal) string_literal, (sizeof(string_literal) - 1)
|
||||
|
||||
// For debugging purposes.
|
||||
// #define TBP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
#undef TBP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
|
||||
/**
|
||||
* @class TrxBoundaryParser
|
||||
*
|
||||
* @ TrxBoundaryParser is a class capable of parsing and returning the
|
||||
* correct type mask of statements affecting the transaction state and
|
||||
* autocommit mode.
|
||||
*
|
||||
* The class is intended to be used in context where the performance is
|
||||
* of utmost importance; consequently it is defined in its entirety
|
||||
* in the header to allow for aggressive inlining.
|
||||
*/
|
||||
class TrxBoundaryParser : public maxscale::CustomParser
|
||||
{
|
||||
TrxBoundaryParser(const TrxBoundaryParser&);
|
||||
TrxBoundaryParser& operator = (const TrxBoundaryParser&);
|
||||
|
||||
public:
|
||||
enum token_t
|
||||
{
|
||||
TK_AUTOCOMMIT,
|
||||
TK_BEGIN,
|
||||
TK_COMMA,
|
||||
TK_COMMIT,
|
||||
TK_CONSISTENT,
|
||||
TK_DOT,
|
||||
TK_EQ,
|
||||
TK_FALSE,
|
||||
TK_GLOBAL,
|
||||
TK_GLOBAL_VAR,
|
||||
TK_ONE,
|
||||
TK_ONLY,
|
||||
TK_READ,
|
||||
TK_ROLLBACK,
|
||||
TK_SESSION,
|
||||
TK_SESSION_VAR,
|
||||
TK_SET,
|
||||
TK_SNAPSHOT,
|
||||
TK_START,
|
||||
TK_TRANSACTION,
|
||||
TK_TRUE,
|
||||
TK_WITH,
|
||||
TK_WORK,
|
||||
TK_WRITE,
|
||||
TK_ZERO,
|
||||
|
||||
PARSER_UNKNOWN_TOKEN,
|
||||
PARSER_EXHAUSTED,
|
||||
};
|
||||
|
||||
/**
|
||||
* TrxBoundaryParser is not thread-safe. As a very lightweight class,
|
||||
* the intention is that an instance is created on the stack whenever
|
||||
* parsing needs to be performed.
|
||||
*
|
||||
* @code
|
||||
* void f(GWBUF *pBuf)
|
||||
* {
|
||||
* TrxBoundaryParser tbp;
|
||||
*
|
||||
* uint32_t type_mask = tbp.parse(pBuf);
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
TrxBoundaryParser()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type mask of a statement, provided the statement affects
|
||||
* transaction state or autocommit mode.
|
||||
*
|
||||
* @param pSql SQL statament.
|
||||
* @param len Length of pSql.
|
||||
*
|
||||
* @return The corresponding type mask or 0, if the statement does not
|
||||
* affect transaction state or autocommit mode.
|
||||
*/
|
||||
uint32_t type_mask_of(const char* pSql, size_t len)
|
||||
{
|
||||
uint32_t type_mask = 0;
|
||||
|
||||
m_pSql = pSql;
|
||||
m_len = len;
|
||||
|
||||
m_pI = m_pSql;
|
||||
m_pEnd = m_pI + m_len;
|
||||
|
||||
return parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type mask of a statement, provided the statement affects
|
||||
* transaction state or autocommit mode.
|
||||
*
|
||||
* @param pBuf A COM_QUERY
|
||||
*
|
||||
* @return The corresponding type mask or 0, if the statement does not
|
||||
* affect transaction state or autocommit mode.
|
||||
*/
|
||||
uint32_t type_mask_of(GWBUF* pBuf)
|
||||
{
|
||||
uint32_t type_mask = 0;
|
||||
|
||||
char* pSql;
|
||||
if (modutil_extract_SQL(pBuf, &pSql, &m_len))
|
||||
{
|
||||
m_pSql = pSql;
|
||||
m_pI = m_pSql;
|
||||
m_pEnd = m_pI + m_len;
|
||||
|
||||
type_mask = parse();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
private:
|
||||
enum token_required_t
|
||||
{
|
||||
TOKEN_REQUIRED,
|
||||
TOKEN_NOT_REQUIRED,
|
||||
};
|
||||
|
||||
void log_unexpected()
|
||||
{
|
||||
#ifdef TBP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
MXS_NOTICE("Transaction tracking: In statement '%.*s', unexpected token at '%.*s'.",
|
||||
(int)m_len, m_pSql, (int)(m_pEnd - m_pI), m_pI);
|
||||
#endif
|
||||
}
|
||||
|
||||
void log_exhausted()
|
||||
{
|
||||
#ifdef TBP_LOG_UNEXPECTED_AND_EXHAUSTED
|
||||
MXS_NOTICE("Transaction tracking: More tokens expected in statement '%.*s'.", (int)m_len, m_pSql);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t parse()
|
||||
{
|
||||
uint32_t type_mask = 0;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_BEGIN:
|
||||
type_mask = parse_begin(type_mask);
|
||||
break;
|
||||
|
||||
case TK_COMMIT:
|
||||
type_mask = parse_commit(type_mask);
|
||||
break;
|
||||
|
||||
case TK_ROLLBACK:
|
||||
type_mask = parse_rollback(type_mask);
|
||||
break;
|
||||
|
||||
case TK_START:
|
||||
type_mask = parse_start(type_mask);
|
||||
break;
|
||||
|
||||
case TK_SET:
|
||||
type_mask = parse_set(0);
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_begin(uint32_t type_mask)
|
||||
{
|
||||
type_mask |= QUERY_TYPE_BEGIN_TRX;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_WORK:
|
||||
type_mask = parse_work(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_commit(uint32_t type_mask)
|
||||
{
|
||||
type_mask |= QUERY_TYPE_COMMIT;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_WORK:
|
||||
type_mask = parse_work(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_only(uint32_t type_mask)
|
||||
{
|
||||
type_mask |= QUERY_TYPE_READ;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_COMMA:
|
||||
type_mask = parse_transaction(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_read(uint32_t type_mask)
|
||||
{
|
||||
token_t token = next_token(TOKEN_REQUIRED);
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_ONLY:
|
||||
type_mask = parse_only(type_mask);
|
||||
break;
|
||||
|
||||
case TK_WRITE:
|
||||
type_mask = parse_write(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
type_mask = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_rollback(uint32_t type_mask)
|
||||
{
|
||||
type_mask |= QUERY_TYPE_ROLLBACK;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_WORK:
|
||||
type_mask = parse_work(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_set_autocommit(uint32_t type_mask)
|
||||
{
|
||||
token_t token = next_token(TOKEN_REQUIRED);
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_EQ:
|
||||
token = next_token(TOKEN_REQUIRED);
|
||||
if (token == TK_ONE || token == TK_TRUE)
|
||||
{
|
||||
type_mask |= (QUERY_TYPE_COMMIT | QUERY_TYPE_ENABLE_AUTOCOMMIT);
|
||||
}
|
||||
else if (token == TK_ZERO || token == TK_FALSE)
|
||||
{
|
||||
type_mask = (QUERY_TYPE_BEGIN_TRX | QUERY_TYPE_DISABLE_AUTOCOMMIT);
|
||||
}
|
||||
else
|
||||
{
|
||||
type_mask = 0;
|
||||
|
||||
if (token != PARSER_EXHAUSTED)
|
||||
{
|
||||
log_unexpected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
type_mask = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_set(uint32_t type_mask)
|
||||
{
|
||||
token_t token = next_token(TOKEN_REQUIRED);
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_AUTOCOMMIT:
|
||||
type_mask = parse_set_autocommit(type_mask);
|
||||
break;
|
||||
|
||||
case TK_GLOBAL:
|
||||
case TK_SESSION:
|
||||
token = next_token(TOKEN_REQUIRED);
|
||||
if (token == TK_AUTOCOMMIT)
|
||||
{
|
||||
type_mask = parse_set_autocommit(type_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
type_mask = 0;
|
||||
if (token != PARSER_EXHAUSTED)
|
||||
{
|
||||
log_unexpected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TK_GLOBAL_VAR:
|
||||
case TK_SESSION_VAR:
|
||||
token = next_token(TOKEN_REQUIRED);
|
||||
if (token == TK_DOT)
|
||||
{
|
||||
token = next_token(TOKEN_REQUIRED);
|
||||
if (token == TK_AUTOCOMMIT)
|
||||
{
|
||||
type_mask = parse_set_autocommit(type_mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
type_mask = 0;
|
||||
if (token != PARSER_EXHAUSTED)
|
||||
{
|
||||
log_unexpected();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type_mask = 0;
|
||||
if (token != PARSER_EXHAUSTED)
|
||||
{
|
||||
log_unexpected();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
type_mask = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_start(uint32_t type_mask)
|
||||
{
|
||||
token_t token = next_token(TOKEN_REQUIRED);
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_TRANSACTION:
|
||||
type_mask = parse_transaction(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
type_mask = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_transaction(uint32_t type_mask)
|
||||
{
|
||||
type_mask |= QUERY_TYPE_BEGIN_TRX;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_READ:
|
||||
type_mask = parse_read(type_mask);
|
||||
break;
|
||||
|
||||
case TK_WITH:
|
||||
type_mask = parse_with_consistent_snapshot(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_with_consistent_snapshot(uint32_t type_mask)
|
||||
{
|
||||
token_t token = next_token(TOKEN_REQUIRED);
|
||||
|
||||
if (token == TK_CONSISTENT)
|
||||
{
|
||||
token = next_token(TOKEN_REQUIRED);
|
||||
|
||||
if (token == TK_SNAPSHOT)
|
||||
{
|
||||
token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_COMMA:
|
||||
type_mask = parse_transaction(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_work(uint32_t type_mask)
|
||||
{
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
uint32_t parse_write(uint32_t type_mask)
|
||||
{
|
||||
type_mask |= QUERY_TYPE_WRITE;
|
||||
|
||||
token_t token = next_token();
|
||||
|
||||
switch (token)
|
||||
{
|
||||
case TK_COMMA:
|
||||
type_mask = parse_transaction(type_mask);
|
||||
break;
|
||||
|
||||
case PARSER_EXHAUSTED:
|
||||
break;
|
||||
|
||||
default:
|
||||
type_mask = 0;
|
||||
log_unexpected();
|
||||
}
|
||||
|
||||
return type_mask;
|
||||
}
|
||||
|
||||
// Significantly faster than library version.
|
||||
static char toupper(char c)
|
||||
{
|
||||
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
token_t expect_token(const char* zWord, int len, token_t token)
|
||||
{
|
||||
const char* pI = m_pI;
|
||||
const char* pEnd = zWord + len;
|
||||
|
||||
while ((pI < m_pEnd) && (zWord < pEnd) && (toupper(*pI) == *zWord))
|
||||
{
|
||||
++pI;
|
||||
++zWord;
|
||||
}
|
||||
|
||||
if (zWord == pEnd)
|
||||
{
|
||||
if ((pI == m_pEnd) || (!isalpha(*pI))) // Handwritten isalpha not faster than library version.
|
||||
{
|
||||
m_pI = pI;
|
||||
}
|
||||
else
|
||||
{
|
||||
token = PARSER_UNKNOWN_TOKEN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token = PARSER_UNKNOWN_TOKEN;
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
void bypass_whitespace()
|
||||
{
|
||||
m_pI = modutil_MySQL_bypass_whitespace(const_cast<char*>(m_pI), m_pEnd - m_pI);
|
||||
}
|
||||
|
||||
token_t next_token(token_required_t required = TOKEN_NOT_REQUIRED)
|
||||
{
|
||||
token_t token = PARSER_UNKNOWN_TOKEN;
|
||||
|
||||
bypass_whitespace();
|
||||
|
||||
if (m_pI == m_pEnd)
|
||||
{
|
||||
token = PARSER_EXHAUSTED;
|
||||
}
|
||||
else if (*m_pI == ';')
|
||||
{
|
||||
++m_pI;
|
||||
|
||||
while ((m_pI != m_pEnd) && isspace(*m_pI))
|
||||
{
|
||||
++m_pI;
|
||||
}
|
||||
|
||||
if (m_pI != m_pEnd)
|
||||
{
|
||||
MXS_WARNING("Non-space data found after semi-colon: '%.*s'.",
|
||||
(int)(m_pEnd - m_pI), m_pI);
|
||||
}
|
||||
|
||||
token = PARSER_EXHAUSTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (*m_pI)
|
||||
{
|
||||
case '@':
|
||||
if (is_next_alpha('A', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("@@AUTOCOMMIT"), TK_AUTOCOMMIT);
|
||||
}
|
||||
else if (is_next_alpha('S', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("@@SESSION"), TK_SESSION_VAR);
|
||||
}
|
||||
else if (is_next_alpha('G', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("@@GLOBAL"), TK_GLOBAL_VAR);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
case 'A':
|
||||
token = expect_token(TBP_EXPECT_TOKEN("AUTOCOMMIT"), TK_AUTOCOMMIT);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
token = expect_token(TBP_EXPECT_TOKEN("BEGIN"), TK_BEGIN);
|
||||
break;
|
||||
|
||||
case ',':
|
||||
++m_pI;
|
||||
token = TK_COMMA;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
case 'C':
|
||||
if (is_next_alpha('O'))
|
||||
{
|
||||
if (is_next_alpha('M', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("COMMIT"), TK_COMMIT);
|
||||
}
|
||||
else if (is_next_alpha('N', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("CONSISTENT"), TK_CONSISTENT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '.':
|
||||
++m_pI;
|
||||
token = TK_DOT;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
++m_pI;
|
||||
token = TK_EQ;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
case 'F':
|
||||
token = expect_token(TBP_EXPECT_TOKEN("FALSE"), TK_FALSE);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
case 'G':
|
||||
token = expect_token(TBP_EXPECT_TOKEN("GLOBAL"), TK_GLOBAL);
|
||||
break;
|
||||
|
||||
case '1':
|
||||
{
|
||||
char c;
|
||||
if (!peek_next_char(&c) || !isdigit(c))
|
||||
{
|
||||
++m_pI;
|
||||
token = TK_ONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
case 'O':
|
||||
if (is_next_alpha('F'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("OFF"), TK_ZERO);
|
||||
}
|
||||
else if (is_next_alpha('N'))
|
||||
{
|
||||
if (is_next_alpha('L', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("ONLY"), TK_ONLY);
|
||||
}
|
||||
else
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("ON"), TK_ONE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (is_next_alpha('E'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("READ"), TK_READ);
|
||||
}
|
||||
else if (is_next_alpha('O'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("ROLLBACK"), TK_ROLLBACK);
|
||||
}
|
||||
break;
|
||||
|
||||
case 's':
|
||||
case 'S':
|
||||
if (is_next_alpha('E'))
|
||||
{
|
||||
if (is_next_alpha('S', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("SESSION"), TK_SESSION);
|
||||
}
|
||||
else
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("SET"), TK_SET);
|
||||
}
|
||||
}
|
||||
else if (is_next_alpha('N'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("SNAPSHOT"), TK_SNAPSHOT);
|
||||
}
|
||||
else if (is_next_alpha('T'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("START"), TK_START);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
case 'T':
|
||||
if (is_next_alpha('R'))
|
||||
{
|
||||
if (is_next_alpha('A', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("TRANSACTION"), TK_TRANSACTION);
|
||||
}
|
||||
else if (is_next_alpha('U', 2))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("TRUE"), TK_TRUE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
case 'W':
|
||||
if (is_next_alpha('I'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("WITH"), TK_WITH);
|
||||
}
|
||||
else if (is_next_alpha('O'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("WORK"), TK_WORK);
|
||||
}
|
||||
else if (is_next_alpha('R'))
|
||||
{
|
||||
token = expect_token(TBP_EXPECT_TOKEN("WRITE"), TK_WRITE);
|
||||
}
|
||||
break;
|
||||
|
||||
case '0':
|
||||
{
|
||||
char c;
|
||||
if (!peek_next_char(&c) || !isdigit(c))
|
||||
{
|
||||
++m_pI;
|
||||
token = TK_ZERO;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
if ((token == PARSER_EXHAUSTED) && (required == TOKEN_REQUIRED))
|
||||
{
|
||||
log_exhausted();
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
28
server/core/internal/worker.h
Normal file
28
server/core/internal/worker.h
Normal file
@ -0,0 +1,28 @@
|
||||
#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 <maxscale/worker.h>
|
||||
|
||||
MXS_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* Query whether worker should shutdown.
|
||||
*
|
||||
* @param worker The worker in question.
|
||||
*
|
||||
* @return True, if the worker should shut down, false otherwise.
|
||||
*/
|
||||
bool mxs_worker_should_shutdown(MXS_WORKER* worker);
|
||||
|
||||
MXS_END_DECLS
|
||||
528
server/core/internal/worker.hh
Normal file
528
server/core/internal/worker.hh
Normal file
@ -0,0 +1,528 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <maxscale/platform.h>
|
||||
#include <maxscale/session.h>
|
||||
#include <maxscale/utils.hh>
|
||||
#include "messagequeue.hh"
|
||||
#include "poll.h"
|
||||
#include "worker.h"
|
||||
#include "workertask.hh"
|
||||
#include "session.hh"
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
class Semaphore;
|
||||
|
||||
struct WORKER_STATISTICS
|
||||
{
|
||||
WORKER_STATISTICS()
|
||||
{
|
||||
memset(this, 0, sizeof(WORKER_STATISTICS));
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
MAXNFDS = 10,
|
||||
N_QUEUE_TIMES = 30
|
||||
};
|
||||
|
||||
int64_t n_read; /*< Number of read events */
|
||||
int64_t n_write; /*< Number of write events */
|
||||
int64_t n_error; /*< Number of error events */
|
||||
int64_t n_hup; /*< Number of hangup events */
|
||||
int64_t n_accept; /*< Number of accept events */
|
||||
int64_t n_polls; /*< Number of poll cycles */
|
||||
int64_t n_pollev; /*< Number of polls returning events */
|
||||
int64_t n_nbpollev; /*< Number of polls returning events */
|
||||
int64_t n_fds[MAXNFDS]; /*< Number of wakeups with particular n_fds value */
|
||||
int64_t evq_length; /*< Event queue length */
|
||||
int64_t evq_max; /*< Maximum event queue length */
|
||||
int64_t blockingpolls; /*< Number of epoll_waits with a timeout specified */
|
||||
uint32_t qtimes[N_QUEUE_TIMES + 1];
|
||||
uint32_t exectimes[N_QUEUE_TIMES + 1];
|
||||
int64_t maxqtime;
|
||||
int64_t maxexectime;
|
||||
};
|
||||
|
||||
class Worker : public MXS_WORKER
|
||||
, private MessageQueue::Handler
|
||||
, private MXS_POLL_DATA
|
||||
{
|
||||
Worker(const Worker&);
|
||||
Worker& operator = (const Worker&);
|
||||
|
||||
public:
|
||||
typedef WORKER_STATISTICS STATISTICS;
|
||||
typedef WorkerTask Task;
|
||||
typedef WorkerDisposableTask DisposableTask;
|
||||
typedef Registry<MXS_SESSION> SessionsById;
|
||||
typedef std::vector<DCB*> Zombies;
|
||||
|
||||
enum state_t
|
||||
{
|
||||
STOPPED,
|
||||
IDLE,
|
||||
POLLING,
|
||||
PROCESSING,
|
||||
ZPROCESSING
|
||||
};
|
||||
|
||||
enum execute_mode_t
|
||||
{
|
||||
EXECUTE_AUTO, /**< Execute tasks immediately */
|
||||
EXECUTE_QUEUED /**< Only queue tasks for execution */
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the worker mechanism.
|
||||
*
|
||||
* To be called once at process startup. This will cause as many workers
|
||||
* to be created as the number of threads defined.
|
||||
*
|
||||
* @return True if the initialization succeeded, false otherwise.
|
||||
*/
|
||||
static bool init();
|
||||
|
||||
/**
|
||||
* Finalize the worker mechanism.
|
||||
*
|
||||
* To be called once at process shutdown. This will cause all workers
|
||||
* to be destroyed. When the function is called, no worker should be
|
||||
* running anymore.
|
||||
*/
|
||||
static void finish();
|
||||
|
||||
/**
|
||||
* Returns the id of the worker
|
||||
*
|
||||
* @return The id of the worker.
|
||||
*/
|
||||
int id() const
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the state of the worker.
|
||||
*
|
||||
* @return The current state.
|
||||
*
|
||||
* @attentions The state might have changed the moment after the function returns.
|
||||
*/
|
||||
state_t state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns statistics for this worker.
|
||||
*
|
||||
* @return The worker specific statistics.
|
||||
*
|
||||
* @attentions The statistics may change at any time.
|
||||
*/
|
||||
const STATISTICS& statistics() const
|
||||
{
|
||||
return m_statistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns statistics for all workers.
|
||||
*
|
||||
* @return Combined statistics.
|
||||
*
|
||||
* @attentions The statistics may no longer be accurate by the time it has
|
||||
* been returned. The returned values may also not represent a
|
||||
* 100% consistent set.
|
||||
*/
|
||||
static STATISTICS get_statistics();
|
||||
|
||||
/**
|
||||
* Return a specific combined statistic value.
|
||||
*
|
||||
* @param what What to return.
|
||||
*
|
||||
* @return The corresponding value.
|
||||
*/
|
||||
static int64_t get_one_statistic(POLL_STAT what);
|
||||
|
||||
/**
|
||||
* Return this worker's statistics.
|
||||
*
|
||||
* @return Local statistics for this worker.
|
||||
*/
|
||||
const STATISTICS& get_local_statistics() const
|
||||
{
|
||||
return m_statistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a file descriptor to the epoll instance of the worker.
|
||||
*
|
||||
* @param fd The file descriptor to be added.
|
||||
* @param events Mask of epoll event types.
|
||||
* @param pData The poll data associated with the descriptor:
|
||||
*
|
||||
* data->handler : Handler that knows how to deal with events
|
||||
* for this particular type of 'struct mxs_poll_data'.
|
||||
* data->thread.id: Will be updated by the worker.
|
||||
*
|
||||
* @attention The provided file descriptor must be non-blocking.
|
||||
* @attention @c pData must remain valid until the file descriptor is
|
||||
* removed from the worker.
|
||||
*
|
||||
* @return True, if the descriptor could be added, false otherwise.
|
||||
*/
|
||||
bool add_fd(int fd, uint32_t events, MXS_POLL_DATA* pData);
|
||||
|
||||
/**
|
||||
* Add a file descriptor to the epoll instance shared between all workers.
|
||||
* Events occuring on the provided file descriptor will be handled by all
|
||||
* workers. This is primarily intended for listening sockets where the
|
||||
* only event is EPOLLIN, signaling that accept() can be used on the listening
|
||||
* socket for creating a connected socket to a client.
|
||||
*
|
||||
* @param fd The file descriptor to be added.
|
||||
* @param events Mask of epoll event types.
|
||||
* @param pData The poll data associated with the descriptor:
|
||||
*
|
||||
* data->handler : Handler that knows how to deal with events
|
||||
* for this particular type of 'struct mxs_poll_data'.
|
||||
* data->thread.id: 0
|
||||
*
|
||||
* @return True, if the descriptor could be added, false otherwise.
|
||||
*/
|
||||
static bool add_shared_fd(int fd, uint32_t events, MXS_POLL_DATA* pData);
|
||||
|
||||
/**
|
||||
* Remove a file descriptor from the worker's epoll instance.
|
||||
*
|
||||
* @param fd The file descriptor to be removed.
|
||||
*
|
||||
* @return True on success, false on failure.
|
||||
*/
|
||||
bool remove_fd(int fd);
|
||||
|
||||
/**
|
||||
* Remove a file descriptor from the epoll instance shared between all workers.
|
||||
*
|
||||
* @param fd The file descriptor to be removed.
|
||||
*
|
||||
* @return True on success, false on failure.
|
||||
*/
|
||||
static bool remove_shared_fd(int fd);
|
||||
|
||||
/**
|
||||
* Register zombie for later deletion.
|
||||
*
|
||||
* @param pZombie DCB that will be deleted at end of event loop.
|
||||
*
|
||||
* @note The DCB must be owned by this worker.
|
||||
*/
|
||||
void register_zombie(DCB* pZombie);
|
||||
|
||||
/**
|
||||
* Main function of worker.
|
||||
*
|
||||
* The worker will run the poll loop, until it is told to shut down.
|
||||
*
|
||||
* @attention This function will run in the calling thread.
|
||||
*/
|
||||
void run();
|
||||
|
||||
/**
|
||||
* Run worker in separate thread.
|
||||
*
|
||||
* This function will start a new thread, in which the `run`
|
||||
* function will be executed.
|
||||
*
|
||||
* @param stack_size The stack size of the new thread. A value of 0 means
|
||||
* that the pthread default should be used.
|
||||
*
|
||||
* @return True if the thread could be started, false otherwise.
|
||||
*/
|
||||
bool start(size_t stack_size = 0);
|
||||
|
||||
/**
|
||||
* Waits for the worker to finish.
|
||||
*/
|
||||
void join();
|
||||
|
||||
/**
|
||||
* Initate shutdown of worker.
|
||||
*
|
||||
* @attention A call to this function will only initiate the shutdowm,
|
||||
* the worker will not have shut down when the function returns.
|
||||
*
|
||||
* @attention This function is signal safe.
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* Query whether worker should shutdown.
|
||||
*
|
||||
* @return True, if the worker should shut down, false otherwise.
|
||||
*/
|
||||
bool should_shutdown() const
|
||||
{
|
||||
return m_should_shutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts a task to a worker for execution.
|
||||
*
|
||||
* @param pTask The task to be executed.
|
||||
* @param pSem If non-NULL, will be posted once the task's `execute` return.
|
||||
* @param mode Execution mode
|
||||
*
|
||||
* @return True if the task could be posted (i.e. not executed), false otherwise.
|
||||
*
|
||||
* @attention The instance must remain valid for as long as it takes for the
|
||||
* task to be transferred to the worker and its `execute` function
|
||||
* to be called.
|
||||
*
|
||||
* The semaphore can be used for waiting for the task to be finished.
|
||||
*
|
||||
* @code
|
||||
* Semaphore sem;
|
||||
* MyTask task;
|
||||
*
|
||||
* pWorker->execute(&task, &sem);
|
||||
* sem.wait();
|
||||
*
|
||||
* MyResult& result = task.result();
|
||||
* @endcode
|
||||
*/
|
||||
bool post(Task* pTask, Semaphore* pSem = NULL, enum execute_mode_t mode = EXECUTE_AUTO);
|
||||
|
||||
/**
|
||||
* Posts a task to a worker for execution.
|
||||
*
|
||||
* @param pTask The task to be executed.
|
||||
* @param mode Execution mode
|
||||
*
|
||||
* @return True if the task could be posted (i.e. not executed), false otherwise.
|
||||
*
|
||||
* @attention Once the task has been executed, it will be deleted.
|
||||
*/
|
||||
bool post(std::auto_ptr<DisposableTask> sTask, enum execute_mode_t mode = EXECUTE_AUTO);
|
||||
|
||||
template<class T>
|
||||
bool post(std::auto_ptr<T> sTask, enum execute_mode_t mode = EXECUTE_AUTO)
|
||||
{
|
||||
return post(std::auto_ptr<DisposableTask>(sTask.release()), mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts a task to all workers for execution.
|
||||
*
|
||||
* @param pTask The task to be executed.
|
||||
* @param pSem If non-NULL, will be posted once per worker when the task's
|
||||
* `execute` return.
|
||||
*
|
||||
* @return How many workers the task was posted to.
|
||||
*
|
||||
* @attention The very same task will be posted to all workers. The task
|
||||
* should either not have any sharable data or then it should
|
||||
* have data specific to each worker that can be accessed
|
||||
* without locks.
|
||||
*/
|
||||
static size_t broadcast(Task* pTask, Semaphore* pSem = NULL);
|
||||
|
||||
/**
|
||||
* Posts a task to all workers for execution.
|
||||
*
|
||||
* @param pTask The task to be executed.
|
||||
*
|
||||
* @return How many workers the task was posted to.
|
||||
*
|
||||
* @attention The very same task will be posted to all workers. The task
|
||||
* should either not have any sharable data or then it should
|
||||
* have data specific to each worker that can be accessed
|
||||
* without locks.
|
||||
*
|
||||
* @attention Once the task has been executed by all workers, it will
|
||||
* be deleted.
|
||||
*/
|
||||
static size_t broadcast(std::auto_ptr<DisposableTask> sTask);
|
||||
|
||||
template<class T>
|
||||
static size_t broadcast(std::auto_ptr<T> sTask)
|
||||
{
|
||||
return broadcast(std::auto_ptr<DisposableTask>(sTask.release()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a task on all workers in serial mode (the task is executed
|
||||
* on at most one worker thread at a time). When the function returns
|
||||
* the task has been executed on all workers.
|
||||
*
|
||||
* @param task The task to be executed.
|
||||
*
|
||||
* @return How many workers the task was posted to.
|
||||
*
|
||||
* @warning This function is extremely inefficient and will be slow compared
|
||||
* to the other functions. Only use this function when printing thread-specific
|
||||
* data to stdout.
|
||||
*/
|
||||
static size_t execute_serially(Task& task);
|
||||
|
||||
/**
|
||||
* Executes a task on all workers concurrently and waits until all workers
|
||||
* are done. That is, when the function returns the task has been executed
|
||||
* by all workers.
|
||||
*
|
||||
* @param task The task to be executed.
|
||||
*
|
||||
* @return How many workers the task was posted to.
|
||||
*/
|
||||
static size_t execute_concurrently(Task& task);
|
||||
|
||||
/**
|
||||
* Post a message to a worker.
|
||||
*
|
||||
* @param msg_id The message id.
|
||||
* @param arg1 Message specific first argument.
|
||||
* @param arg2 Message specific second argument.
|
||||
*
|
||||
* @return True if the message could be sent, false otherwise. If the message
|
||||
* posting fails, errno is set appropriately.
|
||||
*
|
||||
* @attention The return value tells *only* whether the message could be sent,
|
||||
* *not* that it has reached the worker.
|
||||
*
|
||||
* @attention This function is signal safe.
|
||||
*/
|
||||
bool post_message(uint32_t msg_id, intptr_t arg1, intptr_t arg2);
|
||||
|
||||
/**
|
||||
* Return a reference to the session registry of this worker.
|
||||
*
|
||||
* @return Session registry.
|
||||
*/
|
||||
SessionsById& session_registry();
|
||||
|
||||
/**
|
||||
* Broadcast a message to all worker.
|
||||
*
|
||||
* @param msg_id The message id.
|
||||
* @param arg1 Message specific first argument.
|
||||
* @param arg2 Message specific second argument.
|
||||
*
|
||||
* @return The number of messages posted; if less that ne number of workers
|
||||
* then some postings failed.
|
||||
*
|
||||
* @attention The return value tells *only* whether message could be posted,
|
||||
* *not* that it has reached the worker.
|
||||
*
|
||||
* @attentsion Exactly the same arguments are passed to all workers. Take that
|
||||
* into account if the passed data must be freed.
|
||||
*
|
||||
* @attention This function is signal safe.
|
||||
*/
|
||||
static size_t broadcast_message(uint32_t msg_id, intptr_t arg1, intptr_t arg2);
|
||||
|
||||
/**
|
||||
* Initate shutdown of all workers.
|
||||
*
|
||||
* @attention A call to this function will only initiate the shutdowm,
|
||||
* the workers will not have shut down when the function returns.
|
||||
*
|
||||
* @attention This function is signal safe.
|
||||
*/
|
||||
static void shutdown_all();
|
||||
|
||||
/**
|
||||
* Return the worker associated with the provided worker id.
|
||||
*
|
||||
* @param worker_id A worker id.
|
||||
*
|
||||
* @return The corresponding worker instance, or NULL if the id does
|
||||
* not correspond to a worker.
|
||||
*/
|
||||
static Worker* get(int worker_id);
|
||||
|
||||
/**
|
||||
* Return the worker associated with the current thread.
|
||||
*
|
||||
* @return The worker instance, or NULL if the current thread does not have a worker.
|
||||
*/
|
||||
static Worker* get_current();
|
||||
|
||||
/**
|
||||
* Return the worker id associated with the current thread.
|
||||
*
|
||||
* @return A worker instance, or -1 if the current thread does not have a worker.
|
||||
*/
|
||||
static int get_current_id();
|
||||
|
||||
/**
|
||||
* Set the number of non-blocking poll cycles that will be done before
|
||||
* a blocking poll will take place.
|
||||
*
|
||||
* @param nbpolls Number of non-blocking polls to perform before blocking.
|
||||
*/
|
||||
static void set_nonblocking_polls(unsigned int nbpolls);
|
||||
|
||||
/**
|
||||
* Maximum time to block in epoll_wait.
|
||||
*
|
||||
* @param maxwait Maximum wait time in millliseconds.
|
||||
*/
|
||||
static void set_maxwait(unsigned int maxwait);
|
||||
|
||||
private:
|
||||
Worker(int id,
|
||||
int epoll_fd);
|
||||
virtual ~Worker();
|
||||
|
||||
static Worker* create(int id, int epoll_listener_fd);
|
||||
|
||||
void delete_zombies();
|
||||
|
||||
bool post_disposable(DisposableTask* pTask, enum execute_mode_t mode = EXECUTE_AUTO);
|
||||
|
||||
void handle_message(MessageQueue& queue, const MessageQueue::Message& msg); // override
|
||||
|
||||
static void thread_main(void* arg);
|
||||
|
||||
void poll_waitevents();
|
||||
|
||||
static uint32_t epoll_instance_handler(struct mxs_poll_data* data, int wid, uint32_t events);
|
||||
uint32_t handle_epoll_events(uint32_t events);
|
||||
|
||||
private:
|
||||
int m_id; /*< The id of the worker. */
|
||||
state_t m_state; /*< The state of the worker */
|
||||
int m_epoll_fd; /*< The epoll file descriptor. */
|
||||
STATISTICS m_statistics; /*< Worker statistics. */
|
||||
MessageQueue* m_pQueue; /*< The message queue of the worker. */
|
||||
THREAD m_thread; /*< The thread handle of the worker. */
|
||||
bool m_started; /*< Whether the thread has been started or not. */
|
||||
bool m_should_shutdown; /*< Whether shutdown should be performed. */
|
||||
bool m_shutdown_initiated; /*< Whether shutdown has been initated. */
|
||||
SessionsById m_sessions; /*< A mapping of session_id->MXS_SESSION. The map
|
||||
* should contain sessions exclusive to this
|
||||
* worker and not e.g. listener sessions. For now,
|
||||
* it's up to the protocol to decide whether a new
|
||||
* session is added to the map. */
|
||||
Zombies m_zombies; /*< DCBs to be deleted. */
|
||||
};
|
||||
|
||||
}
|
||||
84
server/core/internal/workertask.hh
Normal file
84
server/core/internal/workertask.hh
Normal file
@ -0,0 +1,84 @@
|
||||
#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 <maxscale/cppdefs.hh>
|
||||
|
||||
namespace maxscale
|
||||
{
|
||||
|
||||
class Worker;
|
||||
|
||||
/**
|
||||
* A WorkerTask represents a task to be performed by a Worker.
|
||||
*/
|
||||
class WorkerTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~WorkerTask();
|
||||
|
||||
/**
|
||||
* @brief Called in the context of a specific worker.
|
||||
*
|
||||
* @param worker The worker in whose context `execute` is called.
|
||||
*
|
||||
* @attention As the function is called by a worker, the body of `execute`
|
||||
* should execute quickly and not perform any blocking operations.
|
||||
*/
|
||||
virtual void execute(Worker& worker) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A WorkerDisposableTask represents a task to be performed by a Worker.
|
||||
*
|
||||
* When the task has been executed, the instance will automatically be
|
||||
* deleted.
|
||||
*/
|
||||
class WorkerDisposableTask
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~WorkerDisposableTask();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
WorkerDisposableTask();
|
||||
|
||||
/**
|
||||
* @brief Called in the context of a specific worker.
|
||||
*
|
||||
* @param worker The worker in whose context `execute` is called.
|
||||
*
|
||||
* @attention As the function is called by a worker, the body of `execute`
|
||||
* should execute quickly and not perform any blocking operations.
|
||||
*/
|
||||
virtual void execute(Worker& worker) = 0;
|
||||
|
||||
private:
|
||||
friend class Worker;
|
||||
|
||||
void inc_ref();
|
||||
void dec_ref();
|
||||
|
||||
private:
|
||||
int32_t m_count;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user