Move headers from server/include to include/maxscale

- Headers now to be included as <maxscale/xyz.h>
- First step, no cleanup of headers has been made. Only moving
  from one place to another + necessary modifications.
This commit is contained in:
Johan Wikman
2016-10-13 15:20:51 +03:00
parent ef5bbd9353
commit e41589be10
235 changed files with 1010 additions and 1010 deletions

View File

@ -0,0 +1,66 @@
#ifndef _ADMINUSERS_H
#define _ADMINUSERS_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/bsl.
*
* Change Date: 2019-07-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 adminusers.h - Administration users support routines
*
* @verbatim
* Revision History
*
* Date Who Description
* 18/07/13 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <maxscale/dcb.h>
#define ADMIN_SALT "$1$MXS"
/* Max length of fields in for admin users */
#define ADMIN_USER_MAXLEN 128
#define ADMIN_PASSWORD_MAXLEN 128
/** Default user for the administrative interface */
#define DEFAULT_ADMIN_USER "@DEFAULT_ADMIN_USER@"
/*
* MySQL session specific data
*
*/
typedef struct admin_session
{
#if defined(SS_DEBUG)
skygw_chk_t adminses_chk_top;
#endif
char user[ADMIN_USER_MAXLEN + 1]; /*< username */
bool validated; /* Was user validated? */
#if defined(SS_DEBUG)
skygw_chk_t adminses_chk_tail;
#endif
} ADMIN_session;
extern const char *admin_enable_linux_account(const char *uname);
extern const char *admin_disable_linux_account(const char *uname);
extern bool admin_linux_account_enabled(const char *uname);
extern const char *admin_add_inet_user(const char *uname, const char *password);
extern const char *admin_remove_inet_user(const char *uname, const char *password);
extern bool admin_inet_user_exists(const char *uname);
extern bool admin_verify_inet_user(const char *uname, const char *password);
extern void dcb_PrintAdminUsers(DCB *dcb);
#endif

82
include/maxscale/alloc.h Normal file
View File

@ -0,0 +1,82 @@
#ifndef _MAXSCALE_ALLOC_H
#define _MAXSCALE_ALLOC_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/bsl.
*
* Change Date: 2019-07-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 <stdlib.h>
#include <string.h>
#include <maxscale/skygw_debug.h>
EXTERN_C_BLOCK_BEGIN
/*
* NOTE: Do not use these functions directly, use the macros below.
*/
// "caller" arg temporarily disabled so that existing code
// using the previous version of mxs_alloc etc. will continue
// to compile.
void *mxs_malloc(size_t size/*, const char *caller*/);
void *mxs_calloc(size_t nmemb, size_t size/*, const char *caller*/);
void *mxs_realloc(void *ptr, size_t size/*, const char *caller*/);
void mxs_free(void *ptr/*, const char *caller*/);
char *mxs_strdup(const char *s/*, const char *caller*/);
char *mxs_strndup(const char *s, size_t n/*, const char *caller*/);
char *mxs_strdup_a(const char *s/*, const char *caller*/);
char *mxs_strndup_a(const char *s, size_t n/*, const char *caller*/);
/*
* NOTE: USE these macros instead of the functions above.
*/
#define MXS_MALLOC(size) mxs_malloc(size/*, __func__*/)
#define MXS_CALLOC(nmemb, size) mxs_calloc(nmemb, size/*, __func__*/)
#define MXS_REALLOC(ptr, size) mxs_realloc(ptr, size/*, __func__*/)
#define MXS_FREE(ptr) mxs_free(ptr/*, __func__*/)
#define MXS_STRDUP(s) mxs_strdup(s/*, __func__*/)
#define MXS_STRNDUP(s, n) mxs_strndup(s, n/*, __func__*/)
#define MXS_STRDUP_A(s) mxs_strdup_a(s/*, __func__*/)
#define MXS_STRNDUP_A(s, n) mxs_strndup_a(s, n/*, __func__*/)
/**
* @brief Abort the process if the pointer is NULL.
*
* To be used in circumstances where a memory allocation failure
* cannot - currently - be dealt with properly.
*/
#define MXS_ABORT_IF_NULL(p) do { if (!p) { abort(); } } while (false)
/**
* @brief Abort the process if the provided value is non-zero.
*
* To be used in circumstances where a memory allocation or other
* fatal error cannot - currently - be dealt with properly.
*/
#define MXS_ABORT_IF_TRUE(b) do { if (b) { abort(); } } while (false)
/**
* @brief Abort the process if the provided value is zero.
*
* To be used in circumstances where a memory allocation or other
* fatal error cannot - currently - be dealt with properly.
*/
#define MXS_ABORT_IF_FALSE(b) do { if (!b) { abort(); } } while (false)
EXTERN_C_BLOCK_END
#endif

34
include/maxscale/atomic.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef _ATOMIC_H
#define _ATOMIC_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/bsl.
*
* Change Date: 2019-07-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 atomic.h The atomic operations used within the gateway
*
* @verbatim
* Revision History
*
* Date Who Description
* 10/06/13 Mark Riddoch Initial implementation
* 23/06/15 Martin Brampton Alternative for C++
*
* @endverbatim
*/
#ifdef __cplusplus
extern "C" int atomic_add(int *variable, int value);
#else
extern int atomic_add(int *variable, int value);
#endif
#endif

220
include/maxscale/buffer.h Normal file
View File

@ -0,0 +1,220 @@
#ifndef _BUFFER_H
#define _BUFFER_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/bsl.
*
* Change Date: 2019-07-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 buffer.h Definitions relating the gateway buffer manipulation facilities.
*
* These are used to store all data coming in form or going out to the client and the
* backend structures.
*
* The buffers are designed to be used in linked lists and such that they may be passed
* from one side of the gateway to another without the need to copy data. It may be the case
* that not all of the data in the buffer is valid, to this end a start and end pointer are
* included that point to the first valid byte in the buffer and the first byte after the
* last valid byte. This allows data to be consumed from either end of the buffer whilst
* still allowing for the copy free semantics of the buffering system.
*
* @verbatim
* Revision History
*
* Date Who Description
* 10/06/2013 Mark Riddoch Initial implementation
* 11/07/2013 Mark Riddoch Addition of reference count in the gwbuf
* 16/07/2013 Massimiliano Pinto Added command type for the queue
* 10/07/2014 Mark Riddoch Addition of hints
* 15/07/2014 Mark Riddoch Added buffer properties
* 03/10/2014 Martin Brampton Pointer arithmetic standard conformity
* Add more buffer handling macros
* Add gwbuf_rtrim (handle chains)
* 09/11/2014 Martin Brampton Add dprintAllBuffers (conditional compilation)
*
* @endverbatim
*/
#include <string.h>
#include <maxscale/skygw_debug.h>
#include <maxscale/hint.h>
#include <maxscale/spinlock.h>
#include <stdint.h>
EXTERN_C_BLOCK_BEGIN
/**
* Buffer properties - used to store properties related to the buffer
* contents. This may be added at any point during the processing of the
* data, especially in the protocol stage of the processing.
*/
typedef struct buf_property
{
char *name;
char *value;
struct buf_property *next;
} BUF_PROPERTY;
typedef enum
{
GWBUF_TYPE_UNDEFINED = 0x00,
GWBUF_TYPE_PLAINSQL = 0x01,
GWBUF_TYPE_MYSQL = 0x02,
GWBUF_TYPE_SINGLE_STMT = 0x04,
GWBUF_TYPE_SESCMD_RESPONSE = 0x08,
GWBUF_TYPE_RESPONSE_END = 0x10,
GWBUF_TYPE_SESCMD = 0x20,
GWBUF_TYPE_HTTP = 0x40
} gwbuf_type_t;
#define GWBUF_IS_TYPE_UNDEFINED(b) (b->gwbuf_type == 0)
#define GWBUF_IS_TYPE_PLAINSQL(b) (b->gwbuf_type & GWBUF_TYPE_PLAINSQL)
#define GWBUF_IS_TYPE_MYSQL(b) (b->gwbuf_type & GWBUF_TYPE_MYSQL)
#define GWBUF_IS_TYPE_SINGLE_STMT(b) (b->gwbuf_type & GWBUF_TYPE_SINGLE_STMT)
#define GWBUF_IS_TYPE_SESCMD_RESPONSE(b) (b->gwbuf_type & GWBUF_TYPE_SESCMD_RESPONSE)
#define GWBUF_IS_TYPE_RESPONSE_END(b) (b->gwbuf_type & GWBUF_TYPE_RESPONSE_END)
#define GWBUF_IS_TYPE_SESCMD(b) (b->gwbuf_type & GWBUF_TYPE_SESCMD)
/**
* A structure to encapsulate the data in a form that the data itself can be
* shared between multiple GWBUF's without the need to make multiple copies
* but still maintain separate data pointers.
*/
typedef struct
{
unsigned char *data; /*< Physical memory that was allocated */
int refcount; /*< Reference count on the buffer */
} SHARED_BUF;
typedef enum
{
GWBUF_INFO_NONE = 0x0,
GWBUF_INFO_PARSED = 0x1
} gwbuf_info_t;
#define GWBUF_IS_PARSED(b) (b->gwbuf_info & GWBUF_INFO_PARSED)
/**
* A structure for cleaning up memory allocations of structures which are
* referred to by GWBUF and deallocated in gwbuf_free but GWBUF doesn't
* know what they are.
* All functions on the list are executed before freeing memory of GWBUF struct.
*/
typedef enum
{
GWBUF_PARSING_INFO
} bufobj_id_t;
typedef struct buffer_object_st buffer_object_t;
struct buffer_object_st
{
bufobj_id_t bo_id;
void* bo_data;
void (*bo_donefun_fp)(void *);
buffer_object_t* bo_next;
};
/**
* The buffer structure used by the descriptor control blocks.
*
* Linked lists of buffers are created as data is read from a descriptor
* or written to a descriptor. The use of linked lists of buffers with
* flexible data pointers is designed to minimise the need for data to
* be copied within the gateway.
*/
typedef struct gwbuf
{
SPINLOCK gwbuf_lock;
struct gwbuf *next; /*< Next buffer in a linked chain of buffers */
struct gwbuf *tail; /*< Last buffer in a linked chain of buffers */
void *start; /*< Start of the valid data */
void *end; /*< First byte after the valid data */
SHARED_BUF *sbuf; /*< The shared buffer with the real data */
buffer_object_t *gwbuf_bufobj; /*< List of objects referred to by GWBUF */
gwbuf_info_t gwbuf_info; /*< Info bits */
gwbuf_type_t gwbuf_type; /*< buffer's data type information */
HINT *hint; /*< Hint data for this buffer */
BUF_PROPERTY *properties; /*< Buffer properties */
} GWBUF;
/*<
* Macros to access the data in the buffers
*/
/*< First valid, unconsumed byte in the buffer */
#define GWBUF_DATA(b) ((b)->start)
/*< Number of bytes in the individual buffer */
#define GWBUF_LENGTH(b) ((char *)(b)->end - (char *)(b)->start)
/*< Return the byte at offset byte from the start of the unconsumed portion of the buffer */
#define GWBUF_DATA_CHAR(b, byte) (GWBUF_LENGTH(b) < ((byte)+1) ? -1 : *(((char *)(b)->start)+4))
/*< Check that the data in a buffer has the SQL marker*/
#define GWBUF_IS_SQL(b) (0x03 == GWBUF_DATA_CHAR(b,4))
/*< Check whether the buffer is contiguous*/
#define GWBUF_IS_CONTIGUOUS(b) (((b) == NULL) || ((b)->next == NULL))
/*< True if all bytes in the buffer have been consumed */
#define GWBUF_EMPTY(b) ((char *)(b)->start >= (char *)(b)->end)
/*< Consume a number of bytes in the buffer */
#define GWBUF_CONSUME(b, bytes) ((b)->start = bytes > ((char *)(b)->end - (char *)(b)->start) ? (b)->end : (void *)((char *)(b)->start + (bytes)));
/*< Check if a given pointer is within the buffer */
#define GWBUF_POINTER_IN_BUFFER (ptr, b)\
((char *)(ptr) >= (char *)(b)->start && (char *)(ptr) < (char *)(b)->end)
/*< Consume a complete buffer */
#define GWBUF_CONSUME_ALL(b) gwbuf_consume((b), GWBUF_LENGTH((b)))
#define GWBUF_RTRIM(b, bytes)\
((b)->end = bytes > ((char *)(b)->end - (char *)(b)->start) ? (b)->start : \
(void *)((char *)(b)->end - (bytes)));
#define GWBUF_TYPE(b) (b)->gwbuf_type
/*<
* Function prototypes for the API to maniplate the buffers
*/
extern GWBUF *gwbuf_alloc(unsigned int size);
extern GWBUF *gwbuf_alloc_and_load(unsigned int size, const void *data);
extern void gwbuf_free(GWBUF *buf);
extern GWBUF *gwbuf_clone(GWBUF *buf);
extern GWBUF *gwbuf_append(GWBUF *head, GWBUF *tail);
extern GWBUF *gwbuf_consume(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_trim(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_rtrim(GWBUF *head, unsigned int length);
extern unsigned int gwbuf_length(GWBUF *head);
extern int gwbuf_count(GWBUF *head);
extern size_t gwbuf_copy_data(GWBUF *buffer, size_t offset, size_t bytes,
uint8_t* dest);
extern GWBUF *gwbuf_split(GWBUF **buf, size_t length);
extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type);
extern GWBUF *gwbuf_clone_all(GWBUF* head);
extern void gwbuf_set_type(GWBUF *head, gwbuf_type_t type);
extern int gwbuf_add_property(GWBUF *buf, char *name, char *value);
extern char *gwbuf_get_property(GWBUF *buf, char *name);
extern GWBUF *gwbuf_make_contiguous(GWBUF *);
extern int gwbuf_add_hint(GWBUF *, HINT *);
void gwbuf_add_buffer_object(GWBUF* buf,
bufobj_id_t id,
void* data,
void (*donefun_fp)(void *));
void* gwbuf_get_buffer_object_data(GWBUF* buf, bufobj_id_t id);
#if defined(BUFFER_TRACE)
extern void dprintAllBuffers(void *pdcb);
#endif
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,80 @@
#ifndef _DBUSERS_H
#define _DBUSERS_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/bsl.
*
* Change Date: 2019-07-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>
#include <arpa/inet.h>
/**
* @file dbusers.h Extarct user information form the backend database
*
* @verbatim
* Revision History
*
* Date Who Description
* 25/06/13 Mark Riddoch Initial implementation
* 25/02/13 Massimiliano Pinto Added users table refresh rate default values
* 28/02/14 Massimiliano Pinto Added MySQL user and host data structure
* 03/10/14 Massimiliano Pinto Added netmask to MySQL user and host data structure
* 13/10/14 Massimiliano Pinto Added resource to MySQL user and host data structure
*
* @endverbatim
*/
/* Refresh rate limits for load users from database */
#define USERS_REFRESH_TIME 30 /* Allowed time interval (in seconds) after last update*/
#define USERS_REFRESH_MAX_PER_TIME 4 /* Max number of load calls within the time interval */
/** Default timeout values used by the connections which fetch user authentication data */
#define DEFAULT_AUTH_CONNECT_TIMEOUT 3
#define DEFAULT_AUTH_READ_TIMEOUT 1
#define DEFAULT_AUTH_WRITE_TIMEOUT 2
/* Max length of fields in the mysql.user table */
#define MYSQL_USER_MAXLEN 128
#define MYSQL_PASSWORD_LEN 41
#define MYSQL_HOST_MAXLEN 60
#define MYSQL_DATABASE_MAXLEN 128
#define MYSQL_TABLE_MAXLEN 64
/** Cache directory and file names */
static const char DBUSERS_DIR[] = "cache";
static const char DBUSERS_FILE[] = "dbusers";
/**
* MySQL user and host data structure
*/
typedef struct mysql_user_host_key
{
char *user;
struct sockaddr_in ipv4;
int netmask;
char *resource;
char hostname[MYSQL_HOST_MAXLEN + 1];
} MYSQL_USER_HOST;
extern int add_mysql_users_with_host_ipv4(USERS *users, const char *user, const char *host,
char *passwd, const char *anydb, const char *db);
extern bool check_service_permissions(SERVICE* service);
extern int dbusers_load(USERS *, const char *filename);
extern int dbusers_save(USERS *, const char *filename);
extern int load_mysql_users(SERV_LISTENER *listener);
extern int mysql_users_add(USERS *users, MYSQL_USER_HOST *key, char *auth);
extern USERS *mysql_users_alloc();
extern char *mysql_users_fetch(USERS *users, MYSQL_USER_HOST *key);
extern int reload_mysql_users(SERV_LISTENER *listener);
extern int replace_mysql_users(SERV_LISTENER *listener);
#endif

372
include/maxscale/dcb.h Normal file
View File

@ -0,0 +1,372 @@
#ifndef _DCB_H
#define _DCB_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/bsl.
*
* Change Date: 2019-07-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/spinlock.h>
#include <maxscale/buffer.h>
#include <maxscale/listmanager.h>
#include <maxscale/gw_protocol.h>
#include <maxscale/gw_authenticator.h>
#include <maxscale/gw_ssl.h>
#include <maxscale/modinfo.h>
#include <maxscale/gwbitmask.h>
#include <maxscale/skygw_utils.h>
#include <netinet/in.h>
#define ERRHANDLE
struct session;
struct server;
struct service;
struct servlistener;
/**
* @file dcb.h The Descriptor Control Block
*
* The function pointer table used by descriptors to call relevant functions
* within the protocol specific code.
*
* @verbatim
* Revision History
*
* Date Who Description
* 01/06/2013 Mark Riddoch Initial implementation
* 11/06/2013 Mark Riddoch Updated GWPROTOCOL structure with new
* entry points
* 18/06/2013 Mark Riddoch Addition of the listener entry point
* 02/07/2013 Massimiliano Pinto Addition of delayqlock, delayq and authlock
* for handling backend asynchronous protocol connection
* and a generic lock for backend authentication
* 12/07/2013 Massimiliano Pinto Added auth entry point
* 15/07/2013 Massimiliano Pinto Added session entry point
* 16/07/2013 Massimiliano Pinto Added command type for dcb
* 07/02/2014 Massimiliano Pinto Added ipv4 data struct into for dcb
* 07/05/2014 Mark Riddoch Addition of callback mechanism
* 08/05/2014 Mark Riddoch Addition of writeq high and low watermarks
* 27/08/2014 Mark Riddoch Addition of write event queuing
* 23/09/2014 Mark Riddoch New poll processing queue
* 19/06/2015 Martin Brampton Provision of persistent connections
* 20/01/2016 Martin Brampton Moved GWPROTOCOL to gw_protocol.h
* 01/02/2016 Martin Brampton Added fields for SSL and authentication
* 27/06/2016 Martin Brampton Changed DCB to conform to list manager
*
* @endverbatim
*/
struct dcb;
/**
* The event queue structure used in the polling loop to maintain a queue
* of events that need to be processed for the DCB.
*
* next The next DCB in the event queue
* prev The previous DCB in the event queue
* pending_events The events that are pending processing
* processing_events The evets currently being processed
* processing Flag to indicate the processing status of the DCB
* eventqlock Spinlock to protect this structure
* inserted Insertion time for logging purposes
* started Time that the processign started
*/
typedef struct
{
struct dcb *next;
struct dcb *prev;
uint32_t pending_events;
uint32_t processing_events;
int processing;
SPINLOCK eventqlock;
unsigned long inserted;
unsigned long started;
} DCBEVENTQ;
#define DCBEVENTQ_INIT {NULL, NULL, 0, 0, 0, SPINLOCK_INIT, 0, 0}
#define DCBFD_CLOSED -1
/**
* The statistics gathered on a descriptor control block
*/
typedef struct dcbstats
{
int n_reads; /*< Number of reads on this descriptor */
int n_writes; /*< Number of writes on this descriptor */
int n_accepts; /*< Number of accepts on this descriptor */
int n_buffered; /*< Number of buffered writes */
int n_high_water; /*< Number of crosses of high water mark */
int n_low_water; /*< Number of crosses of low water mark */
} DCBSTATS;
#define DCBSTATS_INIT {0}
/**
* The data structure that is embedded witin a DCB and manages the complex memory
* management issues of a DCB.
*
* The DCB structures are used as the user data within the polling loop. This means that
* polling threads may aschronously wake up and access these structures. It is not possible
* to simple remove the DCB from the epoll system and then free the data, as every thread
* that is currently running an epoll call must wake up and re-issue the epoll_wait system
* call, the is the only way we can be sure that no polling thread is pending a wakeup or
* processing an event that will access the DCB.
*
* We solve this issue by making the dcb_free routine merely mark a DCB as a zombie and
* place it on a special zombie list. Before placing the DCB on the zombie list we create
* a bitmask with a bit set in it for each active polling thread. Each thread will call
* a routine to process the zombie list at the end of the polling loop. This routine
* will clear the bit value that corresponds to the calling thread. Once the bitmask
* is completely cleared the DCB can finally be freed and removed from the zombie list.
*/
typedef struct
{
GWBITMASK bitmask; /*< The bitmask of threads */
struct dcb *next; /*< Next pointer for the zombie list */
} DCBMM;
#define DCBMM_INIT {GWBITMASK_INIT}
/* DCB states */
typedef enum
{
DCB_STATE_UNDEFINED, /*< State variable with no state */
DCB_STATE_ALLOC, /*< Memory allocated but not populated */
DCB_STATE_POLLING, /*< Waiting in the poll loop */
DCB_STATE_WAITING, /*< Client wanting a connection */
DCB_STATE_LISTENING, /*< The DCB is for a listening socket */
DCB_STATE_DISCONNECTED, /*< The socket is now closed */
DCB_STATE_NOPOLLING, /*< Removed from poll mask */
DCB_STATE_ZOMBIE, /*< DCB is no longer active, waiting to free it */
} dcb_state_t;
typedef enum
{
DCB_ROLE_SERVICE_LISTENER, /*< Receives initial connect requests from clients */
DCB_ROLE_CLIENT_HANDLER, /*< Serves dedicated client */
DCB_ROLE_BACKEND_HANDLER, /*< Serves back end connection */
DCB_ROLE_INTERNAL /*< Internal DCB not connected to the outside */
} dcb_role_t;
#define DCB_STRTYPE(dcb) (dcb->dcb_role == DCB_ROLE_CLIENT_HANDLER ? "Client DCB" : \
dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER ? "Backend DCB" : \
dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER ? "Listener DCB" : \
dcb->dcb_role == DCB_ROLE_INTERNAL ? "Internal DCB" : "Unknown DCB")
/**
* Callback reasons for the DCB callback mechanism.
*/
typedef enum
{
DCB_REASON_CLOSE, /*< The DCB is closing */
DCB_REASON_DRAINED, /*< The write delay queue has drained */
DCB_REASON_HIGH_WATER, /*< Cross high water mark */
DCB_REASON_LOW_WATER, /*< Cross low water mark */
DCB_REASON_ERROR, /*< An error was flagged on the connection */
DCB_REASON_HUP, /*< A hangup was detected */
DCB_REASON_NOT_RESPONDING /*< Server connection was lost */
} DCB_REASON;
/**
* Callback structure - used to track callbacks registered on a DCB
*/
typedef struct dcb_callback
{
DCB_REASON reason; /*< The reason for the callback */
int (*cb)(struct dcb *dcb, DCB_REASON reason, void *userdata);
void *userdata; /*< User data to be sent in the callback */
struct dcb_callback *next; /*< Next callback for this DCB */
} DCB_CALLBACK;
/**
* State of SSL connection
*/
typedef enum
{
SSL_HANDSHAKE_UNKNOWN, /*< The DCB has unknown SSL status */
SSL_HANDSHAKE_REQUIRED, /*< SSL handshake is needed */
SSL_HANDSHAKE_DONE, /*< The SSL handshake completed OK */
SSL_ESTABLISHED, /*< The SSL connection is in use */
SSL_HANDSHAKE_FAILED /*< The SSL handshake failed */
} SSL_STATE;
/**
* Descriptor Control Block
*
* A wrapper for a network descriptor within the gateway, it contains all the
* state information necessary to allow for the implementation of the asynchronous
* operation of the protocol and gateway functions. It also provides links to the service
* and session data that is required to route the information within the gateway.
*
* It is important to hold the state information here such that any thread within the
* gateway may be selected to execute the required actions when a network event occurs.
*
* Note that the first few fields (up to and including "entry_is_ready") must
* precisely match the LIST_ENTRY structure defined in the list manager.
*/
typedef struct dcb
{
LIST_ENTRY_FIELDS
skygw_chk_t dcb_chk_top;
bool dcb_errhandle_called; /*< this can be called only once */
bool dcb_is_zombie; /**< Whether the DCB is in the zombie list */
bool draining_flag; /**< Set while write queue is drained */
bool drain_called_while_busy; /**< Set as described */
dcb_role_t dcb_role;
SPINLOCK dcb_initlock;
DCBEVENTQ evq; /**< The event queue for this DCB */
int fd; /**< The descriptor */
dcb_state_t state; /**< Current descriptor state */
SSL_STATE ssl_state; /**< Current state of SSL if in use */
int flags; /**< DCB flags */
char *remote; /**< Address of remote end */
char *user; /**< User name for connection */
struct sockaddr_in ipv4; /**< remote end IPv4 address */
char *protoname; /**< Name of the protocol */
void *protocol; /**< The protocol specific state */
size_t protocol_packet_length; /**< How long the protocol specific packet is */
size_t protocol_bytes_processed; /**< How many bytes of a packet have been read */
struct session *session; /**< The owning session */
struct servlistener *listener; /**< For a client DCB, the listener data */
GWPROTOCOL func; /**< The protocol functions for this descriptor */
GWAUTHENTICATOR authfunc; /**< The authenticator functions for this descriptor */
int writeqlen; /**< Current number of byes in the write queue */
SPINLOCK writeqlock; /**< Write Queue spinlock */
GWBUF *writeq; /**< Write Data Queue */
SPINLOCK delayqlock; /**< Delay Backend Write Queue spinlock */
GWBUF *delayq; /**< Delay Backend Write Data Queue */
GWBUF *dcb_readqueue; /**< read queue for storing incomplete reads */
SPINLOCK authlock; /**< Generic Authorization spinlock */
DCBSTATS stats; /**< DCB related statistics */
unsigned int dcb_server_status; /*< the server role indicator from SERVER */
struct dcb *nextpersistent; /**< Next DCB in the persistent pool for SERVER */
time_t persistentstart; /**< Time when DCB placed in persistent pool */
struct service *service; /**< The related service */
void *data; /**< Specific client data, shared between DCBs of this session */
void *authenticator_data; /**< The authenticator data for this DCB */
DCBMM memdata; /**< The data related to DCB memory management */
SPINLOCK cb_lock; /**< The lock for the callbacks linked list */
DCB_CALLBACK *callbacks; /**< The list of callbacks for the DCB */
SPINLOCK pollinlock;
int pollinbusy;
int readcheck;
SPINLOCK polloutlock;
int polloutbusy;
int writecheck;
long last_read; /*< Last time the DCB received data */
int high_water; /**< High water mark */
int low_water; /**< Low water mark */
struct server *server; /**< The associated backend server */
SSL* ssl; /*< SSL struct for connection */
bool ssl_read_want_read; /*< Flag */
bool ssl_read_want_write; /*< Flag */
bool ssl_write_want_read; /*< Flag */
bool ssl_write_want_write; /*< Flag */
int dcb_port; /**< port of target server */
skygw_chk_t dcb_chk_tail;
} DCB;
#define DCB_INIT {.dcb_chk_top = CHK_NUM_DCB, .dcb_initlock = SPINLOCK_INIT, \
.evq = DCBEVENTQ_INIT, .ipv4 = {0}, .func = {0}, .authfunc = {0}, \
.writeqlock = SPINLOCK_INIT, .delayqlock = SPINLOCK_INIT, \
.authlock = SPINLOCK_INIT, .stats = {0}, .memdata = DCBMM_INIT, \
.cb_lock = SPINLOCK_INIT, .pollinlock = SPINLOCK_INIT, \
.fd = DCBFD_CLOSED, .stats = DCBSTATS_INIT, .ssl_state = SSL_HANDSHAKE_UNKNOWN, \
.state = DCB_STATE_ALLOC, .polloutlock = SPINLOCK_INIT, .dcb_chk_tail = CHK_NUM_DCB, \
.authenticator_data = NULL}
/**
* The DCB usage filer used for returning DCB's in use for a certain reason
*/
typedef enum
{
DCB_USAGE_CLIENT,
DCB_USAGE_LISTENER,
DCB_USAGE_BACKEND,
DCB_USAGE_INTERNAL,
DCB_USAGE_ZOMBIE,
DCB_USAGE_ALL
} DCB_USAGE;
#if defined(FAKE_CODE)
extern unsigned char dcb_fake_write_errno[10240];
extern __int32_t dcb_fake_write_ev[10240];
extern bool fail_next_backend_fd;
extern bool fail_next_client_fd;
extern int fail_next_accept;
extern int fail_accept_errno;
#endif /* FAKE_CODE */
/* A few useful macros */
#define DCB_SESSION(x) (x)->session
#define DCB_PROTOCOL(x, type) (type *)((x)->protocol)
#define DCB_ISZOMBIE(x) ((x)->state == DCB_STATE_ZOMBIE)
#define DCB_WRITEQLEN(x) (x)->writeqlen
#define DCB_SET_LOW_WATER(x, lo) (x)->low_water = (lo);
#define DCB_SET_HIGH_WATER(x, hi) (x)->low_water = (hi);
#define DCB_BELOW_LOW_WATER(x) ((x)->low_water && (x)->writeqlen < (x)->low_water)
#define DCB_ABOVE_HIGH_WATER(x) ((x)->high_water && (x)->writeqlen > (x)->high_water)
#define DCB_POLL_BUSY(x) ((x)->evq.next != NULL)
DCB *dcb_get_zombies(void);
int dcb_write(DCB *, GWBUF *);
DCB *dcb_accept(DCB *listener, GWPROTOCOL *protocol_funcs);
bool dcb_pre_alloc(int number);
DCB *dcb_alloc(dcb_role_t, struct servlistener *);
void dcb_free(DCB *);
void dcb_free_all_memory(DCB *dcb);
DCB *dcb_connect(struct server *, struct session *, const char *);
DCB *dcb_clone(DCB *);
int dcb_read(DCB *, GWBUF **, int);
int dcb_drain_writeq(DCB *);
void dcb_close(DCB *);
DCB *dcb_process_zombies(int); /* Process Zombies except the one behind the pointer */
void printAllDCBs(); /* Debug to print all DCB in the system */
void printDCB(DCB *); /* Debug print routine */
void dprintDCBList(DCB *); /* Debug print DCB list statistics */
void dprintAllDCBs(DCB *); /* Debug to print all DCB in the system */
void dprintOneDCB(DCB *, DCB *); /* Debug to print one DCB */
void dprintDCB(DCB *, DCB *); /* Debug to print a DCB in the system */
void dListDCBs(DCB *); /* List all DCBs in the system */
void dListClients(DCB *); /* List al the client DCBs */
const char *gw_dcb_state2string(dcb_state_t); /* DCB state to string */
void dcb_printf(DCB *, const char *, ...) __attribute__((format(printf, 2, 3))); /* DCB version of printf */
void dcb_hashtable_stats(DCB *, void *); /**< Print statisitics */
int dcb_add_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *), void *);
int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *), void *);
int dcb_isvalid(DCB *); /* Check the DCB is in the linked list */
int dcb_count_by_usage(DCB_USAGE); /* Return counts of DCBs */
int dcb_persistent_clean_count(DCB *, bool); /* Clean persistent and return count */
void dcb_call_foreach (struct server* server, DCB_REASON reason);
void dcb_hangup_foreach (struct server* server);
size_t dcb_get_session_id(DCB* dcb);
bool dcb_get_ses_log_info(DCB* dcb, size_t* sesid, int* enabled_logs);
char *dcb_role_name(DCB *); /* Return the name of a role */
int dcb_accept_SSL(DCB* dcb);
int dcb_connect_SSL(DCB* dcb);
int dcb_listen(DCB *listener, const char *config, const char *protocol_name);
void dcb_append_readqueue(DCB *dcb, GWBUF *buffer);
/**
* DCB flags values
*/
#define DCBF_CLONE 0x0001 /*< DCB is a clone */
#define DCBF_HUNG 0x0002 /*< Hangup has been dispatched */
#define DCBF_REPLIED 0x0004 /*< DCB was written to */
#define DCB_IS_CLONE(d) ((d)->flags & DCBF_CLONE)
#define DCB_REPLIED(d) ((d)->flags & DCBF_REPLIED)
#endif /* _DCB_H */

View File

@ -0,0 +1,46 @@
/*
* 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/bsl.
*
* Change Date: 2019-07-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 def_monitor_event.h
*
* @verbatim
* Revision History
*
* Date Who Description
* 01-06-2013 Martin Brampton Initial implementation
*/
ADDITEM( UNDEFINED_MONITOR_EVENT, undefined ),
ADDITEM( MASTER_DOWN_EVENT, master_down ),
ADDITEM( MASTER_UP_EVENT, master_up ),
ADDITEM( SLAVE_DOWN_EVENT, slave_down ),
ADDITEM( SLAVE_UP_EVENT, slave_up ),
ADDITEM( SERVER_DOWN_EVENT, server_down ),
ADDITEM( SERVER_UP_EVENT, server_up ),
ADDITEM( SYNCED_DOWN_EVENT, synced_down ),
ADDITEM( SYNCED_UP_EVENT, synced_up ),
ADDITEM( DONOR_DOWN_EVENT, donor_down ),
ADDITEM( DONOR_UP_EVENT, donor_up ),
ADDITEM( NDB_DOWN_EVENT, ndb_down ),
ADDITEM( NDB_UP_EVENT, ndb_up ),
ADDITEM( LOST_MASTER_EVENT, lost_master ),
ADDITEM( LOST_SLAVE_EVENT, lost_slave ),
ADDITEM( LOST_SYNCED_EVENT, lost_synced ),
ADDITEM( LOST_DONOR_EVENT, lost_donor ),
ADDITEM( LOST_NDB_EVENT, lost_ndb ),
ADDITEM( NEW_MASTER_EVENT, new_master ),
ADDITEM( NEW_SLAVE_EVENT, new_slave ),
ADDITEM( NEW_SYNCED_EVENT, new_synced ),
ADDITEM( NEW_DONOR_EVENT, new_donor ),
ADDITEM( NEW_NDB_EVENT, new_ndb ),

View File

@ -0,0 +1,41 @@
#ifndef _EXTERN_CMD_HG
#define _EXTERN_CMD_HG
/*
* 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/bsl.
*
* Change Date: 2019-07-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 <unistd.h>
#include <string.h>
#include <errno.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
#include <maxscale/maxscale_pcre2.h>
#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 */
} EXTERNCMD;
char* externcmd_extract_command(const char* argstr);
EXTERNCMD* externcmd_allocate(char* argstr);
void externcmd_free(EXTERNCMD* cmd);
int externcmd_execute(EXTERNCMD* cmd);
bool externcmd_substitute_arg(EXTERNCMD* cmd, const char* re, const char* replace);
bool externcmd_can_execute(const char* argstr);
bool externcmd_matches(const EXTERNCMD* cmd, const char* match);
#endif

119
include/maxscale/filter.h Normal file
View File

@ -0,0 +1,119 @@
#ifndef _FILTER_H
#define _FILTER_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/bsl.
*
* Change Date: 2019-07-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 filter.h - The filter interface mechanisms
*
* Revision History
*
* Date Who Description
* 27/05/2014 Mark Riddoch Initial implementation
*
*/
#include <maxscale/dcb.h>
#include <maxscale/session.h>
#include <maxscale/buffer.h>
#include <stdint.h>
/**
* The FILTER handle points to module specific data, so the best we can do
* is to make it a void * externally.
*/
typedef void *FILTER;
/**
* The structure used to pass name, value pairs to the filter instances
*/
typedef struct
{
char *name; /**< Name of the parameter */
char *value; /**< Value of the parameter */
} FILTER_PARAMETER;
/**
* @verbatim
* The "module object" structure for a query router module
*
* The entry points are:
* createInstance Called by the service to create a new
* instance of the filter
* newSession Called to create a new user session
* within the filter
* closeSession Called when a session is closed
* freeSession Called when a session is freed
* setDownstream Sets the downstream component of the
* filter pipline
* routeQuery Called on each query that requires
* routing
* clientReply Called for each reply packet
* diagnostics Called to force the filter to print
* diagnostic output
*
* @endverbatim
*
* @see load_module
*/
typedef struct filter_object
{
FILTER *(*createInstance)(const char *name,
char **options,
FILTER_PARAMETER **params);
void *(*newSession)(FILTER *instance, SESSION *session);
void (*closeSession)(FILTER *instance, void *fsession);
void (*freeSession)(FILTER *instance, void *fsession);
void (*setDownstream)(FILTER *instance, void *fsession, DOWNSTREAM *downstream);
void (*setUpstream)(FILTER *instance, void *fsession, UPSTREAM *downstream);
int (*routeQuery)(FILTER *instance, void *fsession, GWBUF *queue);
int (*clientReply)(FILTER *instance, void *fsession, GWBUF *queue);
void (*diagnostics)(FILTER *instance, void *fsession, DCB *dcb);
} FILTER_OBJECT;
/**
* The filter API version. If the FILTER_OBJECT structure or the filter API
* is changed these values must be updated in line with the rules in the
* file modinfo.h.
*/
#define FILTER_VERSION {2, 1, 0}
/**
* The definition of a filter from the configuration file.
* This is basically the link between a plugin to load and the
* optons to pass to that plugin.
*/
typedef struct filter_def
{
char *name; /**< The Filter name */
char *module; /**< The module to load */
char **options; /**< The options set for this filter */
FILTER_PARAMETER **parameters; /**< The filter parameters */
FILTER filter; /**< The runtime filter */
FILTER_OBJECT *obj; /**< The "MODULE_OBJECT" for the filter */
SPINLOCK spin; /**< Spinlock to protect the filter definition */
struct filter_def *next; /**< Next filter in the chain of all filters */
} FILTER_DEF;
FILTER_DEF *filter_alloc(char *, char *);
void filter_free(FILTER_DEF *);
bool filter_load(FILTER_DEF* filter);
FILTER_DEF *filter_find(char *);
void filterAddOption(FILTER_DEF *, char *);
void filterAddParameter(FILTER_DEF *, char *, char *);
DOWNSTREAM *filterApply(FILTER_DEF *, SESSION *, DOWNSTREAM *);
UPSTREAM *filterUpstream(FILTER_DEF *, void *, UPSTREAM *);
int filter_standard_parameter(char *);
void dprintAllFilters(DCB *);
void dprintFilter(DCB *, FILTER_DEF *);
void dListFilters(DCB *);
#endif

86
include/maxscale/gw.h Normal file
View File

@ -0,0 +1,86 @@
#ifndef _GW_HG
#define _GW_HG
/*
* 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/bsl.
*
* Change Date: 2019-07-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 <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <fcntl.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <maxscale/gwdirs.h>
#define EXIT_FAILURE 1
// network buffer is 32K
#define MAX_BUFFER_SIZE 32768
/**
* Configuration for send and receive socket buffer sizes for
* backend and cleint connections.
*/
#define GW_BACKEND_SO_SNDBUF (128 * 1024)
#define GW_BACKEND_SO_RCVBUF (128 * 1024)
#define GW_CLIENT_SO_SNDBUF (128 * 1024)
#define GW_CLIENT_SO_RCVBUF (128 * 1024)
#define GW_NOINTR_CALL(A) do { errno = 0; A; } while (errno == EINTR)
#define GW_MYSQL_LOOP_TIMEOUT 300000000
#define GW_MYSQL_READ 0
#define GW_MYSQL_WRITE 1
#define GW_MYSQL_PROTOCOL_VERSION 10 // version is 10
#define GW_MYSQL_HANDSHAKE_FILLER 0x00
#define GW_MYSQL_SERVER_CAPABILITIES_BYTE1 0xff
#define GW_MYSQL_SERVER_CAPABILITIES_BYTE2 0xf7
#define GW_MYSQL_SERVER_LANGUAGE 0x08
#define GW_MYSQL_MAX_PACKET_LEN 0xffffffL;
#define GW_MYSQL_SCRAMBLE_SIZE 20
// debug for mysql_* functions
#define MYSQL_CONN_DEBUG
#undef MYSQL_CONN_DEBUG
#include "dcb.h"
bool gw_daemonize(void);
int do_read_dcb(DCB *dcb);
void MySQLListener(int epfd, char *config_bind);
int MySQLAccept(DCB *listener);
int do_read_dcb(DCB *dcb);
int do_read_10(DCB *dcb, uint8_t *buffer);
int MySQLWrite(DCB *dcb, GWBUF *queue);
int setnonblocking(int fd);
int gw_getsockerrno(int fd);
int parse_bindconfig(const char *, struct sockaddr_in *);
int setipaddress(struct in_addr *, char *);
char* get_libdir();
long get_processor_count();
void clean_up_pathname(char *path);
bool mxs_mkdir_all(const char *path, int mask);
#endif

View File

@ -0,0 +1,138 @@
#ifndef GW_AUTHENTICATOR_H
#define GW_AUTHENTICATOR_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/bsl.
*
* Change Date: 2019-07-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 protocol.h
*
* The authenticator module interface definitions for MaxScale
*
* @verbatim
* Revision History
*
* Date Who Description
* 17/02/16 Martin Brampton Initial implementation
*
* @endverbatim
*/
#include <maxscale/buffer.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/dh.h>
/** Maximum number of authenticator options */
#define AUTHENTICATOR_MAX_OPTIONS 256
struct dcb;
struct server;
struct session;
struct servlistener;
/**
* @verbatim
* The operations that can be performed on the descriptor
*
* initialize Initialize the authenticator instance. The return value
* of this function will be given to the `create` entry point.
* If a module does not implement this entry point, the value
* given to the `create` is NULL.
*
* create Create a data structure unique to this DCB, stored in
* `dcb->authenticator_data`. If a module does not implement
* this entry point, `dcb->authenticator_data` will be set to NULL.
*
* extract Extract the data from a buffer and place in a structure
* shared at the session level, stored in `dcb->data`
*
* connectSSL Determine whether the connection can support SSL
*
* authenticate Carry out the authentication
*
* free Free extracted data. This is only called for the client
* side authenticators so backend authenticators should not
* implement it.
*
* destroy Destroy the unique DCB data returned by the `create`
* entry point.
*
* loadUsers Load or update authenticator user data
* @endverbatim
*
* This forms the "module object" for authenticator modules within the gateway.
*
* @see load_module
*/
typedef struct gw_authenticator
{
void* (*initialize)(char **options);
void* (*create)(void* instance);
int (*extract)(struct dcb *, GWBUF *);
bool (*connectssl)(struct dcb *);
int (*authenticate)(struct dcb *);
void (*free)(struct dcb *);
void (*destroy)(void *);
int (*loadusers)(struct servlistener *);
} GWAUTHENTICATOR;
/** Return values for extract and authenticate entry points */
#define MXS_AUTH_SUCCEEDED 0 /**< Authentication was successful */
#define MXS_AUTH_FAILED 1 /**< Authentication failed */
#define MXS_AUTH_FAILED_DB 2 /**< Authentication failed, database not found */
#define MXS_AUTH_FAILED_SSL 3 /**< SSL authentication failed */
#define MXS_AUTH_INCOMPLETE 4 /**< Authentication is not yet complete */
#define MXS_AUTH_SSL_INCOMPLETE 5 /**< SSL connection is not yet complete */
#define MXS_AUTH_NO_SESSION 6
/** Return values for the loadusers entry point */
#define MXS_AUTH_LOADUSERS_OK 0 /**< Users loaded successfully */
#define MXS_AUTH_LOADUSERS_ERROR 1 /**< Failed to load users */
/**
* Authentication states
*
* The state usually goes from INIT to CONNECTED and alternates between
* MESSAGE_READ and RESPONSE_SENT until ending up in either FAILED or COMPLETE.
*
* If the server immediately rejects the connection, the state ends up in
* HANDSHAKE_FAILED. If the connection creation would block, instead of going to
* the CONNECTED state, the connection will be in PENDING_CONNECT state until
* the connection can be created.
*/
typedef enum
{
MXS_AUTH_STATE_INIT, /**< Initial authentication state */
MXS_AUTH_STATE_PENDING_CONNECT,/**< Connection creation is underway */
MXS_AUTH_STATE_CONNECTED, /**< Network connection to server created */
MXS_AUTH_STATE_MESSAGE_READ, /**< Read a authentication message from the server */
MXS_AUTH_STATE_RESPONSE_SENT, /**< Responded to the read authentication message */
MXS_AUTH_STATE_FAILED, /**< Authentication failed */
MXS_AUTH_STATE_HANDSHAKE_FAILED, /**< Authentication failed immediately */
MXS_AUTH_STATE_COMPLETE /**< Authentication is complete */
} mxs_auth_state_t;
/**
* The GWAUTHENTICATOR version data. The following should be updated whenever
* the GWAUTHENTICATOR structure is changed. See the rules defined in modinfo.h
* that define how these numbers should change.
*/
#define GWAUTHENTICATOR_VERSION {1, 1, 0}
bool authenticator_init(void **instance, const char *authenticator, const char *options);
char* get_default_authenticator(const char *protocol);
#endif /* GW_AUTHENTICATOR_H */

View File

@ -0,0 +1,86 @@
#ifndef GW_PROTOCOL_H
#define GW_PROTOCOL_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/bsl.
*
* Change Date: 2019-07-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 protocol.h
*
* The listener definitions for MaxScale
*
* @verbatim
* Revision History
*
* Date Who Description
* 22/01/16 Martin Brampton Initial implementation
* 31/05/16 Martin Brampton Add API entry for connection limit
*
* @endverbatim
*/
#include <maxscale/buffer.h>
struct dcb;
struct server;
struct session;
/**
* @verbatim
* The operations that can be performed on the descriptor
*
* read EPOLLIN handler for the socket
* write MaxScale data write entry point
* write_ready EPOLLOUT handler for the socket, indicates
* that the socket is ready to send more data
* error EPOLLERR handler for the socket
* hangup EPOLLHUP handler for the socket
* accept Accept handler for listener socket only
* connect Create a connection to the specified server
* for the session pased in
* close MaxScale close entry point for the socket
* listen Create a listener for the protocol
* auth Authentication entry point
* session Session handling entry point
* @endverbatim
*
* This forms the "module object" for protocol modules within the gateway.
*
* @see load_module
*/
typedef struct gw_protocol
{
int (*read)(struct dcb *);
int (*write)(struct dcb *, GWBUF *);
int (*write_ready)(struct dcb *);
int (*error)(struct dcb *);
int (*hangup)(struct dcb *);
int (*accept)(struct dcb *);
int (*connect)(struct dcb *, struct server *, struct session *);
int (*close)(struct dcb *);
int (*listen)(struct dcb *, char *);
int (*auth)(struct dcb *, struct server *, struct session *, GWBUF *);
int (*session)(struct dcb *, void *);
char *(*auth_default)();
int (*connlimit)(struct dcb *, int limit);
} GWPROTOCOL;
/**
* The GWPROTOCOL version data. The following should be updated whenever
* the GWPROTOCOL structure is changed. See the rules defined in modinfo.h
* that define how these numbers should change.
*/
#define GWPROTOCOL_VERSION {1, 1, 0}
#endif /* GW_PROTOCOL_H */

81
include/maxscale/gw_ssl.h Normal file
View File

@ -0,0 +1,81 @@
#ifndef _GW_SSL_H
#define _GW_SSL_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/bsl.
*
* Change Date: 2019-07-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 gw_ssl.h
*
* The SSL definitions for MaxScale
*
* @verbatim
* Revision History
*
* Date Who Description
* 27/01/16 Martin Brampton Initial implementation
*
* @endverbatim
*/
#include <maxscale/gw_protocol.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/dh.h>
struct dcb;
typedef enum ssl_method_type
{
SERVICE_TLS10,
#ifdef OPENSSL_1_0
SERVICE_TLS11,
SERVICE_TLS12,
#endif
SERVICE_SSL_MAX,
SERVICE_TLS_MAX,
SERVICE_SSL_TLS_MAX
} ssl_method_type_t;
/**
* Return codes for SSL authentication checks
*/
#define SSL_AUTH_CHECKS_OK 0
#define SSL_ERROR_CLIENT_NOT_SSL 1
#define SSL_ERROR_ACCEPT_FAILED 2
/**
* The ssl_listener structure is used to aggregate the SSL configuration items
* and data for a particular listener
*/
typedef struct ssl_listener
{
SSL_CTX *ctx;
SSL_METHOD *method; /*< SSLv3 or TLS1.0/1.1/1.2 methods
* see: https://www.openssl.org/docs/ssl/SSL_CTX_new.html */
int ssl_cert_verify_depth; /*< SSL certificate verification depth */
int ssl_method_type; /*< Which of the SSLv3 or TLS1.0/1.1/1.2 methods to use */
char *ssl_cert; /*< SSL certificate */
char *ssl_key; /*< SSL private key */
char *ssl_ca_cert; /*< SSL CA certificate */
bool ssl_init_done; /*< If SSL has already been initialized for this service */
} SSL_LISTENER;
int ssl_authenticate_client(struct dcb *dcb, bool is_capable);
bool ssl_is_connection_healthy(struct dcb *dcb);
bool ssl_check_data_to_process(struct dcb *dcb);
bool ssl_required_by_dcb(struct dcb *dcb);
bool ssl_required_but_not_negotiated(struct dcb *dcb);
const char* ssl_method_type_to_string(ssl_method_type_t method_type);
#endif /* _GW_SSL_H */

View File

@ -0,0 +1,58 @@
#ifndef _GWBITMASK_H
#define _GWBITMASK_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/bsl.
*
* Change Date: 2019-07-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/spinlock.h>
#include <maxscale/limits.h>
/**
* @file gwbitmask.h An implementation of an arbitrarily long bitmask
*
* @verbatim
* Revision History
*
* Date Who Description
* 28/06/13 Mark Riddoch Initial implementation
* 17/10/15 Martin Brampton Add bitmask_render_readable
*
* @endverbatim
*/
/* This number MUST an be exact multiple of 8 */
#define MXS_BITMASK_LENGTH (MXS_MAX_THREADS + 1) /**< Number of bits in the bitmask */
#define MXS_BITMASK_SIZE (MXS_BITMASK_LENGTH / 8) /**< Number of bytes in the bitmask */
/**
* The bitmask structure used to store a fixed size bitmask
*/
typedef struct
{
SPINLOCK lock; /**< Lock to protect the bitmask */
unsigned char bits[MXS_BITMASK_SIZE]; /**< The bits themselves */
} GWBITMASK;
#define GWBITMASK_INIT {SPINLOCK_INIT}
extern void bitmask_init(GWBITMASK *);
extern void bitmask_free(GWBITMASK *);
extern int bitmask_set(GWBITMASK *, int);
extern int bitmask_clear(GWBITMASK *, int);
extern int bitmask_clear_without_spinlock(GWBITMASK *, int);
extern int bitmask_isset(GWBITMASK *, int);
extern int bitmask_isallclear(GWBITMASK *);
extern void bitmask_copy(GWBITMASK *, GWBITMASK *);
extern char *bitmask_render_readable(GWBITMASK *);
#endif

View File

@ -0,0 +1,81 @@
#ifndef _GW_DIRS_HG
#define _GW_DIRS_HG
/*
* 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/bsl.
*
* Change Date: 2019-07-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.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <stdlib.h>
#include <string.h>
#include <maxscale/skygw_utils.h>
EXTERN_C_BLOCK_BEGIN
/**
* All of the following DEFAULT_* variables are defined in cmake/install_layout.cmake
*/
#define MXS_DEFAULT_PID_SUBPATH "@DEFAULT_PID_SUBPATH@"
#define MXS_DEFAULT_LOG_SUBPATH "@DEFAULT_LOG_SUBPATH@"
#define MXS_DEFAULT_DATA_SUBPATH "@DEFAULT_DATA_SUBPATH@"
#define MXS_DEFAULT_LIB_SUBPATH "@DEFAULT_LIB_SUBPATH@"
#define MXS_DEFAULT_CACHE_SUBPATH "@DEFAULT_CACHE_SUBPATH@"
#define MXS_DEFAULT_LANG_SUBPATH "@DEFAULT_LANG_SUBPATH@"
#define MXS_DEFAULT_EXEC_SUBPATH "@DEFAULT_EXEC_SUBPATH@"
#define MXS_DEFAULT_CONFIG_SUBPATH "@DEFAULT_CONFIG_SUBPATH@"
/** Default file locations, configured by CMake */
static const char* default_cnf_fname = "maxscale.cnf";
static const char* default_configdir = "@DEFAULT_CONFIGDIR@";
/*< This should be changed to just /run eventually,
* the /var/run folder is an old standard and the newer FSH 3.0
* uses /run for PID files.*/
static const char* default_piddir = "@DEFAULT_PIDDIR@";
static const char* default_logdir = "@DEFAULT_LOGDIR@";
static const char* default_datadir = "@DEFAULT_DATADIR@";
static const char* default_libdir = "@DEFAULT_LIBDIR@";
static const char* default_cachedir = "@DEFAULT_CACHEDIR@";
static const char* default_langdir = "@DEFAULT_LANGDIR@";
static const char* default_execdir = "@DEFAULT_EXECDIR@";
static char* configdir = NULL;
static char* logdir = NULL;
static char* libdir = NULL;
static char* cachedir = NULL;
static char* maxscaledatadir = NULL; /*< The data directory */
static char* processdatadir = NULL; /*< Process specific data directory */
static char* langdir = NULL;
static char* piddir = NULL;
static char* execdir = NULL;
void set_libdir(char* param);
void set_datadir(char* param);
void set_process_datadir(char* param);
void set_cachedir(char* param);
void set_configdir(char* param);
void set_logdir(char* param);
void set_langdir(char* param);
void set_piddir(char* param);
void set_execdir(char* param);
char* get_libdir();
char* get_datadir();
char* get_process_datadir();
char* get_cachedir();
char* get_configdir();
char* get_piddir();
char* get_logdir();
char* get_langdir();
char* get_execdir();
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,155 @@
#ifndef _HASTABLE_H
#define _HASTABLE_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/bsl.
*
* Change Date: 2019-07-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 hashtable.h A general purpose hashtable mechanism for use within the
* gateway
*
* @verbatim
* Revision History
*
* Date Who Description
* 23/06/2013 Mark Riddoch Initial implementation
* 23/07/2013 Mark Riddoch Addition of iterator mechanism
* 08/01/2014 Massimiliano Pinto Added function pointers for key/value copy and free
* the routine hashtable_memory_fns() changed accordingly
*
* @endverbatim
*/
#include <maxscale/skygw_debug.h>
#include <maxscale/spinlock.h>
EXTERN_C_BLOCK_BEGIN
/**
* The entries within a hashtable.
*
* A NULL value for key indicates an empty entry.
* The next pointer is the overflow chain for this hashentry.
*/
typedef struct hashentry
{
void *key; /**< The value of the key or NULL if empty entry */
void *value; /**< The value associated with key */
struct hashentry *next; /**< The overflow chain */
} HASHENTRIES;
/**
* HASHTABLE iterator - used to walk the hashtable in a thread safe
* way
*/
typedef struct hashiterator
{
struct hashtable *table; /**< The hashtable the iterator refers to */
int chain; /**< The current chain we are walking */
int depth; /**< The current depth down the chain */
} HASHITERATOR;
/**
* The type definition for the hash function
*/
typedef int (*HASHHASHFN)(const void *);
/**
* The type definition for the comparison function
*/
typedef int (*HASHCMPFN)(const void *, const void *);
/**
* The type definition for the key/value copying functions
*/
typedef void *(*HASHCOPYFN)(const void *);
/**
* The type definition for the key/value freeing functions
*/
typedef void (*HASHFREEFN)(void *);
/**
* The general purpose hashtable struct.
*/
typedef struct hashtable
{
#if defined(SS_DEBUG)
skygw_chk_t ht_chk_top;
#endif
int hashsize; /**< The number of HASHENTRIES */
HASHENTRIES **entries; /**< The entries themselves */
HASHHASHFN hashfn; /**< The hash function */
HASHCMPFN cmpfn; /**< The key comparison function */
HASHCOPYFN kcopyfn; /**< Optional key copy function */
HASHCOPYFN vcopyfn; /**< Optional value copy function */
HASHFREEFN kfreefn; /**< Optional key free function */
HASHFREEFN vfreefn; /**< Optional value free function */
SPINLOCK spin; /**< Internal spinlock for the hashtable */
int n_readers; /**< Number of clients reading the table */
int writelock; /**< The table is locked by a writer */
bool ht_isflat; /**< Indicates whether hashtable is in stack or heap */
int n_elements; /**< Number of added elements */
#if defined(SS_DEBUG)
skygw_chk_t ht_chk_tail;
#endif
} HASHTABLE;
extern HASHTABLE *hashtable_alloc(int, HASHHASHFN hashfn, HASHCMPFN cmpfn);
HASHTABLE *hashtable_alloc_flat(HASHTABLE* target,
int size,
HASHHASHFN hashfn,
HASHCMPFN cmpfn);
/**< Allocate a hashtable */
extern void hashtable_memory_fns(HASHTABLE *table,
HASHCOPYFN kcopyfn,
HASHCOPYFN vcopyfn,
HASHFREEFN kfreefn,
HASHFREEFN vfreefn);
/**< Provide an interface to control key/value memory
* manipulation
*/
extern void hashtable_free(HASHTABLE *); /**< Free a hashtable */
extern int hashtable_add(HASHTABLE *, void *, void *); /**< Add an entry */
extern int hashtable_delete(HASHTABLE *, void *);
/**< Delete an entry table */
extern void *hashtable_fetch(HASHTABLE *, void *);
/**< Fetch the data for a given key */
extern void hashtable_stats(HASHTABLE *); /**< Print statisitics */
void hashtable_get_stats(void* hashtable,
int* hashsize,
int* nelems,
int* longest);
extern int hashtable_save(HASHTABLE *,
const char *filename,
int (*keywrite)(int, void*),
int (*valuewrite)(int, void*));
extern int hashtable_load(HASHTABLE *,
const char *filename,
void *(*keyread)(int),
void *(*valueread)(int));
extern HASHITERATOR *hashtable_iterator(HASHTABLE *);
/**< Allocate an iterator on the hashtable */
extern void *hashtable_next(HASHITERATOR *);
/**< Return the key of the hash table iterator */
extern void hashtable_iterator_free(HASHITERATOR *);
extern int hashtable_size(HASHTABLE *table);
extern void hashtable_item_free(void *data);
extern int hashtable_item_strcasecmp(const void* str1, const void* str2);
extern int hashtable_item_strcmp(const void* str1, const void* str2);
extern void* hashtable_item_strdup(const void *str);
extern int hashtable_item_strhash(const void *str);
EXTERN_C_BLOCK_END
#endif

66
include/maxscale/hint.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef _HINT_H
#define _HINT_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/bsl.
*
* Change Date: 2019-07-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 hint.h The generic hint data that may be attached to buffers
*
* @verbatim
* Revision History
*
* Date Who Description
* 10/07/14 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <maxscale/skygw_debug.h>
/**
* The types of hint that are supported by the generic hinting mechanism.
*/
typedef enum
{
HINT_ROUTE_TO_MASTER = 1,
HINT_ROUTE_TO_SLAVE,
HINT_ROUTE_TO_NAMED_SERVER,
HINT_ROUTE_TO_UPTODATE_SERVER,
HINT_ROUTE_TO_ALL, /*< not implemented yet */
HINT_PARAMETER
} HINT_TYPE;
/**
* A generic hint.
*
* A hint has a type associated with it and may optionally have hint
* specific data.
* Multiple hints may be attached to a single buffer.
*/
typedef struct hint
{
HINT_TYPE type; /*< The Type of hint */
void *data; /*< Type specific data */
void *value; /*< Parameter value for hint */
unsigned int dsize; /*< Size of the hint data */
struct hint *next; /*< Another hint for this buffer */
} HINT;
extern HINT *hint_alloc(HINT_TYPE, void *, unsigned int);
extern HINT *hint_create_parameter(HINT *, char *, char *);
extern HINT *hint_create_route(HINT *, HINT_TYPE, char *);
extern void hint_free(HINT *);
extern HINT *hint_dup(HINT *);
bool hint_exists(HINT **, HINT_TYPE);
#endif

View File

@ -0,0 +1,24 @@
#ifndef _HK_HEARTBEAT_H
#define _HK_HEARTBEAT_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/bsl.
*
* Change Date: 2019-07-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.
*/
/**
* The global housekeeper heartbeat value. This value is incremented
* every 100 milliseconds and may be used for crude timing etc.
*/
extern long hkheartbeat;
#endif

View File

@ -0,0 +1,57 @@
#ifndef _HOUSEKEEPER_H
#define _HOUSEKEEPER_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/bsl.
*
* Change Date: 2019-07-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 <time.h>
#include <maxscale/dcb.h>
#include <maxscale/hk_heartbeat.h>
/**
* @file housekeeper.h A mechanism to have task run periodically
*
* @verbatim
* Revision History
*
* Date Who Description
* 29/08/14 Mark Riddoch Initial implementation
*
* @endverbatim
*/
typedef enum
{
HK_REPEATED = 1,
HK_ONESHOT
} HKTASK_TYPE;
/**
* The housekeeper task list
*/
typedef struct hktask
{
char *name; /*< A simple task name */
void (*task)(void *data); /*< The task to call */
void *data; /*< Data to pass the task */
int frequency; /*< How often to call the tasks (seconds) */
time_t nextdue; /*< When the task should be next run */
HKTASK_TYPE type; /*< The task type */
struct hktask *next; /*< Next task in the list */
} HKTASK;
extern void hkinit();
extern int hktask_add(const char *name, void (*task)(void *), void *data, int frequency);
extern int hktask_oneshot(const char *name, void (*task)(void *), void *data, int when);
extern int hktask_remove(const char *name);
extern void hkshutdown();
extern void hkshow_tasks(DCB *pdcb);
#endif

24
include/maxscale/limits.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef _MAXSCALE_LIMITS_H
#define _MAXSCALE_LIMITS_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/bsl.
*
* Change Date: 2019-07-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.
*/
// This file defines hard limits of MaxScale.
// Thread information is stored in a bitmask whose size must be a
// multiple of 8. The bitmask is indexed using the thread id that start
// from 1. Hence, the hard maximum number of threads must be a
// multiple of 8 minus 1.
#define MXS_MAX_THREADS 255
#endif

View File

@ -0,0 +1,68 @@
#ifndef _LISTENER_H
#define _LISTENER_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/bsl.
*
* Change Date: 2019-07-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 listener.h
*
* The listener definitions for MaxScale
*
* @verbatim
* Revision History
*
* Date Who Description
* 19/01/16 Martin Brampton Initial implementation
*
* @endverbatim
*/
#include <maxscale/gw_protocol.h>
#include <maxscale/gw_ssl.h>
#include <maxscale/hashtable.h>
struct dcb;
struct service;
/**
* The servlistener structure is used to link a service to the protocols that
* are used to support that service. It defines the name of the protocol module
* that should be loaded to support the client connection and the port that the
* protocol should use to listen for incoming client connections.
*/
typedef struct servlistener
{
char *name; /**< Name of the listener */
char *protocol; /**< Protocol module to load */
unsigned short port; /**< Port to listen on */
char *address; /**< Address to listen with */
char *authenticator; /**< Name of authenticator */
void *auth_instance; /**< Authenticator instance created in GWAUTHENTICATOR::initialize() */
SSL_LISTENER *ssl; /**< Structure of SSL data or NULL */
struct dcb *listener; /**< The DCB for the listener */
struct users *users; /**< The user data for this listener */
HASHTABLE *resources; /**< hastable for listener resources, i.e. database names */
struct service* service; /**< The service which used by this listener */
SPINLOCK lock;
struct servlistener *next; /**< Next service protocol */
} SERV_LISTENER;
SERV_LISTENER *listener_alloc(struct service* service, char *name, char *protocol,
char *address, unsigned short port, char *authenticator,
char* options, SSL_LISTENER *ssl);
void listener_free(SERV_LISTENER* listener);
int listener_set_ssl_version(SSL_LISTENER *ssl_listener, char* version);
void listener_set_certificates(SSL_LISTENER *ssl_listener, char* cert, char* key, char* ca_cert);
int listener_init_SSL(SSL_LISTENER *ssl_listener);
#endif

View File

@ -0,0 +1,119 @@
#ifndef _LISTMANAGER_H
#define _LISTMANAGER_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/bsl.
*
* Change Date: 2019-07-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 listmanager.h The List Manager header file
*
*
* @verbatim
* Revision History
*
* Date Who Description
* 20/04/2016 Martin Brampton Initial implementation
*
* @endverbatim
*/
#include <maxscale/spinlock.h>
#include <maxscale/skygw_debug.h>
struct dcb;
/*
* The possible types of list that could be supported. At present, only
* LIST_TYPE_RECYCLABLE is fully tested.
*/
typedef enum
{
LIST_TYPE_SIMPLE, /* A simple linked list with pointer to last entry */
LIST_TYPE_RECYCLABLE, /* A simple linked list, entries are recycled */
LIST_TYPE_DOUBLE, /* A doubly linked list, next and previous */
} list_type_t;
/*
* The list entry structure
*
* Each list entry must have this format, but will typically be extended
* well beyond these items. The "previous" field is only required for
* a doubly linked list, LIST_TYPE_DOUBLE.
*
* The first data to be used with the list manager is the DCB. Note that
* the first few fields in the DCB structure correspond exactly to the
* fields in the list entry structure. The pointers used need to be cast
* as appropriate in order to be able to use the same data as either a DCB
* or a list entry.
*
*/
#define LIST_ENTRY_FIELDS \
skygw_chk_t list_entry_chk_top; \
struct list_entry *next; \
struct list_entry *previous; \
bool entry_is_in_use; \
bool entry_is_ready; \
skygw_chk_t list_entry_chk_tail;
typedef struct list_entry
{
LIST_ENTRY_FIELDS
} list_entry_t;
/*
* The list configuration structure
*
* This provides the basis for a list. It can be declared and initialised
* statically, for example in server/core/dcb.c. It includes an anchor
* pointer for the list, a pointer to the last entry in the list and the
* last entry that was found to be free and reused.
*
* The count tells us the current number of entries in live use, and maximum
* is the highest number ever observed in live use. The freecount is the
* number of entries currently free and ready for reuse. The entry_size is
* the actual size of the real entries, e.g. the DCB structure (NOT the size
* of the list entry structure).
*
* A spinlock is declared for use during list manipulation operations.
*/
typedef struct
{
list_type_t list_type;
size_t entry_size;
SPINLOCK list_lock;
list_entry_t *all_entries;
list_entry_t *last_entry;
list_entry_t *last_free;
int count;
int maximum;
int freecount;
int num_malloc;
} LIST_CONFIG;
void list_initialise(LIST_CONFIG *list_config, list_type_t type_of_list, size_t entry_size);
bool list_pre_alloc(LIST_CONFIG *list_config, int num_entries, void (*init_struct)(void *));
list_entry_t *list_find_free(LIST_CONFIG *list_config, void (*init_struct)(void *));
void dprintListStats(struct dcb *pdcb, LIST_CONFIG *list_config, const char *listname);
void list_free_entry (LIST_CONFIG *list_config, list_entry_t *to_be_freed);
list_entry_t *list_start_iteration(LIST_CONFIG *list_config);
list_entry_t *list_iterate(LIST_CONFIG *list_config, list_entry_t *current_entry);
void list_terminate_iteration_early(LIST_CONFIG *list_config, list_entry_t *current_entry);
bool list_is_entry_in_use(LIST_CONFIG *list_config, list_entry_t *to_be_found);
void list_add_to_end(LIST_CONFIG *list_config, list_entry_t *new_entry);
void list_map(LIST_CONFIG *list_config, bool (*callback)(void *, ...));
/* The following UNTESTED! */
list_entry_t *list_remove_first(LIST_CONFIG *list_config);
list_entry_t *list_remove_last(LIST_CONFIG *list_config);
#endif /* LISTMANAGER_H */

View File

@ -0,0 +1,202 @@
/*
* 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/bsl.
*
* Change Date: 2019-07-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.
*/
#if !defined(LOG_MANAGER_H)
#define LOG_MANAGER_H
#include <stdbool.h>
#include <syslog.h>
#include <unistd.h>
#if defined(__cplusplus)
extern "C" {
#endif
/*
* We need a common.h file that is included by every component.
*/
#if !defined(STRERROR_BUFLEN)
#define STRERROR_BUFLEN 512
#endif
/**
* If MXS_MODULE_NAME is defined before log_manager.h is included, then all
* logged messages will be prefixed with that string enclosed in square brackets.
* For instance, the following
*
* #define MXS_MODULE_NAME "xyz"
* #include <log_manager.h>
*
* will lead to every logged message looking like:
*
* 2016-08-12 13:49:11 error : [xyz] The gadget was not ready
*
* In general, the value of MXS_MODULE_NAME should be the name of the shared
* library to which the source file, where MXS_MODULE_NAME is defined, belongs.
*
* Note that a file that is compiled into multiple modules should
* have MXS_MODULE_NAME defined as something else than the name of a real
* module, or not at all.
*
* Any file that is compiled into maxscale-common should *not* have
* MXS_MODULE_NAME defined.
*/
#if !defined(MXS_MODULE_NAME)
#define MXS_MODULE_NAME NULL
#endif
typedef enum
{
MXS_LOG_TARGET_DEFAULT = 0,
MXS_LOG_TARGET_FS = 1, // File system
MXS_LOG_TARGET_SHMEM = 2, // Shared memory
MXS_LOG_TARGET_STDOUT = 3, // Standard output
} mxs_log_target_t;
/**
* Thread-specific logging information.
*/
typedef struct mxs_log_info
{
size_t li_sesid;
int li_enabled_priorities;
} mxs_log_info_t;
extern int mxs_log_enabled_priorities;
extern ssize_t mxs_log_session_count[];
extern __thread mxs_log_info_t mxs_log_tls;
/**
* Check if specified log type is enabled in general or if it is enabled
* for the current session.
*
* @param priority One of the syslog LOG_ERR, LOG_WARNING, etc. constants.
*/
#define MXS_LOG_PRIORITY_IS_ENABLED(priority) \
(((mxs_log_enabled_priorities & (1 << priority)) || \
(mxs_log_session_count[priority] > 0 && \
mxs_log_tls.li_enabled_priorities & (1 << priority))) ? true : false)
/**
* LOG_AUGMENT_WITH_FUNCTION Each logged line is suffixed with [function-name].
*/
typedef enum
{
MXS_LOG_AUGMENT_WITH_FUNCTION = 1,
MXS_LOG_AUGMENTATION_MASK = (MXS_LOG_AUGMENT_WITH_FUNCTION)
} mxs_log_augmentation_t;
typedef struct mxs_log_throttling
{
size_t count; // Maximum number of a specific message...
size_t window_ms; // ...during this many milliseconds.
size_t suppress_ms; // If exceeded, suppress such messages for this many ms.
} MXS_LOG_THROTTLING;
bool mxs_log_init(const char* ident, const char* logdir, mxs_log_target_t target);
void mxs_log_finish(void);
int mxs_log_flush();
int mxs_log_flush_sync();
int mxs_log_rotate();
int mxs_log_set_priority_enabled(int priority, bool enabled);
void mxs_log_set_syslog_enabled(bool enabled);
void mxs_log_set_maxlog_enabled(bool enabled);
void mxs_log_set_highprecision_enabled(bool enabled);
void mxs_log_set_augmentation(int bits);
void mxs_log_set_throttling(const MXS_LOG_THROTTLING* throttling);
void mxs_log_get_throttling(MXS_LOG_THROTTLING* throttling);
int mxs_log_message(int priority,
const char* modname,
const char* file, int line, const char* function,
const char* format, ...) __attribute__((format(printf, 6, 7)));
/**
* Log an error, warning, notice, info, or debug message.
*
* @param priority One of the syslog constants (LOG_ERR, LOG_WARNING, ...)
* @param format The printf format of the message.
* @param ... Arguments, depending on the format.
*
* NOTE: Should typically not be called directly. Use some of the
* MXS_ERROR, MXS_WARNING, etc. macros instead.
*/
#define MXS_LOG_MESSAGE(priority, format, ...)\
mxs_log_message(priority, MXS_MODULE_NAME, __FILE__, __LINE__, __func__, format, ##__VA_ARGS__)
/**
* Log an alert, error, warning, notice, info, or debug message.
*
* MXS_ALERT Not throttled To be used when the system is about to go down in flames.
* MXS_ERROR Throttled For errors.
* MXS_WARNING Throttled For warnings.
* MXS_NOTICE Not Throttled For messages deemed important, typically used during startup.
* MXS_INFO Not Throttled For information thought to be of value for investigating some problem.
* MXS_DEBUG Not Throttled For debugging messages during development. Should be removed when a
* feature is ready.
*
* @param format The printf format of the message.
* @param ... Arguments, depending on the format.
*/
#define MXS_ALERT(format, ...) MXS_LOG_MESSAGE(LOG_ALERT, format, ##__VA_ARGS__)
#define MXS_ERROR(format, ...) MXS_LOG_MESSAGE(LOG_ERR, format, ##__VA_ARGS__)
#define MXS_WARNING(format, ...) MXS_LOG_MESSAGE(LOG_WARNING, format, ##__VA_ARGS__)
#define MXS_NOTICE(format, ...) MXS_LOG_MESSAGE(LOG_NOTICE, format, ##__VA_ARGS__)
#define MXS_INFO(format, ...) MXS_LOG_MESSAGE(LOG_INFO, format, ##__VA_ARGS__)
#define MXS_DEBUG(format, ...) MXS_LOG_MESSAGE(LOG_DEBUG, format, ##__VA_ARGS__)
/**
* Log an out of memory error using custom message.
*
* @param message Text to be logged.
*/
// TODO: In an OOM situation, the default logging will (most likely) *not* work,
// TODO: as memory is allocated as part of the process. A custom route, that does
// TODO: not allocate memory, must be created for OOM messages.
// TODO: So, currently these are primarily placeholders.
#define MXS_OOM_MESSAGE(message) MXS_ERROR("OOM: %s", message);
/**
* Log an out of memory error using custom message, if the
* provided pointer is NULL.
*
* @param p If NULL, an OOM message will be logged.
* @param message Text to be logged.
*/
#define MXS_OOM_MESSAGE_IFNULL(p, m) do { if (!p) { MXS_OOM_MESSAGE(m); } } while (false)
/**
* Log an out of memory error using a default message.
*/
#define MXS_OOM() MXS_OOM_MESSAGE(__func__)
/**
* Log an out of memory error using a default message, if the
* provided pointer is NULL.
*
* @param p If NULL, an OOM message will be logged.
*/
#define MXS_OOM_IFNULL(p) do { if (!p) { MXS_OOM(); } } while (false)
enum
{
MXS_OOM_MESSAGE_MAXLEN = 80 /** Maximum length of an OOM message, including the
trailing NULL. If longer, it will be cut. */
};
#if defined(__cplusplus)
}
#endif
#endif /** LOG_MANAGER_H */

View File

@ -0,0 +1,163 @@
#ifndef _MAXSCALE_CONFIG_H
#define _MAXSCALE_CONFIG_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/bsl.
*
* Change Date: 2019-07-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/skygw_utils.h>
#include <sys/utsname.h>
#include <stdint.h>
#include <openssl/sha.h>
#include <maxscale/spinlock.h>
/**
* @file config.h The configuration handling elements
*
* @verbatim
* Revision History
*
* Date Who Description
* 21/06/13 Mark Riddoch Initial implementation
* 07/05/14 Massimiliano Pinto Added version_string to global configuration
* 23/05/14 Massimiliano Pinto Added id to global configuration
* 17/10/14 Mark Riddoch Added poll tuning configuration parameters
* 05/03/15 Massimiliano Pinto Added sysname, release, sha1_mac to gateway struct
*
* @endverbatim
*/
#define DEFAULT_NBPOLLS 3 /**< Default number of non block polls before we block */
#define DEFAULT_POLLSLEEP 1000 /**< Default poll wait time (milliseconds) */
#define _RELEASE_STR_LENGTH 256 /**< release len */
#define DEFAULT_NTHREADS 1 /**< Default number of polling threads */
/**
* Maximum length for configuration parameter value.
*/
enum
{
MAX_PARAM_LEN = 256
};
typedef enum
{
UNDEFINED_TYPE = 0x00,
STRING_TYPE = 0x01,
COUNT_TYPE = 0x02,
PERCENT_TYPE = 0x04,
BOOL_TYPE = 0x08,
SQLVAR_TARGET_TYPE = 0x10
} config_param_type_t;
typedef enum
{
TYPE_UNDEFINED = 0,
TYPE_MASTER,
TYPE_ALL
} target_t;
enum
{
MAX_RLAG_NOT_AVAILABLE = -1,
MAX_RLAG_UNDEFINED = -2
};
#define PARAM_IS_TYPE(p,t) ((p) & (t))
/**
* The config parameter
*/
typedef struct config_parameter
{
char *name; /**< The name of the parameter */
char *value; /**< The value of the parameter */
union
{
/*< qualified parameter value by type */
char* valstr; /*< terminated char* array */
int valcount; /*< int */
int valpercent; /*< int */
bool valbool; /*< bool */
target_t valtarget; /*< sql variable route target */
} qfd;
config_param_type_t qfd_param_type;
struct config_parameter *next; /**< Next pointer in the linked list */
} CONFIG_PARAMETER;
/**
* The config context structure, used to build the configuration
* data during the parse process
*/
typedef struct config_context
{
char *object; /**< The name of the object being configured */
CONFIG_PARAMETER *parameters; /**< The list of parameter values */
void *element; /**< The element created from the data */
struct config_context *next; /**< Next pointer in the linked list */
} CONFIG_CONTEXT;
/**
* The gateway global configuration data
*/
typedef struct
{
int n_threads; /**< Number of polling threads */
char *version_string; /**< The version string of embedded db library */
char release_string[_RELEASE_STR_LENGTH]; /**< The release name string of the system */
char sysname[_UTSNAME_SYSNAME_LENGTH]; /**< The OS name of the system */
uint8_t mac_sha1[SHA_DIGEST_LENGTH]; /**< The SHA1 digest of an interface MAC address */
unsigned long id; /**< MaxScale ID */
unsigned int n_nbpoll; /**< Tune number of non-blocking polls */
unsigned int pollsleep; /**< Wait time in blocking polls */
int syslog; /**< Log to syslog */
int maxlog; /**< Log to MaxScale's own logs */
int log_to_shm; /**< Write log-file to shared memory */
unsigned int auth_conn_timeout; /**< Connection timeout for the user authentication */
unsigned int auth_read_timeout; /**< Read timeout for the user authentication */
unsigned int auth_write_timeout; /**< Write timeout for the user authentication */
bool skip_permission_checks; /**< Skip service and monitor permission checks */
char qc_name[PATH_MAX]; /**< The name of the query classifier to load */
char* qc_args; /**< Arguments for the query classifier */
} GATEWAY_CONF;
char* config_clean_string_list(char* str);
CONFIG_PARAMETER* config_clone_param(CONFIG_PARAMETER* param);
void config_enable_feedback_task(void);
void config_disable_feedback_task(void);
unsigned long config_get_gateway_id(void);
GATEWAY_CONF* config_get_global_options();
CONFIG_PARAMETER* config_get_param(CONFIG_PARAMETER* params, const char* name);
config_param_type_t config_get_paramtype(CONFIG_PARAMETER* param);
bool config_get_valint(int* val,
CONFIG_PARAMETER* param,
const char* name, /*< if NULL examine current param only */
config_param_type_t ptype);
bool config_get_valbool(bool* val,
CONFIG_PARAMETER* param,
const char* name, /*< if NULL examine current param only */
config_param_type_t ptype);
bool config_get_valtarget(target_t* val,
CONFIG_PARAMETER* param,
const char* name, /*< if NULL examine current param only */
config_param_type_t ptype);
bool config_load(char *);
unsigned int config_nbpolls();
double config_percentage_value(char *str);
unsigned int config_pollsleep();
int config_reload();
bool config_set_qualified_param(CONFIG_PARAMETER* param,
void* val,
config_param_type_t type);
int config_threadcount();
int config_truth_value(char *);
void free_config_parameter(CONFIG_PARAMETER* p1);
bool is_internal_service(const char *router);
#endif

View File

@ -0,0 +1,46 @@
#ifndef _MAXSCALE_H
#define _MAXSCALE_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/bsl.
*
* Change Date: 2019-07-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 maxscale.h
*
* Some general definitions for MaxScale
*
* @verbatim
* Revision History
*
* Date Who Description
* 05/02/14 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <time.h>
/* Exit status for MaxScale */
#define MAXSCALE_SHUTDOWN 0 /* Good shutdown */
#define MAXSCALE_BADCONFIG 1 /* Configuration fiel error */
#define MAXSCALE_NOLIBRARY 2 /* No embedded library found */
#define MAXSCALE_NOSERVICES 3 /* No servics are running */
#define MAXSCALE_ALREADYRUNNING 4 /* MaxScale is already runing */
#define MAXSCALE_BADARG 5 /* Bad command line argument */
#define MAXSCALE_INTERNALERROR 6 /* Internal error, see error log */
void maxscale_reset_starttime(void);
time_t maxscale_started(void);
int maxscale_uptime(void);
#endif

View File

@ -0,0 +1,47 @@
#ifndef _MAXSCALE_PCRE2_H
#define _MAXSCALE_PCRE2_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/bsl.
*
* Change Date: 2019-07-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.
*
*/
#ifndef PCRE2_CODE_UNIT_WIDTH
#define PCRE2_CODE_UNIT_WIDTH 8
#endif
#include <pcre2.h>
/**
* @file maxscale_pcre2.h - Utility functions for regular expression matching
* with the bundled PCRE2 library.
*
* @verbatim
* Revision History
*
* Date Who Description
* 30-10-2015 Markus Makela Initial implementation
* @endverbatim
*/
typedef enum
{
MXS_PCRE2_MATCH,
MXS_PCRE2_NOMATCH,
MXS_PCRE2_ERROR
} mxs_pcre2_result_t;
mxs_pcre2_result_t mxs_pcre2_substitute(pcre2_code *re, const char *subject,
const char *replace, char** dest, size_t* size);
mxs_pcre2_result_t mxs_pcre2_simple_match(const char* pattern, const char* subject,
int options, int* error);
#endif

62
include/maxscale/memlog.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef _MEMLOG_H
#define _MEMLOG_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/bsl.
*
* Change Date: 2019-07-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 memlog.h The memory logging mechanism
*
* @verbatim
* Revision History
*
* Date Who Description
* 26/09/14 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <maxscale/spinlock.h>
typedef enum { ML_INT, ML_LONG, ML_LONGLONG, ML_STRING } MEMLOGTYPE;
typedef struct memlog
{
char *name;
SPINLOCK lock;
void *values;
int offset;
int size;
MEMLOGTYPE type;
unsigned int flags;
unsigned int iflags;
struct memlog *next;
} MEMLOG;
/*
* MEMLOG flag bits
*/
#define MLNOAUTOFLUSH 0x0001
/*
* MEMLOG internal flags
*/
#define MLWRAPPED 0x0001
extern MEMLOG *memlog_create(char *, MEMLOGTYPE, int);
extern void memlog_destroy(MEMLOG *);
extern void memlog_set(MEMLOG *, unsigned int);
extern void memlog_log(MEMLOG *, void *);
extern void memlog_flush_all();
extern void memlog_flush(MEMLOG *);
#endif

79
include/maxscale/mlist.h Normal file
View File

@ -0,0 +1,79 @@
#ifndef _MLIST_H
#define _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/bsl.
*
* Change Date: 2019-07-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/skygw_utils.h>
EXTERN_C_BLOCK_BEGIN
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);
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,86 @@
#ifndef _MODINFO_H
#define _MODINFO_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/bsl.
*
* Change Date: 2019-07-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 modinfo.h The module information interface
*
* @verbatim
* Revision History
*
* Date Who Description
* 02/06/14 Mark Riddoch Initial implementation
*
* @endverbatim
*/
/**
* The status of the module. This gives some idea of the module
* maturity.
*/
typedef enum
{
MODULE_IN_DEVELOPMENT = 0,
MODULE_ALPHA_RELEASE,
MODULE_BETA_RELEASE,
MODULE_GA,
MODULE_EXPERIMENTAL
} MODULE_STATUS;
/**
* The API implemented by the module
*/
typedef enum
{
MODULE_API_PROTOCOL = 0,
MODULE_API_ROUTER,
MODULE_API_MONITOR,
MODULE_API_FILTER,
MODULE_API_AUTHENTICATOR,
MODULE_API_QUERY_CLASSIFIER,
} MODULE_API;
/**
* The module version structure.
*
* The rules for changing these values are:
*
* Any change that affects an inexisting call in the API in question,
* making the new API no longer compatible with the old,
* must increment the major version.
*
* Any change that adds to the API, but does not alter the existing API
* calls, must increment the minor version.
*
* Any change that is purely cosmetic and does not affect the calling
* conventions of the API must increment only the patch version number.
*/
typedef struct
{
int major;
int minor;
int patch;
} MODULE_VERSION;
/**
* The module information structure
*/
typedef struct
{
MODULE_API modapi;
MODULE_STATUS status;
MODULE_VERSION api_version;
char *description;
} MODULE_INFO;
#endif

View File

@ -0,0 +1,76 @@
#ifndef _MODULES_H
#define _MODULES_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/bsl.
*
* Change Date: 2019-07-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>
#include <maxscale/modinfo.h>
#include <maxscale/resultset.h>
#include <maxscale/skygw_debug.h>
EXTERN_C_BLOCK_BEGIN
/**
* @file modules.h Utilities for loading modules
*
* The module interface used within the gateway
*
* @verbatim
* Revision History
*
* Date Who Description
* 13/06/13 Mark Riddoch Initial implementation
* 08/07/13 Mark Riddoch Addition of monitor modules
* 29/05/14 Mark Riddoch Addition of filter modules
* 01/10/14 Mark Riddoch Addition of call to unload all modules on shutdown
* 19/02/15 Mark Riddoch Addition of moduleGetList
* 26/02/15 Massimiliano Pinto Addition of module_feedback_send
*
* @endverbatim
*/
typedef struct modules
{
char *module; /**< The name of the module */
char *type; /**< The module type */
char *version; /**< Module version */
void *handle; /**< The handle returned by dlopen */
void *modobj; /**< The module "object" this is the set of entry points */
MODULE_INFO
*info; /**< The module information */
struct modules
*next; /**< Next module in the linked list */
} MODULES;
/**
* 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 */
extern void *load_module(const char *module, const char *type);
extern void unload_module(const char *module);
extern void unload_all_modules();
extern void printModules();
extern void dprintAllModules(DCB *);
extern RESULTSET *moduleGetList();
extern void module_feedback_send(void*);
extern void moduleShowFeedbackReport(DCB *dcb);
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,73 @@
#ifndef _MODUTIL_H
#define _MODUTIL_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/bsl.
*
* Change Date: 2019-07-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 modutil.h A set of useful routines for module writers
*
* @verbatim
* Revision History
*
* Date Who Description
* 04/06/14 Mark Riddoch Initial implementation
* 24/06/14 Mark Riddoch Add modutil_MySQL_Query to enable multipacket queries
* 24/10/14 Massimiliano Pinto Add modutil_send_mysql_err_packet to send a mysql ERR_Packet
*
* @endverbatim
*/
#include <maxscale/buffer.h>
#include <maxscale/dcb.h>
#include <string.h>
#include <maxscale/maxscale_pcre2.h>
#define PTR_IS_RESULTSET(b) (b[0] == 0x01 && b[1] == 0x0 && b[2] == 0x0 && b[3] == 0x01)
#define PTR_IS_EOF(b) (b[0] == 0x05 && b[1] == 0x0 && b[2] == 0x0 && b[4] == 0xfe)
#define PTR_IS_OK(b) (b[4] == 0x00)
#define PTR_IS_ERR(b) (b[4] == 0xff)
#define PTR_IS_LOCAL_INFILE(b) (b[4] == 0xfb)
#define IS_FULL_RESPONSE(buf) (modutil_count_signal_packets(buf,0,0) == 2)
#define PTR_EOF_MORE_RESULTS(b) ((PTR_IS_EOF(b) && ptr[7] & 0x08))
extern int modutil_is_SQL(GWBUF *);
extern int modutil_is_SQL_prepare(GWBUF *);
extern int modutil_extract_SQL(GWBUF *, char **, int *);
extern int modutil_MySQL_Query(GWBUF *, char **, int *, int *);
extern char* modutil_get_SQL(GWBUF *);
extern GWBUF* modutil_replace_SQL(GWBUF *, char *);
extern char* modutil_get_query(GWBUF* buf);
extern int modutil_send_mysql_err_packet(DCB *, int, int, int, const char *, const char *);
GWBUF* modutil_get_next_MySQL_packet(GWBUF** p_readbuf);
GWBUF* modutil_get_complete_packets(GWBUF** p_readbuf);
int modutil_MySQL_query_len(GWBUF* buf, int* nbytes_missing);
void modutil_reply_parse_error(DCB* backend_dcb, char* errstr, uint32_t flags);
void modutil_reply_auth_error(DCB* backend_dcb, char* errstr, uint32_t flags);
int modutil_count_statements(GWBUF* buffer);
GWBUF* modutil_create_query(char* query);
GWBUF* modutil_create_mysql_err_msg(int packet_number,
int affected_rows,
int merrno,
const char *statemsg,
const char *msg);
int modutil_count_signal_packets(GWBUF*, int, int, int*);
mxs_pcre2_result_t modutil_mysql_wildcard_match(const char* pattern, const char* string);
/** Character and token searching functions */
char* strnchr_esc(char* ptr, char c, int len);
char* strnchr_esc_mysql(char* ptr, char c, int len);
bool is_mysql_statement_end(const char* start, int len);
bool is_mysql_sp_end(const char* start, int len);
char* modutil_get_canonical(GWBUF* querybuf);
#endif

229
include/maxscale/monitor.h Normal file
View File

@ -0,0 +1,229 @@
#ifndef _MONITOR_H
#define _MONITOR_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/bsl.
*
* Change Date: 2019-07-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 <mysql.h>
#include <maxscale/server.h>
#include <maxscale/dcb.h>
#include <maxscale/log_manager.h>
#include <maxscale/resultset.h>
#include <maxscale/maxconfig.h>
#include <maxscale/externcmd.h>
#include <maxscale/secrets.h>
/**
* @file monitor.h The interface to the monitor module
*
* @verbatim
* Revision History
*
* Date Who Description
* 07/07/13 Mark Riddoch Initial implementation
* 25/07/13 Mark Riddoch Addition of diagnotics
* 23/05/14 Mark Riddoch Addition of routine to find monitors by name
* 23/05/14 Massimiliano Pinto Addition of defaultId and setInterval
* 23/06/14 Massimiliano Pinto Addition of replicationHeartbeat
* 28/08/14 Massimiliano Pinto Addition of detectStaleMaster
* 30/10/14 Massimiliano Pinto Addition of disableMasterFailback
* 07/11/14 Massimiliano Pinto Addition of setNetworkTimeout
* 19/02/15 Mark Riddoch Addition of monitorGetList
* 19/11/15 Martin Brampton Automation of event and name declaration, absorption
* of what was formerly monitor_common.h
*
* @endverbatim
*/
/**
* The "Module Object" for a monitor module.
*
* The monitor modules are designed to monitor the backend databases that the gateway
* connects to and provide information regarding the status of the databases that
* is used in the routing decisions.
*
* startMonitor is called to start the monitoring process, it is called on the main
* thread of the gateway and is responsible for creating a thread for the monitor
* itself to run on. This should use the entry points defined in the thread.h
* header file rather than make direct calls to the operating system thrading libraries.
* The return from startMonitor is a void * handle that will be passed to all other monitor
* API calls.
*
* stopMonitor is responsible for shuting down and destroying a monitor, it is called
* with the void * handle that was returned by startMonitor.
*
* registerServer is called to register a server that must be monitored with a running
* monitor. this will be called with the handle returned from the startMonitor call and
* the SERVER structure that the monitor must update and monitor. The SERVER structure
* contains the information required to connect to the monitored server.
*
* unregisterServer is called to remove a server from the set of servers that need to be
* monitored.
*/
struct monitor;
typedef struct monitor MONITOR;
typedef struct
{
void *(*startMonitor)(MONITOR *monitor, const CONFIG_PARAMETER *params);
void (*stopMonitor)(MONITOR *monitor);
void (*diagnostics)(DCB *, const MONITOR *);
} MONITOR_OBJECT;
/**
* The monitor API version number. Any change to the monitor module API
* must change these versions usign the rules defined in modinfo.h
*/
#define MONITOR_VERSION {3, 0, 0}
/** Monitor's poll frequency */
#define MON_BASE_INTERVAL_MS 100
/**
* Monitor state bit mask values
*/
typedef enum
{
MONITOR_STATE_ALLOC = 0x00,
MONITOR_STATE_RUNNING = 0x01,
MONITOR_STATE_STOPPING = 0x02,
MONITOR_STATE_STOPPED = 0x04,
MONITOR_STATE_FREED = 0x08
} monitor_state_t;
/**
* Monitor network timeout types
*/
typedef enum
{
MONITOR_CONNECT_TIMEOUT = 0,
MONITOR_READ_TIMEOUT = 1,
MONITOR_WRITE_TIMEOUT = 2
} monitor_timeouts_t;
/*
* Results of attempt at database connection for monitoring
*/
typedef enum
{
MONITOR_CONN_OK,
MONITOR_CONN_REFUSED,
MONITOR_CONN_TIMEOUT
} connect_result_t;
#define MON_ARG_MAX 8192
#define DEFAULT_CONNECT_TIMEOUT 3
#define DEFAULT_READ_TIMEOUT 1
#define DEFAULT_WRITE_TIMEOUT 2
#define MONITOR_RUNNING 1
#define MONITOR_STOPPING 2
#define MONITOR_STOPPED 3
#define MONITOR_INTERVAL 10000 // in milliseconds
#define MONITOR_DEFAULT_ID 1UL // unsigned long value
/*
* Create declarations of the enum for monitor events and also the array of
* structs containing the matching names. The data is taken from def_monitor_event.h
*/
#undef ADDITEM
#define ADDITEM( _event_type, _event_name ) _event_type
typedef enum
{
#include "def_monitor_event.h"
MAX_MONITOR_EVENT
} monitor_event_t;
#undef ADDITEM
typedef struct monitor_def_s
{
char name[30];
} monitor_def_t;
extern const monitor_def_t monitor_event_definitions[];
/**
* The linked list of servers that are being monitored by the monitor module.
*/
typedef struct monitor_servers
{
SERVER *server; /**< The server being monitored */
MYSQL *con; /**< The MySQL connection */
bool log_version_err;
int mon_err_count;
unsigned int mon_prev_status;
unsigned int pending_status; /**< Pending Status flag bitmap */
struct monitor_servers *next; /**< The next server in the list */
} MONITOR_SERVERS;
/**
* Representation of the running monitor.
*/
struct monitor
{
char *name; /**< The name of the monitor module */
char *user; /*< Monitor username */
char *password; /*< Monitor password */
SPINLOCK lock;
CONFIG_PARAMETER* parameters; /*< configuration parameters */
MONITOR_SERVERS* databases; /*< List of databases the monitor monitors */
monitor_state_t state; /**< The state of the monitor */
int connect_timeout; /**< Connect timeout in seconds for mysql_real_connect */
int read_timeout; /**< Timeout in seconds to read from the server.
* There are retries and the total effective timeout
* value is three times the option value.
*/
int write_timeout; /**< Timeout in seconds for each attempt to write to the server.
* There are retries and the total effective timeout value is
* two times the option value.
*/
MONITOR_OBJECT *module; /**< The "monitor object" */
void *handle; /**< Handle returned from startMonitor */
size_t interval; /**< The monitor interval */
struct monitor *next; /**< Next monitor in the linked list */
};
extern MONITOR *monitor_alloc(char *, char *);
extern void monitor_free(MONITOR *);
extern MONITOR *monitor_find(char *);
extern void monitorAddServer(MONITOR *, SERVER *);
extern void monitorAddUser(MONITOR *, char *, char *);
extern void monitorAddParameters(MONITOR *monitor, CONFIG_PARAMETER *params);
extern void monitorStop(MONITOR *);
extern void monitorStart(MONITOR *, void*);
extern void monitorStopAll();
extern void monitorStartAll();
extern void monitorShowAll(DCB *);
extern void monitorShow(DCB *, MONITOR *);
extern void monitorList(DCB *);
extern void monitorSetInterval (MONITOR *, unsigned long);
extern bool monitorSetNetworkTimeout(MONITOR *, int, int);
extern RESULTSET *monitorGetList();
extern bool check_monitor_permissions(MONITOR* monitor, const char* query);
monitor_event_t mon_name_to_event(const char* tok);
monitor_event_t mon_get_event_type(MONITOR_SERVERS* node);
const char* mon_get_event_name(MONITOR_SERVERS* node);
void monitor_clear_pending_status(MONITOR_SERVERS *ptr, int bit);
void monitor_set_pending_status(MONITOR_SERVERS *ptr, int bit);
bool mon_status_changed(MONITOR_SERVERS* mon_srv);
bool mon_print_fail_status(MONITOR_SERVERS* mon_srv);
void monitor_launch_script(MONITOR* mon, MONITOR_SERVERS* ptr, char* script);
int mon_parse_event_string(bool* events, size_t count, char* string);
connect_result_t mon_connect_to_db(MONITOR* mon, MONITOR_SERVERS *database);
void mon_log_connect_error(MONITOR_SERVERS* database, connect_result_t rval);
void mon_log_state_change(MONITOR_SERVERS *ptr);
#endif

View File

@ -0,0 +1,94 @@
#ifndef MYSQL_BINLOG_H
#define MYSQL_BINLOG_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/bsl.
*
* Change Date: 2019-07-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 mysql_binlog.h - Extracting information from binary logs
*/
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
/** Maximum GTID string length */
#define GTID_MAX_LEN 64
/** Table map column types */
#define TABLE_COL_TYPE_DECIMAL 0x00
#define TABLE_COL_TYPE_TINY 0x01
#define TABLE_COL_TYPE_SHORT 0x02
#define TABLE_COL_TYPE_LONG 0x03
#define TABLE_COL_TYPE_FLOAT 0x04
#define TABLE_COL_TYPE_DOUBLE 0x05
#define TABLE_COL_TYPE_NULL 0x06
#define TABLE_COL_TYPE_TIMESTAMP 0x07
#define TABLE_COL_TYPE_LONGLONG 0x08
#define TABLE_COL_TYPE_INT24 0x09
#define TABLE_COL_TYPE_DATE 0x0a
#define TABLE_COL_TYPE_TIME 0x0b
#define TABLE_COL_TYPE_DATETIME 0x0c
#define TABLE_COL_TYPE_YEAR 0x0d
#define TABLE_COL_TYPE_NEWDATE 0x0e
#define TABLE_COL_TYPE_VARCHAR 0x0f
#define TABLE_COL_TYPE_BIT 0x10
#define TABLE_COL_TYPE_TIMESTAMP2 0x11
#define TABLE_COL_TYPE_DATETIME2 0x12
#define TABLE_COL_TYPE_TIME2 0x13
#define TABLE_COL_TYPE_NEWDECIMAL 0xf6
#define TABLE_COL_TYPE_ENUM 0xf7
#define TABLE_COL_TYPE_SET 0xf8
#define TABLE_COL_TYPE_TINY_BLOB 0xf9
#define TABLE_COL_TYPE_MEDIUM_BLOB 0xfa
#define TABLE_COL_TYPE_LONG_BLOB 0xfb
#define TABLE_COL_TYPE_BLOB 0xfc
#define TABLE_COL_TYPE_VAR_STRING 0xfd
#define TABLE_COL_TYPE_STRING 0xfe
#define TABLE_COL_TYPE_GEOMETRY 0xff
/**
* RBR row event flags
*/
#define ROW_EVENT_END_STATEMENT 0x0001
#define ROW_EVENT_NO_FKCHECK 0x0002
#define ROW_EVENT_NO_UKCHECK 0x0004
#define ROW_EVENT_HAS_COLUMNS 0x0008
/** The table ID used for end of statement row events */
#define TABLE_DUMMY_ID 0x00ffffff
const char* column_type_to_string(uint8_t type);
/** Column type checking functions */
bool column_is_variable_string(uint8_t type);
bool column_is_fixed_string(uint8_t type);
bool column_is_blob(uint8_t type);
bool column_is_temporal(uint8_t type);
bool column_is_bit(uint8_t type);
bool column_is_decimal(uint8_t type);
/** Various types are stored as fixed string types and the real type is stored
* in the table metadata */
bool fixed_string_is_enum(uint8_t type);
/** Value unpacking */
uint64_t unpack_temporal_value(uint8_t type, uint8_t *ptr, uint8_t* metadata, struct tm *tm);
uint64_t unpack_enum(uint8_t *ptr, uint8_t *metadata, uint8_t *dest);
uint64_t unpack_numeric_field(uint8_t *ptr, uint8_t type, uint8_t* metadata, uint8_t* val);
uint64_t unpack_bit(uint8_t *ptr, uint8_t *null_mask, uint32_t col_count,
uint32_t curr_col_index, uint8_t *metadata, uint64_t *dest);
void format_temporal_value(char *str, size_t size, uint8_t type, struct tm *tm);
#endif /* MYSQL_BINLOG_H */

View File

@ -0,0 +1,33 @@
#ifndef _MYSQL_UTILS_H
#define _MYSQL_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/bsl.
*
* Change Date: 2019-07-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 <stdlib.h>
#include <stdint.h>
#include <mysql.h>
#include <maxscale/server.h>
/** Length-encoded integers */
size_t leint_bytes(uint8_t* ptr);
uint64_t leint_value(uint8_t* c);
uint64_t leint_consume(uint8_t ** c);
/** Length-encoded strings */
char* lestr_consume_dup(uint8_t** c);
char* lestr_consume(uint8_t** c, size_t *size);
MYSQL *mxs_mysql_real_connect(MYSQL *mysql, SERVER *server, const char *user, const char *passwd);
#endif

View File

@ -0,0 +1,60 @@
#ifndef _NOTIFICATION_SERVICE_H
#define _NOTIFICATION_SERVICE_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/bsl.
*
* Change Date: 2019-07-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 notification.h
*
* The configuration stuct for notification/feedback service
*
* @verbatim
* Revision History
*
* Date Who Description
* 02/03/15 Massimiliano Pinto Initial implementation
*
* @endverbatim
*/
#define _NOTIFICATION_CONNECT_TIMEOUT 30
#define _NOTIFICATION_OPERATION_TIMEOUT 30
#define _NOTIFICATION_SEND_PENDING 0
#define _NOTIFICATION_SEND_OK 1
#define _NOTIFICATION_SEND_ERROR 2
#define _NOTIFICATION_REPORT_ROW_LEN 255
#include <stdint.h>
/**
* The configuration and usage information data for feeback service
*/
typedef struct
{
int feedback_enable; /**< Enable/Disable Notification feedback */
char *feedback_url; /**< URL to which the data is sent */
char *feedback_user_info; /**< User info included in the feedback data sent */
int feedback_timeout; /**< An attempt to write/read the data times out and fails after this many seconds */
int feedback_connect_timeout; /**< An attempt to send the data times out and fails after this many seconds */
int feedback_last_action; /**< Holds the feedback last send action status */
int feedback_frequency; /*< Frequency of the housekeeper task */
char *release_info; /**< Operating system Release name */
char *sysname; /**< Operating system name */
uint8_t *mac_sha1; /**< First available MAC address*/
} FEEDBACK_CONF;
extern char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len);
extern void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out);
extern FEEDBACK_CONF * config_get_feedback_data();
#endif

View File

@ -0,0 +1,51 @@
#ifndef _PLATFORM_H
#define _PLATFORM_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/bsl.
*
* Change Date: 2019-07-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.
*/
#if !defined(__cplusplus)
#if __STDC_VERSION__ >= 201112
#if defined(__STDC_NO_THREADS__)
#define thread_local _Thread_local
#else
#include <threads.h>
#endif
#else // __STDC_VERSION >= 201112
#if defined(__GNUC__)
#define thread_local __thread
#else
#error Do not know how to define thread_local on this compiler/OS platform.
#endif
#endif
#else // __cplusplus
// C++11 supports thread_local natively.
#if __cplusplus < 201103
#if defined(__GNUC__)
#define thread_local __thread
#else
#error Do not know how to define thread_local on this compiler/OS platform.
#endif
#endif // __cplusplus < 201103
#endif // __cplusplus
#endif // _PLATFORM_H

70
include/maxscale/poll.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef _POLL_H
#define _POLL_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/bsl.
*
* Change Date: 2019-07-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>
#include <maxscale/gwbitmask.h>
#include <maxscale/resultset.h>
#include <sys/epoll.h>
/**
* @file poll.h The poll related functionality
*
* @verbatim
* Revision History
*
* Date Who Description
* 19/06/13 Mark Riddoch Initial implementation
* 17/10/15 Martin Brampton Declare fake event functions
*
* @endverbatim
*/
#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_PENDING,
POLL_STAT_EVQ_MAX,
POLL_STAT_MAX_QTIME,
POLL_STAT_MAX_EXECTIME
} POLL_STAT;
extern void poll_init();
extern int poll_add_dcb(DCB *);
extern int poll_remove_dcb(DCB *);
extern void poll_waitevents(void *);
extern void poll_shutdown();
extern GWBITMASK *poll_bitmask();
extern void poll_set_maxwait(unsigned int);
extern void poll_set_nonblocking_polls(unsigned int);
extern void dprintPollStats(DCB *);
extern void dShowThreads(DCB *dcb);
extern void poll_add_epollin_event_to_dcb(DCB* dcb, GWBUF* buf);
extern void dShowEventQ(DCB *dcb);
extern void dShowEventStats(DCB *dcb);
extern int poll_get_stat(POLL_STAT stat);
extern RESULTSET *eventTimesGetList();
extern void poll_fake_event(DCB *dcb, enum EPOLL_EVENTS ev);
extern void poll_fake_hangup_event(DCB *dcb);
extern void poll_fake_write_event(DCB *dcb);
extern void poll_fake_read_event(DCB *dcb);
#endif

View File

@ -0,0 +1,135 @@
#ifndef QUERY_CLASSIFIER_HG
#define QUERY_CLASSIFIER_HG
/*
* 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/bsl.
*
* Change Date: 2019-07-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/skygw_utils.h>
#include <maxscale/buffer.h>
EXTERN_C_BLOCK_BEGIN
typedef enum
{
QUERY_TYPE_UNKNOWN = 0x000000, /*< Initial value, can't be tested bitwisely */
QUERY_TYPE_LOCAL_READ = 0x000001, /*< Read non-database data, execute in MaxScale:any */
QUERY_TYPE_READ = 0x000002, /*< Read database data:any */
QUERY_TYPE_WRITE = 0x000004, /*< Master data will be modified:master */
QUERY_TYPE_MASTER_READ = 0x000008, /*< Read from the master:master */
QUERY_TYPE_SESSION_WRITE = 0x000010, /*< Session data will be modified:master or all */
/** Not implemented yet */
//QUERY_TYPE_USERVAR_WRITE = 0x000020, /*< Write a user variable:master or all */
QUERY_TYPE_USERVAR_READ = 0x000040, /*< Read a user variable:master or any */
QUERY_TYPE_SYSVAR_READ = 0x000080, /*< Read a system variable:master or any */
/** Not implemented yet */
//QUERY_TYPE_SYSVAR_WRITE = 0x000100, /*< Write a system variable:master or all */
QUERY_TYPE_GSYSVAR_READ = 0x000200, /*< Read global system variable:master or any */
QUERY_TYPE_GSYSVAR_WRITE = 0x000400, /*< Write global system variable:master or all */
QUERY_TYPE_BEGIN_TRX = 0x000800, /*< BEGIN or START TRANSACTION */
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x001000, /*< SET autocommit=1 */
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x002000, /*< SET autocommit=0 */
QUERY_TYPE_ROLLBACK = 0x004000, /*< ROLLBACK */
QUERY_TYPE_COMMIT = 0x008000, /*< COMMIT */
QUERY_TYPE_PREPARE_NAMED_STMT = 0x010000, /*< Prepared stmt with name from user:all */
QUERY_TYPE_PREPARE_STMT = 0x020000, /*< Prepared stmt with id provided by server:all */
QUERY_TYPE_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */
QUERY_TYPE_CREATE_TMP_TABLE = 0x080000, /*< Create temporary table:master (could be all) */
QUERY_TYPE_READ_TMP_TABLE = 0x100000, /*< Read temporary table:master (could be any) */
QUERY_TYPE_SHOW_DATABASES = 0x200000, /*< Show list of databases */
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
} qc_query_type_t;
typedef enum
{
QUERY_OP_UNDEFINED = 0,
QUERY_OP_SELECT = (1 << 0),
QUERY_OP_UPDATE = (1 << 1),
QUERY_OP_INSERT = (1 << 2),
QUERY_OP_DELETE = (1 << 3),
QUERY_OP_TRUNCATE = (1 << 4),
QUERY_OP_ALTER = (1 << 5),
QUERY_OP_CREATE = (1 << 6),
QUERY_OP_DROP = (1 << 7),
QUERY_OP_CHANGE_DB = (1 << 8),
QUERY_OP_LOAD = (1 << 9),
QUERY_OP_GRANT = (1 << 10),
QUERY_OP_REVOKE = (1 << 11)
} qc_query_op_t;
typedef enum qc_parse_result
{
QC_QUERY_INVALID = 0, /*< The query was not recognized or could not be parsed. */
QC_QUERY_TOKENIZED = 1, /*< The query was classified based on tokens; incompletely classified. */
QC_QUERY_PARTIALLY_PARSED = 2, /*< The query was only partially parsed; incompletely classified. */
QC_QUERY_PARSED = 3 /*< The query was fully parsed; completely classified. */
} qc_parse_result_t;
#define QUERY_IS_TYPE(mask,type) ((mask & type) == type)
bool qc_init(const char* plugin_name, const char* plugin_args);
void qc_end(void);
typedef struct query_classifier QUERY_CLASSIFIER;
QUERY_CLASSIFIER* qc_load(const char* plugin_name);
void qc_unload(QUERY_CLASSIFIER* classifier);
bool qc_thread_init(void);
void qc_thread_end(void);
qc_parse_result_t qc_parse(GWBUF* querybuf);
uint32_t qc_get_type(GWBUF* querybuf);
qc_query_op_t qc_get_operation(GWBUF* querybuf);
char* qc_get_created_table_name(GWBUF* querybuf);
bool qc_is_drop_table_query(GWBUF* querybuf);
bool qc_is_real_query(GWBUF* querybuf);
char** qc_get_table_names(GWBUF* querybuf, int* tblsize, bool fullnames);
char* qc_get_canonical(GWBUF* querybuf);
bool qc_query_has_clause(GWBUF* buf);
char* qc_get_qtype_str(qc_query_type_t qtype);
char* qc_get_affected_fields(GWBUF* buf);
char** qc_get_database_names(GWBUF* querybuf, int* size);
const char* qc_op_to_string(qc_query_op_t op);
const char* qc_type_to_string(qc_query_type_t type);
char* qc_types_to_string(uint32_t types);
struct query_classifier
{
bool (*qc_init)(const char* args);
void (*qc_end)(void);
bool (*qc_thread_init)(void);
void (*qc_thread_end)(void);
qc_parse_result_t (*qc_parse)(GWBUF* querybuf);
uint32_t (*qc_get_type)(GWBUF* querybuf);
qc_query_op_t (*qc_get_operation)(GWBUF* querybuf);
char* (*qc_get_created_table_name)(GWBUF* querybuf);
bool (*qc_is_drop_table_query)(GWBUF* querybuf);
bool (*qc_is_real_query)(GWBUF* querybuf);
char** (*qc_get_table_names)(GWBUF* querybuf, int* tblsize, bool fullnames);
char* (*qc_get_canonical)(GWBUF* querybuf);
bool (*qc_query_has_clause)(GWBUF* buf);
char* (*qc_get_affected_fields)(GWBUF* buf);
char** (*qc_get_database_names)(GWBUF* querybuf, int* size);
};
#define QUERY_CLASSIFIER_VERSION {1, 0, 0}
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,70 @@
#ifndef _QUEUEMANAGER_H
#define _QUEUEMANAGER_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/bsl.
*
* Change Date: 2019-07-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 queuemanager.h The Queue Manager header file
*
*
* @verbatim
* Revision History
*
* Date Who Description
* 27/04/2016 Martin Brampton Initial implementation
*
* @endverbatim
*/
#include <stdbool.h>
#include <maxscale/spinlock.h>
#define CONNECTION_QUEUE_LIMIT 1000
typedef struct queue_entry
{
void *queued_object;
long heartbeat;
#if defined(SS_DEBUG)
long sequence_check;
#endif /* SS_DEBUG */
} QUEUE_ENTRY;
typedef struct queue_config
{
int queue_limit;
int start;
int end;
int timeout;
bool has_entries;
SPINLOCK queue_lock;
QUEUE_ENTRY *queue_array;
#if defined(SS_DEBUG)
long sequence_number;
#endif /* SS_DEBUG */
} QUEUE_CONFIG;
QUEUE_CONFIG *mxs_queue_alloc(int limit, int timeout);
void mxs_queue_free(QUEUE_CONFIG *queue_config);
bool mxs_enqueue(QUEUE_CONFIG *queue_config, void *new_entry);
bool mxs_dequeue(QUEUE_CONFIG *queue_config, QUEUE_ENTRY *result);
bool mxs_dequeue_if_expired(QUEUE_CONFIG *queue_config, QUEUE_ENTRY *result);
static inline int
mxs_queue_count(QUEUE_CONFIG *queue_config)
{
int count = queue_config->end - queue_config->start;
return count < 0 ? (count + queue_config->queue_limit + 1): count;
}
#endif /* QUEUEMANAGER_H */

View File

@ -0,0 +1,33 @@
#ifndef RANDOM_JKISS_H
#define RANDOM_JKISS_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/bsl.
*
* Change Date: 2019-07-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: random_jkiss.h
* Author: mbrampton
*
* Created on 26 August 2015, 15:34
*/
#ifdef __cplusplus
extern "C" {
#endif
extern unsigned int random_jkiss(void);
#ifdef __cplusplus
}
#endif
#endif /* RANDOM_H */

56
include/maxscale/rdtsc.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef _RDTSC_H
#define _RDTSC_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/bsl.
*
* Change Date: 2019-07-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 rdtsc.h Access the process time-stamp counter
*
* This is an Intel only facilty that is used to access an accurate time
* value, the granularity of which is related to the processor clock speed
* and the overhead for access is much lower than using any system call
* mechanism.
*
*
* @verbatim
* Revision History
*
* Date Who Description
* 19/09/2014 Mark Riddoch Initial implementation
*
* @endverbatim
*/
typedef unsigned long long CYCLES;
/**
* Get the current time-stamp counter value from the processor. This is the
* count of CPU cyceles as a 64 bit value.
*
* The value returned is related to the clock speed, to obtian a value in
* seconds divide the returned value by the clock frequency for the processor.
*
* Note, on multi-processsor systems care much be taken to avoid the thread
* moving to a different processor when taken succsive value of RDTSC to
* obtian accurate timing. This may be done by setting pocessor affinity for
* the thread. See sched_setaffinity/sched_getaffinity.
*
* @return CPU cycle count
*/
static __inline__ CYCLES rdtsc(void)
{
unsigned long long int x;
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
return x;
}
#endif

View File

@ -0,0 +1,88 @@
#ifndef _RESULTSET_H
#define _RESULTSET_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/bsl.
*
* Change Date: 2019-07-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 resultset.h The MaxScale generic result set mechanism
*
* @verbatim
* Revision History
*
* Date Who Description
* 17/02/15 Mark Riddoch Initial implementation
*
* @endverbatim
*/
#include <maxscale/dcb.h>
/**
* Column types
*/
typedef enum
{
COL_TYPE_VARCHAR = 0x0f,
COL_TYPE_VARSTRING = 0xfd
} RESULT_COL_TYPE;
/**
* The result set column definition. Each result set has an order linked
* list of column definitions.
*/
typedef struct resultcolumn
{
char *name; /*< Column name */
int len; /*< Column length */
RESULT_COL_TYPE type; /*< Column type */
struct resultcolumn *next; /*< next column */
} RESULT_COLUMN;
/**
* A representation of a row within a result set.
*/
typedef struct resultrow
{
int n_cols; /*< No. of columns in row */
char **cols; /*< The columns themselves */
} RESULT_ROW;
struct resultset;
/**
* Type of callback function used to supply each row
*/
typedef RESULT_ROW * (*RESULT_ROW_CB)(struct resultset *, void *);
/**
* The representation of the result set itself.
*/
typedef struct resultset
{
int n_cols; /*< No. of columns */
RESULT_COLUMN *column; /*< Linked list of column definitions */
RESULT_ROW_CB fetchrow; /*< Fetch a row for the result set */
void *userdata; /*< User data for the fetch row call */
} RESULTSET;
extern RESULTSET *resultset_create(RESULT_ROW_CB, void *);
extern void resultset_free(RESULTSET *);
extern int resultset_add_column(RESULTSET *, const char *, int, RESULT_COL_TYPE);
extern void resultset_column_free(RESULT_COLUMN *);
extern RESULT_ROW *resultset_make_row(RESULTSET *);
extern void resultset_free_row(RESULT_ROW *);
extern int resultset_row_set(RESULT_ROW *, int, const char *);
extern void resultset_stream_mysql(RESULTSET *, DCB *);
extern void resultset_stream_json(RESULTSET *, DCB *);
#endif

105
include/maxscale/router.h Normal file
View File

@ -0,0 +1,105 @@
#ifndef _ROUTER_H
#define _ROUTER_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/bsl.
*
* Change Date: 2019-07-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 router.h - The query router interface mechanisms
*
* Revision History
*
* Date Who Description
* 14/06/2013 Mark Riddoch Initial implementation
* 26/06/2013 Mark Riddoch Addition of router options and the diagnostic entry point
* 15/07/2013 Massimiliano Pinto Added clientReply entry point
* 16/07/2013 Massimiliano Pinto Added router commands values
* 22/10/2013 Massimiliano Pinto Added router errorReply entry point
* 27/10/2015 Martin Brampton Add RCAP_TYPE_NO_RSESSION
*
*/
#include <maxscale/service.h>
#include <maxscale/session.h>
#include <maxscale/buffer.h>
#include <stdint.h>
/**
* The ROUTER handle points to module specific data, so the best we can do
* is to make it a void * externally.
*/
typedef void *ROUTER;
typedef enum error_action
{
ERRACT_NEW_CONNECTION = 0x001,
ERRACT_REPLY_CLIENT = 0x002
} error_action_t;
/**
* @verbatim
* The "module object" structure for a query router module
*
* The entry points are:
* createInstance Called by the service to create a new instance of the query router
* newSession Called to create a new user session within the query router
* closeSession Called when a session is closed
* routeQuery Called on each query that requires routing
* diagnostics Called to force the router to print diagnostic output
* clientReply Called to reply to client the data from one or all backends
* errorReply Called to reply to client errors with optional closeSession or make a request for
* a new backend connection
*
* @endverbatim
*
* @see load_module
*/
typedef struct router_object
{
ROUTER *(*createInstance)(SERVICE *service, char **options);
void *(*newSession)(ROUTER *instance, SESSION *session);
void (*closeSession)(ROUTER *instance, void *router_session);
void (*freeSession)(ROUTER *instance, void *router_session);
int (*routeQuery)(ROUTER *instance, void *router_session, GWBUF *queue);
void (*diagnostics)(ROUTER *instance, DCB *dcb);
void (*clientReply)(ROUTER* instance, void* router_session, GWBUF* queue, DCB *backend_dcb);
void (*handleError)(ROUTER* instance,
void* router_session,
GWBUF* errmsgbuf,
DCB* backend_dcb,
error_action_t action,
bool* succp);
int (*getCapabilities)();
} ROUTER_OBJECT;
/**
* The router module API version. Any change that changes the router API
* must update these versions numbers in accordance with the rules in
* modinfo.h.
*/
#define ROUTER_VERSION { 1, 0, 0 }
/**
* Router capability type. Indicates what kind of input router accepts.
*/
typedef enum router_capability_t
{
RCAP_TYPE_UNDEFINED = 0x00,
RCAP_TYPE_STMT_INPUT = 0x01, /**< Statement per buffer */
RCAP_TYPE_PACKET_INPUT = 0x02, /**< Data as it was read from DCB */
RCAP_TYPE_NO_RSESSION = 0x04, /**< Router does not use router sessions */
RCAP_TYPE_NO_USERS_INIT = 0x08 /**< Prevent the loading of authenticator
users when the service is started */
} router_capability_t;
#endif

View File

@ -0,0 +1,59 @@
#ifndef _SECRETS_H
#define _SECRETS_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/bsl.
*
* Change Date: 2019-07-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 secrets.h
*
* @verbatim
* Revision History
*
* Date Who Description
* 23/06/2013 Massimiliano Pinto Initial implementation
*
* @endverbatim
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <openssl/aes.h>
#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
};
extern int secrets_writeKeys(const char *directory);
extern char *decryptPassword(const char *);
extern char *encryptPassword(const char*, const char *);
#endif

225
include/maxscale/server.h Normal file
View File

@ -0,0 +1,225 @@
#ifndef _SERVER_H
#define _SERVER_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/bsl.
*
* Change Date: 2019-07-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>
#include <maxscale/resultset.h>
/**
* @file service.h
*
* The server level definitions within the gateway
*
* @verbatim
* Revision History
*
* Date Who Description
* 14/06/13 Mark Riddoch Initial implementation
* 21/06/13 Mark Riddoch Addition of server status flags
* 22/07/13 Mark Riddoch Addition of JOINED status for Galera
* 18/05/14 Mark Riddoch Addition of unique_name field
* 20/05/14 Massimiliano Pinto Addition of server_string field
* 20/05/14 Massimiliano Pinto Addition of node_id field
* 23/05/14 Massimiliano Pinto Addition of rlag and node_ts fields
* 03/06/14 Mark Riddoch Addition of maintainance mode
* 20/06/14 Massimiliano Pinto Addition of master_id, depth, slaves fields
* 26/06/14 Mark Riddoch Adidtion of server parameters
* 30/07/14 Massimiliano Pinto Addition of NDB status for MySQL Cluster
* 30/08/14 Massimiliano Pinto Addition of SERVER_STALE_STATUS
* 27/10/14 Massimiliano Pinto Addition of SERVER_MASTER_STICKINESS
* 19/02/15 Mark Riddoch Addition of serverGetList
* 01/06/15 Massimiliano Pinto Addition of server_update_address/port
* 19/06/15 Martin Brampton Extra fields for persistent connections, CHK_SERVER
*
* @endverbatim
*/
#define MAX_SERVER_NAME_LEN 1024
#define MAX_NUM_SLAVES 128 /**< Maximum number of slaves under a single server*/
/**
* The server parameters used for weighting routing decissions
*
*/
typedef struct server_params
{
char *name; /**< Parameter name */
char *value; /**< Parameter value */
struct server_params *next; /**< Next Paramter in the linked list */
} SERVER_PARAM;
/**
* The server statistics structure
*
*/
typedef struct
{
int n_connections; /**< Number of connections */
int n_current; /**< Current connections */
int n_current_ops; /**< Current active operations */
int n_persistent; /**< Current persistent pool */
} SERVER_STATS;
/**
* The SERVER structure defines a backend server. Each server has a name
* or IP address for the server, a port that the server listens on and
* the name of a protocol module that is loaded to implement the protocol
* between the gateway and the server.
*/
typedef struct server
{
#if defined(SS_DEBUG)
skygw_chk_t server_chk_top;
#endif
SPINLOCK lock; /**< Common access lock */
char *unique_name; /**< Unique name for the server */
char *name; /**< Server name/IP address*/
unsigned short port; /**< Port to listen on */
char *protocol; /**< Protocol module to use */
char *authenticator; /**< Authenticator module name */
void *auth_instance; /**< Authenticator instance */
SSL_LISTENER *server_ssl; /**< SSL data structure for server, if any */
unsigned int status; /**< Status flag bitmap for the server */
char *monuser; /**< User name to use to monitor the db */
char *monpw; /**< Password to use to monitor the db */
SERVER_STATS stats; /**< The server statistics */
struct server *next; /**< Next server */
struct server *nextdb; /**< Next server in list attached to a service */
char *server_string; /**< Server version string, i.e. MySQL server version */
long node_id; /**< Node id, server_id for M/S or local_index for Galera */
int rlag; /**< Replication Lag for Master / Slave replication */
unsigned long node_ts; /**< Last timestamp set from M/S monitor module */
SERVER_PARAM *parameters; /**< Parameters of a server that may be used to weight routing decisions */
long master_id; /**< Master server id of this node */
int depth; /**< Replication level in the tree */
long slaves[MAX_NUM_SLAVES]; /**< Slaves of this node */
bool master_err_is_logged; /*< If node failed, this indicates whether it is logged */
DCB *persistent; /**< List of unused persistent connections to the server */
SPINLOCK persistlock; /**< Lock for adjusting the persistent connections list */
long persistpoolmax; /**< Maximum size of persistent connections pool */
long persistmaxtime; /**< Maximum number of seconds connection can live */
int persistmax; /**< Maximum pool size actually achieved since startup */
#if defined(SS_DEBUG)
skygw_chk_t server_chk_tail;
#endif
} SERVER;
/**
* Status bits in the server->status member.
*
* These are a bitmap of attributes that may be applied to a server
*/
#define SERVER_RUNNING 0x0001 /**<< The server is up and running */
#define SERVER_MASTER 0x0002 /**<< The server is a master, i.e. can handle writes */
#define SERVER_SLAVE 0x0004 /**<< The server is a slave, i.e. can handle reads */
#define SERVER_JOINED 0x0008 /**<< The server is joined in a Galera cluster */
#define SERVER_NDB 0x0010 /**<< The server is part of a MySQL cluster setup */
#define SERVER_MAINT 0x0020 /**<< Server is in maintenance mode */
#define SERVER_SLAVE_OF_EXTERNAL_MASTER 0x0040 /**<< Server is slave of a Master outside
the provided replication topology */
#define SERVER_STALE_STATUS 0x0080 /**<< Server stale status, monitor didn't update it */
#define SERVER_MASTER_STICKINESS 0x0100 /**<< Server Master stickiness */
#define SERVER_AUTH_ERROR 0x1000 /**<< Authentication error from monitor */
#define SERVER_STALE_SLAVE 0x2000 /**<< Slave status is possible even without a master */
#define SERVER_RELAY_MASTER 0x4000 /**<< Server is a relay master */
/**
* Is the server running - the macro returns true if the server is marked as running
* regardless of it's state as a master or slave
*/
#define SERVER_IS_RUNNING(server) (((server)->status & (SERVER_RUNNING|SERVER_MAINT)) == SERVER_RUNNING)
/**
* Is the server marked as down - the macro returns true if the server is believed
* to be inoperable.
*/
#define SERVER_IS_DOWN(server) (((server)->status & SERVER_RUNNING) == 0)
/**
* Is the server a master? The server must be both running and marked as master
* in order for the macro to return true
*/
#define SERVER_IS_MASTER(server) SRV_MASTER_STATUS((server)->status)
#define SRV_MASTER_STATUS(status) ((status & \
(SERVER_RUNNING|SERVER_MASTER|SERVER_MAINT)) == \
(SERVER_RUNNING|SERVER_MASTER))
/**
* Is the server valid candidate for root master. The server must be running,
* marked as master and not have maintenance bit set.
*/
#define SERVER_IS_ROOT_MASTER(server) \
(((server)->status & (SERVER_RUNNING|SERVER_MASTER|SERVER_MAINT)) == (SERVER_RUNNING|SERVER_MASTER))
/**
* Is the server a slave? The server must be both running and marked as a slave
* in order for the macro to return true
*/
#define SERVER_IS_SLAVE(server) \
(((server)->status & (SERVER_RUNNING|SERVER_SLAVE|SERVER_MAINT)) == \
(SERVER_RUNNING|SERVER_SLAVE))
/**
* Is the server joined Galera node? The server must be running and joined.
*/
#define SERVER_IS_JOINED(server) \
(((server)->status & (SERVER_RUNNING|SERVER_JOINED|SERVER_MAINT)) == (SERVER_RUNNING|SERVER_JOINED))
/**
* Is the server a SQL node in MySQL Cluster? The server must be running and with NDB status
*/
#define SERVER_IS_NDB(server) \
(((server)->status & (SERVER_RUNNING|SERVER_NDB|SERVER_MAINT)) == (SERVER_RUNNING|SERVER_NDB))
/**
* Is the server in maintenance mode.
*/
#define SERVER_IN_MAINT(server) ((server)->status & SERVER_MAINT)
/** server is not master, slave or joined */
#define SERVER_NOT_IN_CLUSTER(s) (((s)->status & (SERVER_MASTER|SERVER_SLAVE|SERVER_JOINED|SERVER_NDB)) == 0)
#define SERVER_IS_IN_CLUSTER(s) (((s)->status & (SERVER_MASTER|SERVER_SLAVE|SERVER_JOINED|SERVER_NDB)) != 0)
#define SERVER_IS_RELAY_SERVER(server) \
(((server)->status & (SERVER_RUNNING|SERVER_MASTER|SERVER_SLAVE|SERVER_MAINT)) == \
(SERVER_RUNNING|SERVER_MASTER|SERVER_SLAVE))
extern SERVER *server_alloc(char *, char *, unsigned short, char*, char*);
extern int server_free(SERVER *);
extern SERVER *server_find_by_unique_name(char *);
extern SERVER *server_find(char *, unsigned short);
extern void printServer(SERVER *);
extern void printAllServers();
extern void dprintAllServers(DCB *);
extern void dprintAllServersJson(DCB *);
extern void dprintServer(DCB *, SERVER *);
extern void dprintPersistentDCBs(DCB *, SERVER *);
extern void dListServers(DCB *);
extern char *server_status(SERVER *);
extern void server_clear_set_status(SERVER *server, int specified_bits, int bits_to_set);
extern void server_set_status(SERVER *, int);
extern void server_clear_status(SERVER *, int);
extern void server_transfer_status(SERVER *dest_server, SERVER *source_server);
extern void serverAddMonUser(SERVER *, char *, char *);
extern void serverAddParameter(SERVER *, char *, char *);
extern char *serverGetParameter(SERVER *, char *);
extern void server_update(SERVER *, char *, char *, char *);
extern void server_set_unique_name(SERVER *, char *);
extern DCB *server_get_persistent(SERVER *, char *, const char *);
extern void server_update_address(SERVER *, char *);
extern void server_update_port(SERVER *, unsigned short);
extern RESULTSET *serverGetList();
extern unsigned int server_map_status(char *str);
extern bool server_set_version_string(SERVER* server, const char* string);
#endif

225
include/maxscale/service.h Normal file
View File

@ -0,0 +1,225 @@
#ifndef _SERVICE_H
#define _SERVICE_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/bsl.
*
* Change Date: 2019-07-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 <time.h>
#include <maxscale/gw_protocol.h>
#include <maxscale/spinlock.h>
#include <maxscale/dcb.h>
#include <maxscale/server.h>
#include <maxscale/listener.h>
#include <maxscale/filter.h>
#include <maxscale/hashtable.h>
#include <maxscale/resultset.h>
#include <maxscale/maxconfig.h>
#include <maxscale/queuemanager.h>
#include <openssl/crypto.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/dh.h>
/**
* @file service.h
*
* The service level definitions within the gateway
*
* @verbatim
* Revision History
*
* Date Who Description
* 14/06/13 Mark Riddoch Initial implementation
* 18/06/13 Mark Riddoch Addition of statistics and function
* prototypes
* 23/06/13 Mark Riddoch Added service user and users
* 06/02/14 Massimiliano Pinto Added service flag for root user access
* 25/02/14 Massimiliano Pinto Added service refresh limit feature
* 07/05/14 Massimiliano Pinto Added version_string field to service
* struct
* 29/05/14 Mark Riddoch Filter API mechanism
* 26/06/14 Mark Riddoch Added WeightBy support
* 09/09/14 Massimiliano Pinto Added service option for localhost authentication
* 09/10/14 Massimiliano Pinto Added service resources via hashtable
* 31/05/16 Martin Brampton Add fields to support connection throttling
*
* @endverbatim
*/
struct server;
struct router;
struct router_object;
struct users;
/**
* The service statistics structure
*/
typedef struct
{
time_t started; /**< The time when the service was started */
int n_failed_starts; /**< Number of times this service has failed to start */
int n_sessions; /**< Number of sessions created on service since start */
int n_current; /**< Current number of sessions */
} SERVICE_STATS;
/**
* The service user structure holds the information that is needed
for this service to allow the gateway to login to the backend
database and extact information such as the user table or other
database status or configuration data.
*/
typedef struct
{
char *name; /**< The user name to use to extract information */
char *authdata; /**< The authentication data requied */
} SERVICE_USER;
/**
* The service refresh rate holds the counter and last load time_t
for this service to load users data from the backend database
*/
typedef struct
{
int nloads;
time_t last;
} SERVICE_REFRESH_RATE;
typedef struct server_ref_t
{
struct server_ref_t *next;
SERVER* server;
} SERVER_REF;
#define SERVICE_MAX_RETRY_INTERVAL 3600 /*< The maximum interval between service start retries */
/** Value of service timeout if timeout checks are disabled */
#define SERVICE_NO_SESSION_TIMEOUT LONG_MAX
/**
* Parameters that are automatically detected but can also be configured by the
* user are initially set to this value.
*/
#define SERVICE_PARAM_UNINIT -1
/**
* Defines a service within the gateway.
*
* A service is a combination of a set of backend servers, a routing mechanism
* and a set of client side protocol/port pairs used to listen for new connections
* to the service.
*/
typedef struct service
{
char *name; /**< The service name */
int state; /**< The service state */
int client_count; /**< Number of connected clients */
int max_connections; /**< Maximum client connections */
QUEUE_CONFIG *queued_connections; /**< Queued connections, if set */
SERV_LISTENER *ports; /**< Linked list of ports and protocols
* that this service will listen on.
*/
char *routerModule; /**< Name of router module to use */
char **routerOptions; /**< Router specific option strings */
struct router_object *router; /**< The router we are using */
void *router_instance; /**< The router instance for this service */
char *version_string; /** version string for this service listeners */
SERVER_REF *dbref; /** server references */
SERVICE_USER credentials; /**< The cedentials of the service user */
SPINLOCK spin; /**< The service spinlock */
SERVICE_STATS stats; /**< The service statistics */
int enable_root; /**< Allow root user access */
int localhost_match_wildcard_host; /**< Match localhost against wildcard */
CONFIG_PARAMETER* svc_config_param;/*< list of config params and values */
int svc_config_version; /*< Version number of configuration */
bool svc_do_shutdown; /*< tells the service to exit loops etc. */
bool users_from_all; /*< Load users from one server or all of them */
bool strip_db_esc; /*< Remove the '\' characters from database names
* when querying them from the server. MySQL Workbench seems
* to escape at least the underscore character. */
SPINLOCK users_table_spin; /**< The spinlock for users data refresh */
SERVICE_REFRESH_RATE rate_limit; /**< The refresh rate limit for users table */
FILTER_DEF **filters; /**< Ordered list of filters */
int n_filters; /**< Number of filters */
long conn_idle_timeout; /**< Session timeout in seconds */
char *weightby;
struct service *next; /**< The next service in the linked list */
bool retry_start; /*< If starting of the service should be retried later */
bool log_auth_warnings; /*< Log authentication failures and warnings */
} SERVICE;
typedef enum count_spec_t
{
COUNT_NONE = 0,
COUNT_ATLEAST,
COUNT_EXACT,
COUNT_ATMOST
} count_spec_t;
#define SERVICE_STATE_ALLOC 1 /**< The service has been allocated */
#define SERVICE_STATE_STARTED 2 /**< The service has been started */
#define SERVICE_STATE_FAILED 3 /**< The service failed to start */
#define SERVICE_STATE_STOPPED 4 /**< The service has been stopped */
extern SERVICE *service_alloc(const char *, const char *);
extern int service_free(SERVICE *);
extern SERVICE *service_find(char *);
extern int service_isvalid(SERVICE *);
extern int serviceAddProtocol(SERVICE *service, char *name, char *protocol,
char *address, unsigned short port,
char *authenticator, char *options,
SSL_LISTENER *ssl);
extern int serviceHasProtocol(SERVICE *service, const char *protocol,
const char* address, unsigned short port);
extern void serviceAddBackend(SERVICE *, SERVER *);
extern int serviceHasBackend(SERVICE *, SERVER *);
extern void serviceAddRouterOption(SERVICE *, char *);
extern void serviceClearRouterOptions(SERVICE *);
extern int serviceStart(SERVICE *);
extern int serviceStartAll();
extern void serviceStartProtocol(SERVICE *, char *, int);
extern int serviceStop(SERVICE *);
extern int serviceRestart(SERVICE *);
extern int serviceSetUser(SERVICE *, char *, char *);
extern int serviceGetUser(SERVICE *, char **, char **);
extern bool serviceSetFilters(SERVICE *, char *);
extern int serviceSetSSL(SERVICE *service, char* action);
extern int serviceSetSSLVersion(SERVICE *service, char* version);
extern int serviceSetSSLVerifyDepth(SERVICE* service, int depth);
extern void serviceSetCertificates(SERVICE *service, char* cert, char* key, char* ca_cert);
extern int serviceEnableRootUser(SERVICE *, int );
extern int serviceSetTimeout(SERVICE *, int );
extern int serviceSetConnectionLimits(SERVICE *, int, int, int);
extern void serviceSetRetryOnFailure(SERVICE *service, char* value);
extern void serviceWeightBy(SERVICE *, char *);
extern char *serviceGetWeightingParameter(SERVICE *);
extern int serviceEnableLocalhostMatchWildcardHost(SERVICE *, int);
extern int serviceStripDbEsc(SERVICE* service, int action);
extern int serviceAuthAllServers(SERVICE *service, int action);
extern void service_update(SERVICE *, char *, char *, char *);
extern int service_refresh_users(SERVICE *);
extern void printService(SERVICE *);
extern void printAllServices();
extern void dprintAllServices(DCB *);
extern bool service_set_param_value(SERVICE* service,
CONFIG_PARAMETER* param,
char* valstr,
count_spec_t count_spec,
config_param_type_t type);
extern void dprintService(DCB *, SERVICE *);
extern void dListServices(DCB *);
extern void dListListeners(DCB *);
extern char* service_get_name(SERVICE* svc);
extern void service_shutdown();
extern int serviceSessionCountAll();
extern RESULTSET *serviceGetList();
extern RESULTSET *serviceGetListenerList();
extern bool service_all_services_have_listeners();
#endif

204
include/maxscale/session.h Normal file
View File

@ -0,0 +1,204 @@
#ifndef _SESSION_H
#define _SESSION_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/bsl.
*
* Change Date: 2019-07-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 session.h
*
* @verbatim
* Revision History
*
* Date Who Description
* 01-06-2013 Mark Riddoch Initial implementation
* 14-06-2013 Massimiliano Pinto Added void *data to session
* for session specific data
* 01-07-2013 Massimiliano Pinto Removed backends pointer
* from struct session
* 02-09-2013 Massimiliano Pinto Added session ref counter
* 29-05-2014 Mark Riddoch Support for filter mechanism
* added
* 20-02-2015 Markus Mäkelä Added session timeouts
* 27/06/2016 Martin Brampton Modify session struct for list manager
*
* @endverbatim
*/
#include <time.h>
#include <maxscale/atomic.h>
#include <maxscale/buffer.h>
#include <maxscale/listmanager.h>
#include <maxscale/spinlock.h>
#include <maxscale/resultset.h>
#include <maxscale/skygw_utils.h>
#include <maxscale/log_manager.h>
struct dcb;
struct service;
struct filter_def;
/**
* The session statistics structure
*/
typedef struct
{
time_t connect; /**< Time when the session was started */
} SESSION_STATS;
#define SESSION_STATS_INIT {0}
typedef enum
{
SESSION_STATE_ALLOC, /*< for all sessions */
SESSION_STATE_READY, /*< for router session */
SESSION_STATE_ROUTER_READY, /*< for router session */
SESSION_STATE_STOPPING, /*< session and router are being closed */
SESSION_STATE_LISTENER, /*< for listener session */
SESSION_STATE_LISTENER_STOPPED, /*< for listener session */
SESSION_STATE_TO_BE_FREED, /*< ready to be freed as soon as there are no references */
SESSION_STATE_FREE, /*< for all sessions */
SESSION_STATE_DUMMY /*< dummy session for consistency */
} session_state_t;
/**
* The downstream element in the filter chain. This may refer to
* another filter or to a router.
*/
typedef struct
{
void *instance;
void *session;
int (*routeQuery)(void *instance, void *session, GWBUF *request);
} DOWNSTREAM;
#define DOWNSTREAM_INIT {0}
/**
* The upstream element in the filter chain. This may refer to
* another filter or to the protocol implementation.
*/
typedef struct
{
void *instance;
void *session;
int (*clientReply)(void *instance, void *session, GWBUF *response);
int (*error)(void *instance, void *session, void *);
} UPSTREAM;
#define UPSTREAM_INIT {0}
/**
* Structure used to track the filter instances and sessions of the filters
* that are in use within a session.
*/
typedef struct
{
struct filter_def *filter;
void *instance;
void *session;
} SESSION_FILTER;
#define SESSION_FILTER_INIT {0}
/**
* Filter type for the sessionGetList call
*/
typedef enum
{
SESSION_LIST_ALL,
SESSION_LIST_CONNECTION
} SESSIONLISTFILTER;
/**
* The session status block
*
* A session status block is created for each user (client) connection
* to the database, it links the descriptors, routing implementation
* and originating service together for the client session.
*
* Note that the first few fields (up to and including "entry_is_ready") must
* precisely match the LIST_ENTRY structure defined in the list manager.
*/
typedef struct session
{
LIST_ENTRY_FIELDS
skygw_chk_t ses_chk_top;
SPINLOCK ses_lock;
session_state_t state; /*< Current descriptor state */
size_t ses_id; /*< Unique session identifier */
int enabled_log_priorities; /*< Bitfield of enabled syslog priorities */
struct dcb *client_dcb; /*< The client connection */
void *router_session; /*< The router instance data */
SESSION_STATS stats; /*< Session statistics */
struct service *service; /*< The service this session is using */
int n_filters; /*< Number of filter sessions */
SESSION_FILTER *filters; /*< The filters in use within this session */
DOWNSTREAM head; /*< Head of the filter chain */
UPSTREAM tail; /*< The tail of the filter chain */
int refcount; /*< Reference count on the session */
bool ses_is_child; /*< this is a child session */
skygw_chk_t ses_chk_tail;
} SESSION;
#define SESSION_INIT {.ses_chk_top = CHK_NUM_SESSION, .ses_lock = SPINLOCK_INIT, \
.stats = SESSION_STATS_INIT, .head = DOWNSTREAM_INIT, .tail = UPSTREAM_INIT, \
.state = SESSION_STATE_ALLOC, .ses_chk_tail = CHK_NUM_SESSION}
/** Whether to do session timeout checks */
extern bool check_timeouts;
/** When the next timeout check is done. This is compared to hkheartbeat in
* hk_heartbeat.h */
extern long next_timeout_check;
#define SESSION_PROTOCOL(x, type) DCB_PROTOCOL((x)->client_dcb, type)
/**
* A convenience macro that can be used by the protocol modules to route
* the incoming data to the first element in the pipeline of filters and
* routers.
*/
#define SESSION_ROUTE_QUERY(sess, buf) \
((sess)->head.routeQuery)((sess)->head.instance, \
(sess)->head.session, (buf))
/**
* A convenience macro that can be used by the router modules to route
* the replies to the first element in the pipeline of filters and
* the protocol.
*/
#define SESSION_ROUTE_REPLY(sess, buf) \
((sess)->tail.clientReply)((sess)->tail.instance, \
(sess)->tail.session, (buf))
SESSION *session_alloc(struct service *, struct dcb *);
bool session_pre_alloc(int number);
SESSION *session_set_dummy(struct dcb *);
bool session_free(SESSION *);
int session_isvalid(SESSION *);
int session_reply(void *inst, void *session, GWBUF *data);
char *session_get_remote(SESSION *);
char *session_getUser(SESSION *);
void printAllSessions();
void printSession(SESSION *);
void dprintSessionList(DCB *pdcb);
void dprintAllSessions(struct dcb *);
void dprintSession(struct dcb *, SESSION *);
void dListSessions(struct dcb *);
char *session_state(session_state_t);
bool session_link_dcb(SESSION *, struct dcb *);
SESSION* get_session_by_router_ses(void* rses);
void session_enable_log_priority(SESSION* ses, int priority);
void session_disable_log_priority(SESSION* ses, int priority);
RESULTSET *sessionGetList(SESSIONLISTFILTER);
void process_idle_sessions();
void enable_session_timeouts();
#endif

View File

@ -0,0 +1,581 @@
/*
* 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/bsl.
*
* Change Date: 2019-07-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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#define __USE_UNIX98 1
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#if !defined(SKYGW_DEBUG_H)
#define SKYGW_DEBUG_H
#ifdef __cplusplus
#define EXTERN_C_BLOCK_BEGIN extern "C" {
#define EXTERN_C_BLOCK_END }
#define EXTERN_C_FUNC extern "C"
#else
#define EXTERN_C_BLOCK_BEGIN
#define EXTERN_C_BLOCK_END
#define EXTERN_C_FUNC
#endif
#if defined(SS_DEBUG)
# define SS_PROF
#endif
#if defined(SS_DEBUG) || defined(SS_PROF)
# define ss_prof(exp) exp
#else
# define ss_prof(exp)
#endif /* SS_DEBUG || SS_PROF */
#if defined(SS_DEBUG) && defined(LOG_ASSERT)
#include <maxscale/log_manager.h>
# define ss_dassert(exp) do { if(!(exp)){\
MXS_ERROR("debug assert %s:%d\n", (char*)__FILE__, __LINE__);\
mxs_log_flush_sync(); assert(exp);} } while (false)
#define ss_info_dassert(exp,info) do { if(!(exp)){\
MXS_ERROR("debug assert %s:%d %s\n", (char*)__FILE__, __LINE__, info);\
mxs_log_flush_sync();assert(exp);} } while (false)
# define ss_debug(exp) exp
# define ss_dfprintf fprintf
# define ss_dfflush fflush
# define ss_dfwrite fwrite
#elif defined(SS_DEBUG)
# define ss_debug(exp) exp
# define ss_dfprintf fprintf
# define ss_dfflush fflush
# define ss_dfwrite fwrite
# define ss_dassert(exp) \
{ \
if (!(exp)) { \
ss_dfprintf(stderr, \
"debug assert %s:%d\n", \
(char*)__FILE__, \
__LINE__); \
ss_dfflush(stderr); \
assert(exp); \
} \
}
# define ss_info_dassert(exp, info) \
{ \
if (!(exp)) { \
ss_dfprintf(stderr, "debug assert %s:%d, %s\n", \
(char *)__FILE__, \
__LINE__, \
info); \
ss_dfflush(stderr); \
assert((exp)); \
} \
}
#else /* SS_DEBUG */
# define ss_debug(exp)
# define ss_dfprintf(a, b, ...)
# define ss_dfflush(s)
# define ss_dfwrite(a, b, c, d)
# define ss_dassert(exp)
# define ss_info_dassert(exp, info)
#endif /* SS_DEBUG */
#define CHK_NUM_BASE 101
typedef enum skygw_chk_t
{
CHK_NUM_SLIST = CHK_NUM_BASE,
CHK_NUM_SLIST_NODE,
CHK_NUM_SLIST_CURSOR,
CHK_NUM_MLIST,
CHK_NUM_MLIST_NODE,
CHK_NUM_MLIST_CURSOR,
CHK_NUM_QUERY_TEST,
CHK_NUM_LOGFILE,
CHK_NUM_FILEWRITER,
CHK_NUM_THREAD,
CHK_NUM_SIMPLE_MUTEX,
CHK_NUM_MESSAGE,
CHK_NUM_RWLOCK,
CHK_NUM_FNAMES,
CHK_NUM_LOGMANAGER,
CHK_NUM_FILE,
CHK_NUM_BLOCKBUF,
CHK_NUM_HASHTABLE,
CHK_NUM_DCB,
CHK_NUM_PROTOCOL,
CHK_NUM_SESSION,
CHK_NUM_SERVER,
CHK_NUM_ROUTER_SES,
CHK_NUM_MY_SESCMD,
CHK_NUM_ROUTER_PROPERTY,
CHK_NUM_SESCMD_CUR,
CHK_NUM_BACKEND,
CHK_NUM_BACKEND_REF,
CHK_NUM_PREP_STMT,
CHK_NUM_PINFO,
CHK_NUM_MYSQLSES,
CHK_NUM_ADMINSES,
CHK_NUM_MANAGED_LIST
} skygw_chk_t;
# define STRBOOL(b) ((b) ? "true" : "false")
# define STRQTYPE(t) ((t) == QUERY_TYPE_WRITE ? "QUERY_TYPE_WRITE" : \
((t) == QUERY_TYPE_READ ? "QUERY_TYPE_READ" : \
((t) == QUERY_TYPE_SESSION_WRITE ? "QUERY_TYPE_SESSION_WRITE" : \
((t) == QUERY_TYPE_UNKNOWN ? "QUERY_TYPE_UNKNOWN" : \
((t) == QUERY_TYPE_LOCAL_READ ? "QUERY_TYPE_LOCAL_READ" : \
((t) == QUERY_TYPE_MASTER_READ ? "QUERY_TYPE_MASTER_READ" : \
((t) == QUERY_TYPE_USERVAR_READ ? "QUERY_TYPE_USERVAR_READ" : \
((t) == QUERY_TYPE_SYSVAR_READ ? "QUERY_TYPE_SYSVAR_READ" : \
((t) == QUERY_TYPE_GSYSVAR_READ ? "QUERY_TYPE_GSYSVAR_READ" : \
((t) == QUERY_TYPE_GSYSVAR_WRITE ? "QUERY_TYPE_GSYSVAR_WRITE" : \
((t) == QUERY_TYPE_BEGIN_TRX ? "QUERY_TYPE_BEGIN_TRX" : \
((t) == QUERY_TYPE_ENABLE_AUTOCOMMIT ? "QUERY_TYPE_ENABLE_AUTOCOMMIT" : \
((t) == QUERY_TYPE_DISABLE_AUTOCOMMIT ? "QUERY_TYPE_DISABLE_AUTOCOMMIT" : \
((t) == QUERY_TYPE_ROLLBACK ? "QUERY_TYPE_ROLLBACK" : \
((t) == QUERY_TYPE_COMMIT ? "QUERY_TYPE_COMMIT" : \
((t) == QUERY_TYPE_PREPARE_NAMED_STMT ? "QUERY_TYPE_PREPARE_NAMED_STMT" : \
((t) == QUERY_TYPE_PREPARE_STMT ? "QUERY_TYPE_PREPARE_STMT" : \
((t) == QUERY_TYPE_EXEC_STMT ? "QUERY_TYPE_EXEC_STMT" : \
((t) == QUERY_TYPE_CREATE_TMP_TABLE ? "QUERY_TYPE_CREATE_TMP_TABLE" : \
((t) == QUERY_TYPE_READ_TMP_TABLE ? "QUERY_TYPE_READ_TMP_TABLE" : \
((t) == QUERY_TYPE_SHOW_DATABASES ? "QUERY_TYPE_SHOW_DATABASES" : \
((t) == QUERY_TYPE_SHOW_TABLES ? "QUERY_TYPE_SHOW_TABLES" : \
"Unknown query type"))))))))))))))))))))))
#define STRLOGPRIORITYNAME(n)\
((n) == LOG_EMERG ? "LOG_EMERG" : \
((n) == LOG_ALERT ? "LOG_ALERT" : \
((n) == LOG_CRIT ? "LOG_CRIT" : \
((n) == LOG_ERR ? "LOG_ERR" : \
((n) == LOG_WARNING ? "LOG_WARNING" : \
((n) == LOG_NOTICE ? "LOG_NOTICE" : \
((n) == LOG_INFO ? "LOG_INFO" : \
((n) == LOG_DEBUG ? "LOG_DEBUG" : \
"Unknown log priority"))))))))
#define STRPACKETTYPE(p) ((p) == MYSQL_COM_INIT_DB ? "COM_INIT_DB" : \
((p) == MYSQL_COM_CREATE_DB ? "COM_CREATE_DB" : \
((p) == MYSQL_COM_DROP_DB ? "COM_DROP_DB" : \
((p) == MYSQL_COM_REFRESH ? "COM_REFRESH" : \
((p) == MYSQL_COM_DEBUG ? "COM_DEBUG" : \
((p) == MYSQL_COM_PING ? "COM_PING" : \
((p) == MYSQL_COM_CHANGE_USER ? "COM_CHANGE_USER" : \
((p) == MYSQL_COM_QUERY ? "COM_QUERY" : \
((p) == MYSQL_COM_SHUTDOWN ? "COM_SHUTDOWN" : \
((p) == MYSQL_COM_PROCESS_INFO ? "COM_PROCESS_INFO" : \
((p) == MYSQL_COM_CONNECT ? "COM_CONNECT" : \
((p) == MYSQL_COM_PROCESS_KILL ? "COM_PROCESS_KILL" : \
((p) == MYSQL_COM_TIME ? "COM_TIME" : \
((p) == MYSQL_COM_DELAYED_INSERT ? "COM_DELAYED_INSERT" : \
((p) == MYSQL_COM_DAEMON ? "COM_DAEMON" : \
((p) == MYSQL_COM_QUIT ? "COM_QUIT" : \
((p) == MYSQL_COM_STMT_PREPARE ? "MYSQL_COM_STMT_PREPARE" : \
((p) == MYSQL_COM_STMT_EXECUTE ? "MYSQL_COM_STMT_EXECUTE" : \
"UNKNOWN MYSQL PACKET TYPE"))))))))))))))))))
#define STRDCBSTATE(s) ((s) == DCB_STATE_ALLOC ? "DCB_STATE_ALLOC" : \
((s) == DCB_STATE_POLLING ? "DCB_STATE_POLLING" : \
((s) == DCB_STATE_LISTENING ? "DCB_STATE_LISTENING" : \
((s) == DCB_STATE_DISCONNECTED ? "DCB_STATE_DISCONNECTED" : \
((s) == DCB_STATE_NOPOLLING ? "DCB_STATE_NOPOLLING" : \
((s) == DCB_STATE_ZOMBIE ? "DCB_STATE_ZOMBIE" : \
((s) == DCB_STATE_UNDEFINED ? "DCB_STATE_UNDEFINED" : "DCB_STATE_UNKNOWN")))))))
#define STRSESSIONSTATE(s) ((s) == SESSION_STATE_ALLOC ? "SESSION_STATE_ALLOC" : \
((s) == SESSION_STATE_DUMMY ? "SESSION_STATE_DUMMY" : \
((s) == SESSION_STATE_READY ? "SESSION_STATE_READY" : \
((s) == SESSION_STATE_LISTENER ? "SESSION_STATE_LISTENER" : \
((s) == SESSION_STATE_ROUTER_READY ? "SESSION_STATE_ROUTER_READY" : \
((s) == SESSION_STATE_LISTENER_STOPPED ? "SESSION_STATE_LISTENER_STOPPED" : \
(s) == SESSION_STATE_STOPPING ? "SESSION_STATE_STOPPING":\
"SESSION_STATE_UNKNOWN"))))))
#define STRPROTOCOLSTATE(s) ((s) == MXS_AUTH_STATE_INIT ? "MXS_AUTH_STATE_INIT" : \
((s) == MXS_AUTH_STATE_PENDING_CONNECT ? "MXS_AUTH_STATE_PENDING_CONNECT" : \
((s) == MXS_AUTH_STATE_CONNECTED ? "MXS_AUTH_STATE_CONNECTED" : \
((s) == MXS_AUTH_STATE_MESSAGE_READ ? "MXS_AUTH_STATE_MESSAGE_READ" : \
((s) == MXS_AUTH_STATE_RESPONSE_SENT ? "MXS_AUTH_STATE_RESPONSE_SENT" : \
((s) == MXS_AUTH_STATE_FAILED ? "MXS_AUTH_STATE_FAILED" : \
((s) == MXS_AUTH_STATE_COMPLETE ? "MXS_AUTH_STATE_COMPLETE" : \
"UNKNOWN AUTH STATE")))))))
#define STRITEMTYPE(t) ((t) == Item::FIELD_ITEM ? "FIELD_ITEM" : \
((t) == Item::FUNC_ITEM ? "FUNC_ITEM" : \
((t) == Item::SUM_FUNC_ITEM ? "SUM_FUNC_ITEM" : \
((t) == Item::STRING_ITEM ? "STRING_ITEM" : \
((t) == Item::INT_ITEM ? "INT_ITEM" : \
((t) == Item::REAL_ITEM ? "REAL_ITEM" : \
((t) == Item::NULL_ITEM ? "NULL_ITEM" : \
((t) == Item::VARBIN_ITEM ? "VARBIN_ITEM" : \
((t) == Item::COPY_STR_ITEM ? "COPY_STR_ITEM" : \
((t) == Item::FIELD_AVG_ITEM ? "FIELD_AVG_ITEM" : \
((t) == Item::DEFAULT_VALUE_ITEM ? "DEFAULT_VALUE_ITEM" : \
((t) == Item::PROC_ITEM ? "PROC_ITEM" : \
((t) == Item::COND_ITEM ? "COND_ITEM" : \
((t) == Item::REF_ITEM ? "REF_ITEM" : \
(t) == Item::FIELD_STD_ITEM ? "FIELD_STD_ITEM" : \
((t) == Item::FIELD_VARIANCE_ITEM ? "FIELD_VARIANCE_ITEM" : \
((t) == Item::INSERT_VALUE_ITEM ? "INSERT_VALUE_ITEM": \
((t) == Item::SUBSELECT_ITEM ? "SUBSELECT_ITEM" : \
((t) == Item::ROW_ITEM ? "ROW_ITEM" : \
((t) == Item::CACHE_ITEM ? "CACHE_ITEM" : \
((t) == Item::TYPE_HOLDER ? "TYPE_HOLDER" : \
((t) == Item::PARAM_ITEM ? "PARAM_ITEM" : \
((t) == Item::TRIGGER_FIELD_ITEM ? "TRIGGER_FIELD_ITEM" : \
((t) == Item::DECIMAL_ITEM ? "DECIMAL_ITEM" : \
((t) == Item::XPATH_NODESET ? "XPATH_NODESET" : \
((t) == Item::XPATH_NODESET_CMP ? "XPATH_NODESET_CMP" : \
((t) == Item::VIEW_FIXER_ITEM ? "VIEW_FIXER_ITEM" : \
((t) == Item::EXPR_CACHE_ITEM ? "EXPR_CACHE_ITEM" : \
"Unknown item")))))))))))))))))))))))))))
#define STRDCBROLE(r) ((r) == DCB_ROLE_SERVICE_LISTENER ? "DCB_ROLE_SERVICE_LISTENER" : \
((r) == DCB_ROLE_CLIENT_HANDLER ? "DCB_ROLE_CLIENT_HANDLER" : \
((r) == DCB_ROLE_BACKEND_HANDLER ? "DCB_ROLE_BACKEND_HANDLER" : \
"UNKNOWN DCB ROLE")))
#define STRBETYPE(t) ((t) == BE_MASTER ? "BE_MASTER" : \
((t) == BE_SLAVE ? "BE_SLAVE" : \
((t) == BE_UNDEFINED ? "BE_UNDEFINED" : \
"Unknown backend tpe")))
#define STRCRITERIA(c) ((c) == UNDEFINED_CRITERIA ? "UNDEFINED_CRITERIA" : \
((c) == LEAST_GLOBAL_CONNECTIONS ? "LEAST_GLOBAL_CONNECTIONS" : \
((c) == LEAST_ROUTER_CONNECTIONS ? "LEAST_ROUTER_CONNECTIONS" : \
((c) == LEAST_BEHIND_MASTER ? "LEAST_BEHIND_MASTER" : \
((c) == LEAST_CURRENT_OPERATIONS ? "LEAST_CURRENT_OPERATIONS" : "Unknown criteria")))))
#define STRSRVSTATUS(s) (SERVER_IS_MASTER(s) ? "RUNNING MASTER" : \
(SERVER_IS_SLAVE(s) ? "RUNNING SLAVE" : \
(SERVER_IS_JOINED(s) ? "RUNNING JOINED" : \
(SERVER_IS_NDB(s) ? "RUNNING NDB" : \
((SERVER_IS_RUNNING(s) && SERVER_IN_MAINT(s)) ? "RUNNING MAINTENANCE" : \
(SERVER_IS_RELAY_SERVER(s) ? "RUNNING RELAY" : \
(SERVER_IS_RUNNING(s) ? "RUNNING (only)" : \
(SERVER_IS_DOWN(s) ? "DOWN" : "UNKNOWN STATUS"))))))))
#define STRTARGET(t) (t == TARGET_ALL ? "TARGET_ALL" : \
(t == TARGET_MASTER ? "TARGET_MASTER" : \
(t == TARGET_SLAVE ? "TARGET_SLAVE" : \
(t == TARGET_NAMED_SERVER ? "TARGET_NAMED_SERVER" : \
(t == TARGET_UNDEFINED ? "TARGET_UNDEFINED" : \
"Unknown target value")))))
#define BREFSRV(b) (b->bref_backend->backend_server)
#define STRHINTTYPE(t) (t == HINT_ROUTE_TO_MASTER ? "HINT_ROUTE_TO_MASTER" : \
((t) == HINT_ROUTE_TO_SLAVE ? "HINT_ROUTE_TO_SLAVE" : \
((t) == HINT_ROUTE_TO_NAMED_SERVER ? "HINT_ROUTE_TO_NAMED_SERVER" : \
((t) == HINT_ROUTE_TO_UPTODATE_SERVER ? "HINT_ROUTE_TO_UPTODATE_SERVER" : \
((t) == HINT_ROUTE_TO_ALL ? "HINT_ROUTE_TO_ALL" : \
((t) == HINT_PARAMETER ? "HINT_PARAMETER" : "UNKNOWN HINT TYPE"))))))
#define STRDCBREASON(r) ((r) == DCB_REASON_CLOSE ? "DCB_REASON_CLOSE" : \
((r) == DCB_REASON_DRAINED ? "DCB_REASON_DRAINED" : \
((r) == DCB_REASON_HIGH_WATER ? "DCB_REASON_HIGH_WATER" : \
((r) == DCB_REASON_LOW_WATER ? "DCB_REASON_LOW_WATER" : \
((r) == DCB_REASON_ERROR ? "DCB_REASON_ERROR" : \
((r) == DCB_REASON_HUP ? "DCB_REASON_HUP" : \
((r) == DCB_REASON_NOT_RESPONDING ? "DCB_REASON_NOT_RESPONDING" : \
"Unknown DCB reason")))))))
#define CHK_MLIST(l) { \
ss_info_dassert((l->mlist_chk_top == CHK_NUM_MLIST && \
l->mlist_chk_tail == CHK_NUM_MLIST), \
"Single-linked list structure under- or overflow"); \
if (l->mlist_first == NULL) { \
ss_info_dassert(l->mlist_nodecount == 0, \
"List head is NULL but element counter is not zero."); \
ss_info_dassert(l->mlist_last == NULL, \
"List head is NULL but tail has node"); \
} else { \
ss_info_dassert(l->mlist_nodecount > 0, \
"List head has node but element counter is not " \
"positive."); \
CHK_MLIST_NODE(l->mlist_first); \
CHK_MLIST_NODE(l->mlist_last); \
} \
if (l->mlist_nodecount == 0) { \
ss_info_dassert(l->mlist_first == NULL, \
"Element counter is zero but head has node"); \
ss_info_dassert(l->mlist_last == NULL, \
"Element counter is zero but tail has node"); \
} \
}
#define CHK_MLIST_NODE(n) { \
ss_info_dassert((n->mlnode_chk_top == CHK_NUM_MLIST_NODE && \
n->mlnode_chk_tail == CHK_NUM_MLIST_NODE), \
"Single-linked list node under- or overflow"); \
}
#define CHK_MLIST_CURSOR(c) { \
ss_info_dassert(c->mlcursor_chk_top == CHK_NUM_MLIST_CURSOR && \
c->mlcursor_chk_tail == CHK_NUM_MLIST_CURSOR, \
"List cursor under- or overflow"); \
ss_info_dassert(c->mlcursor_list != NULL, \
"List cursor doesn't have list"); \
ss_info_dassert(c->mlcursor_pos != NULL || \
(c->mlcursor_pos == NULL && \
c->mlcursor_list->mlist_first == NULL), \
"List cursor doesn't have position"); \
}
#define CHK_SLIST(l) { \
ss_info_dassert((l->slist_chk_top == CHK_NUM_SLIST && \
l->slist_chk_tail == CHK_NUM_SLIST), \
"Single-linked list structure under- or overflow"); \
if (l->slist_head == NULL) { \
ss_info_dassert(l->slist_nelems == 0, \
"List head is NULL but element counter is not zero."); \
ss_info_dassert(l->slist_tail == NULL, \
"List head is NULL but tail has node"); \
} else { \
ss_info_dassert(l->slist_nelems > 0, \
"List head has node but element counter is not " \
"positive."); \
CHK_SLIST_NODE(l->slist_head); \
CHK_SLIST_NODE(l->slist_tail); \
} \
if (l->slist_nelems == 0) { \
ss_info_dassert(l->slist_head == NULL, \
"Element counter is zero but head has node"); \
ss_info_dassert(l->slist_tail == NULL, \
"Element counter is zero but tail has node"); \
} \
}
#define CHK_SLIST_NODE(n) { \
ss_info_dassert((n->slnode_chk_top == CHK_NUM_SLIST_NODE && \
n->slnode_chk_tail == CHK_NUM_SLIST_NODE), \
"Single-linked list node under- or overflow"); \
}
#define CHK_SLIST_CURSOR(c) { \
ss_info_dassert(c->slcursor_chk_top == CHK_NUM_SLIST_CURSOR && \
c->slcursor_chk_tail == CHK_NUM_SLIST_CURSOR, \
"List cursor under- or overflow"); \
ss_info_dassert(c->slcursor_list != NULL, \
"List cursor doesn't have list"); \
ss_info_dassert(c->slcursor_pos != NULL || \
(c->slcursor_pos == NULL && \
c->slcursor_list->slist_head == NULL), \
"List cursor doesn't have position"); \
}
#define CHK_QUERY_TEST(q) { \
ss_info_dassert(q->qt_chk_top == CHK_NUM_QUERY_TEST && \
q->qt_chk_tail == CHK_NUM_QUERY_TEST, \
"Query test under- or overflow."); \
}
#define CHK_LOGFILE(lf) { \
ss_info_dassert(lf->lf_chk_top == CHK_NUM_LOGFILE && \
lf->lf_chk_tail == CHK_NUM_LOGFILE, \
"Logfile struct under- or overflow"); \
ss_info_dassert(lf->lf_filepath != NULL && \
lf->lf_name_prefix != NULL && \
lf->lf_name_suffix != NULL && \
lf->lf_full_file_name != NULL, \
"NULL in name variable\n"); \
}
#define CHK_FILEWRITER(fwr) { \
ss_info_dassert(fwr->fwr_chk_top == CHK_NUM_FILEWRITER && \
fwr->fwr_chk_tail == CHK_NUM_FILEWRITER, \
"File writer struct under- or overflow"); \
}
#define CHK_THREAD(thr) { \
ss_info_dassert(thr->sth_chk_top == CHK_NUM_THREAD && \
thr->sth_chk_tail == CHK_NUM_THREAD, \
"Thread struct under- or overflow"); \
}
#define CHK_SIMPLE_MUTEX(sm) { \
ss_info_dassert(sm->sm_chk_top == CHK_NUM_SIMPLE_MUTEX && \
sm->sm_chk_tail == CHK_NUM_SIMPLE_MUTEX, \
"Simple mutex struct under- or overflow"); \
}
#define CHK_MESSAGE(mes) { \
ss_info_dassert(mes->mes_chk_top == CHK_NUM_MESSAGE && \
mes->mes_chk_tail == CHK_NUM_MESSAGE, \
"Message struct under- or overflow"); \
}
#define CHK_MLIST_ISLOCKED(l) { \
ss_info_dassert((l.mlist_uselock && l.mlist_islocked) || \
!(l.mlist_uselock || l.mlist_islocked), \
("mlist is not locked although it should.")); \
CHK_MUTEXED_FOR_THR(l.mlist_uselock,l.mlist_rwlock); \
}
#define CHK_MUTEXED_FOR_THR(b,l) { \
ss_info_dassert(!b || \
(b && (l->srw_rwlock_thr == pthread_self())), \
"rwlock is not acquired although it should be."); \
}
#define CHK_FNAMES_CONF(fn) { \
ss_info_dassert(fn->fn_chk_top == CHK_NUM_FNAMES && \
fn->fn_chk_tail == CHK_NUM_FNAMES, \
"File names confs struct under- or overflow"); \
}
#define CHK_LOGMANAGER(lm) { \
ss_info_dassert(lm->lm_chk_top == CHK_NUM_LOGMANAGER && \
lm->lm_chk_tail == CHK_NUM_LOGMANAGER, \
"Log manager struct under- or overflow"); \
}
#define CHK_FILE(f) { \
ss_info_dassert(f->sf_chk_top == CHK_NUM_FILE && \
f->sf_chk_tail == CHK_NUM_FILE, \
"File struct under- or overflow"); \
}
#define CHK_BLOCKBUF(bb) { \
ss_info_dassert(bb->bb_chk_top == CHK_NUM_BLOCKBUF, \
"Block buf under- or overflow"); \
}
#define CHK_HASHTABLE(t) { \
ss_info_dassert(t->ht_chk_top == CHK_NUM_HASHTABLE && \
t->ht_chk_tail == CHK_NUM_HASHTABLE, \
"Hashtable under- or overflow"); \
}
#define CHK_MANAGED_LIST(l) { \
ss_info_dassert(l->list_entry_chk_top == CHK_NUM_MANAGED_LIST && \
l->list_entry_chk_tail == CHK_NUM_MANAGED_LIST, \
"Managed list under- or overflow"); \
}
#define CHK_DCB(d) { \
ss_info_dassert(d->dcb_chk_top == CHK_NUM_DCB && \
d->dcb_chk_tail == CHK_NUM_DCB, \
"Dcb under- or overflow"); \
CHK_MANAGED_LIST(d) \
}
#define CHK_PROTOCOL(p) { \
ss_info_dassert(p->protocol_chk_top == CHK_NUM_PROTOCOL && \
p->protocol_chk_tail == CHK_NUM_PROTOCOL, \
"Protocol under- or overflow"); \
}
#define CHK_SESSION(s) { \
ss_info_dassert(s->ses_chk_top == CHK_NUM_SESSION && \
s->ses_chk_tail == CHK_NUM_SESSION, \
"Session under- or overflow"); \
CHK_MANAGED_LIST(s) \
}
#define CHK_SERVER(s) { \
ss_info_dassert(s->server_chk_top == CHK_NUM_SERVER && \
s->server_chk_tail == CHK_NUM_SERVER, \
"Server under- or overflow"); \
}
#define CHK_GWBUF(b) { \
ss_info_dassert(((char *)(b)->start <= (char *)(b)->end), \
"gwbuf start has passed the endpoint"); \
}
#define CHK_CLIENT_RSES(r) { \
ss_info_dassert((r)->rses_chk_top == CHK_NUM_ROUTER_SES && \
(r)->rses_chk_tail == CHK_NUM_ROUTER_SES, \
"Router client session has invalid check fields"); \
}
#define CHK_RSES_PROP(p) { \
ss_info_dassert((p)->rses_prop_chk_top == CHK_NUM_ROUTER_PROPERTY && \
(p)->rses_prop_chk_tail == CHK_NUM_ROUTER_PROPERTY, \
"Router property has invalid check fields"); \
}
#define CHK_MYSQL_SESCMD(s) { \
ss_info_dassert((s)->my_sescmd_chk_top == CHK_NUM_MY_SESCMD && \
(s)->my_sescmd_chk_tail == CHK_NUM_MY_SESCMD, \
"Session command has invalid check fields"); \
}
#define CHK_SESCMD_CUR(c) { \
ss_info_dassert((c)->scmd_cur_chk_top == CHK_NUM_SESCMD_CUR && \
(c)->scmd_cur_chk_tail == CHK_NUM_SESCMD_CUR, \
"Session command cursor has invalid check fields"); \
}
#define CHK_BACKEND(b) { \
ss_info_dassert((b)->be_chk_top == CHK_NUM_BACKEND && \
(b)->be_chk_tail == CHK_NUM_BACKEND, \
"BACKEND has invalid check fields"); \
}
#define CHK_BACKEND_REF(r) { \
ss_info_dassert((r)->bref_chk_top == CHK_NUM_BACKEND_REF && \
(r)->bref_chk_tail == CHK_NUM_BACKEND_REF, \
"Backend reference has invalid check fields"); \
}
#define CHK_PREP_STMT(p) { \
ss_info_dassert((p)->pstmt_chk_top == CHK_NUM_PREP_STMT && \
(p)->pstmt_chk_tail == CHK_NUM_PREP_STMT, \
"Prepared statement struct has invalid check fields"); \
}
#define CHK_PARSING_INFO(p) { \
ss_info_dassert((p)->pi_chk_top == CHK_NUM_PINFO && \
(p)->pi_chk_tail == CHK_NUM_PINFO, \
"Parsing info struct has invalid check fields"); \
}
#define CHK_MYSQL_SESSION(s) { \
ss_info_dassert((s)->myses_chk_top == CHK_NUM_MYSQLSES && \
(s)->myses_chk_tail == CHK_NUM_MYSQLSES, \
"MYSQL session struct has invalid check fields"); \
}
#define CHK_ADMIN_SESSION(s) { \
ss_info_dassert((s)->adminses_chk_top == CHK_NUM_ADMINSES && \
(s)->adminses_chk_tail == CHK_NUM_ADMINSES, \
"Admin session struct has invalid check fields"); \
}
#if defined(FAKE_CODE)
static bool conn_open[10240];
#endif /* FAKE_CODE */
#endif /* SKYGW_DEBUG_H */

View File

@ -0,0 +1,47 @@
/*
* 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/bsl.
*
* Change Date: 2019-07-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.
*/
#if !defined(SKYGW_TYPES_H)
#define SKYGW_TYPES_H
#include <math.h>
#include <stdbool.h>
#include <ctype.h>
#define SECOND_USEC (1024*1024L)
#define MSEC_USEC (1024L)
#define KILOBYTE_BYTE (1024L)
#define MEGABYTE_BYTE (1024*1024L)
#define GIGABYTE_BYTE (1024*1024*1024L)
#define KB KILOBYTE_BYTE
#define MB MEGABYTE_BYTE
#define GB GIGABYTE_BYTE
#define CALCLEN(i) ((size_t)(floor(log10(abs(i))) + 1))
#define UINTLEN(i) (i<10 ? 1 : (i<100 ? 2 : (i<1000 ? 3 : CALCLEN(i))))
#if !defined(PATH_MAX)
# if defined(__USE_POSIX)
# define PATH_MAX _POSIX_PATH_MAX
# else
# define PATH_MAX 256
# endif
#endif
#define MAX_ERROR_MSG PATH_MAX
#define array_nelems(a) ((uint)(sizeof(a)/sizeof(a[0])))
#endif /* SKYGW_TYPES_H */

View File

@ -0,0 +1,208 @@
#ifndef _SKYGW_UTILS_H
#define _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/bsl.
*
* Change Date: 2019-07-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.
*/
/*
* We need a common.h file that is included by every component.
*/
#if !defined(STRERROR_BUFLEN)
#define STRERROR_BUFLEN 512
#endif
#ifndef MIN
#define MIN(a,b) (a<b ? a : b)
#endif
#ifndef MAX
#define MAX(a,b) (a>b ? a : b)
#endif
#define FSYNCLIMIT 10
#include <maxscale/skygw_types.h>
#include <maxscale/skygw_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;
};
EXTERN_C_BLOCK_BEGIN
bool utils_init(); /*< Call this first before using any other function */
void utils_end();
EXTERN_C_BLOCK_END
/** 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);
EXTERN_C_BLOCK_BEGIN
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);
EXTERN_C_BLOCK_END
/** 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 */
EXTERN_C_BLOCK_BEGIN
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 */
EXTERN_C_BLOCK_END
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);
EXTERN_C_BLOCK_BEGIN
size_t get_decimal_len(size_t s);
char* remove_mysql_comments(const char** src, const size_t* srcsize, char** dest,
size_t* destsize);
char* replace_values(const char** src, const size_t* srcsize, char** dest,
size_t* destsize);
char* replace_literal(char* haystack,
const char* needle,
const char* replacement);
char* replace_quoted(const char** src, const size_t* srcsize, char** dest, size_t* destsize);
bool is_valid_posix_path(char* path);
bool strip_escape_chars(char*);
char* trim(char *str);
char* squeeze_whitespace(char* str);
EXTERN_C_BLOCK_END
#endif /* SKYGW_UTILS_H */

66
include/maxscale/slist.h Normal file
View File

@ -0,0 +1,66 @@
#ifndef _SLIST_H
#define _SLIST_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/bsl.
*
* Change Date: 2019-07-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/skygw_utils.h>
EXTERN_C_BLOCK_BEGIN
typedef struct slist_node_st slist_node_t;
typedef struct slist_st slist_t;
typedef struct slist_cursor_st slist_cursor_t;
/** Single-linked list */
struct slist_node_st
{
skygw_chk_t slnode_chk_top;
slist_t* slnode_list;
slist_node_t* slnode_next;
void* slnode_data;
size_t slnode_cursor_refcount;
skygw_chk_t slnode_chk_tail;
};
struct slist_st
{
skygw_chk_t slist_chk_top;
slist_node_t* slist_head;
slist_node_t* slist_tail;
int slist_nelems;
slist_t* slist_cursors_list;
skygw_chk_t slist_chk_tail;
};
struct slist_cursor_st
{
skygw_chk_t slcursor_chk_top;
slist_t* slcursor_list;
slist_node_t* slcursor_pos;
skygw_chk_t slcursor_chk_tail;
};
slist_cursor_t* slist_init(void);
void slist_done(slist_cursor_t* c);
size_t slist_size(slist_cursor_t* c);
void slcursor_add_data(slist_cursor_t* c, void* data);
void* slcursor_get_data(slist_cursor_t* c);
void slcursor_remove_data(slist_cursor_t* c);
bool slcursor_move_to_begin(slist_cursor_t* c);
bool slcursor_step_ahead(slist_cursor_t* c);
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,79 @@
#ifndef _SPINLOCK_H
#define _SPINLOCK_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/bsl.
*
* Change Date: 2019-07-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 spinlock.h
*
* Spinlock implementation for MaxScale.
*
* Spinlocks are cheap locks that can be used to protect short code blocks, they are
* generally wasteful as any blocked threads will spin, consuming CPU cycles, waiting
* for the lock to be released. However they are useful in that they do not involve
* system calls and are light weight when the expected wait time for a lock is low.
*/
#include <maxscale/skygw_debug.h>
EXTERN_C_BLOCK_BEGIN
#define SPINLOCK_PROFILE 0
/**
* The spinlock structure.
*
* In normal builds the structure merely contains a lock value which
* is 0 if the spinlock is not taken and greater than zero if it is held.
*
* In builds with the SPINLOCK_PROFILE option set this structure also holds
* a number of profile related fields that count the number of spins, number
* of waiting threads and the number of times the lock has been acquired.
*/
typedef struct spinlock
{
int lock; /*< Is the lock held? */
#if SPINLOCK_PROFILE
int spins; /*< Number of spins on this lock */
int maxspins; /*< Max no of spins to acquire lock */
int acquired; /*< No. of times lock was acquired */
int waiting; /*< No. of threads acquiring this lock */
int max_waiting; /*< Max no of threads waiting for lock */
int contended; /*< No. of times acquire was contended */
THREAD owner; /*< Last owner of this lock */
#endif
} SPINLOCK;
#ifndef TRUE
#define TRUE true
#endif
#ifndef FALSE
#define FALSE false
#endif
#if SPINLOCK_PROFILE
#define SPINLOCK_INIT { 0, 0, 0, 0, 0, 0, 0, 0 }
#else
#define SPINLOCK_INIT { 0 }
#endif
#define SPINLOCK_IS_LOCKED(l) ((l)->lock != 0 ? true : false)
extern void spinlock_init(SPINLOCK *lock);
extern void spinlock_acquire(const SPINLOCK *lock);
extern int spinlock_acquire_nowait(const SPINLOCK *lock);
extern void spinlock_release(const SPINLOCK *lock);
extern void spinlock_stats(const SPINLOCK *lock, void (*reporter)(void *, char *, int), void *hdl);
EXTERN_C_BLOCK_END
#endif

View File

@ -0,0 +1,71 @@
#ifndef _STATISTICS_HG
#define _STATISTICS_HG
/*
* 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/bsl.
*
* Change Date: 2019-07-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 statistics.h - Lock-free statistics gathering
*
* @verbatim
* Revision History
*
* Date Who Description
* 21/01/16 Markus Makela Initial implementation
* 15/06/16 Martin Brampton Frequently used functions inlined
* @endverbatim
*/
#include <stdint.h>
typedef void* ts_stats_t;
/** stats_init should be called only once */
void ts_stats_init();
/** No-op for now */
void ts_stats_end();
ts_stats_t ts_stats_alloc();
void ts_stats_free(ts_stats_t stats);
int64_t ts_stats_sum(ts_stats_t stats);
/**
* @brief Increment thread statistics by one
*
* @param stats Statistics to add to
* @param thread_id ID of thread
*/
static void inline
ts_stats_increment(ts_stats_t stats, int thread_id)
{
((int64_t*)stats)[thread_id]++;
}
/**
* @brief Assign a value to a statistics element
*
* This sets the value for the specified thread.
*
* @param stats Statistics to set
* @param value Value to set to
* @param thread_id ID of thread
*
* @note Appears to be unused
*/
static void inline
ts_stats_set(ts_stats_t stats, int value, int thread_id)
{
((int64_t*)stats)[thread_id] = value;
}
#endif

View File

@ -0,0 +1,36 @@
#ifndef TEST_UTILS_H
#define TEST_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/bsl.
*
* Change Date: 2019-07-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/poll.h>
#include <maxscale/dcb.h>
#include <maxscale/housekeeper.h>
#include <maxscale/maxscale_test.h>
#include <maxscale/log_manager.h>
#include <maxscale/statistics.h>
void init_test_env(char *path)
{
int argc = 3;
const char* logdir = path ? path : TEST_LOG_DIR;
ts_stats_init();
mxs_log_init(NULL, logdir, MXS_LOG_TARGET_DEFAULT);
poll_init();
hkinit();
}
#endif

36
include/maxscale/thread.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef _THREAD_H
#define _THREAD_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/bsl.
*
* Change Date: 2019-07-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 thread.h The gateway threading interface
*
* An encapsulation of the threading used by the gateway. This is designed to
* isolate the majority of the gateway code from the pthread library, enabling
* the gateway to be ported to a different threading package with the minimum
* of changes.
*/
/**
* Thread type and thread identifier function macros
*/
#include <pthread.h>
#define THREAD pthread_t
#define thread_self() pthread_self()
extern THREAD *thread_start(THREAD *thd, void (*entry)(void *), void *arg);
extern void thread_wait(THREAD thd);
extern void thread_millisleep(int ms);
#endif

73
include/maxscale/users.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef _USERS_H
#define _USERS_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/bsl.
*
* Change Date: 2019-07-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/hashtable.h>
#include <maxscale/dcb.h>
#include <maxscale/listener.h>
#include <openssl/sha.h>
/**
* @file users.h The functions to manipulate the table of users maintained
* for each service
*
* @verbatim
* Revision History
*
* Date Who Description
* 23/06/13 Mark Riddoch Initial implementation
* 26/02/14 Massimiliano Pinto Added checksum to users' table with SHA1
* 27/02/14 Massimiliano Pinto Added USERS_HASHTABLE_DEFAULT_SIZE
* 28/02/14 Massimiliano Pinto Added usersCustomUserFormat, optional username format routine
*
* @endverbatim
*/
#define USERS_HASHTABLE_DEFAULT_SIZE 52
/**
* The users table statistics structure
*/
typedef struct
{
int n_entries; /**< The number of entries */
int n_adds; /**< The number of inserts */
int n_deletes; /**< The number of deletes */
int n_fetches; /**< The number of fetchs */
} USERS_STATS;
/**
* The user table, this contains the username and authentication data required
* for the authentication implementation within the gateway.
*/
typedef struct users
{
HASHTABLE *data; /**< The hashtable containing the actual data */
char *(*usersCustomUserFormat)(void *); /**< Optional username format routine */
USERS_STATS stats; /**< The statistics for the users table */
unsigned char cksum[SHA_DIGEST_LENGTH]; /**< The users' table ckecksum */
} USERS;
extern USERS *users_alloc(); /**< Allocate a users table */
extern void users_free(USERS *); /**< Free a users table */
extern int users_add(USERS *, char *, char *); /**< Add a user to the users table */
extern int users_delete(USERS *, char *); /**< Delete a user from the users table */
extern char *users_fetch(USERS *, char *); /**< Fetch the authentication data for a user */
extern int users_update(USERS *, char *, char *); /**< Change the password data for a user in
the users table */
extern int users_default_loadusers(SERV_LISTENER *port); /**< A generic implementation of the authenticator
* loadusers entry point */
extern void usersPrint(USERS *); /**< Print data about the users loaded */
extern void dcb_usersPrint(DCB *, USERS *); /**< Print data about the users loaded */
#endif

40
include/maxscale/utils.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef _UTILS_H
#define _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/bsl.
*
* Change Date: 2019-07-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 utils.h Utility functions headers
*
* @verbatim
* Revision History
*
* Date Who Description
* 22/03/16 Martin Brampton Initial implementation
*
* @endverbatim
*/
int setnonblocking(int fd);
char *gw_strend(register const char *s);
static char gw_randomchar();
int gw_generate_random_str(char *output, int len);
int gw_hex2bin(uint8_t *out, const char *in, unsigned int len);
char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len);
void gw_str_xor(uint8_t *output, const uint8_t *input1, const uint8_t *input2, unsigned int len);
void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out);
void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out);
int gw_getsockerrno(int fd);
char *create_hex_sha1_sha1_passwd(char *passwd);
#endif

View File

@ -0,0 +1,2 @@
#define MAXSCALE_VERSION "@MAXSCALE_VERSION@"
#define MAXSCALE_COMMIT "@MAXSCALE_COMMIT@"