Merge branch '2.0' into develop
This commit is contained in:
@ -14,6 +14,7 @@
|
|||||||
as JSON objects (beta level functionality).
|
as JSON objects (beta level functionality).
|
||||||
|
|
||||||
For more details, please refer to:
|
For more details, please refer to:
|
||||||
|
* [MariaDB MaxScale 2.0.3 Release Notes](Release-Notes/MaxScale-2.0.3-Release-Notes.md)
|
||||||
* [MariaDB MaxScale 2.0.2 Release Notes](Release-Notes/MaxScale-2.0.2-Release-Notes.md)
|
* [MariaDB MaxScale 2.0.2 Release Notes](Release-Notes/MaxScale-2.0.2-Release-Notes.md)
|
||||||
* [MariaDB MaxScale 2.0.1 Release Notes](Release-Notes/MaxScale-2.0.1-Release-Notes.md)
|
* [MariaDB MaxScale 2.0.1 Release Notes](Release-Notes/MaxScale-2.0.1-Release-Notes.md)
|
||||||
* [MariaDB MaxScale 2.0.0 Release Notes](Release-Notes/MaxScale-2.0.0-Release-Notes.md)
|
* [MariaDB MaxScale 2.0.0 Release Notes](Release-Notes/MaxScale-2.0.0-Release-Notes.md)
|
||||||
|
@ -622,6 +622,10 @@ serverB | 15 | 27%
|
|||||||
serverC | 10 | 18%
|
serverC | 10 | 18%
|
||||||
serverD | 20 | 36%
|
serverD | 20 | 36%
|
||||||
|
|
||||||
|
_**Note**: If the value of the weighting parameter of an individual server is
|
||||||
|
zero or the relative weight rounds down to zero, no queries will be routed to
|
||||||
|
that server as long as a server with a positive weight is available._
|
||||||
|
|
||||||
Here is an excerpt from an example configuration with the `serv_weight` parameter
|
Here is an excerpt from an example configuration with the `serv_weight` parameter
|
||||||
used as the weighting parameter.
|
used as the weighting parameter.
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@ This document describes the changes in release 2.0.3, when compared to
|
|||||||
release [2.0.2](MaxScale-2.0.2-Release-Notes.md).
|
release [2.0.2](MaxScale-2.0.2-Release-Notes.md).
|
||||||
|
|
||||||
If you are upgrading from release 1.4.4, please also read the release
|
If you are upgrading from release 1.4.4, please also read the release
|
||||||
notes of release [2.0.0](./MaxScale-2.0.0-Release-Notes.md) and
|
notes of release [2.0.0](./MaxScale-2.0.0-Release-Notes.md),
|
||||||
release [2.0.1](./MaxScale-2.0.1-Release-Notes.md).
|
release [2.0.1](./MaxScale-2.0.1-Release-Notes.md) and
|
||||||
|
release [2.0.2](./MaxScale-2.0.2-Release-Notes.md).
|
||||||
|
|
||||||
For any problems you encounter, please submit a bug report at
|
For any problems you encounter, please submit a bug report at
|
||||||
[Jira](https://jira.mariadb.org).
|
[Jira](https://jira.mariadb.org).
|
||||||
@ -22,9 +23,18 @@ support systemd.
|
|||||||
## Bug fixes
|
## Bug fixes
|
||||||
|
|
||||||
[Here](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.0.3)
|
[Here](https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.0.3)
|
||||||
is a list of bugs fixed since the release of MaxScale 2.0.1.
|
is a list of bugs fixed since the release of MaxScale 2.0.2.
|
||||||
|
|
||||||
|
* [MXS-1048](https://jira.mariadb.org/browse/MXS-1048): ShemaRouter can't handle backquoted database names
|
||||||
|
* [MXS-1047](https://jira.mariadb.org/browse/MXS-1047): Batch inserts through Maxscale with C/J stall
|
||||||
|
* [MXS-1045](https://jira.mariadb.org/browse/MXS-1045): Defunct processes after maxscale have executed script during failover
|
||||||
|
* [MXS-1044](https://jira.mariadb.org/browse/MXS-1044): Init-Script for SLES 11 displays error messages when called
|
||||||
|
* [MXS-1043](https://jira.mariadb.org/browse/MXS-1043): Reading last insert id from @@identity variable does not work with maxscale
|
||||||
|
* [MXS-1033](https://jira.mariadb.org/browse/MXS-1033): maxscale crushes on maxadmin request
|
||||||
|
* [MXS-1026](https://jira.mariadb.org/browse/MXS-1026): Crash with NullAuth authenticator
|
||||||
* [MXS-1009](https://jira.mariadb.org/browse/MXS-1009): maxinfo sigsegv in spinlock_release
|
* [MXS-1009](https://jira.mariadb.org/browse/MXS-1009): maxinfo sigsegv in spinlock_release
|
||||||
|
* [MXS-964](https://jira.mariadb.org/browse/MXS-964): Fatal: MaxScale 2.0.1 received fatal signal 6
|
||||||
|
* [MXS-956](https://jira.mariadb.org/browse/MXS-956): Maxscale crash: Removing DCB 0x7fbf94016760 but was in state DCB_STATE_DISCONNECTED which is not legal for a call to dcb_close
|
||||||
|
|
||||||
## Known Issues and Limitations
|
## Known Issues and Limitations
|
||||||
|
|
||||||
@ -45,4 +55,3 @@ from the version of MaxScale. For instance, the tag of version `X.Y.Z` of MaxSca
|
|||||||
is `maxscale-X.Y.Z`.
|
is `maxscale-X.Y.Z`.
|
||||||
|
|
||||||
The source code is available [here](https://github.com/mariadb-corporation/MaxScale).
|
The source code is available [here](https://github.com/mariadb-corporation/MaxScale).
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ issues and communicate with the MaxScale community.
|
|||||||
- Email: maxscale@googlegroups.com
|
- Email: maxscale@googlegroups.com
|
||||||
- Forum: http://groups.google.com/forum/#!forum/maxscale
|
- Forum: http://groups.google.com/forum/#!forum/maxscale
|
||||||
|
|
||||||
|
We're also on the #maria and #maxscale channels on FreeNode.
|
||||||
|
|
||||||
Please report all feature requests, improvements and bugs in the [MariaDB Jira](https://jira.mariadb.org/projects/MXS/issues).
|
Please report all feature requests, improvements and bugs in the [MariaDB Jira](https://jira.mariadb.org/projects/MXS/issues).
|
||||||
|
|
||||||
# Documentation
|
# Documentation
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version")
|
set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version")
|
||||||
set(MAXSCALE_VERSION_MINOR "0" CACHE STRING "Minor version")
|
set(MAXSCALE_VERSION_MINOR "0" CACHE STRING "Minor version")
|
||||||
set(MAXSCALE_VERSION_PATCH "2" CACHE STRING "Patch version")
|
set(MAXSCALE_VERSION_PATCH "3" CACHE STRING "Patch version")
|
||||||
|
|
||||||
# This should only be incremented if a package is rebuilt
|
# This should only be incremented if a package is rebuilt
|
||||||
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")
|
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")
|
||||||
|
@ -1,24 +1,29 @@
|
|||||||
# Check which init.d script to install
|
# Check which init.d script to install
|
||||||
find_file(RPM_FNC functions PATHS /etc/rc.d/init.d)
|
find_file(RPM_FNC functions PATHS /etc/rc.d/init.d)
|
||||||
find_file(DEB_FNC init-functions PATHS /lib/lsb)
|
find_file(DEB_FNC init-functions PATHS /lib/lsb)
|
||||||
|
find_file(SLES_FNC SuSE-release PATHS /etc)
|
||||||
|
|
||||||
if(${RPM_FNC} MATCHES "NOTFOUND" AND ${DEB_FNC} MATCHES "NOTFOUND")
|
if(EXISTS ${RPM_FNC})
|
||||||
message(FATAL_ERROR "Cannot find required init-functions in /lib/lsb/ or /etc/rc.d/init.d/, please confirm that your system files are OK.")
|
set(USE_RPM TRUE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
|
||||||
elseif(${RPM_FNC} MATCHES "NOTFOUND")
|
elseif(EXISTS ${SLES_FNC})
|
||||||
set(HAVE_LSB_FUNCTIONS TRUE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
|
set(USE_SLES TRUE CACHE BOOL "SLES11 has reduced /lib/lsb/init-functions and needs a special init-script")
|
||||||
|
elseif(EXISTS ${DEB_FNC})
|
||||||
|
set(USE_DEB TRUE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
|
||||||
else()
|
else()
|
||||||
set(HAVE_LSB_FUNCTIONS FALSE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
|
message(FATAL_ERROR "Cannot find required init-functions in /lib/lsb/ or /etc/rc.d/init.d/, please confirm that your system files are OK.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(USE_DEB)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/etc/ubuntu/init.d/maxscale.in ${CMAKE_BINARY_DIR}/maxscale @ONLY)
|
||||||
|
elseif(USE_RPM)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/etc/init.d/maxscale.in ${CMAKE_BINARY_DIR}/maxscale @ONLY)
|
||||||
|
elseif(USE_SLES)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/etc/sles11/init.d/maxscale.in ${CMAKE_BINARY_DIR}/maxscale @ONLY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/etc/maxscale.conf.in ${CMAKE_BINARY_DIR}/maxscale.conf @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/etc/maxscale.conf.in ${CMAKE_BINARY_DIR}/maxscale.conf @ONLY)
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/etc/maxscale.service.in ${CMAKE_BINARY_DIR}/maxscale.service @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/etc/maxscale.service.in ${CMAKE_BINARY_DIR}/maxscale.service @ONLY)
|
||||||
|
|
||||||
if(HAVE_LSB_FUNCTIONS)
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/etc/ubuntu/init.d/maxscale.in ${CMAKE_BINARY_DIR}/maxscale @ONLY)
|
|
||||||
else()
|
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/etc/init.d/maxscale.in ${CMAKE_BINARY_DIR}/maxscale @ONLY)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(PACKAGE)
|
if(PACKAGE)
|
||||||
message(STATUS "maxscale.conf will unpack to: /etc/ld.so.conf.d")
|
message(STATUS "maxscale.conf will unpack to: /etc/ld.so.conf.d")
|
||||||
message(STATUS "startup scripts will unpack to to: /etc/init.d")
|
message(STATUS "startup scripts will unpack to to: /etc/init.d")
|
||||||
|
164
etc/sles11/init.d/maxscale.in
Executable file
164
etc/sles11/init.d/maxscale.in
Executable file
@ -0,0 +1,164 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# maxscale: The MariaDB Corporation MaxScale database proxy
|
||||||
|
#
|
||||||
|
# description: MaxScale provides database specific proxy functionality
|
||||||
|
#
|
||||||
|
# processname: maxscale
|
||||||
|
#
|
||||||
|
### BEGIN INIT INFO
|
||||||
|
# Provides: maxscale
|
||||||
|
# Required-Start: $syslog $local_fs
|
||||||
|
# Required-Stop: $syslog $local_fs
|
||||||
|
# Default-Start: 2 3 4 5
|
||||||
|
# Default-Stop: 0 1 6
|
||||||
|
# Short-Description: The maxscale database proxy
|
||||||
|
# Description: MaxScale is a database proxy server that can be used to front end
|
||||||
|
# database clusters offering different routing, filtering and protocol choices
|
||||||
|
### END INIT INFO
|
||||||
|
|
||||||
|
#############################################
|
||||||
|
# MaxScale HOME, PIDFILE, LIB
|
||||||
|
#############################################
|
||||||
|
|
||||||
|
export MAXSCALE_PIDFILE=@MAXSCALE_VARDIR@/run/maxscale/maxscale.pid
|
||||||
|
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:@CMAKE_INSTALL_PREFIX@/@MAXSCALE_LIBDIR@/maxscale
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# LSB Exit codes (non-Status)
|
||||||
|
###############################
|
||||||
|
_RETVAL_GENERIC=1
|
||||||
|
_RETVAL_NOT_INSTALLED=5
|
||||||
|
_RETVAL_NOT_RUNNING=7
|
||||||
|
|
||||||
|
###############################
|
||||||
|
# LSB Status action Exit codes
|
||||||
|
###############################
|
||||||
|
_RETVAL_STATUS_OK=0
|
||||||
|
_RETVAL_STATUS_NOT_RUNNING=3
|
||||||
|
|
||||||
|
# Sanity checks.
|
||||||
|
[ -x @CMAKE_INSTALL_PREFIX@/@MAXSCALE_BINDIR@/maxscale ] || exit $_RETVAL_NOT_INSTALLED
|
||||||
|
|
||||||
|
# Source additional command line arguments.
|
||||||
|
[ -f /etc/default/maxscale ] && . /etc/default/maxscale
|
||||||
|
|
||||||
|
#################################
|
||||||
|
# stop/start/status related vars
|
||||||
|
#################################
|
||||||
|
NAME=maxscale
|
||||||
|
DAEMON=@CMAKE_INSTALL_PREFIX@/@MAXSCALE_BINDIR@/maxscale
|
||||||
|
DAEMON_OPTS="--user=maxscale $MAXSCALE_OPTIONS"
|
||||||
|
|
||||||
|
# Source function library.
|
||||||
|
. /lib/lsb/init-functions
|
||||||
|
|
||||||
|
# we can rearrange this easily
|
||||||
|
processname=maxscale
|
||||||
|
servicename=maxscale
|
||||||
|
|
||||||
|
RETVAL=0
|
||||||
|
|
||||||
|
start() {
|
||||||
|
|
||||||
|
if [ ! -d @MAXSCALE_VARDIR@/log/maxscale ]
|
||||||
|
then
|
||||||
|
mkdir -p @MAXSCALE_VARDIR@/log/maxscale
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d @MAXSCALE_VARDIR@/cache/maxscale ]
|
||||||
|
then
|
||||||
|
mkdir -p @MAXSCALE_VARDIR@/cache/maxscale
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d @MAXSCALE_VARDIR@/lib/maxscale ]
|
||||||
|
then
|
||||||
|
mkdir -p @MAXSCALE_VARDIR@/lib/maxscale
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d @MAXSCALE_VARDIR@/run/maxscale ]
|
||||||
|
then
|
||||||
|
mkdir -p @MAXSCALE_VARDIR@/run/maxscale
|
||||||
|
fi
|
||||||
|
|
||||||
|
chown -R maxscale:maxscale @MAXSCALE_VARDIR@/log/maxscale
|
||||||
|
chown -R maxscale:maxscale @MAXSCALE_VARDIR@/lib/maxscale
|
||||||
|
chown -R maxscale:maxscale @MAXSCALE_VARDIR@/cache/maxscale
|
||||||
|
chown -R maxscale:maxscale @MAXSCALE_VARDIR@/run/maxscale
|
||||||
|
chmod 0755 @MAXSCALE_VARDIR@/log/maxscale
|
||||||
|
chmod 0755 @MAXSCALE_VARDIR@/lib/maxscale
|
||||||
|
chmod 0755 @MAXSCALE_VARDIR@/cache/maxscale
|
||||||
|
chmod 0755 @MAXSCALE_VARDIR@/run/maxscale
|
||||||
|
|
||||||
|
ulimit -HSn 65535
|
||||||
|
echo -n "Starting MaxScale"
|
||||||
|
start_daemon -p "$MAXSCALE_PIDFILE" $DAEMON $DAEMON_OPTS 2> /dev/null > /dev/null
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
checkproc $DAEMON
|
||||||
|
rc_status -v
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() {
|
||||||
|
echo -n "Stopping MaxScale"
|
||||||
|
|
||||||
|
maxscale_wait_stop
|
||||||
|
rc_status -v
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
echo -n "Reloading MaxScale"
|
||||||
|
|
||||||
|
kill -HUP $(cat "$MAXSCALE_PIDFILE")
|
||||||
|
rc_status -v
|
||||||
|
}
|
||||||
|
|
||||||
|
maxscale_wait_stop() {
|
||||||
|
PIDTMP=$(pidofproc -p "$MAXSCALE_PIDFILE" "$DAEMON")
|
||||||
|
kill -TERM "${PIDTMP:-}" 2> /dev/null;
|
||||||
|
if [ -n "${PIDTMP:-}" ] && kill -0 "${PIDTMP:-}" 2> /dev/null; then
|
||||||
|
local i=0
|
||||||
|
while kill -0 "${PIDTMP:-}" 2> /dev/null; do
|
||||||
|
if [ $i = '60' ]; then
|
||||||
|
break
|
||||||
|
STATUS=2
|
||||||
|
fi
|
||||||
|
[ "$VERBOSE" != no ] && echo -n "."
|
||||||
|
sleep 1
|
||||||
|
i=$(($i+1))
|
||||||
|
done
|
||||||
|
return $STATUS
|
||||||
|
else
|
||||||
|
return $STATUS
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# See how we were called.
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
stop
|
||||||
|
;;
|
||||||
|
status)
|
||||||
|
# return 0 on success
|
||||||
|
# return 3 on any error
|
||||||
|
echo -n "Checking MaxScale"
|
||||||
|
checkproc $DAEMON
|
||||||
|
rc_status -v
|
||||||
|
;;
|
||||||
|
restart)
|
||||||
|
stop
|
||||||
|
start
|
||||||
|
;;
|
||||||
|
reload)
|
||||||
|
reload
|
||||||
|
RETVAL=$?
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo $"Usage: $0 {start|stop|status|restart|reload}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit $RETVAL
|
@ -12,7 +12,7 @@ respawn
|
|||||||
# respawn limit 2 5
|
# respawn limit 2 5
|
||||||
|
|
||||||
# Unlimited open files
|
# Unlimited open files
|
||||||
limit nofile unlimited unlimited
|
limit nofile 65535 65535
|
||||||
|
|
||||||
# Make sure /var/run/maxscale exists
|
# Make sure /var/run/maxscale exists
|
||||||
pre-start exec /usr/bin/install -d -o maxscale -g maxscale @MAXSCALE_VARDIR@/run/maxscale
|
pre-start exec /usr/bin/install -d -o maxscale -g maxscale @MAXSCALE_VARDIR@/run/maxscale
|
||||||
|
@ -1305,6 +1305,7 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
if (!rses_begin_locked_router_action(rses))
|
if (!rses_begin_locked_router_action(rses))
|
||||||
{
|
{
|
||||||
/** Session is already closed */
|
/** Session is already closed */
|
||||||
|
problem_dcb->dcb_errhandle_called = true;
|
||||||
*succp = false;
|
*succp = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1327,15 +1328,17 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
}
|
}
|
||||||
session = problem_dcb->session;
|
session = problem_dcb->session;
|
||||||
|
|
||||||
bool close_dcb = true;
|
|
||||||
backend_ref_t *bref = get_bref_from_dcb(rses, problem_dcb);
|
backend_ref_t *bref = get_bref_from_dcb(rses, problem_dcb);
|
||||||
|
|
||||||
if (session == NULL || rses == NULL)
|
if (session == NULL)
|
||||||
{
|
{
|
||||||
|
MXS_ERROR("Session of DCB %p is NULL, won't close the DCB.", problem_dcb);
|
||||||
|
ss_dassert(false);
|
||||||
*succp = false;
|
*succp = false;
|
||||||
}
|
}
|
||||||
else if (DCB_ROLE_CLIENT_HANDLER == problem_dcb->dcb_role)
|
else if (DCB_ROLE_CLIENT_HANDLER == problem_dcb->dcb_role)
|
||||||
{
|
{
|
||||||
|
dcb_close(problem_dcb);
|
||||||
*succp = false;
|
*succp = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1383,6 +1386,9 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
if (bref != NULL)
|
if (bref != NULL)
|
||||||
{
|
{
|
||||||
CHK_BACKEND_REF(bref);
|
CHK_BACKEND_REF(bref);
|
||||||
|
RW_CHK_DCB(bref, problem_dcb);
|
||||||
|
dcb_close(problem_dcb);
|
||||||
|
RW_CLOSE_BREF(bref);
|
||||||
close_failed_bref(bref, true);
|
close_failed_bref(bref, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1399,21 +1405,13 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
*succp = handle_error_new_connection(inst, &rses, problem_dcb, errmsgbuf);
|
*succp = handle_error_new_connection(inst, &rses, problem_dcb, errmsgbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
RW_CHK_DCB(bref, problem_dcb);
|
|
||||||
|
|
||||||
if (bref)
|
if (bref)
|
||||||
{
|
{
|
||||||
/** This is a valid DCB for a backend ref */
|
/** This is a valid DCB for a backend ref */
|
||||||
|
if (BREF_IS_IN_USE(bref) && bref->bref_dcb == problem_dcb)
|
||||||
if (!BREF_IS_IN_USE(bref) || bref->bref_dcb != problem_dcb)
|
|
||||||
{
|
{
|
||||||
/** The backend is closed or the reference was replaced */
|
ss_dassert(false);
|
||||||
dcb_close(problem_dcb);
|
MXS_ERROR("Backend '%s' is still in use and points to the problem DCB.",
|
||||||
RW_CLOSE_BREF(bref);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MXS_ERROR("Backend '%s' is still in use and points to the problem DCB. Not closing.",
|
|
||||||
bref->ref->server->unique_name);
|
bref->ref->server->unique_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1425,29 +1423,13 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
MXS_ERROR("DCB connected to '%s' is not in use by the router "
|
MXS_ERROR("DCB connected to '%s' is not in use by the router "
|
||||||
"session, not closing it. DCB is in state '%s'",
|
"session, not closing it. DCB is in state '%s'",
|
||||||
remote, STRDCBSTATE(problem_dcb->state));
|
remote, STRDCBSTATE(problem_dcb->state));
|
||||||
MXS_ERROR("Backends currently in use:");
|
|
||||||
|
|
||||||
for (int i = 0; i < rses->rses_nbackends; i++)
|
|
||||||
{
|
|
||||||
dcb_state_t state = DCB_STATE_UNDEFINED;
|
|
||||||
if (BREF_IS_IN_USE(&rses->rses_backend_ref[i]))
|
|
||||||
{
|
|
||||||
state = rses->rses_backend_ref[i].bref_dcb->state;
|
|
||||||
}
|
|
||||||
|
|
||||||
MXS_ERROR("%p: %s - %p", &rses->rses_backend_ref[i], STRDCBSTATE(state),
|
|
||||||
rses->rses_backend_ref[i].bref_dcb);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close_dcb = false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ERRACT_REPLY_CLIENT:
|
case ERRACT_REPLY_CLIENT:
|
||||||
{
|
{
|
||||||
handle_error_reply_client(session, rses, problem_dcb, errmsgbuf);
|
handle_error_reply_client(session, rses, problem_dcb, errmsgbuf);
|
||||||
close_dcb = false;
|
|
||||||
*succp = false; /*< no new backend servers were made available */
|
*succp = false; /*< no new backend servers were made available */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1459,12 +1441,6 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close_dcb)
|
|
||||||
{
|
|
||||||
RW_CHK_DCB(bref, problem_dcb);
|
|
||||||
dcb_close(problem_dcb);
|
|
||||||
RW_CLOSE_BREF(bref);
|
|
||||||
}
|
|
||||||
rses_end_locked_router_action(rses);
|
rses_end_locked_router_action(rses);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1594,6 +1570,8 @@ static bool handle_error_new_connection(ROUTER_INSTANCE *inst,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* If bref == NULL it has been replaced already with another one.
|
* If bref == NULL it has been replaced already with another one.
|
||||||
|
*
|
||||||
|
* NOTE: This can never happen.
|
||||||
*/
|
*/
|
||||||
if ((bref = get_bref_from_dcb(myrses, backend_dcb)) == NULL)
|
if ((bref = get_bref_from_dcb(myrses, backend_dcb)) == NULL)
|
||||||
{
|
{
|
||||||
@ -1626,25 +1604,10 @@ static bool handle_error_new_connection(ROUTER_INSTANCE *inst,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RW_CHK_DCB(bref, backend_dcb);
|
||||||
|
dcb_close(backend_dcb);
|
||||||
|
RW_CLOSE_BREF(bref);
|
||||||
close_failed_bref(bref, false);
|
close_failed_bref(bref, false);
|
||||||
|
|
||||||
/**
|
|
||||||
* Error handler is already called for this DCB because
|
|
||||||
* it's not polling anymore. It can be assumed that
|
|
||||||
* it succeed because rses isn't closed.
|
|
||||||
*/
|
|
||||||
if (backend_dcb->state != DCB_STATE_POLLING)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Remove callback because this DCB won't be used
|
|
||||||
* unless it is reconnected later, and then the callback
|
|
||||||
* is set again.
|
|
||||||
*/
|
|
||||||
dcb_remove_callback(backend_dcb, DCB_REASON_NOT_RESPONDING,
|
|
||||||
&router_handle_state_switch, (void *)bref);
|
|
||||||
|
|
||||||
max_nslaves = rses_get_max_slavecount(myrses, myrses->rses_nbackends);
|
max_nslaves = rses_get_max_slavecount(myrses, myrses->rses_nbackends);
|
||||||
max_slave_rlag = rses_get_max_replication_lag(myrses);
|
max_slave_rlag = rses_get_max_replication_lag(myrses);
|
||||||
/**
|
/**
|
||||||
|
@ -31,15 +31,15 @@ MXS_BEGIN_DECLS
|
|||||||
*/
|
*/
|
||||||
#include <maxscale/protocol/mysql.h>
|
#include <maxscale/protocol/mysql.h>
|
||||||
|
|
||||||
#define RW_CHK_DCB(bref, dcb) \
|
#define RW_CHK_DCB(b, d) \
|
||||||
do{ \
|
do{ \
|
||||||
if(dcb->state == DCB_STATE_DISCONNECTED){ \
|
if(d->state == DCB_STATE_DISCONNECTED){ \
|
||||||
MXS_NOTICE("DCB was closed on line %d and another attempt to close it is made on line %d." , \
|
MXS_NOTICE("DCB was closed on line %d and another attempt to close it is made on line %d." , \
|
||||||
(bref) ? (bref)->closed_at : -1, __LINE__); \
|
(b) ? (b)->closed_at : -1, __LINE__); \
|
||||||
} \
|
} \
|
||||||
}while (false)
|
}while (false)
|
||||||
|
|
||||||
#define RW_CLOSE_BREF(b) do{ if (bref){ bref->closed_at = __LINE__; } } while (false)
|
#define RW_CLOSE_BREF(b) do{ if (b){ (b)->closed_at = __LINE__; } } while (false)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following are implemented in rwsplit_mysql.c
|
* The following are implemented in rwsplit_mysql.c
|
||||||
|
@ -1175,6 +1175,14 @@ bool handle_master_is_target(ROUTER_INSTANCE *inst, ROUTER_CLIENT_SES *rses,
|
|||||||
if (rses->rses_config.rw_master_failure_mode == RW_ERROR_ON_WRITE)
|
if (rses->rses_config.rw_master_failure_mode == RW_ERROR_ON_WRITE)
|
||||||
{
|
{
|
||||||
succp = send_readonly_error(rses->client_dcb);
|
succp = send_readonly_error(rses->client_dcb);
|
||||||
|
|
||||||
|
if (rses->rses_master_ref && BREF_IS_IN_USE(rses->rses_master_ref))
|
||||||
|
{
|
||||||
|
close_failed_bref(rses->rses_master_ref, true);
|
||||||
|
RW_CHK_DCB(rses->rses_master_ref, rses->rses_master_ref->bref_dcb);
|
||||||
|
dcb_close(rses->rses_master_ref->bref_dcb);
|
||||||
|
RW_CLOSE_BREF(rses->rses_master_ref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -528,8 +528,9 @@ char* get_shard_target_name(ROUTER_INSTANCE* router,
|
|||||||
query = modutil_get_SQL(buffer);
|
query = modutil_get_SQL(buffer);
|
||||||
if ((tmp = strcasestr(query, "from")))
|
if ((tmp = strcasestr(query, "from")))
|
||||||
{
|
{
|
||||||
char *saved, *tok = strtok_r(tmp, " ;", &saved);
|
const char *delim = "` \n\t;";
|
||||||
tok = strtok_r(NULL, " ;", &saved);
|
char *saved, *tok = strtok_r(tmp, delim, &saved);
|
||||||
|
tok = strtok_r(NULL, delim, &saved);
|
||||||
ss_dassert(tok != NULL);
|
ss_dassert(tok != NULL);
|
||||||
tmp = (char*) hashtable_fetch(ht, tok);
|
tmp = (char*) hashtable_fetch(ht, tok);
|
||||||
|
|
||||||
|
@ -34,16 +34,20 @@ bool extract_database(GWBUF* buf, char* str)
|
|||||||
/** Copy database name from MySQL packet to session */
|
/** Copy database name from MySQL packet to session */
|
||||||
if (qc_get_operation(buf) == QUERY_OP_CHANGE_DB)
|
if (qc_get_operation(buf) == QUERY_OP_CHANGE_DB)
|
||||||
{
|
{
|
||||||
|
const char *delim = "` \n\t;";
|
||||||
|
|
||||||
query = modutil_get_SQL(buf);
|
query = modutil_get_SQL(buf);
|
||||||
tok = strtok_r(query, " ;", &saved);
|
tok = strtok_r(query, delim, &saved);
|
||||||
|
|
||||||
if (tok == NULL || strcasecmp(tok, "use") != 0)
|
if (tok == NULL || strcasecmp(tok, "use") != 0)
|
||||||
{
|
{
|
||||||
MXS_ERROR("extract_database: Malformed change database packet.");
|
MXS_ERROR("extract_database: Malformed chage database packet.");
|
||||||
succp = false;
|
succp = false;
|
||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
tok = strtok_r(NULL, " ;", &saved);
|
tok = strtok_r(NULL, delim, &saved);
|
||||||
|
|
||||||
if (tok == NULL)
|
if (tok == NULL)
|
||||||
{
|
{
|
||||||
MXS_ERROR("extract_database: Malformed change database packet.");
|
MXS_ERROR("extract_database: Malformed change database packet.");
|
||||||
@ -51,16 +55,7 @@ bool extract_database(GWBUF* buf, char* str)
|
|||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = strlen(tok);
|
strncpy(str, tok, MYSQL_DATABASE_MAXLEN);
|
||||||
if (len > MYSQL_DATABASE_MAXLEN)
|
|
||||||
{
|
|
||||||
MXS_ERROR("extract_database: Malformed change database packet, "
|
|
||||||
"too long database name.");
|
|
||||||
succp = false;
|
|
||||||
goto retblock;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(str, tok);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user