Merge branch 'release-1.3.0' into develop

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

View File

@ -27,8 +27,6 @@
## Reference ## Reference
- [MaxAdmin](Reference/MaxAdmin.md) - [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) - [How Errors are Handled in MaxScale](Reference/How-errors-are-handled-in-MaxScale.md)
- [Debug and Diagnostic Support](Reference/Debug-And-Diagnostic-Support.md) - [Debug and Diagnostic Support](Reference/Debug-And-Diagnostic-Support.md)
- [Routing Hints](Reference/Hint-Syntax.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) - [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 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) - [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) - [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 ## Routers
The routing module is the core of a MaxScale service. The router documentation The routing module is the core of a MaxScale service. The router documentation

View File

@ -771,6 +771,8 @@ and short notations
192.%.% 192.%.%
192.168.% 192.168.%
Note that currently wildcards are only supported in conjunction with IP-addresses, not with domain names.
## Error Reporting ## 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. 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 This document describes the changes in release 1.3, when compared to
release 1.2.1. release 1.2.1.
## 1.3.0 Beta ## 1.3.0
**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.
For any problems you encounter, please consider submitting a bug For any problems you encounter, please consider submitting a bug
report at [Jira](https://mariadb.atlassian.net). report at [Jira](https://mariadb.atlassian.net).
@ -149,85 +145,94 @@ details, please read the [Monitor Common](../Monitors/Monitor-Common.md) documen
## Bug fixes ## 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-559](https://mariadb.atlassian.net/browse/MXS-559): Crash due to debug assertion in readwritesplit
* [MXS-415](https://mariadb.atlassian.net/browse/MXS-415): MaxScale 1.2.1 crashed with Signal 6 and 11 * [MXS-551](https://mariadb.atlassian.net/browse/MXS-551): Maxscale BETA 1.3.0 running as root
* [MXS-351](https://mariadb.atlassian.net/browse/MXS-351): Router error handling can cause crash by leaving dangling DCB pointer * [MXS-548](https://mariadb.atlassian.net/browse/MXS-548): Maxscale 1.2.1 crash on Ubuntu 4.04.3 x86_64
* [MXS-428](https://mariadb.atlassian.net/browse/MXS-428): Maxscale crashes at startup. * [MXS-508](https://mariadb.atlassian.net/browse/MXS-508): regex filter ignores username
* [MXS-376](https://mariadb.atlassian.net/browse/MXS-376): MaxScale terminates with SIGABRT. * [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-269](https://mariadb.atlassian.net/browse/MXS-269): Crash in MySQL backend protocol * [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 statement aren't duplicated. * [MXS-500](https://mariadb.atlassian.net/browse/MXS-500): Tee filter hangs when statements 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-499](https://mariadb.atlassian.net/browse/MXS-499): Init script error on Debian Wheezy * [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-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-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-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-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-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-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-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-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-379](https://mariadb.atlassian.net/browse/MXS-379): Incorrect handing of a GWBUF may cause SIGABRT. * [MXS-428](https://mariadb.atlassian.net/browse/MXS-428): Maxscale crashes at startup.
* [MXS-321](https://mariadb.atlassian.net/browse/MXS-321): Incorrect number of connections in maxadmin list view * [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-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-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-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-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-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-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-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-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-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-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-210](https://mariadb.atlassian.net/browse/MXS-210): Check MaxScale user privileges
* [MXS-281](https://mariadb.atlassian.net/browse/MXS-281): SELECT INTO OUTFILE query goes several times to one slave * [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-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-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-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-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-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 ## 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. 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
**`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`. **`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 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 ## 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. 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) `-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) `-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) `-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) `-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/) `-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 `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. `-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]`|`--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. `-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`|print version info and exit
`-V`|`--version-full`|print version info and the commit ID the binary was built from `-V`|`--version-full`|print version info and the commit ID the binary was built from

View File

@ -141,7 +141,7 @@ name: pacemaker
} }
``` ```
**Please note **in this example: **Please note** in this example:
- unicast UDP is used - 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. Relative or absolute pathname of MaxScale configuration file to load.
.TP .TP
.BR -l "[\fIfile|shm\fB], --log=[\fIfile|shm\fB]" .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 .TP
.BR -L " \fIPATH\fB, --logdir=\fIPATH\fB" .BR -L " \fIPATH\fB, --logdir=\fIPATH\fB"
Path to log file directory. 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]" .BR -s " [\fIyes\fB|\fIno\fB], --syslog=[\fIyes\fB|\fIno\fB]"
Log messages to syslog. Log messages to syslog.
.TP .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. Log messages to MaxScale's own log files.
.TP .TP
.BR "-v, --version" .BR "-v, --version"
@ -61,12 +61,27 @@ Print full version information including the Git commit the binary was built fro
.TP .TP
.BR "-?, --help" .BR "-?, --help"
Show the help information for MaxScale and exit. Show the help information for MaxScale and exit.
.SH EXAMPLES .SH EXAMPLES
Tutorials on GitHub: 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 .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: 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_MINOR "3" CACHE STRING "Minor version")
set(MAXSCALE_VERSION_PATCH "0" CACHE STRING "Patch 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_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 # This should be incremented each time a package is rebuilt
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number") set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")

View File

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

View File

@ -930,27 +930,24 @@ static void usage(void)
fprintf(stderr, fprintf(stderr,
"\nUsage : %s [OPTION]...\n\n" "\nUsage : %s [OPTION]...\n\n"
" -d, --nodaemon enable running in terminal process (default:disabled)\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" " (default:/etc/maxscale.cnf)\n"
" -l, --log=[file|shm] log to file or shared memory (default: shm)\n" " -l, --log=[file|shm] log to file or shared memory (default: file)\n"
" -L, --logdir=PATH path to log file directory\n" " -L, --logdir=PATH path to log file directory (default: /var/log/maxscale)\n"
" (default: /var/log/maxscale)\n" " -A, --cachedir=PATH path to cache directory (default: /var/cache/maxscale)\n"
" -A, --cachedir=PATH path to cache directory\n" " -B, --libdir=PATH path to module directory (default: /usr/lib64/maxscale)\n"
" (default: /var/cache/maxscale)\n" " -C, --configdir=PATH path to configuration file directory (default: /etc/)\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"
" -D, --datadir=PATH path to data directory, stored embedded mysql tables\n" " -D, --datadir=PATH path to data directory, stored embedded mysql tables\n"
" (default: /var/cache/maxscale)\n" " (default: /var/cache/maxscale)\n"
" -N, --language=PATH path to errmsg.sys file\n" " -N, --language=PATH path to errmsg.sys file (default: /var/lib/maxscale)\n"
" (default: /var/lib/maxscale)\n" " -P, --piddir=PATH path to PID file directory (default: /var/run/maxscale)\n"
" -P, --piddir=PATH path to PID file directory\n"
" (default: /var/run/maxscale)\n"
" -U, --user=USER run MaxScale as another user.\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" " 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, --syslog=[yes|no] log messages to syslog (default:yes)\n"
" -S, --maxlog=[yes|no] log messages to MaxScale log (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 print version info and exit\n"
" -V, --version-full print full version info and exit\n" " -V, --version-full print full version info and exit\n"
" -?, --help show this help\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) long_options, &option_index)) != -1)
{ {
bool succp = true; bool succp = true;

View File

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

View File

@ -51,8 +51,7 @@
*/ */
#include <modinfo.h> #include <modinfo.h>
MODULE_INFO info = MODULE_INFO info = {
{
MODULE_API_PROTOCOL, MODULE_API_PROTOCOL,
MODULE_GA, MODULE_GA,
GWPROTOCOL_VERSION, GWPROTOCOL_VERSION,
@ -70,8 +69,8 @@ static int gw_backend_hangup(DCB *dcb);
static int backend_write_delayqueue(DCB *dcb); static int backend_write_delayqueue(DCB *dcb);
static void backend_set_delayqueue(DCB *dcb, GWBUF *queue); 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 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); 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_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); extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db, int errcode);
static bool sescmd_response_complete(DCB* dcb); static bool sescmd_response_complete(DCB* dcb);
@ -79,10 +78,9 @@ static bool sescmd_response_complete(DCB* dcb);
#if defined(NOT_USED) #if defined(NOT_USED)
static int gw_session(DCB *backend_dcb, void *data); static int gw_session(DCB *backend_dcb, void *data);
#endif #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 = static GWPROTOCOL MyObject = {
{
gw_read_backend_event, /* Read - EPOLLIN handler */ gw_read_backend_event, /* Read - EPOLLIN handler */
gw_MySQLWrite_backend, /* Write - data from gateway */ gw_MySQLWrite_backend, /* Write - data from gateway */
gw_write_backend_event, /* WriteReady - EPOLLOUT handler */ gw_write_backend_event, /* WriteReady - EPOLLOUT handler */
@ -127,28 +125,34 @@ GWPROTOCOL* GetModuleObject()
return &MyObject; 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_DCB(dcb);
CHK_SESSION(dcb->session); CHK_SESSION(dcb->session);
spinlock_acquire(&dcb->session->ses_lock); 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 else
{ {
MXS_ERROR("%lu [gw_get_shared_session_auth_info] Couldn't get " MXS_ERROR("%lu [gw_get_shared_session_auth_info] Couldn't get "
"session authentication info. Session in a wrong state %d.", "session authentication info. Session in a wrong state %d.",
pthread_self(), pthread_self(), dcb->session->state);
dcb->session->state); rval = false;
} }
spinlock_release(&dcb->session->ses_lock); spinlock_release(&dcb->session->ses_lock);
return rval;
return auth_info;
} }
/** /**
@ -160,7 +164,7 @@ static int gw_read_backend_event(DCB *dcb)
{ {
MySQLProtocol *client_protocol = NULL; MySQLProtocol *client_protocol = NULL;
MySQLProtocol *backend_protocol = NULL; MySQLProtocol *backend_protocol = NULL;
MYSQL_session *current_session = NULL; MYSQL_session local_session;
int rc = 0; int rc = 0;
CHK_DCB(dcb); CHK_DCB(dcb);
@ -178,8 +182,10 @@ static int gw_read_backend_event(DCB *dcb)
CHK_SESSION(dcb->session); CHK_SESSION(dcb->session);
/*< return only with complete session */ /*< return only with complete session */
current_session = gw_get_shared_session_auth_info(dcb); if (!gw_get_shared_session_auth_info(dcb, &local_session))
ss_dassert(current_session != NULL); {
goto return_rc;
}
backend_protocol = (MySQLProtocol *) dcb->protocol; backend_protocol = (MySQLProtocol *) dcb->protocol;
CHK_PROTOCOL(backend_protocol); CHK_PROTOCOL(backend_protocol);
@ -229,9 +235,10 @@ static int gw_read_backend_event(DCB *dcb)
* Decode password and send the auth credentials * Decode password and send the auth credentials
* to backend. * to backend.
*/ */
if (gw_send_authentication_to_backend(current_session->db, if (gw_send_authentication_to_backend(
current_session->user, local_session.db,
current_session->client_sha1, local_session.user,
local_session.client_sha1,
backend_protocol) != 0) backend_protocol) != 0)
{ {
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED; backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
@ -304,7 +311,7 @@ static int gw_read_backend_event(DCB *dcb)
MXS_ERROR("Backend server didn't " MXS_ERROR("Backend server didn't "
"accept authentication for user " "accept authentication for user "
"%s.", "%s.",
current_session->user); local_session.user);
break; break;
case 1: case 1:
backend_protocol->protocol_auth_state = MYSQL_IDLE; backend_protocol->protocol_auth_state = MYSQL_IDLE;
@ -315,7 +322,7 @@ static int gw_read_backend_event(DCB *dcb)
pthread_self(), pthread_self(),
dcb, dcb,
dcb->fd, dcb->fd,
current_session->user); local_session.user);
break; break;
default: default:
ss_dassert(receive_rc == 0); ss_dassert(receive_rc == 0);
@ -326,7 +333,7 @@ static int gw_read_backend_event(DCB *dcb)
pthread_self(), pthread_self(),
dcb, dcb,
dcb->fd, dcb->fd,
current_session->user); local_session.user);
rc = 0; rc = 0;
goto return_with_lock; goto return_with_lock;
break; break;
@ -416,7 +423,7 @@ static int gw_read_backend_event(DCB *dcb)
"user %s.", "user %s.",
pthread_self(), pthread_self(),
dcb->fd, dcb->fd,
current_session->user); local_session.user);
/* check the delay queue and flush the data */ /* check the delay queue and flush the data */
if (dcb->delayq) if (dcb->delayq)
@ -487,7 +494,7 @@ static int gw_read_backend_event(DCB *dcb)
if (dcb->dcb_readqueue) 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); 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 * If protocol has session command set, concatenate whole
* response into one buffer. * 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)); 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 " "Read buffer unexpectedly null, even though response "
"not marked as complete. User: %s", "not marked as complete. User: %s",
pthread_self(), pthread_self(),
current_session->user); local_session.user);
rc = 0; rc = 0;
goto return_rc; goto return_rc;
} }
@ -610,7 +617,7 @@ static int gw_write_backend_event(DCB *dcb)
if (dcb->writeq != NULL) if (dcb->writeq != NULL)
{ {
data = (uint8_t *)GWBUF_DATA(dcb->writeq); data = (uint8_t *) GWBUF_DATA(dcb->writeq);
if (dcb->session->client == NULL) if (dcb->session->client == NULL)
{ {
@ -823,7 +830,7 @@ static int gw_error_backend_event(DCB *dcb)
len = sizeof(error); 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) if (error != 0)
{ {
@ -861,7 +868,7 @@ static int gw_error_backend_event(DCB *dcb)
int error, len; int error, len;
len = sizeof(error); 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) if (error != 0)
{ {
@ -939,10 +946,10 @@ static int gw_create_backend_connection(DCB *backend_dcb,
{ {
/** Copy client flags to backend protocol */ /** Copy client flags to backend protocol */
protocol->client_capabilities = 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 */ /** Copy client charset to backend protocol */
protocol->charset = protocol->charset =
((MySQLProtocol *)(backend_dcb->session->client->protocol))->charset; ((MySQLProtocol *) (backend_dcb->session->client->protocol))->charset;
} }
else else
{ {
@ -1002,7 +1009,6 @@ return_fd:
return fd; return fd;
} }
/** /**
* Error event handler. * Error event handler.
* Create error message, pass it to router's error handler and if error * 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; int error, len;
len = sizeof(error); 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) if (error != 0 && ses_state != SESSION_STATE_STOPPING)
{ {
@ -1238,12 +1244,11 @@ static int backend_write_delayqueue(DCB *dcb)
if (MYSQL_IS_CHANGE_USER(((uint8_t *)GWBUF_DATA(localq)))) if (MYSQL_IS_CHANGE_USER(((uint8_t *)GWBUF_DATA(localq))))
{ {
MYSQL_session* mses; MYSQL_session mses;
GWBUF* new_packet; GWBUF* new_packet;
mses = (MYSQL_session *)dcb->session->client->data; gw_get_shared_session_auth_info(dcb, &mses);
new_packet = gw_create_change_user_packet(mses, new_packet = gw_create_change_user_packet(&mses, dcb->protocol);
(MySQLProtocol *)dcb->protocol);
/** /**
* Remove previous packet which lacks scramble * Remove previous packet which lacks scramble
* and append the new. * and append the new.
@ -1315,10 +1320,10 @@ static int gw_change_user(DCB *backend,
MYSQL_session *current_session = NULL; MYSQL_session *current_session = NULL;
MySQLProtocol *backend_protocol = NULL; MySQLProtocol *backend_protocol = NULL;
MySQLProtocol *client_protocol = NULL; MySQLProtocol *client_protocol = NULL;
char username[MYSQL_USER_MAXLEN+1]=""; char username[MYSQL_USER_MAXLEN + 1] = "";
char database[MYSQL_DATABASE_MAXLEN+1]=""; char database[MYSQL_DATABASE_MAXLEN + 1] = "";
char current_database[MYSQL_DATABASE_MAXLEN+1]=""; char current_database[MYSQL_DATABASE_MAXLEN + 1] = "";
uint8_t client_sha1[MYSQL_SCRAMBLE_LEN]=""; uint8_t client_sha1[MYSQL_SCRAMBLE_LEN] = "";
uint8_t *client_auth_packet = GWBUF_DATA(queue); uint8_t *client_auth_packet = GWBUF_DATA(queue);
unsigned int auth_token_len = 0; unsigned int auth_token_len = 0;
uint8_t *auth_token = NULL; 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 */ /* now get the user, after 4 bytes header and 1 byte command */
client_auth_packet += 5; 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; client_auth_packet += strlen(username) + 1;
/* get the auth token len */ /* get the auth token len */
@ -1354,7 +1359,7 @@ static int gw_change_user(DCB *backend,
} }
/* get new database name */ /* 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 */ /* get character set */
if (strlen(database)) if (strlen(database))
@ -1371,44 +1376,47 @@ 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 */
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. * 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. * 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 * 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,
client_protocol->scramble,
sizeof(client_protocol->scramble),
username,
client_sha1);
if (auth_ret != 0)
{
if (!service_refresh_users(backend->session->client->service))
{
/* 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, auth_ret = gw_check_mysql_scramble_data(backend->session->client,
auth_token, auth_token_len, auth_token, auth_token_len,
client_protocol->scramble, client_protocol->scramble,
sizeof(client_protocol->scramble), sizeof(client_protocol->scramble),
username, username, client_sha1);
client_sha1); strncpy(current_session->db, current_database, MYSQL_DATABASE_MAXLEN);
} spinlock_release(&in_session->ses_lock);
}
/* copy back current datbase to client session */ if (auth_ret != 0)
strcpy(current_session->db, current_database); {
if (service_refresh_users(backend->session->client->service) == 0)
{
/* Try authentication again with new repository data */
/* Note: if no auth client authentication will fail */
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);
strncpy(current_session->db, current_database, MYSQL_DATABASE_MAXLEN);
spinlock_release(&in_session->ses_lock);
}
}
/* let's free the auth_token now */ /* let's free the auth_token now */
if (auth_token) if (auth_token)
@ -1457,7 +1465,9 @@ static int gw_change_user(DCB *backend,
MYSQL_COM_CHANGE_USER); MYSQL_COM_CHANGE_USER);
modutil_reply_auth_error(backend, message, 0); modutil_reply_auth_error(backend, message, 0);
rv = 1; rv = 1;
} else { }
else
{
rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol); rv = gw_send_change_user_to_backend(database, username, client_sha1, backend_protocol);
/* /*
* Now copy new data into user session * Now copy new data into user session
@ -1473,7 +1483,6 @@ retblock:
return rv; return rv;
} }
/** /**
* Move packets or parts of packets from readbuf to outbuf as the packet headers * Move packets or parts of packets from readbuf to outbuf as the packet headers
* and lengths have been noticed and counted. * and lengths have been noticed and counted.
@ -1583,8 +1592,8 @@ static GWBUF* process_response_data(DCB* dcb,
/** Move the prefix of the buffer to outbuf from redbuf */ /** Move the prefix of the buffer to outbuf from redbuf */
outbuf = gwbuf_append(outbuf, outbuf = gwbuf_append(outbuf,
gwbuf_clone_portion(readbuf, 0, (size_t)nbytes_left)); gwbuf_clone_portion(readbuf, 0, (size_t) nbytes_left));
readbuf = gwbuf_consume(readbuf, (size_t)nbytes_left); readbuf = gwbuf_consume(readbuf, (size_t) nbytes_left);
ss_dassert(npackets_left > 0); ss_dassert(npackets_left > 0);
npackets_left -= 1; npackets_left -= 1;
nbytes_left = 0; nbytes_left = 0;
@ -1624,19 +1633,19 @@ static GWBUF* process_response_data(DCB* dcb,
{ {
MXS_DEBUG("%lu [%s] Read %d packets. Waiting for %d more " MXS_DEBUG("%lu [%s] Read %d packets. Waiting for %d more "
"packets for a total of %d packets.", "packets for a total of %d packets.",
pthread_self(),__FUNCTION__, pthread_self(), __FUNCTION__,
initial_packets - npackets_left, initial_packets - npackets_left,
npackets_left,initial_packets); npackets_left, initial_packets);
/** Store the already read data into the readqueue of the DCB /** Store the already read data into the readqueue of the DCB
* and restore the response status to the initial number of packets */ * 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); protocol_set_response_status(p, initial_packets, initial_bytes);
return NULL; return NULL;
} }
data = GWBUF_DATA(readbuf); 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 */ /** Store new status to protocol structure */
protocol_set_response_status(p, npackets_left, nbytes_left); protocol_set_response_status(p, npackets_left, nbytes_left);
} }
@ -1645,7 +1654,6 @@ static GWBUF* process_response_data(DCB* dcb,
return outbuf; return outbuf;
} }
static bool sescmd_response_complete(DCB* dcb) static bool sescmd_response_complete(DCB* dcb)
{ {
int npackets_left; int npackets_left;

View File

@ -1566,8 +1566,6 @@ void check_drop_tmp_table(
char** tbl = NULL; char** tbl = NULL;
char *hkey,*dbname; char *hkey,*dbname;
MYSQL_session* data; MYSQL_session* data;
DCB* master_dcb = NULL;
rses_property_t* rses_prop_tmp; rses_property_t* rses_prop_tmp;
if(router_cli_ses == NULL || querybuf == NULL) if(router_cli_ses == NULL || querybuf == NULL)
@ -1577,27 +1575,14 @@ void check_drop_tmp_table(
return; 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.", MXS_ERROR("[%s] Error: Client DCB is NULL.", __FUNCTION__);
__FUNCTION__);
return; return;
} }
rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES]; rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES];
master_dcb = router_cli_ses->rses_master_ref->bref_dcb; data = (MYSQL_session*)router_cli_ses->client_dcb->session->data;
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;
if(data == NULL) if(data == NULL)
{ {
@ -1668,32 +1653,20 @@ static qc_query_type_t is_read_tmp_table(
return type; 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.", MXS_ERROR("[%s] Error: Client DCB is NULL.", __FUNCTION__);
__FUNCTION__);
return type; return type;
} }
if (BREF_IS_IN_USE(router_cli_ses->rses_master_ref)) if (BREF_IS_IN_USE(router_cli_ses->rses_master_ref))
{ {
rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES]; rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES];
master_dcb = router_cli_ses->rses_master_ref->bref_dcb; data = (MYSQL_session*)router_cli_ses->client_dcb->session->data;
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;
if(data == NULL) 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; return qtype;
} }
@ -1765,7 +1738,6 @@ static void check_create_tmp_table(
int klen = 0; int klen = 0;
char *hkey,*dbname; char *hkey,*dbname;
MYSQL_session* data; MYSQL_session* data;
DCB* master_dcb = NULL;
rses_property_t* rses_prop_tmp; rses_property_t* rses_prop_tmp;
HASHTABLE* h; HASHTABLE* h;
@ -1776,28 +1748,15 @@ static void check_create_tmp_table(
return; 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.", MXS_ERROR("[%s] Error: Client DCB is NULL.", __FUNCTION__);
__FUNCTION__);
return; return;
} }
router_cli_ses->have_tmp_tables = true; router_cli_ses->have_tmp_tables = true;
rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES]; rses_prop_tmp = router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES];
master_dcb = router_cli_ses->rses_master_ref->bref_dcb; data = (MYSQL_session*)router_cli_ses->client_dcb->session->data;
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;
if(data == NULL) if(data == NULL)
{ {
@ -2097,10 +2056,10 @@ static bool route_single_stmt(
* Read stored master DCB pointer. If master is not set, routing must * Read stored master DCB pointer. If master is not set, routing must
* be aborted * 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); char* query_str = modutil_get_query(querybuf);
CHK_DCB(master_dcb);
MXS_ERROR("Can't route %s:%s:\"%s\" to " MXS_ERROR("Can't route %s:%s:\"%s\" to "
"backend server. Session doesn't have a Master " "backend server. Session doesn't have a Master "
"node", "node",
@ -2112,6 +2071,7 @@ static bool route_single_stmt(
goto retblock; goto retblock;
} }
CHK_DCB(master_dcb);
packet = GWBUF_DATA(querybuf); packet = GWBUF_DATA(querybuf);
packet_len = gw_mysql_get_byte3(packet); packet_len = gw_mysql_get_byte3(packet);
@ -2491,7 +2451,6 @@ static bool route_single_stmt(
#if defined(SS_EXTRA_DEBUG) #if defined(SS_EXTRA_DEBUG)
MXS_INFO("Found DCB for slave."); MXS_INFO("Found DCB for slave.");
#endif #endif
atomic_add(&inst->stats.n_slave, 1); atomic_add(&inst->stats.n_slave, 1);
} }
else else
@ -2847,21 +2806,17 @@ static void clientReply (
uint8_t* replybuf = (uint8_t *)GWBUF_DATA(writebuf); uint8_t* replybuf = (uint8_t *)GWBUF_DATA(writebuf);
size_t len = MYSQL_GET_PACKET_LEN(buf); size_t len = MYSQL_GET_PACKET_LEN(buf);
size_t replylen = MYSQL_GET_PACKET_LEN(replybuf); size_t replylen = MYSQL_GET_PACKET_LEN(replybuf);
char* cmdstr = strndup(&((char *)buf)[5], len-4);
char* err = strndup(&((char *)replybuf)[8], 5); char* err = strndup(&((char *)replybuf)[8], 5);
char* replystr = strndup(&((char *)replybuf)[13], char* replystr = strndup(&((char *)replybuf)[13],
replylen-4-5); replylen-4-5);
ss_dassert(len+4 == GWBUF_LENGTH(scur->scmd_cur_cmd->my_sescmd_buf)); ss_dassert(len+4 == GWBUF_LENGTH(scur->scmd_cur_cmd->my_sescmd_buf));
MXS_ERROR("Failed to execute %s in %s:%d. %s %s", MXS_ERROR("Failed to execute session command in %s:%d. Error was: %s %s",
cmdstr,
bref->bref_backend->backend_server->name, bref->bref_backend->backend_server->name,
bref->bref_backend->backend_server->port, bref->bref_backend->backend_server->port,
err, err,
replystr); replystr);
free(cmdstr);
free(err); free(err);
free(replystr); free(replystr);
} }
@ -2893,12 +2848,10 @@ static void clientReply (
* This applies to session commands only. Counter decrement * This applies to session commands only. Counter decrement
* for other type of queries is done outside this block. * for other type of queries is done outside this block.
*/ */
if (writebuf != NULL && client_dcb != NULL)
{
/** Set response status as replied */ /** Set response status as replied */
bref_clear_state(bref, BREF_WAITING_RESULT); bref_clear_state(bref, BREF_WAITING_RESULT);
} }
}
/** /**
* Clear BREF_QUERY_ACTIVE flag and decrease waiter counter. * Clear BREF_QUERY_ACTIVE flag and decrease waiter counter.
* This applies for queries other than session commands. * This applies for queries other than session commands.
@ -3815,8 +3768,8 @@ static GWBUF* sescmd_cursor_process_replies(
if(bref->reply_cmd != scmd->reply_cmd) if(bref->reply_cmd != scmd->reply_cmd)
{ {
MXS_INFO("Backend server '%s' response differs from master's response. " MXS_ERROR("Slave server '%s': response differs from master's response. "
"Closing connection.", "Closing connection due to inconsistent session state.",
bref->bref_backend->backend_server->unique_name); bref->bref_backend->backend_server->unique_name);
sescmd_cursor_set_active(scur,false); sescmd_cursor_set_active(scur,false);
bref_clear_state(bref,BREF_QUERY_ACTIVE); 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; bool rval = false;
spinlock_acquire(&client->shardmap->lock); spinlock_acquire(&client->shardmap->lock);
if (client->shardmap->state == SHMAP_READY) if (client->shardmap->state != SHMAP_UNINIT)
{ {
struct string_array strarray; struct string_array strarray;
const int size = hashtable_size(client->shardmap->hash); const int size = hashtable_size(client->shardmap->hash);
@ -1849,11 +1849,6 @@ static int routeQuery(ROUTER* instance,
char errbuf[26+MYSQL_DATABASE_MAXLEN]; char errbuf[26+MYSQL_DATABASE_MAXLEN];
CHK_CLIENT_RSES(router_cli_ses); 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)) if (!rses_begin_locked_router_action(router_cli_ses))
@ -4313,7 +4308,7 @@ int process_show_shards(ROUTER_CLIENT_SES* rses)
int rval = 0; int rval = 0;
spinlock_acquire(&rses->shardmap->lock); spinlock_acquire(&rses->shardmap->lock);
if (rses->shardmap->state == SHMAP_READY) if(rses->shardmap->state != SHMAP_UNINIT)
{ {
HASHITERATOR* iter = hashtable_iterator(rses->shardmap->hash); HASHITERATOR* iter = hashtable_iterator(rses->shardmap->hash);
struct shard_list sl; struct shard_list sl;
@ -4380,7 +4375,7 @@ bool handle_default_db(ROUTER_CLIENT_SES *router_cli_ses)
char* target = NULL; char* target = NULL;
spinlock_acquire(&router_cli_ses->shardmap->lock); 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); target = hashtable_fetch(router_cli_ses->shardmap->hash, router_cli_ses->connect_db);
} }