Merge branch '2.1' into develop
This commit is contained in:
@ -12,7 +12,7 @@
|
|||||||
* MySQL Monitor now has a failover mode.
|
* MySQL Monitor now has a failover mode.
|
||||||
* Named Server Filter now supports wildcards for source option.
|
* Named Server Filter now supports wildcards for source option.
|
||||||
* Binlog Server can now be configured to encrypt binlog files.
|
* Binlog Server can now be configured to encrypt binlog files.
|
||||||
* New filters, _cache, _ccrfilter_, _masking_, and _maxrows_ are introduced.
|
* New filters, _cache_, _ccrfilter_, _insertstream_, _masking_, and _maxrows_ are introduced.
|
||||||
|
|
||||||
For more details, please refer to:
|
For more details, please refer to:
|
||||||
* [MariaDB MaxScale 2.1.0 Release Notes](Release-Notes/MaxScale-2.1.0-Release-Notes.md)
|
* [MariaDB MaxScale 2.1.0 Release Notes](Release-Notes/MaxScale-2.1.0-Release-Notes.md)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Consistent Critical Read Filter
|
# Consistent Critical Read Filter
|
||||||
|
|
||||||
|
This filter was introduced in MariaDB MaxScale 2.1.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The Consistent Critical Read (CCR) filter allows consistent critical reads to be
|
The Consistent Critical Read (CCR) filter allows consistent critical reads to be
|
||||||
@ -68,3 +70,24 @@ An optional parameter that can be used to control which statements don't trigger
|
|||||||
the statement re-routing. This does the opposite of the _match_ parameter. The
|
the statement re-routing. This does the opposite of the _match_ parameter. The
|
||||||
parameter value is a regular expression that is used to match against the SQL
|
parameter value is a regular expression that is used to match against the SQL
|
||||||
text. Only non-SELECT statements are inspected.
|
text. Only non-SELECT statements are inspected.
|
||||||
|
|
||||||
|
## Example Configuration
|
||||||
|
|
||||||
|
Here is a minimal filter configuration for the CCRFilter which should solve most
|
||||||
|
problems with critical reads after writes.
|
||||||
|
|
||||||
|
```
|
||||||
|
[CCRFilter]
|
||||||
|
type=filter
|
||||||
|
module=ccrfilter
|
||||||
|
time=5
|
||||||
|
```
|
||||||
|
|
||||||
|
This configuration will force all read queries after a write to the master for 5
|
||||||
|
seconds, preventing read scaling until the modifications have been replicated to
|
||||||
|
the slaves.
|
||||||
|
|
||||||
|
For best performance, the value of _time_ should be slightly greater than the
|
||||||
|
actual replication lag between the master and its slaves. If the number of
|
||||||
|
critical read statements is known, the _count_ parameter could be used to
|
||||||
|
control the number reads that are sent to the master.
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Cache
|
# Cache
|
||||||
|
|
||||||
|
This filter was introduced in MariaDB MaxScale 2.1.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
The cache filter is a simple cache that is capable of caching the result of
|
The cache filter is a simple cache that is capable of caching the result of
|
||||||
SELECTs, so that subsequent identical SELECTs are served directly by MaxScale,
|
SELECTs, so that subsequent identical SELECTs are served directly by MaxScale,
|
||||||
@ -8,6 +10,11 @@ without the queries being routed to any server.
|
|||||||
_Note that the cache is still experimental and that non-backward compatible
|
_Note that the cache is still experimental and that non-backward compatible
|
||||||
changes may be made._
|
changes may be made._
|
||||||
|
|
||||||
|
Note that installing the cache causes all statements to be parsed. The
|
||||||
|
implication of that is that unless statements _already_ need to be parsed,
|
||||||
|
e.g. due to the presence of another filter or the chosen router, then adding
|
||||||
|
the cache will not necessarily improve the performance, but may decrease it.
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
All of these limitations may be addressed in forthcoming releases.
|
All of these limitations may be addressed in forthcoming releases.
|
||||||
@ -639,3 +646,44 @@ The value is a boolean and the default is `false`.
|
|||||||
```
|
```
|
||||||
storage_options=collect_statistics=true
|
storage_options=collect_statistics=true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
In the following we define a cache _MyCache_ that uses the cache storage module
|
||||||
|
`storage_inmemory` and whose _soft ttl_ is `30` seconds and whose _hard ttl_ is
|
||||||
|
`45` seconds. The cached data is shared between all threads and the maximum size
|
||||||
|
of the cached data is `50` mebibytes. The rules for the cache are in the file
|
||||||
|
`cache_rules.json`.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
```
|
||||||
|
[MyCache]
|
||||||
|
type=filter
|
||||||
|
module=cache
|
||||||
|
storage=storage_inmemory
|
||||||
|
soft_ttl=30
|
||||||
|
hard_ttl=45
|
||||||
|
cached_data=shared
|
||||||
|
max_size=50Mi
|
||||||
|
rules=cache_rules.json
|
||||||
|
|
||||||
|
[MyService]
|
||||||
|
type=service
|
||||||
|
...
|
||||||
|
filters=MyCache
|
||||||
|
```
|
||||||
|
|
||||||
|
### `cache_rules.json`
|
||||||
|
The rules specify that the data of the table `sbtest` should be cached.
|
||||||
|
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"store": [
|
||||||
|
{
|
||||||
|
"attribute": "table",
|
||||||
|
"op": "=",
|
||||||
|
"value": "sbtest"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
# Insert Stream Filter
|
# Insert Stream Filter
|
||||||
|
|
||||||
|
This filter was introduced in MariaDB MaxScale 2.1.
|
||||||
|
|
||||||
|
## Overview
|
||||||
The _insertstream_ filter converts bulk inserts into CSV data streams that are
|
The _insertstream_ filter converts bulk inserts into CSV data streams that are
|
||||||
consumed by the backend server via the LOAD DATA LOCAL INFILE mechanism. This
|
consumed by the backend server via the LOAD DATA LOCAL INFILE mechanism. This
|
||||||
leverages the speed advantage of LOAD DATA LOCAL INFILE over regular inserts
|
leverages the speed advantage of LOAD DATA LOCAL INFILE over regular inserts
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Masking
|
# Masking
|
||||||
|
|
||||||
|
This filter was introduced in MariaDB MaxScale 2.1.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
With the _masking_ filter it is possible to obfuscate the returned
|
With the _masking_ filter it is possible to obfuscate the returned
|
||||||
value of a particular column.
|
value of a particular column.
|
||||||
@ -302,3 +304,47 @@ MaxScale> call command masking reload MyMaskingFilter
|
|||||||
```
|
```
|
||||||
`MyMaskingFilter` refers to a particular filter section in the
|
`MyMaskingFilter` refers to a particular filter section in the
|
||||||
MariaDB MaxScale configuration file.
|
MariaDB MaxScale configuration file.
|
||||||
|
|
||||||
|
# Example
|
||||||
|
|
||||||
|
In the following we configure a masking filter _MyMasking_ that should always log a
|
||||||
|
warning if a masking rule matches a column that is of a type that cannot be masked,
|
||||||
|
and that should abort the client connection if a resultset package is larger than
|
||||||
|
16MB. The rules for the masking filter are in the file `masking_rules.json`.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
```
|
||||||
|
[MyMasking]
|
||||||
|
type=filter
|
||||||
|
module=masking
|
||||||
|
warn_type_mismatch=always
|
||||||
|
large_payload=abort
|
||||||
|
rules=masking_rules.json
|
||||||
|
|
||||||
|
[MyService]
|
||||||
|
type=service
|
||||||
|
...
|
||||||
|
filters=MyMasking
|
||||||
|
```
|
||||||
|
|
||||||
|
### `masking_rules.json`
|
||||||
|
|
||||||
|
The rules specify that the data of a column whose name is `ssn`, should
|
||||||
|
be replaced with the string _012345-ABCD_. If the length of the data is
|
||||||
|
not exactly the same as the length of the replacement value, then the
|
||||||
|
data should be replaced with as many _X_ characters as needed.
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"replace": {
|
||||||
|
"column": "ssn"
|
||||||
|
},
|
||||||
|
"with": {
|
||||||
|
"value": "012345-ABCD",
|
||||||
|
"fill": "X"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Maxrows
|
# Maxrows
|
||||||
|
|
||||||
|
This filter was introduced in MariaDB MaxScale 2.1.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
The maxrows filter is capable of restricting the amount of rows that a SELECT,
|
The maxrows filter is capable of restricting the amount of rows that a SELECT,
|
||||||
a prepared statement or stored procedure could return to the client application.
|
a prepared statement or stored procedure could return to the client application.
|
||||||
@ -68,3 +70,16 @@ Default is `0`. To log everything, give `debug` a value of `3`.
|
|||||||
```
|
```
|
||||||
debug=2
|
debug=2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Example Configuration
|
||||||
|
|
||||||
|
Here is an example of filter configuration where the max number of returned
|
||||||
|
rows is 10000 and max allowed resultset size is 256KB
|
||||||
|
|
||||||
|
```
|
||||||
|
[MaxRows]
|
||||||
|
type=filter
|
||||||
|
module=maxrows
|
||||||
|
max_resultset_rows=10000
|
||||||
|
max_resultset_size=256000
|
||||||
|
```
|
||||||
|
@ -10,6 +10,38 @@ report at [Jira](https://jira.mariadb.org).
|
|||||||
|
|
||||||
## Changed Features
|
## Changed Features
|
||||||
|
|
||||||
|
### `router_options` to Parameters
|
||||||
|
|
||||||
|
The `router_options` values can also be given as parameters to the service for
|
||||||
|
the _readwritesplit_, _schemarouter_ and _binlogrouter_ modules.
|
||||||
|
|
||||||
|
What this means is that in MaxScale 2.1 the following _readwritesplit_
|
||||||
|
configration.
|
||||||
|
|
||||||
|
```
|
||||||
|
[RW Split Router]
|
||||||
|
type=service
|
||||||
|
router=readwritesplit
|
||||||
|
servers=server1
|
||||||
|
user=maxuser
|
||||||
|
passwd=maxpwd
|
||||||
|
router_options=slave_selection_criteria=LEAST_ROUTER_CONNECTIONS,max_sescmd_history=10,disable_sescmd_history=false
|
||||||
|
```
|
||||||
|
|
||||||
|
Can also be written in the following form.
|
||||||
|
|
||||||
|
```
|
||||||
|
[RW Split Router]
|
||||||
|
type=service
|
||||||
|
router=readwritesplit
|
||||||
|
servers=server1
|
||||||
|
user=maxuser
|
||||||
|
passwd=maxpwd
|
||||||
|
slave_selection_criteria=LEAST_ROUTER_CONNECTIONS
|
||||||
|
max_sescmd_history=10
|
||||||
|
disable_sescmd_history=false
|
||||||
|
```
|
||||||
|
|
||||||
### Configuration Files
|
### Configuration Files
|
||||||
|
|
||||||
From 2.1.0 onwards MariaDB MaxScale supports hierarchical configuration
|
From 2.1.0 onwards MariaDB MaxScale supports hierarchical configuration
|
||||||
@ -271,6 +303,17 @@ to large sets of data with a single query.
|
|||||||
For more information, refer to the [Maxrows](../Filters/Maxrows.md)
|
For more information, refer to the [Maxrows](../Filters/Maxrows.md)
|
||||||
documentation.
|
documentation.
|
||||||
|
|
||||||
|
### Insert stream filter
|
||||||
|
|
||||||
|
The _insertstream_ filter converts bulk inserts into CSV data streams that are
|
||||||
|
consumed by the backend server via the LOAD DATA LOCAL INFILE mechanism. This
|
||||||
|
leverages the speed advantage of LOAD DATA LOCAL INFILE over regular inserts
|
||||||
|
while also reducing the overall network traffic by condensing the inserted
|
||||||
|
values into CSV.
|
||||||
|
|
||||||
|
For more information, refer to the [Insert Stream Filter](../Filters/Insert-Stream-Filter.md)
|
||||||
|
documentation.
|
||||||
|
|
||||||
### Galeramon Monitor new option
|
### Galeramon Monitor new option
|
||||||
The `set_donor_nodes` option allows the setting of _global variable_ _wsrep_sst_donor_ with a list the preferred donor nodes (among slave ones).
|
The `set_donor_nodes` option allows the setting of _global variable_ _wsrep_sst_donor_ with a list the preferred donor nodes (among slave ones).
|
||||||
|
|
||||||
|
56
Documentation/Upgrading/Upgrading-To-MaxScale-2.1.md
Normal file
56
Documentation/Upgrading/Upgrading-To-MaxScale-2.1.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
# Upgrading MariaDB MaxScale from 2.0 to 2.1
|
||||||
|
|
||||||
|
This document describes particular issues to take into account when upgrading
|
||||||
|
MariaDB MaxScale from version 2.0 to 2.1.
|
||||||
|
|
||||||
|
For more information about MariaDB MaxScale 2.1, please refer to the
|
||||||
|
[ChangeLog](../Changelog.md).
|
||||||
|
|
||||||
|
For a complete list of changes in MaxScale 2.1.0, refer to the
|
||||||
|
[MaxScale 2.1.0 Release Notes](../Release-Notes/MaxScale-2.1.0-Release-Notes.md).
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Before starting the upgrade, we **strongly** recommend you back up your current
|
||||||
|
configuration file.
|
||||||
|
|
||||||
|
## MaxScale Log Files
|
||||||
|
|
||||||
|
The name of the log file was changed from _maxscaleN.log_ to _maxscale.log_. The
|
||||||
|
default location for the log file is _/var/log/maxscale/maxscale.log_.
|
||||||
|
|
||||||
|
Rotating the log files will cause MaxScale to reopen the file instead of
|
||||||
|
renaming them. This makes the MaxScale logging facility _logrotate_ compatible.
|
||||||
|
|
||||||
|
## ReadWriteSplit
|
||||||
|
|
||||||
|
The `disable_sescmd_history` option is now enabled by default. This means that
|
||||||
|
slaves will not be recovered mid-session even if a replacement slave is
|
||||||
|
available. To enable the legacy behavior, add the `disable_sescmd_history=true`
|
||||||
|
parameter to the service definition.
|
||||||
|
|
||||||
|
## Persistent Connections
|
||||||
|
|
||||||
|
The MySQL session state is reset in MaxScale 2.1 for persistent
|
||||||
|
connections. This means that any modifications to the session state (default
|
||||||
|
database, user variable etc.) will not survive if the connection is put into the
|
||||||
|
connection pool. For most users, this is the expected behavior.
|
||||||
|
|
||||||
|
## User Data Cache
|
||||||
|
|
||||||
|
The location of the MySQL user data cache was moved from
|
||||||
|
`/var/cache/maxscale/<Service>` to `/var/cache/maxscale/<Service>/<Listener>`.
|
||||||
|
|
||||||
|
## Galeramon Monitoring Algorithm
|
||||||
|
|
||||||
|
Galeramon will assign the master status *only* to the node which has a
|
||||||
|
_wsrep_local_index_ value of 0. This will guarantee consistent writes with
|
||||||
|
multiple MaxScales but it also causes slower changes of the master node.
|
||||||
|
|
||||||
|
To enable the legacy behavior, add `root_node_as_master=false` to the Galera
|
||||||
|
monitor configuration.
|
||||||
|
|
||||||
|
## MaxAdmin Editing Mode
|
||||||
|
|
||||||
|
The default editing mode was changed from _vim_ to _emacs_ mode. To start
|
||||||
|
maxadmin in the legacy mode, use the `-i` option.
|
@ -190,7 +190,6 @@ typedef struct dcb
|
|||||||
bool draining_flag; /**< Set while write queue is drained */
|
bool draining_flag; /**< Set while write queue is drained */
|
||||||
bool drain_called_while_busy; /**< Set as described */
|
bool drain_called_while_busy; /**< Set as described */
|
||||||
dcb_role_t dcb_role;
|
dcb_role_t dcb_role;
|
||||||
SPINLOCK dcb_initlock;
|
|
||||||
DCBEVENTQ evq; /**< The event queue for this DCB */
|
DCBEVENTQ evq; /**< The event queue for this DCB */
|
||||||
int fd; /**< The descriptor */
|
int fd; /**< The descriptor */
|
||||||
dcb_state_t state; /**< Current descriptor state */
|
dcb_state_t state; /**< Current descriptor state */
|
||||||
@ -207,32 +206,20 @@ typedef struct dcb
|
|||||||
struct servlistener *listener; /**< For a client DCB, the listener data */
|
struct servlistener *listener; /**< For a client DCB, the listener data */
|
||||||
MXS_PROTOCOL func; /**< The protocol functions for this descriptor */
|
MXS_PROTOCOL func; /**< The protocol functions for this descriptor */
|
||||||
MXS_AUTHENTICATOR authfunc; /**< The authenticator functions for this descriptor */
|
MXS_AUTHENTICATOR authfunc; /**< The authenticator functions for this descriptor */
|
||||||
|
|
||||||
int writeqlen; /**< Current number of byes in the write queue */
|
int writeqlen; /**< Current number of byes in the write queue */
|
||||||
SPINLOCK writeqlock; /**< Write Queue spinlock */
|
|
||||||
GWBUF *writeq; /**< Write Data Queue */
|
GWBUF *writeq; /**< Write Data Queue */
|
||||||
SPINLOCK delayqlock; /**< Delay Backend Write Queue spinlock */
|
|
||||||
GWBUF *delayq; /**< Delay Backend Write Data Queue */
|
GWBUF *delayq; /**< Delay Backend Write Data Queue */
|
||||||
GWBUF *dcb_readqueue; /**< read queue for storing incomplete reads */
|
GWBUF *dcb_readqueue; /**< read queue for storing incomplete reads */
|
||||||
GWBUF *dcb_fakequeue; /**< Fake event queue for generated events */
|
GWBUF *dcb_fakequeue; /**< Fake event queue for generated events */
|
||||||
|
|
||||||
DCBSTATS stats; /**< DCB related statistics */
|
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 */
|
struct dcb *nextpersistent; /**< Next DCB in the persistent pool for SERVER */
|
||||||
time_t persistentstart; /**< Time when DCB placed in persistent pool */
|
time_t persistentstart; /**< Time when DCB placed in persistent pool */
|
||||||
struct service *service; /**< The related service */
|
struct service *service; /**< The related service */
|
||||||
void *data; /**< Specific client data, shared between DCBs of this session */
|
void *data; /**< Specific client data, shared between DCBs of this session */
|
||||||
void *authenticator_data; /**< The authenticator data for this DCB */
|
void *authenticator_data; /**< The authenticator data for this DCB */
|
||||||
DCBMM memdata; /**< The data related to DCB memory management */
|
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 */
|
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 */
|
long last_read; /*< Last time the DCB received data */
|
||||||
int high_water; /**< High water mark */
|
int high_water; /**< High water mark */
|
||||||
int low_water; /**< Low water mark */
|
int low_water; /**< Low water mark */
|
||||||
@ -242,7 +229,6 @@ typedef struct dcb
|
|||||||
bool ssl_read_want_write; /*< Flag */
|
bool ssl_read_want_write; /*< Flag */
|
||||||
bool ssl_write_want_read; /*< Flag */
|
bool ssl_write_want_read; /*< Flag */
|
||||||
bool ssl_write_want_write; /*< Flag */
|
bool ssl_write_want_write; /*< Flag */
|
||||||
int dcb_port; /**< port of target server */
|
|
||||||
bool was_persistent; /**< Whether this DCB was in the persistent pool */
|
bool was_persistent; /**< Whether this DCB was in the persistent pool */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -253,13 +239,11 @@ typedef struct dcb
|
|||||||
skygw_chk_t dcb_chk_tail;
|
skygw_chk_t dcb_chk_tail;
|
||||||
} DCB;
|
} DCB;
|
||||||
|
|
||||||
#define DCB_INIT {.dcb_chk_top = CHK_NUM_DCB, .dcb_initlock = SPINLOCK_INIT, \
|
#define DCB_INIT {.dcb_chk_top = CHK_NUM_DCB, \
|
||||||
.evq = DCBEVENTQ_INIT, .ipv4 = {0}, .func = {0}, .authfunc = {0}, \
|
.evq = DCBEVENTQ_INIT, .ipv4 = {0}, .func = {0}, .authfunc = {0}, \
|
||||||
.writeqlock = SPINLOCK_INIT, .delayqlock = SPINLOCK_INIT, \
|
|
||||||
.stats = {0}, .memdata = DCBMM_INIT, \
|
.stats = {0}, .memdata = DCBMM_INIT, \
|
||||||
.cb_lock = SPINLOCK_INIT, .pollinlock = SPINLOCK_INIT, \
|
|
||||||
.fd = DCBFD_CLOSED, .stats = DCBSTATS_INIT, .ssl_state = SSL_HANDSHAKE_UNKNOWN, \
|
.fd = DCBFD_CLOSED, .stats = DCBSTATS_INIT, .ssl_state = SSL_HANDSHAKE_UNKNOWN, \
|
||||||
.state = DCB_STATE_ALLOC, .polloutlock = SPINLOCK_INIT, .dcb_chk_tail = CHK_NUM_DCB, \
|
.state = DCB_STATE_ALLOC, .dcb_chk_tail = CHK_NUM_DCB, \
|
||||||
.authenticator_data = NULL, .thread = {0}}
|
.authenticator_data = NULL, .thread = {0}}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -269,7 +269,6 @@ typedef struct
|
|||||||
#endif
|
#endif
|
||||||
int fd; /*< The socket descriptor */
|
int fd; /*< The socket descriptor */
|
||||||
struct dcb* owner_dcb; /*< The DCB of the socket we are running on */
|
struct dcb* owner_dcb; /*< The DCB of the socket we are running on */
|
||||||
SPINLOCK protocol_lock; /*< Protocol lock */
|
|
||||||
mysql_server_cmd_t current_command; /*< Current command being executed */
|
mysql_server_cmd_t current_command; /*< Current command being executed */
|
||||||
server_command_t protocol_command; /*< session command list */
|
server_command_t protocol_command; /*< session command list */
|
||||||
server_command_t* protocol_cmd_history; /*< session command history */
|
server_command_t* protocol_cmd_history; /*< session command history */
|
||||||
|
@ -126,7 +126,6 @@ typedef struct mxs_upstream
|
|||||||
typedef struct session
|
typedef struct session
|
||||||
{
|
{
|
||||||
skygw_chk_t ses_chk_top;
|
skygw_chk_t ses_chk_top;
|
||||||
SPINLOCK ses_lock;
|
|
||||||
mxs_session_state_t state; /*< Current descriptor state */
|
mxs_session_state_t state; /*< Current descriptor state */
|
||||||
size_t ses_id; /*< Unique session identifier */
|
size_t ses_id; /*< Unique session identifier */
|
||||||
int enabled_log_priorities; /*< Bitfield of enabled syslog priorities */
|
int enabled_log_priorities; /*< Bitfield of enabled syslog priorities */
|
||||||
|
@ -1931,8 +1931,9 @@ check_config_objects(CONFIG_CONTEXT *context)
|
|||||||
if (mod == NULL ||
|
if (mod == NULL ||
|
||||||
!config_param_is_valid(mod->parameters, params->name, params->value, context))
|
!config_param_is_valid(mod->parameters, params->name, params->value, context))
|
||||||
{
|
{
|
||||||
MXS_ERROR("Unexpected parameter '%s' or parameter value for object '%s' of type '%s'.",
|
MXS_ERROR("Unexpected parameter '%s' for object '%s' of type '%s', "
|
||||||
params->name, obj->object, type);
|
"or '%s' is an invalid value for parameter '%s'.",
|
||||||
|
params->name, obj->object, type, params->value, params->name);
|
||||||
rval = false;
|
rval = false;
|
||||||
}
|
}
|
||||||
else if (is_path_parameter(mod->parameters, params->name))
|
else if (is_path_parameter(mod->parameters, params->name))
|
||||||
|
@ -429,13 +429,13 @@ dcb_free_all_memory(DCB *dcb)
|
|||||||
gwbuf_free(dcb->dcb_fakequeue);
|
gwbuf_free(dcb->dcb_fakequeue);
|
||||||
dcb->dcb_fakequeue = NULL;
|
dcb->dcb_fakequeue = NULL;
|
||||||
}
|
}
|
||||||
spinlock_acquire(&dcb->cb_lock);
|
|
||||||
while ((cb_dcb = dcb->callbacks) != NULL)
|
while ((cb_dcb = dcb->callbacks) != NULL)
|
||||||
{
|
{
|
||||||
dcb->callbacks = cb_dcb->next;
|
dcb->callbacks = cb_dcb->next;
|
||||||
MXS_FREE(cb_dcb);
|
MXS_FREE(cb_dcb);
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
if (dcb->ssl)
|
if (dcb->ssl)
|
||||||
{
|
{
|
||||||
SSL_free(dcb->ssl);
|
SSL_free(dcb->ssl);
|
||||||
@ -757,10 +757,6 @@ dcb_connect(SERVER *server, MXS_SESSION *session, const char *protocol)
|
|||||||
*/
|
*/
|
||||||
dcb->server = server;
|
dcb->server = server;
|
||||||
|
|
||||||
/** Copy status field to DCB */
|
|
||||||
dcb->dcb_server_status = server->status;
|
|
||||||
dcb->dcb_port = server->port;
|
|
||||||
|
|
||||||
dcb->was_persistent = false;
|
dcb->was_persistent = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1721,13 +1717,13 @@ dcb_maybe_add_persistent(DCB *dcb)
|
|||||||
session_put_ref(local_session);
|
session_put_ref(local_session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinlock_acquire(&dcb->cb_lock);
|
|
||||||
while ((loopcallback = dcb->callbacks) != NULL)
|
while ((loopcallback = dcb->callbacks) != NULL)
|
||||||
{
|
{
|
||||||
dcb->callbacks = loopcallback->next;
|
dcb->callbacks = loopcallback->next;
|
||||||
MXS_FREE(loopcallback);
|
MXS_FREE(loopcallback);
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
dcb->nextpersistent = dcb->server->persistent[dcb->thread.id];
|
dcb->nextpersistent = dcb->server->persistent[dcb->thread.id];
|
||||||
dcb->server->persistent[dcb->thread.id] = dcb;
|
dcb->server->persistent[dcb->thread.id] = dcb;
|
||||||
atomic_add(&dcb->server->stats.n_persistent, 1);
|
atomic_add(&dcb->server->stats.n_persistent, 1);
|
||||||
@ -2070,20 +2066,7 @@ dprintDCB(DCB *pdcb, DCB *dcb)
|
|||||||
{
|
{
|
||||||
dcb_printf(pdcb, "\t\tDCB is a clone.\n");
|
dcb_printf(pdcb, "\t\tDCB is a clone.\n");
|
||||||
}
|
}
|
||||||
#if SPINLOCK_PROFILE
|
|
||||||
dcb_printf(pdcb, "\tInitlock Statistics:\n");
|
|
||||||
spinlock_stats(&dcb->dcb_initlock, spin_reporter, pdcb);
|
|
||||||
dcb_printf(pdcb, "\tWrite Queue Lock Statistics:\n");
|
|
||||||
spinlock_stats(&dcb->writeqlock, spin_reporter, pdcb);
|
|
||||||
dcb_printf(pdcb, "\tDelay Queue Lock Statistics:\n");
|
|
||||||
spinlock_stats(&dcb->delayqlock, spin_reporter, pdcb);
|
|
||||||
dcb_printf(pdcb, "\tPollin Lock Statistics:\n");
|
|
||||||
spinlock_stats(&dcb->pollinlock, spin_reporter, pdcb);
|
|
||||||
dcb_printf(pdcb, "\tPollout Lock Statistics:\n");
|
|
||||||
spinlock_stats(&dcb->polloutlock, spin_reporter, pdcb);
|
|
||||||
dcb_printf(pdcb, "\tCallback Lock Statistics:\n");
|
|
||||||
spinlock_stats(&dcb->cb_lock, spin_reporter, pdcb);
|
|
||||||
#endif
|
|
||||||
if (dcb->persistentstart)
|
if (dcb->persistentstart)
|
||||||
{
|
{
|
||||||
char buff[20];
|
char buff[20];
|
||||||
@ -2337,8 +2320,8 @@ dcb_add_callback(DCB *dcb,
|
|||||||
ptr->cb = callback;
|
ptr->cb = callback;
|
||||||
ptr->userdata = userdata;
|
ptr->userdata = userdata;
|
||||||
ptr->next = NULL;
|
ptr->next = NULL;
|
||||||
spinlock_acquire(&dcb->cb_lock);
|
|
||||||
cb = dcb->callbacks;
|
cb = dcb->callbacks;
|
||||||
|
|
||||||
while (cb)
|
while (cb)
|
||||||
{
|
{
|
||||||
if (cb->reason == reason && cb->cb == callback &&
|
if (cb->reason == reason && cb->cb == callback &&
|
||||||
@ -2346,7 +2329,6 @@ dcb_add_callback(DCB *dcb,
|
|||||||
{
|
{
|
||||||
/* Callback is a duplicate, abandon it */
|
/* Callback is a duplicate, abandon it */
|
||||||
MXS_FREE(ptr);
|
MXS_FREE(ptr);
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
lastcb = cb;
|
lastcb = cb;
|
||||||
@ -2360,7 +2342,7 @@ dcb_add_callback(DCB *dcb,
|
|||||||
{
|
{
|
||||||
lastcb->next = ptr;
|
lastcb->next = ptr;
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2384,9 +2366,8 @@ dcb_remove_callback(DCB *dcb,
|
|||||||
{
|
{
|
||||||
DCB_CALLBACK *cb, *pcb = NULL;
|
DCB_CALLBACK *cb, *pcb = NULL;
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
|
|
||||||
spinlock_acquire(&dcb->cb_lock);
|
|
||||||
cb = dcb->callbacks;
|
cb = dcb->callbacks;
|
||||||
|
|
||||||
if (cb == NULL)
|
if (cb == NULL)
|
||||||
{
|
{
|
||||||
rval = 0;
|
rval = 0;
|
||||||
@ -2407,7 +2388,7 @@ dcb_remove_callback(DCB *dcb,
|
|||||||
{
|
{
|
||||||
dcb->callbacks = cb->next;
|
dcb->callbacks = cb->next;
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
MXS_FREE(cb);
|
MXS_FREE(cb);
|
||||||
rval = 1;
|
rval = 1;
|
||||||
break;
|
break;
|
||||||
@ -2416,10 +2397,7 @@ dcb_remove_callback(DCB *dcb,
|
|||||||
cb = cb->next;
|
cb = cb->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!rval)
|
|
||||||
{
|
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
}
|
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2433,22 +2411,19 @@ static void
|
|||||||
dcb_call_callback(DCB *dcb, DCB_REASON reason)
|
dcb_call_callback(DCB *dcb, DCB_REASON reason)
|
||||||
{
|
{
|
||||||
DCB_CALLBACK *cb, *nextcb;
|
DCB_CALLBACK *cb, *nextcb;
|
||||||
|
|
||||||
spinlock_acquire(&dcb->cb_lock);
|
|
||||||
cb = dcb->callbacks;
|
cb = dcb->callbacks;
|
||||||
|
|
||||||
while (cb)
|
while (cb)
|
||||||
{
|
{
|
||||||
if (cb->reason == reason)
|
if (cb->reason == reason)
|
||||||
{
|
{
|
||||||
nextcb = cb->next;
|
nextcb = cb->next;
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
|
|
||||||
MXS_DEBUG("%lu [dcb_call_callback] %s",
|
MXS_DEBUG("%lu [dcb_call_callback] %s",
|
||||||
pthread_self(),
|
pthread_self(),
|
||||||
STRDCBREASON(reason));
|
STRDCBREASON(reason));
|
||||||
|
|
||||||
cb->cb(dcb, reason, cb->userdata);
|
cb->cb(dcb, reason, cb->userdata);
|
||||||
spinlock_acquire(&dcb->cb_lock);
|
|
||||||
cb = nextcb;
|
cb = nextcb;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2456,7 +2431,6 @@ dcb_call_callback(DCB *dcb, DCB_REASON reason)
|
|||||||
cb = cb->next;
|
cb = cb->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->cb_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2488,13 +2462,11 @@ dcb_hangup_foreach(struct server* server)
|
|||||||
|
|
||||||
for (DCB *dcb = all_dcbs[i]; dcb; dcb = dcb->thread.next)
|
for (DCB *dcb = all_dcbs[i]; dcb; dcb = dcb->thread.next)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
if (dcb->state == DCB_STATE_POLLING && dcb->server &&
|
if (dcb->state == DCB_STATE_POLLING && dcb->server &&
|
||||||
dcb->server == server)
|
dcb->server == server)
|
||||||
{
|
{
|
||||||
poll_fake_hangup_event(dcb);
|
poll_fake_hangup_event(dcb);
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&all_dcbs_lock[i]);
|
spinlock_release(&all_dcbs_lock[i]);
|
||||||
|
@ -25,7 +25,7 @@ MXS_BEGIN_DECLS
|
|||||||
#define MXS_UPSTREAM_INIT {0}
|
#define MXS_UPSTREAM_INIT {0}
|
||||||
#define SESSION_FILTER_INIT {0}
|
#define SESSION_FILTER_INIT {0}
|
||||||
|
|
||||||
#define SESSION_INIT {.ses_chk_top = CHK_NUM_SESSION, .ses_lock = SPINLOCK_INIT, \
|
#define SESSION_INIT {.ses_chk_top = CHK_NUM_SESSION, \
|
||||||
.stats = SESSION_STATS_INIT, .head = MXS_DOWNSTREAM_INIT, .tail = MXS_UPSTREAM_INIT, \
|
.stats = SESSION_STATS_INIT, .head = MXS_DOWNSTREAM_INIT, .tail = MXS_UPSTREAM_INIT, \
|
||||||
.state = SESSION_STATE_ALLOC, .ses_chk_tail = CHK_NUM_SESSION}
|
.state = SESSION_STATE_ALLOC, .ses_chk_tail = CHK_NUM_SESSION}
|
||||||
|
|
||||||
|
@ -337,7 +337,6 @@ int poll_add_dcb(DCB *dcb)
|
|||||||
/*<
|
/*<
|
||||||
* Choose new state according to the role of dcb.
|
* Choose new state according to the role of dcb.
|
||||||
*/
|
*/
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
if (dcb->dcb_role == DCB_ROLE_CLIENT_HANDLER || dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER)
|
if (dcb->dcb_role == DCB_ROLE_CLIENT_HANDLER || dcb->dcb_role == DCB_ROLE_BACKEND_HANDLER)
|
||||||
{
|
{
|
||||||
new_state = DCB_STATE_POLLING;
|
new_state = DCB_STATE_POLLING;
|
||||||
@ -388,7 +387,6 @@ int poll_add_dcb(DCB *dcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dcb->thread.id = owner;
|
dcb->thread.id = owner;
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
|
|
||||||
dcb_add_to_list(dcb);
|
dcb_add_to_list(dcb);
|
||||||
|
|
||||||
@ -396,7 +394,6 @@ int poll_add_dcb(DCB *dcb)
|
|||||||
|
|
||||||
if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER)
|
if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
/** Listeners are added to all epoll instances */
|
/** Listeners are added to all epoll instances */
|
||||||
int nthr = config_threadcount();
|
int nthr = config_threadcount();
|
||||||
|
|
||||||
@ -413,7 +410,6 @@ int poll_add_dcb(DCB *dcb)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -448,12 +444,10 @@ int poll_remove_dcb(DCB *dcb)
|
|||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
CHK_DCB(dcb);
|
CHK_DCB(dcb);
|
||||||
|
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
/*< It is possible that dcb has already been removed from the set */
|
/*< It is possible that dcb has already been removed from the set */
|
||||||
if (dcb->state == DCB_STATE_NOPOLLING ||
|
if (dcb->state == DCB_STATE_NOPOLLING ||
|
||||||
dcb->state == DCB_STATE_ZOMBIE)
|
dcb->state == DCB_STATE_ZOMBIE)
|
||||||
{
|
{
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (DCB_STATE_POLLING != dcb->state
|
if (DCB_STATE_POLLING != dcb->state
|
||||||
@ -478,7 +472,6 @@ int poll_remove_dcb(DCB *dcb)
|
|||||||
* DCB_STATE_NOPOLLING.
|
* DCB_STATE_NOPOLLING.
|
||||||
*/
|
*/
|
||||||
dcbfd = dcb->fd;
|
dcbfd = dcb->fd;
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
|
|
||||||
if (dcbfd > 0)
|
if (dcbfd > 0)
|
||||||
{
|
{
|
||||||
@ -486,7 +479,6 @@ int poll_remove_dcb(DCB *dcb)
|
|||||||
|
|
||||||
if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER)
|
if (dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
/** Listeners are added to all epoll instances */
|
/** Listeners are added to all epoll instances */
|
||||||
int nthr = config_threadcount();
|
int nthr = config_threadcount();
|
||||||
|
|
||||||
@ -502,7 +494,6 @@ int poll_remove_dcb(DCB *dcb)
|
|||||||
ss_dassert(error_num);
|
ss_dassert(error_num);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -925,15 +916,12 @@ process_pollq(int thread_id, struct epoll_event *event)
|
|||||||
thread_data[thread_id].event = ev;
|
thread_data[thread_id].event = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
ss_debug(spinlock_acquire(&dcb->dcb_initlock));
|
|
||||||
ss_dassert(dcb->state != DCB_STATE_ALLOC);
|
|
||||||
/* It isn't obvious that this is impossible */
|
/* It isn't obvious that this is impossible */
|
||||||
/* ss_dassert(dcb->state != DCB_STATE_DISCONNECTED); */
|
/* ss_dassert(dcb->state != DCB_STATE_DISCONNECTED); */
|
||||||
if (DCB_STATE_DISCONNECTED == dcb->state)
|
if (DCB_STATE_DISCONNECTED == dcb->state)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ss_debug(spinlock_release(&dcb->dcb_initlock));
|
|
||||||
|
|
||||||
MXS_DEBUG("%lu [poll_waitevents] event %d dcb %p "
|
MXS_DEBUG("%lu [poll_waitevents] event %d dcb %p "
|
||||||
"role %s",
|
"role %s",
|
||||||
@ -1059,11 +1047,10 @@ process_pollq(int thread_id, struct epoll_event *event)
|
|||||||
eno,
|
eno,
|
||||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||||
ts_stats_increment(pollStats.n_hup, thread_id);
|
ts_stats_increment(pollStats.n_hup, thread_id);
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
if ((dcb->flags & DCBF_HUNG) == 0)
|
if ((dcb->flags & DCBF_HUNG) == 0)
|
||||||
{
|
{
|
||||||
dcb->flags |= DCBF_HUNG;
|
dcb->flags |= DCBF_HUNG;
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
/** Read session id to thread's local storage */
|
/** Read session id to thread's local storage */
|
||||||
dcb_get_ses_log_info(dcb,
|
dcb_get_ses_log_info(dcb,
|
||||||
&mxs_log_tls.li_sesid,
|
&mxs_log_tls.li_sesid,
|
||||||
@ -1074,10 +1061,6 @@ process_pollq(int thread_id, struct epoll_event *event)
|
|||||||
dcb->func.hangup(dcb);
|
dcb->func.hangup(dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EPOLLRDHUP
|
#ifdef EPOLLRDHUP
|
||||||
@ -1094,11 +1077,11 @@ process_pollq(int thread_id, struct epoll_event *event)
|
|||||||
eno,
|
eno,
|
||||||
strerror_r(eno, errbuf, sizeof(errbuf)));
|
strerror_r(eno, errbuf, sizeof(errbuf)));
|
||||||
ts_stats_increment(pollStats.n_hup, thread_id);
|
ts_stats_increment(pollStats.n_hup, thread_id);
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
if ((dcb->flags & DCBF_HUNG) == 0)
|
if ((dcb->flags & DCBF_HUNG) == 0)
|
||||||
{
|
{
|
||||||
dcb->flags |= DCBF_HUNG;
|
dcb->flags |= DCBF_HUNG;
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
/** Read session id to thread's local storage */
|
/** Read session id to thread's local storage */
|
||||||
dcb_get_ses_log_info(dcb,
|
dcb_get_ses_log_info(dcb,
|
||||||
&mxs_log_tls.li_sesid,
|
&mxs_log_tls.li_sesid,
|
||||||
@ -1109,10 +1092,6 @@ process_pollq(int thread_id, struct epoll_event *event)
|
|||||||
dcb->func.hangup(dcb);
|
dcb->func.hangup(dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <maxscale/spinlock.h>
|
|
||||||
#include <maxscale/random_jkiss.h>
|
#include <maxscale/random_jkiss.h>
|
||||||
|
|
||||||
/* Public domain code for JKISS RNG - Comment header added */
|
/* Public domain code for JKISS RNG - Comment header added */
|
||||||
@ -42,8 +41,6 @@
|
|||||||
static unsigned int x = 123456789, y = 987654321, z = 43219876, c = 6543217; /* Seed variables */
|
static unsigned int x = 123456789, y = 987654321, z = 43219876, c = 6543217; /* Seed variables */
|
||||||
static bool init = false;
|
static bool init = false;
|
||||||
|
|
||||||
static SPINLOCK random_jkiss_spinlock = SPINLOCK_INIT;
|
|
||||||
|
|
||||||
static unsigned int random_jkiss_devrand(void);
|
static unsigned int random_jkiss_devrand(void);
|
||||||
static void random_init_jkiss(void);
|
static void random_init_jkiss(void);
|
||||||
|
|
||||||
@ -60,14 +57,11 @@ random_jkiss(void)
|
|||||||
unsigned long long t;
|
unsigned long long t;
|
||||||
unsigned int result;
|
unsigned int result;
|
||||||
|
|
||||||
spinlock_acquire(&random_jkiss_spinlock);
|
|
||||||
if (!init)
|
if (!init)
|
||||||
{
|
{
|
||||||
/* Must set init first because initialisation calls this function */
|
/* Must set init first because initialisation calls this function */
|
||||||
init = true;
|
init = true;
|
||||||
spinlock_release(&random_jkiss_spinlock);
|
|
||||||
random_init_jkiss();
|
random_init_jkiss();
|
||||||
spinlock_acquire(&random_jkiss_spinlock);
|
|
||||||
}
|
}
|
||||||
x = 314527869 * x + 1234567;
|
x = 314527869 * x + 1234567;
|
||||||
y ^= y << 5;
|
y ^= y << 5;
|
||||||
@ -77,7 +71,6 @@ random_jkiss(void)
|
|||||||
c = t >> 32;
|
c = t >> 32;
|
||||||
z = t;
|
z = t;
|
||||||
result = x + y + z;
|
result = x + y + z;
|
||||||
spinlock_release(&random_jkiss_spinlock);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +113,6 @@ random_init_jkiss(void)
|
|||||||
{
|
{
|
||||||
int newrand, i;
|
int newrand, i;
|
||||||
|
|
||||||
spinlock_acquire(&random_jkiss_spinlock);
|
|
||||||
if ((newrand = random_jkiss_devrand()) != 0)
|
if ((newrand = random_jkiss_devrand()) != 0)
|
||||||
{
|
{
|
||||||
x = newrand;
|
x = newrand;
|
||||||
@ -140,7 +132,6 @@ random_init_jkiss(void)
|
|||||||
{
|
{
|
||||||
c = newrand % 698769068 + 1; /* Should be less than 698769069 */
|
c = newrand % 698769068 + 1; /* Should be less than 698769069 */
|
||||||
}
|
}
|
||||||
spinlock_release(&random_jkiss_spinlock);
|
|
||||||
|
|
||||||
/* "Warm up" our random number generator */
|
/* "Warm up" our random number generator */
|
||||||
for (i = 0; i < 100; i++)
|
for (i = 0; i < 100; i++)
|
||||||
|
@ -230,7 +230,6 @@ session_set_dummy(DCB *client_dcb)
|
|||||||
session->ses_chk_top = CHK_NUM_SESSION;
|
session->ses_chk_top = CHK_NUM_SESSION;
|
||||||
session->ses_chk_tail = CHK_NUM_SESSION;
|
session->ses_chk_tail = CHK_NUM_SESSION;
|
||||||
session->ses_is_child = false;
|
session->ses_is_child = false;
|
||||||
spinlock_init(&session->ses_lock);
|
|
||||||
session->service = NULL;
|
session->service = NULL;
|
||||||
session->client_dcb = NULL;
|
session->client_dcb = NULL;
|
||||||
session->n_filters = 0;
|
session->n_filters = 0;
|
||||||
@ -285,20 +284,17 @@ void session_disable_log_priority(MXS_SESSION* session, int priority)
|
|||||||
bool
|
bool
|
||||||
session_link_dcb(MXS_SESSION *session, DCB *dcb)
|
session_link_dcb(MXS_SESSION *session, DCB *dcb)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
ss_info_dassert(session->state != SESSION_STATE_FREE,
|
ss_info_dassert(session->state != SESSION_STATE_FREE,
|
||||||
"If session->state is SESSION_STATE_FREE then this attempt to "
|
"If session->state is SESSION_STATE_FREE then this attempt to "
|
||||||
"access freed memory block.");
|
"access freed memory block.");
|
||||||
if (session->state == SESSION_STATE_FREE)
|
if (session->state == SESSION_STATE_FREE)
|
||||||
{
|
{
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
atomic_add(&session->refcount, 1);
|
atomic_add(&session->refcount, 1);
|
||||||
dcb->session = session;
|
dcb->session = session;
|
||||||
/** Move this DCB under the same thread */
|
/** Move this DCB under the same thread */
|
||||||
dcb->thread.id = session->client_dcb->thread.id;
|
dcb->thread.id = session->client_dcb->thread.id;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ add_subdirectory(hintfilter)
|
|||||||
add_subdirectory(luafilter)
|
add_subdirectory(luafilter)
|
||||||
add_subdirectory(mqfilter)
|
add_subdirectory(mqfilter)
|
||||||
add_subdirectory(namedserverfilter)
|
add_subdirectory(namedserverfilter)
|
||||||
|
add_subdirectory(nullfilter)
|
||||||
add_subdirectory(qlafilter)
|
add_subdirectory(qlafilter)
|
||||||
add_subdirectory(regexfilter)
|
add_subdirectory(regexfilter)
|
||||||
add_subdirectory(tee)
|
add_subdirectory(tee)
|
||||||
|
7
server/modules/filter/nullfilter/CMakeLists.txt
Normal file
7
server/modules/filter/nullfilter/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
add_library(nullfilter SHARED
|
||||||
|
nullfilter.cc
|
||||||
|
nullfiltersession.cc
|
||||||
|
)
|
||||||
|
target_link_libraries(nullfilter maxscale-common)
|
||||||
|
set_target_properties(nullfilter PROPERTIES VERSION "1.0.0")
|
||||||
|
install_module(nullfilter core)
|
133
server/modules/filter/nullfilter/nullfilter.cc
Normal file
133
server/modules/filter/nullfilter/nullfilter.cc
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MXS_MODULE_NAME "nullfilter"
|
||||||
|
#include "nullfilter.hh"
|
||||||
|
#include <string>
|
||||||
|
#include <maxscale/utils.h>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
#define VERSION_STRING "V1.0.0"
|
||||||
|
|
||||||
|
const char CAPABILITIES_PARAM[] = "capabilities";
|
||||||
|
|
||||||
|
MXS_ENUM_VALUE capability_values[] =
|
||||||
|
{
|
||||||
|
{ "RCAP_TYPE_STMT_INPUT", RCAP_TYPE_STMT_INPUT },
|
||||||
|
{ "RCAP_TYPE_CONTIGUOUS_INPUT", RCAP_TYPE_CONTIGUOUS_INPUT },
|
||||||
|
{ "RCAP_TYPE_TRANSACTION_TRACKING", RCAP_TYPE_TRANSACTION_TRACKING },
|
||||||
|
{ "RCAP_TYPE_STMT_OUTPUT", RCAP_TYPE_STMT_OUTPUT },
|
||||||
|
{ "RCAP_TYPE_CONTIGUOUS_OUTPUT", RCAP_TYPE_CONTIGUOUS_OUTPUT },
|
||||||
|
{ "RCAP_TYPE_RESULTSET_OUTPUT", RCAP_TYPE_RESULTSET_OUTPUT },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct unit_variables
|
||||||
|
{
|
||||||
|
uint64_t capabilities;
|
||||||
|
bool capabilities_set;
|
||||||
|
} this_unit =
|
||||||
|
{
|
||||||
|
0,
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Global symbols of the Module
|
||||||
|
//
|
||||||
|
|
||||||
|
extern "C" MXS_MODULE* MXS_CREATE_MODULE()
|
||||||
|
{
|
||||||
|
MXS_NOTICE("Nullfilter module %s initialized.", VERSION_STRING);
|
||||||
|
|
||||||
|
static MXS_MODULE info =
|
||||||
|
{
|
||||||
|
MXS_MODULE_API_FILTER,
|
||||||
|
MXS_MODULE_IN_DEVELOPMENT,
|
||||||
|
MXS_FILTER_VERSION,
|
||||||
|
"A null filter that does nothing.",
|
||||||
|
VERSION_STRING,
|
||||||
|
&NullFilter::s_object,
|
||||||
|
NULL, /* Process init. */
|
||||||
|
NULL, /* Process finish. */
|
||||||
|
NULL, /* Thread init. */
|
||||||
|
NULL, /* Thread finish. */
|
||||||
|
{
|
||||||
|
{ CAPABILITIES_PARAM, MXS_MODULE_PARAM_ENUM, NULL, MXS_MODULE_OPT_REQUIRED, capability_values },
|
||||||
|
{ MXS_END_MODULE_PARAMS }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// NullFilter
|
||||||
|
//
|
||||||
|
|
||||||
|
NullFilter::NullFilter(const char* zName)
|
||||||
|
{
|
||||||
|
MXS_NOTICE("Null filter [%s] created.", zName);
|
||||||
|
}
|
||||||
|
|
||||||
|
NullFilter::~NullFilter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
NullFilter* NullFilter::create(const char* zName, char**, MXS_CONFIG_PARAMETER* pParams)
|
||||||
|
{
|
||||||
|
NullFilter* pFilter = NULL;
|
||||||
|
|
||||||
|
uint64_t capabilities = config_get_enum(pParams, CAPABILITIES_PARAM, capability_values);
|
||||||
|
|
||||||
|
if (this_unit.capabilities_set)
|
||||||
|
{
|
||||||
|
MXS_WARNING("The capabilities reported by NullFilter are currently global, "
|
||||||
|
"and not specific for a particular NullFilter instance.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this_unit.capabilities = capabilities;
|
||||||
|
this_unit.capabilities_set = true;
|
||||||
|
|
||||||
|
return new NullFilter(zName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NullFilterSession* NullFilter::newSession(MXS_SESSION* pSession)
|
||||||
|
{
|
||||||
|
return NullFilterSession::create(pSession, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void NullFilter::diagnostics(DCB* pDcb)
|
||||||
|
{
|
||||||
|
dcb_printf(pDcb, "Hello, World!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
uint64_t NullFilter::getCapabilities()
|
||||||
|
{
|
||||||
|
if (!this_unit.capabilities_set)
|
||||||
|
{
|
||||||
|
MXS_ERROR("getCapabilities() called before they have been set.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this_unit.capabilities;
|
||||||
|
}
|
36
server/modules/filter/nullfilter/nullfilter.hh
Normal file
36
server/modules/filter/nullfilter/nullfilter.hh
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||||
|
*
|
||||||
|
* Use of this software is governed by the Business Source License included
|
||||||
|
* in the LICENSE.TXT file and at www.mariadb.com/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/cppdefs.hh>
|
||||||
|
#include <maxscale/filter.hh>
|
||||||
|
#include "nullfiltersession.hh"
|
||||||
|
|
||||||
|
class NullFilter : public maxscale::Filter<NullFilter, NullFilterSession>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~NullFilter();
|
||||||
|
static NullFilter* create(const char* zName, char** pzOptions, MXS_CONFIG_PARAMETER* pParams);
|
||||||
|
|
||||||
|
NullFilterSession* newSession(MXS_SESSION* pSession);
|
||||||
|
|
||||||
|
void diagnostics(DCB* pDcb);
|
||||||
|
|
||||||
|
static uint64_t getCapabilities();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NullFilter(const char* zName);
|
||||||
|
|
||||||
|
NullFilter(const NullFilter&);
|
||||||
|
NullFilter& operator = (const NullFilter&);
|
||||||
|
};
|
31
server/modules/filter/nullfilter/nullfiltersession.cc
Normal file
31
server/modules/filter/nullfilter/nullfiltersession.cc
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define MXS_MODULE_NAME "nullfilter"
|
||||||
|
#include "nullfiltersession.hh"
|
||||||
|
|
||||||
|
NullFilterSession::NullFilterSession(MXS_SESSION* pSession, const NullFilter* pFilter)
|
||||||
|
: maxscale::FilterSession(pSession)
|
||||||
|
, m_filter(*pFilter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NullFilterSession::~NullFilterSession()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//static
|
||||||
|
NullFilterSession* NullFilterSession::create(MXS_SESSION* pSession, const NullFilter* pFilter)
|
||||||
|
{
|
||||||
|
return new NullFilterSession(pSession, pFilter);
|
||||||
|
}
|
35
server/modules/filter/nullfilter/nullfiltersession.hh
Normal file
35
server/modules/filter/nullfilter/nullfiltersession.hh
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||||
|
*
|
||||||
|
* Use of this software is governed by the Business Source License included
|
||||||
|
* in the LICENSE.TXT file and at www.mariadb.com/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/cppdefs.hh>
|
||||||
|
#include <maxscale/filter.hh>
|
||||||
|
|
||||||
|
class NullFilter;
|
||||||
|
|
||||||
|
class NullFilterSession : public maxscale::FilterSession
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~NullFilterSession();
|
||||||
|
|
||||||
|
static NullFilterSession* create(MXS_SESSION* pSession, const NullFilter* pFilter);
|
||||||
|
|
||||||
|
private:
|
||||||
|
NullFilterSession(MXS_SESSION* pSession, const NullFilter* pFilter);
|
||||||
|
|
||||||
|
NullFilterSession(const NullFilterSession&);
|
||||||
|
NullFilterSession& operator = (const NullFilterSession&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const NullFilter& m_filter;
|
||||||
|
};
|
@ -536,7 +536,6 @@ closeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session)
|
|||||||
if ((bsession = my_session->branch_session) != NULL)
|
if ((bsession = my_session->branch_session) != NULL)
|
||||||
{
|
{
|
||||||
CHK_SESSION(bsession);
|
CHK_SESSION(bsession);
|
||||||
spinlock_acquire(&bsession->ses_lock);
|
|
||||||
|
|
||||||
if (bsession->state != SESSION_STATE_STOPPING)
|
if (bsession->state != SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
@ -545,7 +544,6 @@ closeSession(MXS_FILTER *instance, MXS_FILTER_SESSION *session)
|
|||||||
router = bsession->service->router;
|
router = bsession->service->router;
|
||||||
router_instance = bsession->service->router_instance;
|
router_instance = bsession->service->router_instance;
|
||||||
rsession = bsession->router_session;
|
rsession = bsession->router_session;
|
||||||
spinlock_release(&bsession->ses_lock);
|
|
||||||
|
|
||||||
/** Close router session and all its connections */
|
/** Close router session and all its connections */
|
||||||
router->closeSession(router_instance, rsession);
|
router->closeSession(router_instance, rsession);
|
||||||
|
@ -637,9 +637,7 @@ gw_reply_on_error(DCB *dcb, mxs_auth_state_t state)
|
|||||||
session->router_session,
|
session->router_session,
|
||||||
errbuf, dcb, ERRACT_REPLY_CLIENT, &succp);
|
errbuf, dcb, ERRACT_REPLY_CLIENT, &succp);
|
||||||
|
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
ss_dassert(dcb->dcb_errhandle_called);
|
ss_dassert(dcb->dcb_errhandle_called);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -736,9 +734,7 @@ gw_read_and_write(DCB *dcb)
|
|||||||
|
|
||||||
if (!succp)
|
if (!succp)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1173,22 +1169,7 @@ static int gw_error_backend_event(DCB *dcb)
|
|||||||
0,
|
0,
|
||||||
"Lost connection to backend server.");
|
"Lost connection to backend server.");
|
||||||
|
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
ses_state = session->state;
|
ses_state = session->state;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Session might be initialized when DCB already is in the poll set.
|
|
||||||
* Thus hangup can occur in the middle of session initialization.
|
|
||||||
* Only complete and successfully initialized sessions allow for
|
|
||||||
* calling error handler.
|
|
||||||
*/
|
|
||||||
while (ses_state == SESSION_STATE_READY)
|
|
||||||
{
|
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
ses_state = session->state;
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ses_state != SESSION_STATE_ROUTER_READY)
|
if (ses_state != SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
@ -1225,9 +1206,7 @@ static int gw_error_backend_event(DCB *dcb)
|
|||||||
*/
|
*/
|
||||||
if (!succp)
|
if (!succp)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retblock:
|
retblock:
|
||||||
@ -1277,22 +1256,7 @@ static int gw_backend_hangup(DCB *dcb)
|
|||||||
0,
|
0,
|
||||||
"Lost connection to backend server.");
|
"Lost connection to backend server.");
|
||||||
|
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
ses_state = session->state;
|
ses_state = session->state;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Session might be initialized when DCB already is in the poll set.
|
|
||||||
* Thus hangup can occur in the middle of session initialization.
|
|
||||||
* Only complete and successfully initialized sessions allow for
|
|
||||||
* calling error handler.
|
|
||||||
*/
|
|
||||||
while (ses_state == SESSION_STATE_READY)
|
|
||||||
{
|
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
ses_state = session->state;
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ses_state != SESSION_STATE_ROUTER_READY)
|
if (ses_state != SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
@ -1330,9 +1294,7 @@ static int gw_backend_hangup(DCB *dcb)
|
|||||||
/** There are no required backends available, close session. */
|
/** There are no required backends available, close session. */
|
||||||
if (!succp)
|
if (!succp)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retblock:
|
retblock:
|
||||||
@ -1371,7 +1333,7 @@ static int gw_backend_close(DCB *dcb)
|
|||||||
* but client's close and adding client's DCB to zombies list is executed
|
* but client's close and adding client's DCB to zombies list is executed
|
||||||
* only if client's DCB's state does _not_ change in parallel.
|
* only if client's DCB's state does _not_ change in parallel.
|
||||||
*/
|
*/
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
/**
|
/**
|
||||||
* If session->state is STOPPING, start closing client session.
|
* If session->state is STOPPING, start closing client session.
|
||||||
* Otherwise only this backend connection is closed.
|
* Otherwise only this backend connection is closed.
|
||||||
@ -1381,19 +1343,9 @@ static int gw_backend_close(DCB *dcb)
|
|||||||
{
|
{
|
||||||
if (session->client_dcb->state == DCB_STATE_POLLING)
|
if (session->client_dcb->state == DCB_STATE_POLLING)
|
||||||
{
|
{
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
|
|
||||||
/** Close client DCB */
|
/** Close client DCB */
|
||||||
dcb_close(session->client_dcb);
|
dcb_close(session->client_dcb);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
@ -1471,9 +1423,7 @@ static int backend_write_delayqueue(DCB *dcb, GWBUF *buffer)
|
|||||||
|
|
||||||
if (!succp)
|
if (!succp)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1564,8 +1514,6 @@ static int gw_change_user(DCB *backend,
|
|||||||
memcpy(&backend_protocol->charset, client_auth_packet, sizeof(int));
|
memcpy(&backend_protocol->charset, client_auth_packet, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_acquire(&in_session->ses_lock);
|
|
||||||
|
|
||||||
/* save current_database name */
|
/* save current_database name */
|
||||||
strcpy(current_database, current_session->db);
|
strcpy(current_database, current_session->db);
|
||||||
|
|
||||||
@ -1595,7 +1543,6 @@ static int gw_change_user(DCB *backend,
|
|||||||
client_sha1, sizeof(client_sha1));
|
client_sha1, sizeof(client_sha1));
|
||||||
|
|
||||||
strcpy(current_session->db, current_database);
|
strcpy(current_session->db, current_database);
|
||||||
spinlock_release(&in_session->ses_lock);
|
|
||||||
|
|
||||||
if (auth_ret != 0)
|
if (auth_ret != 0)
|
||||||
{
|
{
|
||||||
@ -1603,7 +1550,6 @@ static int gw_change_user(DCB *backend,
|
|||||||
{
|
{
|
||||||
/* Try authentication again with new repository data */
|
/* Try authentication again with new repository data */
|
||||||
/* Note: if no auth client authentication will fail */
|
/* Note: if no auth client authentication will fail */
|
||||||
spinlock_acquire(&in_session->ses_lock);
|
|
||||||
*current_session->db = 0;
|
*current_session->db = 0;
|
||||||
|
|
||||||
auth_ret = dcb->authfunc.reauthenticate(dcb, username,
|
auth_ret = dcb->authfunc.reauthenticate(dcb, username,
|
||||||
@ -1613,7 +1559,6 @@ static int gw_change_user(DCB *backend,
|
|||||||
client_sha1, sizeof(client_sha1));
|
client_sha1, sizeof(client_sha1));
|
||||||
|
|
||||||
strcpy(current_session->db, current_database);
|
strcpy(current_session->db, current_database);
|
||||||
spinlock_release(&in_session->ses_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1361,7 +1361,6 @@ gw_client_close(DCB *dcb)
|
|||||||
if (session != NULL && SESSION_STATE_DUMMY != session->state)
|
if (session != NULL && SESSION_STATE_DUMMY != session->state)
|
||||||
{
|
{
|
||||||
CHK_SESSION(session);
|
CHK_SESSION(session);
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
|
|
||||||
if (session->state != SESSION_STATE_STOPPING)
|
if (session->state != SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
@ -1375,14 +1374,9 @@ gw_client_close(DCB *dcb)
|
|||||||
*/
|
*/
|
||||||
if (session->router_session != NULL)
|
if (session->router_session != NULL)
|
||||||
{
|
{
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
/** Close router session and all its connections */
|
/** Close router session and all its connections */
|
||||||
router->closeSession(router_instance, session->router_session);
|
router->closeSession(router_instance, session->router_session);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -132,27 +132,21 @@ void mysql_protocol_done(DCB* dcb)
|
|||||||
|
|
||||||
p = (MySQLProtocol *)dcb->protocol;
|
p = (MySQLProtocol *)dcb->protocol;
|
||||||
|
|
||||||
spinlock_acquire(&p->protocol_lock);
|
if (p->protocol_state == MYSQL_PROTOCOL_ACTIVE)
|
||||||
|
|
||||||
if (p->protocol_state != MYSQL_PROTOCOL_ACTIVE)
|
|
||||||
{
|
{
|
||||||
goto retblock;
|
scmd = p->protocol_cmd_history;
|
||||||
|
|
||||||
|
while (scmd != NULL)
|
||||||
|
{
|
||||||
|
scmd2 = scmd->scom_next;
|
||||||
|
MXS_FREE(scmd);
|
||||||
|
scmd = scmd2;
|
||||||
|
}
|
||||||
|
|
||||||
|
gwbuf_free(p->stored_query);
|
||||||
|
|
||||||
|
p->protocol_state = MYSQL_PROTOCOL_DONE;
|
||||||
}
|
}
|
||||||
scmd = p->protocol_cmd_history;
|
|
||||||
|
|
||||||
while (scmd != NULL)
|
|
||||||
{
|
|
||||||
scmd2 = scmd->scom_next;
|
|
||||||
MXS_FREE(scmd);
|
|
||||||
scmd = scmd2;
|
|
||||||
}
|
|
||||||
|
|
||||||
gwbuf_free(p->stored_query);
|
|
||||||
|
|
||||||
p->protocol_state = MYSQL_PROTOCOL_DONE;
|
|
||||||
|
|
||||||
retblock:
|
|
||||||
spinlock_release(&p->protocol_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -660,8 +654,6 @@ void protocol_archive_srv_command(MySQLProtocol* p)
|
|||||||
|
|
||||||
CHK_PROTOCOL(p);
|
CHK_PROTOCOL(p);
|
||||||
|
|
||||||
spinlock_acquire(&p->protocol_lock);
|
|
||||||
|
|
||||||
if (p->protocol_state != MYSQL_PROTOCOL_ACTIVE)
|
if (p->protocol_state != MYSQL_PROTOCOL_ACTIVE)
|
||||||
{
|
{
|
||||||
goto retblock;
|
goto retblock;
|
||||||
@ -710,7 +702,6 @@ void protocol_archive_srv_command(MySQLProtocol* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
retblock:
|
retblock:
|
||||||
spinlock_release(&p->protocol_lock);
|
|
||||||
CHK_PROTOCOL(p);
|
CHK_PROTOCOL(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,11 +716,10 @@ void protocol_add_srv_command(MySQLProtocol* p,
|
|||||||
#if defined(EXTRA_SS_DEBUG)
|
#if defined(EXTRA_SS_DEBUG)
|
||||||
server_command_t* c;
|
server_command_t* c;
|
||||||
#endif
|
#endif
|
||||||
spinlock_acquire(&p->protocol_lock);
|
|
||||||
|
|
||||||
if (p->protocol_state != MYSQL_PROTOCOL_ACTIVE)
|
if (p->protocol_state != MYSQL_PROTOCOL_ACTIVE)
|
||||||
{
|
{
|
||||||
goto retblock;
|
return;
|
||||||
}
|
}
|
||||||
/** this is the only server command in protocol */
|
/** this is the only server command in protocol */
|
||||||
if (p->protocol_command.scom_cmd == MYSQL_COM_UNDEFINED)
|
if (p->protocol_command.scom_cmd == MYSQL_COM_UNDEFINED)
|
||||||
@ -758,8 +748,6 @@ void protocol_add_srv_command(MySQLProtocol* p,
|
|||||||
c = c->scom_next;
|
c = c->scom_next;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
retblock:
|
|
||||||
spinlock_release(&p->protocol_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -772,7 +760,7 @@ retblock:
|
|||||||
void protocol_remove_srv_command(MySQLProtocol* p)
|
void protocol_remove_srv_command(MySQLProtocol* p)
|
||||||
{
|
{
|
||||||
server_command_t* s;
|
server_command_t* s;
|
||||||
spinlock_acquire(&p->protocol_lock);
|
|
||||||
s = &p->protocol_command;
|
s = &p->protocol_command;
|
||||||
#if defined(EXTRA_SS_DEBUG)
|
#if defined(EXTRA_SS_DEBUG)
|
||||||
MXS_INFO("Removed command %s from fd %d.",
|
MXS_INFO("Removed command %s from fd %d.",
|
||||||
@ -788,8 +776,6 @@ void protocol_remove_srv_command(MySQLProtocol* p)
|
|||||||
p->protocol_command = *(s->scom_next);
|
p->protocol_command = *(s->scom_next);
|
||||||
MXS_FREE(s->scom_next);
|
MXS_FREE(s->scom_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&p->protocol_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mysql_server_cmd_t protocol_get_srv_command(MySQLProtocol* p,
|
mysql_server_cmd_t protocol_get_srv_command(MySQLProtocol* p,
|
||||||
@ -889,10 +875,8 @@ bool protocol_get_response_status(MySQLProtocol* p,
|
|||||||
|
|
||||||
CHK_PROTOCOL(p);
|
CHK_PROTOCOL(p);
|
||||||
|
|
||||||
spinlock_acquire(&p->protocol_lock);
|
|
||||||
*npackets = p->protocol_command.scom_nresponse_packets;
|
*npackets = p->protocol_command.scom_nresponse_packets;
|
||||||
*nbytes = (ssize_t)p->protocol_command.scom_nbytes_to_read;
|
*nbytes = (ssize_t)p->protocol_command.scom_nbytes_to_read;
|
||||||
spinlock_release(&p->protocol_lock);
|
|
||||||
|
|
||||||
if (*npackets < 0 && *nbytes == 0)
|
if (*npackets < 0 && *nbytes == 0)
|
||||||
{
|
{
|
||||||
@ -912,14 +896,10 @@ void protocol_set_response_status(MySQLProtocol* p,
|
|||||||
{
|
{
|
||||||
CHK_PROTOCOL(p);
|
CHK_PROTOCOL(p);
|
||||||
|
|
||||||
spinlock_acquire(&p->protocol_lock);
|
|
||||||
|
|
||||||
p->protocol_command.scom_nbytes_to_read = nbytes;
|
p->protocol_command.scom_nbytes_to_read = nbytes;
|
||||||
ss_dassert(p->protocol_command.scom_nbytes_to_read >= 0);
|
ss_dassert(p->protocol_command.scom_nbytes_to_read >= 0);
|
||||||
|
|
||||||
p->protocol_command.scom_nresponse_packets = npackets_left;
|
p->protocol_command.scom_nresponse_packets = npackets_left;
|
||||||
|
|
||||||
spinlock_release(&p->protocol_lock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char* create_auth_failed_msg(GWBUF*readbuf,
|
char* create_auth_failed_msg(GWBUF*readbuf,
|
||||||
|
@ -291,20 +291,15 @@ static void handleError(MXS_ROUTER *instance,
|
|||||||
{
|
{
|
||||||
backend_dcb->dcb_errhandle_called = true;
|
backend_dcb->dcb_errhandle_called = true;
|
||||||
}
|
}
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
sesstate = session->state;
|
sesstate = session->state;
|
||||||
client_dcb = session->client_dcb;
|
client_dcb = session->client_dcb;
|
||||||
|
|
||||||
if (sesstate == SESSION_STATE_ROUTER_READY)
|
if (sesstate == SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
CHK_DCB(client_dcb);
|
CHK_DCB(client_dcb);
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
client_dcb->func.write(client_dcb, gwbuf_clone(errbuf));
|
client_dcb->func.write(client_dcb, gwbuf_clone(errbuf));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** false because connection is not available anymore */
|
/** false because connection is not available anymore */
|
||||||
dcb_close(backend_dcb);
|
dcb_close(backend_dcb);
|
||||||
|
@ -82,7 +82,6 @@
|
|||||||
#include <maxscale/atomic.h>
|
#include <maxscale/atomic.h>
|
||||||
#include <maxscale/spinlock.h>
|
#include <maxscale/spinlock.h>
|
||||||
#include <maxscale/dcb.h>
|
#include <maxscale/dcb.h>
|
||||||
#include <maxscale/spinlock.h>
|
|
||||||
#include <maxscale/modinfo.h>
|
#include <maxscale/modinfo.h>
|
||||||
#include <maxscale/log_manager.h>
|
#include <maxscale/log_manager.h>
|
||||||
#include <maxscale/protocol/mysql.h>
|
#include <maxscale/protocol/mysql.h>
|
||||||
@ -105,9 +104,6 @@ static void rses_end_locked_router_action(ROUTER_CLIENT_SES* rses);
|
|||||||
static SERVER_REF *get_root_master(SERVER_REF *servers);
|
static SERVER_REF *get_root_master(SERVER_REF *servers);
|
||||||
static int handle_state_switch(DCB* dcb, DCB_REASON reason, void * routersession);
|
static int handle_state_switch(DCB* dcb, DCB_REASON reason, void * routersession);
|
||||||
|
|
||||||
static SPINLOCK instlock;
|
|
||||||
static ROUTER_INSTANCE *instances;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The module entry point routine. It is this routine that
|
* The module entry point routine. It is this routine that
|
||||||
* must populate the structure that is referred to as the
|
* must populate the structure that is referred to as the
|
||||||
@ -119,8 +115,6 @@ static ROUTER_INSTANCE *instances;
|
|||||||
MXS_MODULE* MXS_CREATE_MODULE()
|
MXS_MODULE* MXS_CREATE_MODULE()
|
||||||
{
|
{
|
||||||
MXS_NOTICE("Initialise readconnroute router module.");
|
MXS_NOTICE("Initialise readconnroute router module.");
|
||||||
spinlock_init(&instlock);
|
|
||||||
instances = NULL;
|
|
||||||
|
|
||||||
static MXS_ROUTER_OBJECT MyObject =
|
static MXS_ROUTER_OBJECT MyObject =
|
||||||
{
|
{
|
||||||
@ -252,10 +246,6 @@ createInstance(SERVICE *service, char **options)
|
|||||||
* insert this router instance into the linked list of routers
|
* insert this router instance into the linked list of routers
|
||||||
* that have been created with this module.
|
* that have been created with this module.
|
||||||
*/
|
*/
|
||||||
spinlock_acquire(&instlock);
|
|
||||||
inst->next = instances;
|
|
||||||
instances = inst;
|
|
||||||
spinlock_release(&instlock);
|
|
||||||
|
|
||||||
return (MXS_ROUTER *) inst;
|
return (MXS_ROUTER *) inst;
|
||||||
}
|
}
|
||||||
@ -710,20 +700,16 @@ static void handleError(MXS_ROUTER *instance, void *router_session, GWBUF *errbu
|
|||||||
{
|
{
|
||||||
problem_dcb->dcb_errhandle_called = true;
|
problem_dcb->dcb_errhandle_called = true;
|
||||||
}
|
}
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
sesstate = session->state;
|
sesstate = session->state;
|
||||||
client_dcb = session->client_dcb;
|
client_dcb = session->client_dcb;
|
||||||
|
|
||||||
if (sesstate == SESSION_STATE_ROUTER_READY)
|
if (sesstate == SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
CHK_DCB(client_dcb);
|
CHK_DCB(client_dcb);
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
client_dcb->func.write(client_dcb, gwbuf_clone(errbuf));
|
client_dcb->func.write(client_dcb, gwbuf_clone(errbuf));
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DCB_ROLE_CLIENT_HANDLER == problem_dcb->dcb_role)
|
if (DCB_ROLE_CLIENT_HANDLER == problem_dcb->dcb_role)
|
||||||
{
|
{
|
||||||
|
@ -1535,10 +1535,8 @@ static void handle_error_reply_client(MXS_SESSION *ses, ROUTER_CLIENT_SES *rses,
|
|||||||
DCB *client_dcb;
|
DCB *client_dcb;
|
||||||
backend_ref_t *bref;
|
backend_ref_t *bref;
|
||||||
|
|
||||||
spinlock_acquire(&ses->ses_lock);
|
|
||||||
sesstate = ses->state;
|
sesstate = ses->state;
|
||||||
client_dcb = ses->client_dcb;
|
client_dcb = ses->client_dcb;
|
||||||
spinlock_release(&ses->ses_lock);
|
|
||||||
|
|
||||||
if ((bref = get_bref_from_dcb(rses, backend_dcb)) != NULL)
|
if ((bref = get_bref_from_dcb(rses, backend_dcb)) != NULL)
|
||||||
{
|
{
|
||||||
|
@ -860,8 +860,6 @@ static void* newSession(MXS_ROUTER* router_inst, MXS_SESSION* session)
|
|||||||
bool using_db = false;
|
bool using_db = false;
|
||||||
bool have_db = false;
|
bool have_db = false;
|
||||||
|
|
||||||
spinlock_acquire(&session->ses_lock);
|
|
||||||
|
|
||||||
/* To enable connecting directly to a sharded database we first need
|
/* To enable connecting directly to a sharded database we first need
|
||||||
* to disable it for the client DCB's protocol so that we can connect to them*/
|
* to disable it for the client DCB's protocol so that we can connect to them*/
|
||||||
if (protocol->client_capabilities & GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB &&
|
if (protocol->client_capabilities & GW_MYSQL_CAPABILITIES_CONNECT_WITH_DB &&
|
||||||
@ -880,8 +878,6 @@ static void* newSession(MXS_ROUTER* router_inst, MXS_SESSION* session)
|
|||||||
MXS_INFO("Client'%s' connecting with empty database.", data->user);
|
MXS_INFO("Client'%s' connecting with empty database.", data->user);
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
|
|
||||||
client_rses = (ROUTER_CLIENT_SES *)MXS_CALLOC(1, sizeof(ROUTER_CLIENT_SES));
|
client_rses = (ROUTER_CLIENT_SES *)MXS_CALLOC(1, sizeof(ROUTER_CLIENT_SES));
|
||||||
|
|
||||||
if (client_rses == NULL)
|
if (client_rses == NULL)
|
||||||
@ -3647,10 +3643,8 @@ static void handle_error_reply_client(MXS_SESSION* ses,
|
|||||||
DCB* client_dcb;
|
DCB* client_dcb;
|
||||||
backend_ref_t* bref;
|
backend_ref_t* bref;
|
||||||
|
|
||||||
spinlock_acquire(&ses->ses_lock);
|
|
||||||
sesstate = ses->state;
|
sesstate = ses->state;
|
||||||
client_dcb = ses->client_dcb;
|
client_dcb = ses->client_dcb;
|
||||||
spinlock_release(&ses->ses_lock);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If bref exists, mark it closed
|
* If bref exists, mark it closed
|
||||||
|
Reference in New Issue
Block a user