Merge branch 'release-1.3.0' into develop

This commit is contained in:
Markus Makela 2016-02-11 10:15:36 +02:00
commit cfefc046e9
15 changed files with 352 additions and 373 deletions

View File

@ -27,8 +27,6 @@
## Reference
- [MaxAdmin](Reference/MaxAdmin.md)
- [MaxScale HA with Corosync-Pacemaker](Reference/MaxScale-HA-with-Corosync-Pacemaker.md)
- [MaxScale HA with Lsyncd](Reference/MaxScale-HA-with-lsyncd.md)
- [How Errors are Handled in MaxScale](Reference/How-errors-are-handled-in-MaxScale.md)
- [Debug and Diagnostic Support](Reference/Debug-And-Diagnostic-Support.md)
- [Routing Hints](Reference/Hint-Syntax.md)
@ -48,9 +46,14 @@ These tutorials are for specific use cases and module combinations.
- [Replication Proxy with the Binlog Router Tutorial](Tutorials/Replication-Proxy-Binlog-Router-Tutorial.md)
- [RabbitMQ Setup and MaxScale Integration Tutorial](Tutorials/RabbitMQ-Setup-And-MaxScale-Integration.md)
- [RabbitMQ and Tee Filter Data Archiving Tutorial](Tutorials/RabbitMQ-And-Tee-Archiving.md)
- [Nagios Plugins for MaxScale Tutorial](Tutorials/Nagios-Plugins.md)
- [Simple Schema Sharding Tutorial](Tutorials/Simple-Sharding-Tutorial.md)
Here are tutorials on monitoring and managing MaxScale in cluster envoronments.
- [Nagios Plugins for MaxScale Tutorial](Tutorials/Nagios-Plugins.md)
- [MaxScale HA with Corosync-Pacemaker](Tutorials/MaxScale-HA-with-Corosync-Pacemaker.md)
- [MaxScale HA with Lsyncd](Tutorials/MaxScale-HA-with-lsyncd.md)
## Routers
The routing module is the core of a MaxScale service. The router documentation

View File

@ -771,6 +771,8 @@ and short notations
192.%.%
192.168.%
Note that currently wildcards are only supported in conjunction with IP-addresses, not with domain names.
## Error Reporting
MaxScale is designed to be executed as a service, therefore all error reports, including configuration errors, are written to the MaxScale error log file. By default, MaxScale will log to a file in `/var/log/maxscale`, the only exception to this is if the log directory is not writable, in which case a message is sent to the standard error descriptor.

View File

@ -3,11 +3,7 @@
This document describes the changes in release 1.3, when compared to
release 1.2.1.
## 1.3.0 Beta
**NOTE** This is a beta release. We think it is better than 1.2.1,
but there may still be rough edges. Keep that in mind when trying it
out.
## 1.3.0
For any problems you encounter, please consider submitting a bug
report at [Jira](https://mariadb.atlassian.net).
@ -149,85 +145,94 @@ details, please read the [Monitor Common](../Monitors/Monitor-Common.md) documen
## Bug fixes
Here is a list of bugs fixed since the release of MaxScale 1.2.1.
[Here is a list of bugs fixed since the release of MaxScale 1.2.1.](https://mariadb.atlassian.net/browse/MXS-550?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20resolution%20in%20(Fixed%2C%20Done)%20AND%20fixVersion%20%3D%201.3.0)
* [MXS-414](https://mariadb.atlassian.net/browse/MXS-414): Maxscale crashed every day!
* [MXS-415](https://mariadb.atlassian.net/browse/MXS-415): MaxScale 1.2.1 crashed with Signal 6 and 11
* [MXS-351](https://mariadb.atlassian.net/browse/MXS-351): Router error handling can cause crash by leaving dangling DCB pointer
* [MXS-428](https://mariadb.atlassian.net/browse/MXS-428): Maxscale crashes at startup.
* [MXS-376](https://mariadb.atlassian.net/browse/MXS-376): MaxScale terminates with SIGABRT.
* [MXS-269](https://mariadb.atlassian.net/browse/MXS-269): Crash in MySQL backend protocol
* [MXS-500](https://mariadb.atlassian.net/browse/MXS-500): Tee filter hangs when statement aren't duplicated.
* [MXS-447](https://mariadb.atlassian.net/browse/MXS-447): Monitors are started before they have been fully configured
* [MXS-417](https://mariadb.atlassian.net/browse/MXS-417): Single character wildcard doesn't work in MaxScale
* [MXS-409](https://mariadb.atlassian.net/browse/MXS-409): prepare should not hit all servers
* [MXS-405](https://mariadb.atlassian.net/browse/MXS-405): Maxscale bin router crash
* [MXS-412](https://mariadb.atlassian.net/browse/MXS-412): show dbusers segmentation fault
* [MXS-289](https://mariadb.atlassian.net/browse/MXS-289): Corrupted memory or empty value are in Master_host field of SHOW SLAVE STATUS when master connection is broken
* [MXS-283](https://mariadb.atlassian.net/browse/MXS-283): SSL connections leak memory
* [MXS-54](https://mariadb.atlassian.net/browse/MXS-54): Write failed auth attempt to trace log
* [MXS-501](https://mariadb.atlassian.net/browse/MXS-501): Use<db> hangs when Tee filter uses matching
* [MXS-559](https://mariadb.atlassian.net/browse/MXS-559): Crash due to debug assertion in readwritesplit
* [MXS-551](https://mariadb.atlassian.net/browse/MXS-551): Maxscale BETA 1.3.0 running as root
* [MXS-548](https://mariadb.atlassian.net/browse/MXS-548): Maxscale 1.2.1 crash on Ubuntu 4.04.3 x86_64
* [MXS-508](https://mariadb.atlassian.net/browse/MXS-508): regex filter ignores username
* [MXS-505](https://mariadb.atlassian.net/browse/MXS-505): if Maxscale fails to start it goes to infinite "try-to-start and fail" loop
* [MXS-501](https://mariadb.atlassian.net/browse/MXS-501): USE <db> hangs when Tee filter uses matching
* [MXS-500](https://mariadb.atlassian.net/browse/MXS-500): Tee filter hangs when statements aren't duplicated.
* [MXS-499](https://mariadb.atlassian.net/browse/MXS-499): Init script error on Debian Wheezy
* [MXS-323](https://mariadb.atlassian.net/browse/MXS-323): mysql_client readwritesplit handleError seems using wrong dcb and cause wrong behavior
* [MXS-494](https://mariadb.atlassian.net/browse/MXS-494): Weight calculation favors servers without connections
* [MXS-493](https://mariadb.atlassian.net/browse/MXS-493): SIGFPE when weightby parameter is 0 and using LEAST_GLOBAL_CONNECTIONS
* [MXS-492](https://mariadb.atlassian.net/browse/MXS-492): Segfault if server is missing weighting parameter
* [MXS-360](https://mariadb.atlassian.net/browse/MXS-360): Persistent connections: maxadmin reports 0 all the time even if connections are created
* [MXS-429](https://mariadb.atlassian.net/browse/MXS-429): Binlog Router crashes due to segmentation fault with no meaningful error if no listener is configured
* [MXS-416](https://mariadb.atlassian.net/browse/MXS-416): Orphan sessions appear after many network errors
* [MXS-472](https://mariadb.atlassian.net/browse/MXS-472): Monitors update status in multiple steps
* [MXS-361](https://mariadb.atlassian.net/browse/MXS-361): crash on backend restart if persistent connections are in use
* [MXS-403](https://mariadb.atlassian.net/browse/MXS-403): Monitor callback to DCBs evades thread control causing crashes
* [MXS-392](https://mariadb.atlassian.net/browse/MXS-392): Update to "Rabbit MQ setup and MaxScale Integration" document
* [MXS-491](https://mariadb.atlassian.net/browse/MXS-491): MaxScale can time out systemd if startup of services takes too long
* [MXS-329](https://mariadb.atlassian.net/browse/MXS-329): The session pointer in a DCB can be null unexpectedly
* [MXS-479](https://mariadb.atlassian.net/browse/MXS-479): localtime must not be used in the multi-threaded program.
* [MXS-480](https://mariadb.atlassian.net/browse/MXS-480): Readwritesplit defaults cause connection pileup
* [MXS-479](https://mariadb.atlassian.net/browse/MXS-479): localtime must not be used in the multi-threaded program.
* [MXS-472](https://mariadb.atlassian.net/browse/MXS-472): Monitors update status in multiple steps
* [MXS-464](https://mariadb.atlassian.net/browse/MXS-464): Upgrade 1.2.0 to 1.2.1 blocking start of `maxscale` service
* [MXS-365](https://mariadb.atlassian.net/browse/MXS-365): Load data local infile connection abort when loading certain files
* [MXS-450](https://mariadb.atlassian.net/browse/MXS-450): Syslog default prefix is MaxScale not maxscale
* [MXS-447](https://mariadb.atlassian.net/browse/MXS-447): Monitors are started before they have been fully configured
* [MXS-436](https://mariadb.atlassian.net/browse/MXS-436): Invalid threads argument is ignored and MaxScale starts with one thread
* [MXS-431](https://mariadb.atlassian.net/browse/MXS-431): Backend authentication fails with schemarouter
* [MXS-394](https://mariadb.atlassian.net/browse/MXS-394): Faults in regex_replace function of regexfilter.c
* [MXS-379](https://mariadb.atlassian.net/browse/MXS-379): Incorrect handing of a GWBUF may cause SIGABRT.
* [MXS-321](https://mariadb.atlassian.net/browse/MXS-321): Incorrect number of connections in maxadmin list view
* [MXS-429](https://mariadb.atlassian.net/browse/MXS-429): Binlog Router crashes due to segmentation fault with no meaningful error if no listener is configured
* [MXS-428](https://mariadb.atlassian.net/browse/MXS-428): Maxscale crashes at startup.
* [MXS-427](https://mariadb.atlassian.net/browse/MXS-427): Logging a large string causes a segmentation fault
* [MXS-417](https://mariadb.atlassian.net/browse/MXS-417): Single character wildcard doesn't work in MaxScale
* [MXS-416](https://mariadb.atlassian.net/browse/MXS-416): Orphan sessions appear after many network errors
* [MXS-415](https://mariadb.atlassian.net/browse/MXS-415): MaxScale 1.2.1 crashed with Signal 6 and 11
* [MXS-414](https://mariadb.atlassian.net/browse/MXS-414): Maxscale crashed every day!
* [MXS-413](https://mariadb.atlassian.net/browse/MXS-413): MaxAdmin hangs with show session
* [MXS-412](https://mariadb.atlassian.net/browse/MXS-412): show dbusers segmentation fault
* [MXS-409](https://mariadb.atlassian.net/browse/MXS-409): prepare should not hit all servers
* [MXS-408](https://mariadb.atlassian.net/browse/MXS-408): Connections to backend databases do not clear promptly
* [MXS-385](https://mariadb.atlassian.net/browse/MXS-385): disable_sescmd_history can cause false data to be read.
* [MXS-407](https://mariadb.atlassian.net/browse/MXS-407): Maxscale binlogrouter binlog names are unncessarily length-limited
* [MXS-405](https://mariadb.atlassian.net/browse/MXS-405): Maxscale bin router crash
* [MXS-403](https://mariadb.atlassian.net/browse/MXS-403): Monitor callback to DCBs evades thread control causing crashes
* [MXS-394](https://mariadb.atlassian.net/browse/MXS-394): Faults in regex_replace function of regexfilter.c
* [MXS-392](https://mariadb.atlassian.net/browse/MXS-392): Update to "Rabbit MQ setup and MaxScale Integration" document
* [MXS-386](https://mariadb.atlassian.net/browse/MXS-386): max_sescmd_history should not close connections
* [MXS-385](https://mariadb.atlassian.net/browse/MXS-385): disable_sescmd_history can cause false data to be read.
* [MXS-379](https://mariadb.atlassian.net/browse/MXS-379): Incorrect handing of a GWBUF may cause SIGABRT.
* [MXS-376](https://mariadb.atlassian.net/browse/MXS-376): MaxScale terminates with SIGABRT.
* [MXS-373](https://mariadb.atlassian.net/browse/MXS-373): If config file is non-existent, maxscale crashes.
* [MXS-366](https://mariadb.atlassian.net/browse/MXS-366): Multi-source slave servers are not detected.
* [MXS-271](https://mariadb.atlassian.net/browse/MXS-271): Schemarouter and unknown databases
* [MXS-365](https://mariadb.atlassian.net/browse/MXS-365): Load data local infile connection abort when loading certain files
* [MXS-363](https://mariadb.atlassian.net/browse/MXS-363): rpm building seems to do something wrong with maxscale libraries
* [MXS-361](https://mariadb.atlassian.net/browse/MXS-361): crash on backend restart if persistent connections are in use
* [MXS-360](https://mariadb.atlassian.net/browse/MXS-360): Persistent connections: maxadmin reports 0 all the time even if connections are created
* [MXS-358](https://mariadb.atlassian.net/browse/MXS-358): Crash, Error in `/usr/bin/maxscale': free(): invalid next size (fast)
* [MXS-352](https://mariadb.atlassian.net/browse/MXS-352): With no backend connection, services aren't started
* [MXS-351](https://mariadb.atlassian.net/browse/MXS-351): Router error handling can cause crash by leaving dangling DCB pointer
* [MXS-345](https://mariadb.atlassian.net/browse/MXS-345): maxscale.conf in /etc/init.d prevents puppet from starting maxscale
* [MXS-342](https://mariadb.atlassian.net/browse/MXS-342): When ini_parse fails to parse config file, no log messages are printed.
* [MXS-333](https://mariadb.atlassian.net/browse/MXS-333): use_sql_variables_in=master doesn't work
* [MXS-329](https://mariadb.atlassian.net/browse/MXS-329): The session pointer in a DCB can be null unexpectedly
* [MXS-323](https://mariadb.atlassian.net/browse/MXS-323): mysql_client readwritesplit handleError seems using wrong dcb and cause wrong behavior
* [MXS-321](https://mariadb.atlassian.net/browse/MXS-321): Incorrect number of connections in maxadmin list view
* [MXS-310](https://mariadb.atlassian.net/browse/MXS-310): MaxScale 1.2 does not completely cleanly change to the maxscale user
* [MXS-297](https://mariadb.atlassian.net/browse/MXS-297): postinstall on debian copies wrong file in /etc/init.d
* [MXS-293](https://mariadb.atlassian.net/browse/MXS-293): Bug in init script, and maxscale --user=maxscale does run as root
* [MXS-291](https://mariadb.atlassian.net/browse/MXS-291): Random number generation has flaws
* [MXS-289](https://mariadb.atlassian.net/browse/MXS-289): Corrupted memory or empty value are in Master_host field of SHOW SLAVE STATUS when master connection is broken
* [MXS-286](https://mariadb.atlassian.net/browse/MXS-286): Fix the content and format of MaxScale-HA-with-Corosync-Pacemaker document
* [MXS-283](https://mariadb.atlassian.net/browse/MXS-283): SSL connections leak memory
* [MXS-282](https://mariadb.atlassian.net/browse/MXS-282): Add example to "Routing Hints" document
* [MXS-281](https://mariadb.atlassian.net/browse/MXS-281): SELECT INTO OUTFILE query goes several times to one slave
* [MXS-280](https://mariadb.atlassian.net/browse/MXS-280): SELECT INTO OUTFILE query succeeds even if backed fails
* [MXS-276](https://mariadb.atlassian.net/browse/MXS-276): Memory leak of buffer in connection router readQuery
* [MXS-274](https://mariadb.atlassian.net/browse/MXS-274): Memory Leak
* [MXS-271](https://mariadb.atlassian.net/browse/MXS-271): Schemarouter and unknown databases
* [MXS-269](https://mariadb.atlassian.net/browse/MXS-269): Crash in MySQL backend protocol
* [MXS-260](https://mariadb.atlassian.net/browse/MXS-260): Multiple MaxScale processes
* [MXS-258](https://mariadb.atlassian.net/browse/MXS-258): ERR_error_string could overflow in future
* [MXS-254](https://mariadb.atlassian.net/browse/MXS-254): Failure to read configuration file results in no error log messages
* [MXS-251](https://mariadb.atlassian.net/browse/MXS-251): Non-thread safe strerror
* [MXS-291](https://mariadb.atlassian.net/browse/MXS-291): Random number generation has flaws
* [MXS-342](https://mariadb.atlassian.net/browse/MXS-342): When ini_parse fails to parse config file, no log messages are printed.
* [MXS-345](https://mariadb.atlassian.net/browse/MXS-345): maxscale.conf in /etc/init.d prevents puppet from starting maxscale
* [MXS-333](https://mariadb.atlassian.net/browse/MXS-333): use_sql_variables_in=master doesn't work
* [MXS-260](https://mariadb.atlassian.net/browse/MXS-260): Multiple MaxScale processes
* [MXS-184](https://mariadb.atlassian.net/browse/MXS-184): init script issues in CentOS 7
* [MXS-280](https://mariadb.atlassian.net/browse/MXS-280): SELECT INTO OUTFILE query succeeds even if backed fails
* [MXS-202](https://mariadb.atlassian.net/browse/MXS-202): User password not handled correctly
* [MXS-282](https://mariadb.atlassian.net/browse/MXS-282): Add example to "Routing Hints" document
* [MXS-220](https://mariadb.atlassian.net/browse/MXS-220): LAST_INSERT_ID() query is redirect to slave if function call is in where clause
* [MXS-196](https://mariadb.atlassian.net/browse/MXS-196): DCB state is changed prior to polling operation
* [MXS-281](https://mariadb.atlassian.net/browse/MXS-281): SELECT INTO OUTFILE query goes several times to one slave
* [MXS-210](https://mariadb.atlassian.net/browse/MXS-210): Check MaxScale user privileges
* [MXS-202](https://mariadb.atlassian.net/browse/MXS-202): User password not handled correctly
* [MXS-197](https://mariadb.atlassian.net/browse/MXS-197): Incorrect sequence of operations with DCB
* [MXS-196](https://mariadb.atlassian.net/browse/MXS-196): DCB state is changed prior to polling operation
* [MXS-195](https://mariadb.atlassian.net/browse/MXS-195): maxscaled.c ineffective DCB disposal
* [MXS-363](https://mariadb.atlassian.net/browse/MXS-363): rpm building seems to do something wrong with maxscale libraries
* [MXS-184](https://mariadb.atlassian.net/browse/MXS-184): init script issues in CentOS 7
* [MXS-183](https://mariadb.atlassian.net/browse/MXS-183): MaxScale crash after 'reload config'
* [MXS-111](https://mariadb.atlassian.net/browse/MXS-111): maxscale binlog events shown in show services seems to be double-counted for the master connection
* [MXS-54](https://mariadb.atlassian.net/browse/MXS-54): Write failed auth attempt to trace log
* [MXS-35](https://mariadb.atlassian.net/browse/MXS-35): bugzillaId-451: maxscale main() exit code is always 0 after it daemonizes
* [MXS-29](https://mariadb.atlassian.net/browse/MXS-29): bugzillaId-589: detect if MAXSCALE_SCHEMA.HEARTBEAT table is not replicated
* [MXS-436](https://mariadb.atlassian.net/browse/MXS-436): Invalid threads argument is ignored and MaxScale starts with one thread
* [MXS-427](https://mariadb.atlassian.net/browse/MXS-427): Logging a large string causes a segmentation fault
* [MXS-352](https://mariadb.atlassian.net/browse/MXS-352): With no backend connection, services aren't started
* [MXS-293](https://mariadb.atlassian.net/browse/MXS-293): Bug in init script, and maxscale --user=maxscale does run as root
* [MXS-210](https://mariadb.atlassian.net/browse/MXS-210): Check MaxScale user privileges
* [MXS-111](https://mariadb.atlassian.net/browse/MXS-111): maxscale binlog events shown in show services seems to be double-counted for the master connection
* [MXS-3](https://mariadb.atlassian.net/browse/MXS-3): Remove code for atomic_add in skygw_utils.cc
* [MXS-258](https://mariadb.atlassian.net/browse/MXS-258): ERR_error_string could overflow in future
* [MXS-310](https://mariadb.atlassian.net/browse/MXS-310): MaxScale 1.2 does not completely cleanly change to the maxscale user
* [MXS-450](https://mariadb.atlassian.net/browse/MXS-450): Syslog default prefix is MaxScale not maxscale
* [MXS-297](https://mariadb.atlassian.net/browse/MXS-297): postinstall on debian copies wrong file in /etc/init.d
## Known Issues and Limitations

View File

@ -77,6 +77,14 @@ When value all is used, queries reading session variables can be routed to any a
In above-mentioned case the user-defined variable would only be updated in the master where query would be routed due to `INSERT` statement.
### `weightby`
This parameter defines the name of the value which is used to calculate the
weights of the servers. The value should be the name of a parameter in the
server definitions and it should exist in all the servers used by this router.
For more information, see the description of the `weightby` parameter in
the [Configuration Guide](../Getting-Started/Configuration-Guide.md).
## Router options
**`router_options`** may include multiple **readwritesplit**-specific options. All the options are parameter-value pairs. All parameters listed in this section must be configured as a value in `router_options`.
@ -135,14 +143,6 @@ disable_sescmd_history=true
master_accept_reads=true
```
### `weightby`
This parameter defines the name of the value which is used to calculate the
weights of the servers. The value should be the name of a parameter in the
server definitions and it should exist in all the servers used by this router.
For more information, see the description of the `weightby` parameter in
the [Configuration Guide](../Getting-Started/Configuration-Guide.md).
## Routing hints
The readwritesplit router supports routing hints. For a detailed guide on hint syntax and functionality, please read [this](../Reference/Hint-Syntax.md) document.

View File

@ -33,7 +33,7 @@ Switch|Long Option|Description
------|-----------|-----------
`-d`|`--nodaemon`|enable running in terminal process (default:disabled)
`-f FILE`|`--config=FILE`|relative or absolute pathname of MaxScale configuration file (default:/etc/maxscale.cnf)
`-l[file shm]`|`--log=[file shm]`|log to file or shared memory (default: shm)
`-l[file shm]`|`--log=[file shm]`|log to file or shared memory (default: file)
`-L PATH`|`--logdir=PATH`|path to log file directory (default: /var/log/maxscale)
`-D PATH`|`--datadir=PATH`|path to data directory, stored embedded mysql tables (default: /var/cache/maxscale)
`-C PATH`|`--configdir=PATH`|path to configuration file directory (default: /etc/)
@ -42,7 +42,7 @@ Switch|Long Option|Description
`P PATH`|`--piddir=PATH`|PID file directory
`-U USER`|`--user=USER`|run MaxScale as another user. The user ID and group ID of this user are used to run MaxScale.
`-s [yes no]`|`--syslog=[yes no]`|log messages to syslog (default:yes)
`-S [yes no]`|`--maxscalelog=[yes no]`|log messages to MaxScale log (default: yes)
`-S [yes no]`|`--maxlog=[yes no]`|log messages to MaxScale log (default: yes)
`-G [0 1]`|`--log_augmentation=[0 1]`|augment messages with the name of the function where the message was logged (default: 0). Primarily for development purposes.
`-v`|`--version`|print version info and exit
`-V`|`--version-full`|print version info and the commit ID the binary was built from

View File

@ -79,7 +79,7 @@ On one of the nodes, say node2 run the corosync-keygen utility and follow
```
[root@node2 ~]# corosync-keygen
Corosync Cluster Engine Authentication key generator. Gathering 1024 bits for key from /dev/random. Press keys on your keyboard to generate entropy.
Corosync Cluster Engine Authentication key generator. Gathering 1024 bits for key from /dev/random. Press keys on your keyboard to generate entropy.
After completion the key will be found in /etc/corosync/authkey.
```
@ -141,7 +141,7 @@ name: pacemaker
}
```
**Please note **in this example:
**Please note** in this example:
- unicast UDP is used

View File

@ -24,7 +24,7 @@ Run MaxScale in the terminal process
Relative or absolute pathname of MaxScale configuration file to load.
.TP
.BR -l "[\fIfile|shm\fB], --log=[\fIfile|shm\fB]"
Log trace and debug logs to file or shared memory. The debug and trace logs are disabled by default and if enabled, will log to shared memory.
Log to file or shared memory. The default is to log to file.
.TP
.BR -L " \fIPATH\fB, --logdir=\fIPATH\fB"
Path to log file directory.
@ -50,7 +50,7 @@ Run MaxScale as another user. The user ID and group ID of this user are used to
.BR -s " [\fIyes\fB|\fIno\fB], --syslog=[\fIyes\fB|\fIno\fB]"
Log messages to syslog.
.TP
.BR -S " [\fIyes\fB|\fIno\fB], \fB--maxscalelog=[\fIyes\fB|\fIno\fB]"
.BR -S " [\fIyes\fB|\fIno\fB], \fB--maxlog=[\fIyes\fB|\fIno\fB]"
Log messages to MaxScale's own log files.
.TP
.BR "-v, --version"
@ -61,12 +61,27 @@ Print full version information including the Git commit the binary was built fro
.TP
.BR "-?, --help"
Show the help information for MaxScale and exit.
.SH EXAMPLES
Tutorials on GitHub:
.UR https://github.com/mariadb-corporation/MaxScale/blob/master/Documentation/Documentation-Contents.md#tutorials
.UE
.RS
.I https://github.com/mariadb-corporation/MaxScale/blob/master/Documentation/Documentation-Contents.md#tutorials
.RE
.SH SEE ALSO
The MaxScale documentation on the MariaDB Knowledge Base:
.RS
.I https://mariadb.com/kb/en/mariadb-enterprise/mariadb-maxscale/
.RE
The MaxScale documentation on GitHub:
.UR https://github.com/mariadb-corporation/MaxScale/blob/master/Documentation/Documentation-Contents.md
.UE
.RS
.I https://github.com/mariadb-corporation/MaxScale/blob/master/Documentation/Documentation-Contents.md
.RE
.SH BUGS
You can see a list of known bugs and report new bugs at:
.RS
.I https://mariadb.atlassian.net/browse/MXS
.RE

View File

@ -12,7 +12,7 @@ macro(set_maxscale_version)
set(MAXSCALE_VERSION_MINOR "3" CACHE STRING "Minor version")
set(MAXSCALE_VERSION_PATCH "0" CACHE STRING "Patch version")
set(MAXSCALE_VERSION_NUMERIC "${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}")
set(MAXSCALE_VERSION "beta-${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}")
set(MAXSCALE_VERSION "${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}")
# This should be incremented each time a package is rebuilt
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")

View File

@ -48,7 +48,7 @@ _RETVAL_STATUS_NOT_RUNNING=3
#################################
NAME=maxscale
DAEMON=@CMAKE_INSTALL_PREFIX@/@MAXSCALE_BINDIR@/maxscale
DAEMON_OPTS='"--user=maxscale" "$MAXSCALE_OPTIONS"'
DAEMON_OPTS="--user=maxscale $MAXSCALE_OPTIONS"
# Source function library.
. /lib/lsb/init-functions
@ -91,7 +91,7 @@ start() {
chmod 0755 @MAXSCALE_VARDIR@/run/maxscale
log_daemon_msg "Starting MaxScale"
start_daemon -p "$MAXSCALE_PIDFILE" "$DAEMON" "$DAEMON_OPTS" 2> /dev/null > /dev/null
start_daemon -p "$MAXSCALE_PIDFILE" $DAEMON $DAEMON_OPTS 2> /dev/null > /dev/null
sleep 2

View File

@ -930,27 +930,24 @@ static void usage(void)
fprintf(stderr,
"\nUsage : %s [OPTION]...\n\n"
" -d, --nodaemon enable running in terminal process (default:disabled)\n"
" -f, --config=FILE relative|absolute pathname of MaxScale configuration file\n"
" -f, --config=FILE relative or absolute pathname of MaxScale configuration file\n"
" (default:/etc/maxscale.cnf)\n"
" -l, --log=[file|shm] log to file or shared memory (default: shm)\n"
" -L, --logdir=PATH path to log file directory\n"
" (default: /var/log/maxscale)\n"
" -A, --cachedir=PATH path to cache directory\n"
" (default: /var/cache/maxscale)\n"
" -B, --libdir=PATH path to module directory\n"
" (default: /usr/lib64/maxscale)\n"
" -C, --configdir=PATH path to configuration file directory\n"
" (default: /etc/)\n"
" -l, --log=[file|shm] log to file or shared memory (default: file)\n"
" -L, --logdir=PATH path to log file directory (default: /var/log/maxscale)\n"
" -A, --cachedir=PATH path to cache directory (default: /var/cache/maxscale)\n"
" -B, --libdir=PATH path to module directory (default: /usr/lib64/maxscale)\n"
" -C, --configdir=PATH path to configuration file directory (default: /etc/)\n"
" -D, --datadir=PATH path to data directory, stored embedded mysql tables\n"
" (default: /var/cache/maxscale)\n"
" -N, --language=PATH path to errmsg.sys file\n"
" (default: /var/lib/maxscale)\n"
" -P, --piddir=PATH path to PID file directory\n"
" (default: /var/run/maxscale)\n"
" -N, --language=PATH path to errmsg.sys file (default: /var/lib/maxscale)\n"
" -P, --piddir=PATH path to PID file directory (default: /var/run/maxscale)\n"
" -U, --user=USER run MaxScale as another user.\n"
" The user ID and group ID of this user are used to run MaxScale.\n"
" -s, --syslog=[yes|no] log messages to syslog (default:yes)\n"
" -S, --maxlog=[yes|no] log messages to MaxScale log (default: yes)\n"
" -G, --log_augmentation=0|1 augment messages with the name of the function where\n"
" the message was logged (default: 0). Primarily for \n"
" development purposes.\n"
" -v, --version print version info and exit\n"
" -V, --version-full print full version info and exit\n"
" -?, --help show this help\n"
@ -1086,7 +1083,7 @@ int main(int argc, char **argv)
}
}
while ((opt = getopt_long(argc, argv, "dc:f:l:vVs:S:?L:D:C:B:U:A:P:G:",
while ((opt = getopt_long(argc, argv, "dc:f:l:vVs:S:?L:D:C:B:U:A:P:G:N:",
long_options, &option_index)) != -1)
{
bool succp = true;

View File

@ -66,6 +66,7 @@
#include <gw.h>
#include <gwdirs.h>
#include <math.h>
#include <version.h>
static RSA *rsa_512 = NULL;
static RSA *rsa_1024 = NULL;

View File

@ -51,12 +51,11 @@
*/
#include <modinfo.h>
MODULE_INFO info =
{
MODULE_API_PROTOCOL,
MODULE_GA,
GWPROTOCOL_VERSION,
"The MySQL to backend server protocol"
MODULE_INFO info = {
MODULE_API_PROTOCOL,
MODULE_GA,
GWPROTOCOL_VERSION,
"The MySQL to backend server protocol"
};
static char *version_str = "V2.0.0";
@ -70,8 +69,8 @@ static int gw_backend_hangup(DCB *dcb);
static int backend_write_delayqueue(DCB *dcb);
static void backend_set_delayqueue(DCB *dcb, GWBUF *queue);
static int gw_change_user(DCB *backend_dcb, SERVER *server, SESSION *in_session, GWBUF *queue);
static GWBUF* process_response_data (DCB* dcb, GWBUF* readbuf, int nbytes_to_process);
extern char* create_auth_failed_msg( GWBUF* readbuf, char* hostaddr, uint8_t* sha1);
static GWBUF* process_response_data(DCB* dcb, GWBUF* readbuf, int nbytes_to_process);
extern char* create_auth_failed_msg(GWBUF* readbuf, char* hostaddr, uint8_t* sha1);
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db, int errcode);
static bool sescmd_response_complete(DCB* dcb);
@ -79,21 +78,20 @@ static bool sescmd_response_complete(DCB* dcb);
#if defined(NOT_USED)
static int gw_session(DCB *backend_dcb, void *data);
#endif
static MYSQL_session* gw_get_shared_session_auth_info(DCB* dcb);
static bool gw_get_shared_session_auth_info(DCB* dcb, MYSQL_session* session);
static GWPROTOCOL MyObject =
{
gw_read_backend_event, /* Read - EPOLLIN handler */
gw_MySQLWrite_backend, /* Write - data from gateway */
gw_write_backend_event, /* WriteReady - EPOLLOUT handler */
gw_error_backend_event, /* Error - EPOLLERR handler */
gw_backend_hangup, /* HangUp - EPOLLHUP handler */
NULL, /* Accept */
gw_create_backend_connection, /* Connect */
gw_backend_close, /* Close */
NULL, /* Listen */
gw_change_user, /* Authentication */
NULL /* Session */
static GWPROTOCOL MyObject = {
gw_read_backend_event, /* Read - EPOLLIN handler */
gw_MySQLWrite_backend, /* Write - data from gateway */
gw_write_backend_event, /* WriteReady - EPOLLOUT handler */
gw_error_backend_event, /* Error - EPOLLERR handler */
gw_backend_hangup, /* HangUp - EPOLLHUP handler */
NULL, /* Accept */
gw_create_backend_connection, /* Connect */
gw_backend_close, /* Close */
NULL, /* Listen */
gw_change_user, /* Authentication */
NULL /* Session */
};
/*
@ -127,28 +125,34 @@ GWPROTOCOL* GetModuleObject()
return &MyObject;
}
static MYSQL_session* gw_get_shared_session_auth_info(DCB* dcb)
/**
* Copy shared session authentication info
*
* @param dcb A backend DCB
* @param session Destination where authentication data is copied
*/
static bool gw_get_shared_session_auth_info(DCB* dcb, MYSQL_session* session)
{
MYSQL_session* auth_info = NULL;
bool rval = true;
CHK_DCB(dcb);
CHK_SESSION(dcb->session);
spinlock_acquire(&dcb->session->ses_lock);
if (dcb->session->state != SESSION_STATE_ALLOC && dcb->session->state != SESSION_STATE_DUMMY)
if (dcb->session->state != SESSION_STATE_ALLOC &&
dcb->session->state != SESSION_STATE_DUMMY)
{
auth_info = dcb->session->data;
memcpy(session, dcb->session->data, sizeof(MYSQL_session));
}
else
{
MXS_ERROR("%lu [gw_get_shared_session_auth_info] Couldn't get "
"session authentication info. Session in a wrong state %d.",
pthread_self(),
dcb->session->state);
pthread_self(), dcb->session->state);
rval = false;
}
spinlock_release(&dcb->session->ses_lock);
return auth_info;
return rval;
}
/**
@ -160,7 +164,7 @@ static int gw_read_backend_event(DCB *dcb)
{
MySQLProtocol *client_protocol = NULL;
MySQLProtocol *backend_protocol = NULL;
MYSQL_session *current_session = NULL;
MYSQL_session local_session;
int rc = 0;
CHK_DCB(dcb);
@ -178,8 +182,10 @@ static int gw_read_backend_event(DCB *dcb)
CHK_SESSION(dcb->session);
/*< return only with complete session */
current_session = gw_get_shared_session_auth_info(dcb);
ss_dassert(current_session != NULL);
if (!gw_get_shared_session_auth_info(dcb, &local_session))
{
goto return_rc;
}
backend_protocol = (MySQLProtocol *) dcb->protocol;
CHK_PROTOCOL(backend_protocol);
@ -229,9 +235,10 @@ static int gw_read_backend_event(DCB *dcb)
* Decode password and send the auth credentials
* to backend.
*/
if (gw_send_authentication_to_backend(current_session->db,
current_session->user,
current_session->client_sha1,
if (gw_send_authentication_to_backend(
local_session.db,
local_session.user,
local_session.client_sha1,
backend_protocol) != 0)
{
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
@ -293,43 +300,43 @@ static int gw_read_backend_event(DCB *dcb)
switch (receive_rc)
{
case -1:
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
MXS_DEBUG("%lu [gw_read_backend_event] after "
"gw_receive_backend_authentication "
"fd %d, state = MYSQL_AUTH_FAILED.",
pthread_self(),
backend_protocol->owner_dcb->fd);
case -1:
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
MXS_DEBUG("%lu [gw_read_backend_event] after "
"gw_receive_backend_authentication "
"fd %d, state = MYSQL_AUTH_FAILED.",
pthread_self(),
backend_protocol->owner_dcb->fd);
MXS_ERROR("Backend server didn't "
"accept authentication for user "
"%s.",
current_session->user);
break;
case 1:
backend_protocol->protocol_auth_state = MYSQL_IDLE;
MXS_ERROR("Backend server didn't "
"accept authentication for user "
"%s.",
local_session.user);
break;
case 1:
backend_protocol->protocol_auth_state = MYSQL_IDLE;
MXS_DEBUG("%lu [gw_read_backend_event] "
"gw_receive_backend_auth succeed. "
"dcb %p fd %d, user %s.",
pthread_self(),
dcb,
dcb->fd,
current_session->user);
break;
default:
ss_dassert(receive_rc == 0);
MXS_DEBUG("%lu [gw_read_backend_event] "
"gw_receive_backend_auth read "
"successfully "
"nothing. dcb %p fd %d, user %s.",
pthread_self(),
dcb,
dcb->fd,
current_session->user);
rc = 0;
goto return_with_lock;
break;
MXS_DEBUG("%lu [gw_read_backend_event] "
"gw_receive_backend_auth succeed. "
"dcb %p fd %d, user %s.",
pthread_self(),
dcb,
dcb->fd,
local_session.user);
break;
default:
ss_dassert(receive_rc == 0);
MXS_DEBUG("%lu [gw_read_backend_event] "
"gw_receive_backend_auth read "
"successfully "
"nothing. dcb %p fd %d, user %s.",
pthread_self(),
dcb,
dcb->fd,
local_session.user);
rc = 0;
goto return_with_lock;
break;
} /* switch */
}
@ -338,9 +345,9 @@ static int gw_read_backend_event(DCB *dcb)
{
GWBUF* errbuf;
bool succp;
/**
* protocol state won't change anymore,
* lock can be freed
/**
* protocol state won't change anymore,
* lock can be freed
*/
spinlock_release(&dcb->authlock);
spinlock_acquire(&dcb->delayqlock);
@ -359,7 +366,7 @@ static int gw_read_backend_event(DCB *dcb)
* client session is not stopping. It is possible that authentication
* fails because the client has closed the connection before all
* backends have done authentication. */
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED &&
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED &&
dcb->session->state != SESSION_STATE_STOPPING)
{
service_refresh_users(dcb->session->service);
@ -416,7 +423,7 @@ static int gw_read_backend_event(DCB *dcb)
"user %s.",
pthread_self(),
dcb->fd,
current_session->user);
local_session.user);
/* check the delay queue and flush the data */
if (dcb->delayq)
@ -429,7 +436,7 @@ static int gw_read_backend_event(DCB *dcb)
spinlock_release(&dcb->authlock);
} /* MYSQL_AUTH_RECV || MYSQL_AUTH_FAILED || MYSQL_HANDSHAKE_FAILED */
} /* MYSQL_AUTH_RECV || MYSQL_AUTH_FAILED || MYSQL_HANDSHAKE_FAILED */
/* reading MySQL command output from backend and writing to the client */
{
@ -487,7 +494,7 @@ static int gw_read_backend_event(DCB *dcb)
if (dcb->dcb_readqueue)
{
read_buffer = gwbuf_append(dcb->dcb_readqueue,read_buffer);
read_buffer = gwbuf_append(dcb->dcb_readqueue, read_buffer);
}
nbytes_read = gwbuf_length(read_buffer);
@ -518,7 +525,7 @@ static int gw_read_backend_event(DCB *dcb)
* If protocol has session command set, concatenate whole
* response into one buffer.
*/
if (protocol_get_srv_command((MySQLProtocol *)dcb->protocol, false) != MYSQL_COM_UNDEFINED)
if (protocol_get_srv_command((MySQLProtocol *) dcb->protocol, false) != MYSQL_COM_UNDEFINED)
{
read_buffer = process_response_data(dcb, read_buffer, gwbuf_length(read_buffer));
/**
@ -537,7 +544,7 @@ static int gw_read_backend_event(DCB *dcb)
"Read buffer unexpectedly null, even though response "
"not marked as complete. User: %s",
pthread_self(),
current_session->user);
local_session.user);
rc = 0;
goto return_rc;
}
@ -610,7 +617,7 @@ static int gw_write_backend_event(DCB *dcb)
if (dcb->writeq != NULL)
{
data = (uint8_t *)GWBUF_DATA(dcb->writeq);
data = (uint8_t *) GWBUF_DATA(dcb->writeq);
if (dcb->session->client == NULL)
{
@ -691,30 +698,30 @@ static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
*/
switch (backend_protocol->protocol_auth_state)
{
case MYSQL_HANDSHAKE_FAILED:
case MYSQL_AUTH_FAILED:
if (dcb->session->state != SESSION_STATE_STOPPING)
{
MXS_ERROR("Unable to write to backend '%s' due to "
"%s failure. Server in state %s.",
dcb->server->unique_name,
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED ?
"handshake" : "authentication",
STRSRVSTATUS(dcb->server));
}
/** Consume query buffer */
while ((queue = gwbuf_consume(
queue,
GWBUF_LENGTH(queue))) != NULL)
{
;
}
rc = 0;
spinlock_release(&dcb->authlock);
goto return_rc;
break;
case MYSQL_HANDSHAKE_FAILED:
case MYSQL_AUTH_FAILED:
if (dcb->session->state != SESSION_STATE_STOPPING)
{
MXS_ERROR("Unable to write to backend '%s' due to "
"%s failure. Server in state %s.",
dcb->server->unique_name,
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED ?
"handshake" : "authentication",
STRSRVSTATUS(dcb->server));
}
/** Consume query buffer */
while ((queue = gwbuf_consume(
queue,
GWBUF_LENGTH(queue))) != NULL)
{
;
}
rc = 0;
spinlock_release(&dcb->authlock);
goto return_rc;
break;
case MYSQL_IDLE:
case MYSQL_IDLE:
{
uint8_t* ptr = GWBUF_DATA(queue);
int cmd = MYSQL_GET_COMMAND(ptr);
@ -744,9 +751,9 @@ static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
rc = dcb_write(dcb, queue);
goto return_rc;
}
break;
break;
default:
default:
{
MXS_DEBUG("%lu [gw_MySQLWrite_backend] delayed write to "
"dcb %p fd %d protocol state %s.",
@ -776,7 +783,7 @@ static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
rc = 1;
goto return_rc;
}
break;
break;
}
return_rc:
return rc;
@ -823,7 +830,7 @@ static int gw_error_backend_event(DCB *dcb)
len = sizeof(error);
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) == 0)
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *) & len) == 0)
{
if (error != 0)
{
@ -861,7 +868,7 @@ static int gw_error_backend_event(DCB *dcb)
int error, len;
len = sizeof(error);
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) == 0)
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *) & len) == 0)
{
if (error != 0)
{
@ -914,8 +921,8 @@ retblock:
* backend server. Positive fd is copied to protocol and to dcb.
* If fails, fd == -1 and socket is closed.
*/
static int gw_create_backend_connection(DCB *backend_dcb,
SERVER *server,
static int gw_create_backend_connection(DCB *backend_dcb,
SERVER *server,
SESSION *session)
{
MySQLProtocol *protocol = NULL;
@ -939,10 +946,10 @@ static int gw_create_backend_connection(DCB *backend_dcb,
{
/** Copy client flags to backend protocol */
protocol->client_capabilities =
((MySQLProtocol *)(backend_dcb->session->client->protocol))->client_capabilities;
((MySQLProtocol *) (backend_dcb->session->client->protocol))->client_capabilities;
/** Copy client charset to backend protocol */
protocol->charset =
((MySQLProtocol *)(backend_dcb->session->client->protocol))->charset;
((MySQLProtocol *) (backend_dcb->session->client->protocol))->charset;
}
else
{
@ -958,51 +965,50 @@ static int gw_create_backend_connection(DCB *backend_dcb,
/*< Set protocol state */
switch (rv)
{
case 0:
ss_dassert(fd > 0);
protocol->fd = fd;
protocol->protocol_auth_state = MYSQL_CONNECTED;
MXS_DEBUG("%lu [gw_create_backend_connection] Established "
"connection to %s:%i, protocol fd %d client "
"fd %d.",
pthread_self(),
server->name,
server->port,
protocol->fd,
session->client->fd);
break;
case 0:
ss_dassert(fd > 0);
protocol->fd = fd;
protocol->protocol_auth_state = MYSQL_CONNECTED;
MXS_DEBUG("%lu [gw_create_backend_connection] Established "
"connection to %s:%i, protocol fd %d client "
"fd %d.",
pthread_self(),
server->name,
server->port,
protocol->fd,
session->client->fd);
break;
case 1:
ss_dassert(fd > 0);
protocol->protocol_auth_state = MYSQL_PENDING_CONNECT;
protocol->fd = fd;
MXS_DEBUG("%lu [gw_create_backend_connection] Connection "
"pending to %s:%i, protocol fd %d client fd %d.",
pthread_self(),
server->name,
server->port,
protocol->fd,
session->client->fd);
break;
case 1:
ss_dassert(fd > 0);
protocol->protocol_auth_state = MYSQL_PENDING_CONNECT;
protocol->fd = fd;
MXS_DEBUG("%lu [gw_create_backend_connection] Connection "
"pending to %s:%i, protocol fd %d client fd %d.",
pthread_self(),
server->name,
server->port,
protocol->fd,
session->client->fd);
break;
default:
ss_dassert(fd == -1);
ss_dassert(protocol->protocol_auth_state == MYSQL_ALLOC);
MXS_DEBUG("%lu [gw_create_backend_connection] Connection "
"failed to %s:%i, protocol fd %d client fd %d.",
pthread_self(),
server->name,
server->port,
protocol->fd,
session->client->fd);
break;
default:
ss_dassert(fd == -1);
ss_dassert(protocol->protocol_auth_state == MYSQL_ALLOC);
MXS_DEBUG("%lu [gw_create_backend_connection] Connection "
"failed to %s:%i, protocol fd %d client fd %d.",
pthread_self(),
server->name,
server->port,
protocol->fd,
session->client->fd);
break;
} /*< switch */
return_fd:
return fd;
}
/**
* Error event handler.
* Create error message, pass it to router's error handler and if error
@ -1068,7 +1074,7 @@ static int gw_backend_hangup(DCB *dcb)
int error, len;
len = sizeof(error);
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&len) == 0)
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *) & len) == 0)
{
if (error != 0 && ses_state != SESSION_STATE_STOPPING)
{
@ -1238,13 +1244,12 @@ static int backend_write_delayqueue(DCB *dcb)
if (MYSQL_IS_CHANGE_USER(((uint8_t *)GWBUF_DATA(localq))))
{
MYSQL_session* mses;
GWBUF* new_packet;
MYSQL_session mses;
GWBUF* new_packet;
mses = (MYSQL_session *)dcb->session->client->data;
new_packet = gw_create_change_user_packet(mses,
(MySQLProtocol *)dcb->protocol);
/**
gw_get_shared_session_auth_info(dcb, &mses);
new_packet = gw_create_change_user_packet(&mses, dcb->protocol);
/**
* Remove previous packet which lacks scramble
* and append the new.
*/
@ -1315,10 +1320,10 @@ static int gw_change_user(DCB *backend,
MYSQL_session *current_session = NULL;
MySQLProtocol *backend_protocol = NULL;
MySQLProtocol *client_protocol = NULL;
char username[MYSQL_USER_MAXLEN+1]="";
char database[MYSQL_DATABASE_MAXLEN+1]="";
char current_database[MYSQL_DATABASE_MAXLEN+1]="";
uint8_t client_sha1[MYSQL_SCRAMBLE_LEN]="";
char username[MYSQL_USER_MAXLEN + 1] = "";
char database[MYSQL_DATABASE_MAXLEN + 1] = "";
char current_database[MYSQL_DATABASE_MAXLEN + 1] = "";
uint8_t client_sha1[MYSQL_SCRAMBLE_LEN] = "";
uint8_t *client_auth_packet = GWBUF_DATA(queue);
unsigned int auth_token_len = 0;
uint8_t *auth_token = NULL;
@ -1331,7 +1336,7 @@ static int gw_change_user(DCB *backend,
/* now get the user, after 4 bytes header and 1 byte command */
client_auth_packet += 5;
strncpy(username, (char *)client_auth_packet,MYSQL_USER_MAXLEN);
strncpy(username, (char *)client_auth_packet, MYSQL_USER_MAXLEN);
client_auth_packet += strlen(username) + 1;
/* get the auth token len */
@ -1354,7 +1359,7 @@ static int gw_change_user(DCB *backend,
}
/* get new database name */
strncpy(database, (char *)client_auth_packet,MYSQL_DATABASE_MAXLEN);
strncpy(database, (char *)client_auth_packet, MYSQL_DATABASE_MAXLEN);
/* get character set */
if (strlen(database))
@ -1371,45 +1376,48 @@ static int gw_change_user(DCB *backend,
memcpy(&backend_protocol->charset, client_auth_packet, sizeof(int));
}
spinlock_acquire(&in_session->ses_lock);
/* save current_database name */
strncpy(current_database, current_session->db,MYSQL_DATABASE_MAXLEN);
strncpy(current_database, current_session->db, MYSQL_DATABASE_MAXLEN);
/*
* Now clear database name in dcb as we don't do local authentication on db name for change user.
* Local authentication only for user@host and if successful the database name change is sent to backend.
*/
strcpy(current_session->db, "");
strncpy(current_session->db, "", MYSQL_DATABASE_MAXLEN);
/*
* decode the token and check the password.
* Decode the token and check the password.
* Note: if auth_token_len == 0 && auth_token == NULL, user is without password
*/
auth_ret = gw_check_mysql_scramble_data(backend->session->client,
auth_token,
auth_token_len,
auth_token, auth_token_len,
client_protocol->scramble,
sizeof(client_protocol->scramble),
username,
client_sha1);
username, client_sha1);
strncpy(current_session->db, current_database, MYSQL_DATABASE_MAXLEN);
spinlock_release(&in_session->ses_lock);
if (auth_ret != 0)
{
if (!service_refresh_users(backend->session->client->service))
if (service_refresh_users(backend->session->client->service) == 0)
{
/* Try authentication again with new repository data */
/* Note: if no auth client authentication will fail */
auth_ret = gw_check_mysql_scramble_data(backend->session->client,
spinlock_acquire(&in_session->ses_lock);
strncpy(current_session->db, "", MYSQL_DATABASE_MAXLEN);
auth_ret = gw_check_mysql_scramble_data(
backend->session->client,
auth_token, auth_token_len,
client_protocol->scramble,
sizeof(client_protocol->scramble),
username,
client_sha1);
username, client_sha1);
strncpy(current_session->db, current_database, MYSQL_DATABASE_MAXLEN);
spinlock_release(&in_session->ses_lock);
}
}
/* copy back current datbase to client session */
strcpy(current_session->db, current_database);
/* let's free the auth_token now */
if (auth_token)
{
@ -1457,7 +1465,9 @@ static int gw_change_user(DCB *backend,
MYSQL_COM_CHANGE_USER);
modutil_reply_auth_error(backend, message, 0);
rv = 1;
} else {
}
else
{
rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol);
/*
* Now copy new data into user session
@ -1473,7 +1483,6 @@ retblock:
return rv;
}
/**
* Move packets or parts of packets from readbuf to outbuf as the packet headers
* and lengths have been noticed and counted.
@ -1486,12 +1495,12 @@ retblock:
*
* @return GWBUF which includes complete MySQL packet
*/
static GWBUF* process_response_data(DCB* dcb,
static GWBUF* process_response_data(DCB* dcb,
GWBUF* readbuf,
int nbytes_to_process)
int nbytes_to_process)
{
int npackets_left = 0; /*< response's packet count */
ssize_t nbytes_left = 0; /*< nbytes to be read for the packet */
ssize_t nbytes_left = 0; /*< nbytes to be read for the packet */
MySQLProtocol* p;
GWBUF* outbuf = NULL;
int initial_packets = npackets_left;
@ -1560,7 +1569,7 @@ static GWBUF* process_response_data(DCB* dcb,
}
nbytes_to_process = 0;
}
/** Packet was read. All bytes belonged to the last packet. */
/** Packet was read. All bytes belonged to the last packet. */
else if (nbytes_left == nbytes_to_process)
{
nbytes_left = 0;
@ -1570,12 +1579,12 @@ static GWBUF* process_response_data(DCB* dcb,
outbuf = gwbuf_append(outbuf, readbuf);
readbuf = NULL;
}
/**
* Packet was read. There should be more since bytes were
* left over.
* Move the next packet to its own buffer and add that next
* to the prev packet's buffer.
*/
/**
* Packet was read. There should be more since bytes were
* left over.
* Move the next packet to its own buffer and add that next
* to the prev packet's buffer.
*/
else /*< nbytes_left < nbytes_to_process */
{
ss_dassert(nbytes_left >= 0);
@ -1583,8 +1592,8 @@ static GWBUF* process_response_data(DCB* dcb,
/** Move the prefix of the buffer to outbuf from redbuf */
outbuf = gwbuf_append(outbuf,
gwbuf_clone_portion(readbuf, 0, (size_t)nbytes_left));
readbuf = gwbuf_consume(readbuf, (size_t)nbytes_left);
gwbuf_clone_portion(readbuf, 0, (size_t) nbytes_left));
readbuf = gwbuf_consume(readbuf, (size_t) nbytes_left);
ss_dassert(npackets_left > 0);
npackets_left -= 1;
nbytes_left = 0;
@ -1611,7 +1620,7 @@ static GWBUF* process_response_data(DCB* dcb,
/** Archive the command */
protocol_archive_srv_command(p);
}
/** Read next packet */
/** Read next packet */
else
{
uint8_t* data;
@ -1624,19 +1633,19 @@ static GWBUF* process_response_data(DCB* dcb,
{
MXS_DEBUG("%lu [%s] Read %d packets. Waiting for %d more "
"packets for a total of %d packets.",
pthread_self(),__FUNCTION__,
pthread_self(), __FUNCTION__,
initial_packets - npackets_left,
npackets_left,initial_packets);
npackets_left, initial_packets);
/** Store the already read data into the readqueue of the DCB
* and restore the response status to the initial number of packets */
dcb->dcb_readqueue = gwbuf_append(outbuf,dcb->dcb_readqueue);
dcb->dcb_readqueue = gwbuf_append(outbuf, dcb->dcb_readqueue);
protocol_set_response_status(p, initial_packets, initial_bytes);
return NULL;
}
data = GWBUF_DATA(readbuf);
nbytes_left = MYSQL_GET_PACKET_LEN(data)+MYSQL_HEADER_LEN;
nbytes_left = MYSQL_GET_PACKET_LEN(data) + MYSQL_HEADER_LEN;
/** Store new status to protocol structure */
protocol_set_response_status(p, npackets_left, nbytes_left);
}
@ -1645,12 +1654,11 @@ static GWBUF* process_response_data(DCB* dcb,
return outbuf;
}
static bool sescmd_response_complete(DCB* dcb)
{
int npackets_left;
ssize_t nbytes_left;
MySQLProtocol* p;
MySQLProtocol* p;
bool succp;
p = DCB_PROTOCOL(dcb, MySQLProtocol);

View File

@ -1566,8 +1566,6 @@ void check_drop_tmp_table(
char** tbl = NULL;
char *hkey,*dbname;
MYSQL_session* data;
DCB* master_dcb = NULL;
rses_property_t* rses_prop_tmp;
if(router_cli_ses == NULL || querybuf == NULL)
@ -1577,27 +1575,14 @@ void check_drop_tmp_table(
return;
}
if(router_cli_ses->rses_master_ref == NULL)
if(router_cli_ses->client_dcb == NULL)
{
MXS_ERROR("[%s] Error: Master server reference is NULL.",
__FUNCTION__);
MXS_ERROR("[%s] Error: Client DCB is NULL.", __FUNCTION__);
return;
}
rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES];
master_dcb = router_cli_ses->rses_master_ref->bref_dcb;
if(master_dcb == NULL || master_dcb->session == NULL)
{
MXS_ERROR("[%s] Error: Master server DBC is NULL. "
"This means that the connection to the master server is already "
"closed while a query is still being routed.",__FUNCTION__);
return;
}
CHK_DCB(master_dcb);
data = (MYSQL_session*)master_dcb->session->data;
data = (MYSQL_session*)router_cli_ses->client_dcb->session->data;
if(data == NULL)
{
@ -1668,32 +1653,20 @@ static qc_query_type_t is_read_tmp_table(
return type;
}
if(router_cli_ses->rses_master_ref == NULL)
if(router_cli_ses->client_dcb == NULL)
{
MXS_ERROR("[%s] Error: Master server reference is NULL.",
__FUNCTION__);
MXS_ERROR("[%s] Error: Client DCB is NULL.", __FUNCTION__);
return type;
}
if (BREF_IS_IN_USE(router_cli_ses->rses_master_ref))
{
rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES];
master_dcb = router_cli_ses->rses_master_ref->bref_dcb;
if(master_dcb == NULL || master_dcb->session == NULL)
{
MXS_ERROR("[%s] Error: Master server DBC is NULL. "
"This means that the connection to the master server is already "
"closed while a query is still being routed.",__FUNCTION__);
return qtype;
}
CHK_DCB(master_dcb);
data = (MYSQL_session*)master_dcb->session->data;
data = (MYSQL_session*)router_cli_ses->client_dcb->session->data;
if(data == NULL)
{
MXS_ERROR("[%s] Error: User data in master server DBC is NULL.",__FUNCTION__);
MXS_ERROR("[%s] Error: User data in client DBC is NULL.",__FUNCTION__);
return qtype;
}
@ -1765,7 +1738,6 @@ static void check_create_tmp_table(
int klen = 0;
char *hkey,*dbname;
MYSQL_session* data;
DCB* master_dcb = NULL;
rses_property_t* rses_prop_tmp;
HASHTABLE* h;
@ -1776,28 +1748,15 @@ static void check_create_tmp_table(
return;
}
if(router_cli_ses->rses_master_ref == NULL)
if(router_cli_ses->client_dcb == NULL)
{
MXS_ERROR("[%s] Error: Master server reference is NULL.",
__FUNCTION__);
MXS_ERROR("[%s] Error: Client DCB is NULL.", __FUNCTION__);
return;
}
router_cli_ses->have_tmp_tables = true;
rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES];
master_dcb = router_cli_ses->rses_master_ref->bref_dcb;
if(master_dcb == NULL || master_dcb->session == NULL)
{
MXS_ERROR("[%s] Error: Master server DCB is NULL. "
"This means that the connection to the master server is already "
"closed while a query is still being routed.",__FUNCTION__);
return;
}
CHK_DCB(master_dcb);
data = (MYSQL_session*)master_dcb->session->data;
data = (MYSQL_session*)router_cli_ses->client_dcb->session->data;
if(data == NULL)
{
@ -2097,10 +2056,10 @@ static bool route_single_stmt(
* Read stored master DCB pointer. If master is not set, routing must
* be aborted
*/
if ((master_dcb = rses->rses_master_ref->bref_dcb) == NULL)
if ((master_dcb = rses->rses_master_ref->bref_dcb) == NULL ||
BREF_IS_CLOSED(rses->rses_master_ref))
{
char* query_str = modutil_get_query(querybuf);
CHK_DCB(master_dcb);
MXS_ERROR("Can't route %s:%s:\"%s\" to "
"backend server. Session doesn't have a Master "
"node",
@ -2112,6 +2071,7 @@ static bool route_single_stmt(
goto retblock;
}
CHK_DCB(master_dcb);
packet = GWBUF_DATA(querybuf);
packet_len = gw_mysql_get_byte3(packet);
@ -2491,7 +2451,6 @@ static bool route_single_stmt(
#if defined(SS_EXTRA_DEBUG)
MXS_INFO("Found DCB for slave.");
#endif
atomic_add(&inst->stats.n_slave, 1);
}
else
@ -2847,21 +2806,17 @@ static void clientReply (
uint8_t* replybuf = (uint8_t *)GWBUF_DATA(writebuf);
size_t len = MYSQL_GET_PACKET_LEN(buf);
size_t replylen = MYSQL_GET_PACKET_LEN(replybuf);
char* cmdstr = strndup(&((char *)buf)[5], len-4);
char* err = strndup(&((char *)replybuf)[8], 5);
char* replystr = strndup(&((char *)replybuf)[13],
replylen-4-5);
ss_dassert(len+4 == GWBUF_LENGTH(scur->scmd_cur_cmd->my_sescmd_buf));
MXS_ERROR("Failed to execute %s in %s:%d. %s %s",
cmdstr,
MXS_ERROR("Failed to execute session command in %s:%d. Error was: %s %s",
bref->bref_backend->backend_server->name,
bref->bref_backend->backend_server->port,
err,
replystr);
free(cmdstr);
free(err);
free(replystr);
}
@ -2893,11 +2848,9 @@ static void clientReply (
* This applies to session commands only. Counter decrement
* for other type of queries is done outside this block.
*/
if (writebuf != NULL && client_dcb != NULL)
{
/** Set response status as replied */
bref_clear_state(bref, BREF_WAITING_RESULT);
}
/** Set response status as replied */
bref_clear_state(bref, BREF_WAITING_RESULT);
}
/**
* Clear BREF_QUERY_ACTIVE flag and decrease waiter counter.
@ -3815,8 +3768,8 @@ static GWBUF* sescmd_cursor_process_replies(
if(bref->reply_cmd != scmd->reply_cmd)
{
MXS_INFO("Backend server '%s' response differs from master's response. "
"Closing connection.",
MXS_ERROR("Slave server '%s': response differs from master's response. "
"Closing connection due to inconsistent session state.",
bref->bref_backend->backend_server->unique_name);
sescmd_cursor_set_active(scur,false);
bref_clear_state(bref,BREF_QUERY_ACTIVE);

View File

@ -1767,7 +1767,7 @@ bool send_database_list(ROUTER_INSTANCE* router, ROUTER_CLIENT_SES* client)
{
bool rval = false;
spinlock_acquire(&client->shardmap->lock);
if (client->shardmap->state == SHMAP_READY)
if (client->shardmap->state != SHMAP_UNINIT)
{
struct string_array strarray;
const int size = hashtable_size(client->shardmap->hash);
@ -1849,12 +1849,7 @@ static int routeQuery(ROUTER* instance,
char errbuf[26+MYSQL_DATABASE_MAXLEN];
CHK_CLIENT_RSES(router_cli_ses);
/** Dirty read for quick check if router is closed. */
if (router_cli_ses->rses_closed)
{
rses_is_closed = true;
}
ss_dassert(!GWBUF_IS_TYPE_UNDEFINED(querybuf));
ss_dassert(!GWBUF_IS_TYPE_UNDEFINED(querybuf));
if (!rses_begin_locked_router_action(router_cli_ses))
{
@ -4313,7 +4308,7 @@ int process_show_shards(ROUTER_CLIENT_SES* rses)
int rval = 0;
spinlock_acquire(&rses->shardmap->lock);
if (rses->shardmap->state == SHMAP_READY)
if(rses->shardmap->state != SHMAP_UNINIT)
{
HASHITERATOR* iter = hashtable_iterator(rses->shardmap->hash);
struct shard_list sl;
@ -4380,7 +4375,7 @@ bool handle_default_db(ROUTER_CLIENT_SES *router_cli_ses)
char* target = NULL;
spinlock_acquire(&router_cli_ses->shardmap->lock);
if (router_cli_ses->shardmap->state == SHMAP_READY)
if(router_cli_ses->shardmap->state != SHMAP_UNINIT)
{
target = hashtable_fetch(router_cli_ses->shardmap->hash, router_cli_ses->connect_db);
}