Support for mysql session variable commands, for example, SET AUTOCOMMIT=0
Session commands are identified by query clasisfier, and added to the session command property list in router client session object. Session commands are then executed in existing backend servers but only one of them will reply to client.
This commit is contained in:
@ -1335,3 +1335,4 @@ int gw_write(
|
|||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,6 +53,8 @@ typedef struct spinlock {
|
|||||||
#define SPINLOCK_INIT { 0 }
|
#define SPINLOCK_INIT { 0 }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SPINLOCK_IS_LOCKED(l) ((l)->lock != 0 ? true : false)
|
||||||
|
|
||||||
extern void spinlock_init(SPINLOCK *lock);
|
extern void spinlock_init(SPINLOCK *lock);
|
||||||
extern void spinlock_acquire(SPINLOCK *lock);
|
extern void spinlock_acquire(SPINLOCK *lock);
|
||||||
extern int spinlock_acquire_nowait(SPINLOCK *lock);
|
extern int spinlock_acquire_nowait(SPINLOCK *lock);
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* @verbatim
|
* @verbatim
|
||||||
* Revision History
|
* Revision History
|
||||||
*
|
*
|
||||||
* bazaar..
|
* See GitHub https://github.com/skysql/MaxScale
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -41,25 +41,88 @@ typedef struct backend {
|
|||||||
int backend_conn_count; /*< Number of connections to the server */
|
int backend_conn_count; /*< Number of connections to the server */
|
||||||
} BACKEND;
|
} BACKEND;
|
||||||
|
|
||||||
|
typedef struct rses_property_st rses_property_t;
|
||||||
|
typedef struct router_client_session ROUTER_CLIENT_SES;
|
||||||
|
|
||||||
|
typedef enum rses_property_type_t {
|
||||||
|
RSES_PROP_TYPE_UNDEFINED=0,
|
||||||
|
RSES_PROP_TYPE_FIRST,
|
||||||
|
RSES_PROP_TYPE_SESCMD=RSES_PROP_TYPE_FIRST,
|
||||||
|
RSES_PROP_TYPE_LAST=RSES_PROP_TYPE_SESCMD,
|
||||||
|
RSES_PROP_TYPE_COUNT=RSES_PROP_TYPE_LAST+1
|
||||||
|
} rses_property_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Session variable command
|
||||||
|
*/
|
||||||
|
typedef struct mysql_sescmd_st {
|
||||||
|
#if defined(SS_DEBUG)
|
||||||
|
skygw_chk_t my_sescmd_chk_top;
|
||||||
|
#endif
|
||||||
|
ROUTER_CLIENT_SES* my_sescmd_rsession; /*< parent router session */
|
||||||
|
rses_property_t* my_sescmd_prop; /*< parent property */
|
||||||
|
GWBUF* my_sescmd_buf; /*< client query reference */
|
||||||
|
bool my_sescmd_is_replied; /*< is cmd replied to client */
|
||||||
|
#if defined(SS_DEBUG)
|
||||||
|
skygw_chk_t my_sescmd_chk_tail;
|
||||||
|
#endif
|
||||||
|
} mysql_sescmd_t;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Property structure
|
||||||
|
*/
|
||||||
|
struct rses_property_st {
|
||||||
|
#if defined(SS_DEBUG)
|
||||||
|
skygw_chk_t rses_prop_chk_top;
|
||||||
|
#endif
|
||||||
|
SPINLOCK rses_prop_lock; /*< protect property content */
|
||||||
|
int rses_prop_refcount;
|
||||||
|
rses_property_type_t rses_prop_type;
|
||||||
|
union rses_prop_data {
|
||||||
|
mysql_sescmd_t sescmd;
|
||||||
|
void* placeholder; /*< to be removed due new type */
|
||||||
|
} rses_prop_data;
|
||||||
|
rses_property_t* rses_prop_next; /*< next property of same type */
|
||||||
|
#if defined(SS_DEBUG)
|
||||||
|
skygw_chk_t rses_prop_chk_tail;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct sescmd_cursor_st {
|
||||||
|
rses_property_t** scmd_cur_ptr_property; /*< address of pointer to owner property */
|
||||||
|
mysql_sescmd_t* scmd_cur_cmd; /*< pointer to current session command */
|
||||||
|
bool scmd_cur_active; /*< true if command is being executed */
|
||||||
|
} sescmd_cursor_t;
|
||||||
|
|
||||||
|
typedef enum backend_type_t {
|
||||||
|
BE_UNDEFINED=-1,
|
||||||
|
BE_MASTER,
|
||||||
|
BE_SLAVE,
|
||||||
|
BE_COUNT
|
||||||
|
} backend_type_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The client session structure used within this router.
|
* The client session structure used within this router.
|
||||||
*/
|
*/
|
||||||
typedef struct router_client_session {
|
struct router_client_session {
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t rses_chk_top;
|
skygw_chk_t rses_chk_top;
|
||||||
#endif
|
#endif
|
||||||
SPINLOCK rses_lock; /*< protects rses_deleted */
|
SPINLOCK rses_lock; /*< protects rses_deleted */
|
||||||
int rses_versno; /*< even = no active update, else odd */
|
int rses_versno; /*< even = no active update, else odd */
|
||||||
bool rses_closed; /*< true when closeSession is called */
|
bool rses_closed; /*< true when closeSession is called */
|
||||||
BACKEND* be_slave; /*< Slave backend used by client session */
|
/** Properties listed by their type */
|
||||||
BACKEND* be_master; /*< Master backend used by client session */
|
rses_property_t* rses_properties[RSES_PROP_TYPE_COUNT];
|
||||||
DCB* slave_dcb; /*< Slave connection */
|
BACKEND* rses_backend[BE_COUNT];/*< Backends used by client session */
|
||||||
DCB* master_dcb; /*< Master connection */
|
DCB* rses_dcb[BE_COUNT];
|
||||||
|
/*< cursor is pointer and status variable to current session command */
|
||||||
|
sescmd_cursor_t rses_cursor[BE_COUNT];
|
||||||
struct router_client_session* next;
|
struct router_client_session* next;
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t rses_chk_tail;
|
skygw_chk_t rses_chk_tail;
|
||||||
#endif
|
#endif
|
||||||
} ROUTER_CLIENT_SES;
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The statistics for this router instance
|
* The statistics for this router instance
|
||||||
@ -88,5 +151,4 @@ typedef struct router_instance {
|
|||||||
struct router_instance* next; /*< Next router on the list */
|
struct router_instance* next; /*< Next router on the list */
|
||||||
} ROUTER_INSTANCE;
|
} ROUTER_INSTANCE;
|
||||||
|
|
||||||
|
#endif /*< _RWSPLITROUTER_H */
|
||||||
#endif
|
|
||||||
|
@ -119,10 +119,10 @@ static ROUTER_OBJECT MyObject = {
|
|||||||
errorReply
|
errorReply
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool rses_begin_router_action(
|
static bool rses_begin_locked_router_action(
|
||||||
ROUTER_CLIENT_SES* rses);
|
ROUTER_CLIENT_SES* rses);
|
||||||
|
|
||||||
static void rses_exit_router_action(
|
static void rses_end_locked_router_action(
|
||||||
ROUTER_CLIENT_SES* rses);
|
ROUTER_CLIENT_SES* rses);
|
||||||
|
|
||||||
static SPINLOCK instlock;
|
static SPINLOCK instlock;
|
||||||
@ -498,13 +498,13 @@ DCB* backend_dcb;
|
|||||||
/**
|
/**
|
||||||
* Lock router client session for secure read and update.
|
* Lock router client session for secure read and update.
|
||||||
*/
|
*/
|
||||||
if (rses_begin_router_action(router_cli_ses))
|
if (rses_begin_locked_router_action(router_cli_ses))
|
||||||
{
|
{
|
||||||
backend_dcb = router_cli_ses->backend_dcb;
|
backend_dcb = router_cli_ses->backend_dcb;
|
||||||
router_cli_ses->backend_dcb = NULL;
|
router_cli_ses->backend_dcb = NULL;
|
||||||
router_cli_ses->rses_closed = true;
|
router_cli_ses->rses_closed = true;
|
||||||
/** Unlock */
|
/** Unlock */
|
||||||
rses_exit_router_action(router_cli_ses);
|
rses_end_locked_router_action(router_cli_ses);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the backend server connection
|
* Close the backend server connection
|
||||||
@ -550,14 +550,14 @@ routeQuery(ROUTER *instance, void *router_session, GWBUF *queue)
|
|||||||
/**
|
/**
|
||||||
* Lock router client session for secure read of DCBs
|
* Lock router client session for secure read of DCBs
|
||||||
*/
|
*/
|
||||||
rses_is_closed = !(rses_begin_router_action(router_cli_ses));
|
rses_is_closed = !(rses_begin_locked_router_action(router_cli_ses));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rses_is_closed)
|
if (!rses_is_closed)
|
||||||
{
|
{
|
||||||
backend_dcb = router_cli_ses->backend_dcb;
|
backend_dcb = router_cli_ses->backend_dcb;
|
||||||
/** unlock */
|
/** unlock */
|
||||||
rses_exit_router_action(router_cli_ses);
|
rses_end_locked_router_action(router_cli_ses);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rses_is_closed || backend_dcb == NULL)
|
if (rses_is_closed || backend_dcb == NULL)
|
||||||
@ -696,7 +696,7 @@ errorReply(
|
|||||||
* @details (write detailed description here)
|
* @details (write detailed description here)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static bool rses_begin_router_action(
|
static bool rses_begin_locked_router_action(
|
||||||
ROUTER_CLIENT_SES* rses)
|
ROUTER_CLIENT_SES* rses)
|
||||||
{
|
{
|
||||||
bool succp = false;
|
bool succp = false;
|
||||||
@ -731,7 +731,7 @@ return_succp:
|
|||||||
* @details (write detailed description here)
|
* @details (write detailed description here)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void rses_exit_router_action(
|
static void rses_end_locked_router_action(
|
||||||
ROUTER_CLIENT_SES* rses)
|
ROUTER_CLIENT_SES* rses)
|
||||||
{
|
{
|
||||||
CHK_CLIENT_RSES(rses);
|
CHK_CLIENT_RSES(rses);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -117,7 +117,9 @@ typedef enum skygw_chk_t {
|
|||||||
CHK_NUM_DCB,
|
CHK_NUM_DCB,
|
||||||
CHK_NUM_PROTOCOL,
|
CHK_NUM_PROTOCOL,
|
||||||
CHK_NUM_SESSION,
|
CHK_NUM_SESSION,
|
||||||
CHK_NUM_ROUTER_SES
|
CHK_NUM_ROUTER_SES,
|
||||||
|
CHK_NUM_MY_SESCMD,
|
||||||
|
CHK_NUM_ROUTER_PROPERTY
|
||||||
} skygw_chk_t;
|
} skygw_chk_t;
|
||||||
|
|
||||||
# define STRBOOL(b) ((b) ? "true" : "false")
|
# define STRBOOL(b) ((b) ? "true" : "false")
|
||||||
@ -428,6 +430,18 @@ typedef enum skygw_chk_t {
|
|||||||
"Router client session has invalid check fields"); \
|
"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"); \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
bool conn_open[10240];
|
bool conn_open[10240];
|
||||||
|
Reference in New Issue
Block a user