Merge branch '2.0' into develop
This commit is contained in:
@ -122,6 +122,7 @@ configure_file(${CMAKE_SOURCE_DIR}/include/maxscale/adminusers.h.in ${CMAKE_BINA
|
|||||||
configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.h.in ${CMAKE_BINARY_DIR}/include/maxscale/maxscale_test.h @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.h.in ${CMAKE_BINARY_DIR}/include/maxscale/maxscale_test.h @ONLY)
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/etc/postinst.in ${CMAKE_BINARY_DIR}/postinst @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/etc/postinst.in ${CMAKE_BINARY_DIR}/postinst @ONLY)
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/etc/postrm.in ${CMAKE_BINARY_DIR}/postrm @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/etc/postrm.in ${CMAKE_BINARY_DIR}/postrm @ONLY)
|
||||||
|
configure_file(${CMAKE_SOURCE_DIR}/etc/upstart/maxscale.conf.in ${CMAKE_BINARY_DIR}/upstart/maxscale.conf @ONLY)
|
||||||
configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.cnf ${CMAKE_BINARY_DIR}/maxscale.cnf @ONLY)
|
configure_file(${CMAKE_SOURCE_DIR}/server/test/maxscale_test.cnf ${CMAKE_BINARY_DIR}/maxscale.cnf @ONLY)
|
||||||
|
|
||||||
set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags")
|
set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags")
|
||||||
|
|||||||
@ -157,7 +157,7 @@ This limits the rule to be active only on certain types of queries. The possible
|
|||||||
|
|
||||||
The `users` directive defines the users to which the rule should be applied.
|
The `users` directive defines the users to which the rule should be applied.
|
||||||
|
|
||||||
`users NAME ... match [any|all|strict_all] rules RULE [,...]`
|
`users NAME... match { any | all | strict_all } rules RULE...`
|
||||||
|
|
||||||
The first keyword is `users`, which identifies this line as a user definition line.
|
The first keyword is `users`, which identifies this line as a user definition line.
|
||||||
|
|
||||||
|
|||||||
@ -673,7 +673,7 @@ grants when loading the users from the backend server.
|
|||||||
|
|
||||||
This parameter takes a boolean value and when enabled, will strip all backslash
|
This parameter takes a boolean value and when enabled, will strip all backslash
|
||||||
(`\`) characters from the database names. The default value for this parameter
|
(`\`) characters from the database names. The default value for this parameter
|
||||||
is true.
|
is true since MaxScale 2.0.1. In previous version, the default value was false.
|
||||||
|
|
||||||
Some visual database management tools automatically escape some characters and
|
Some visual database management tools automatically escape some characters and
|
||||||
this might cause conflicts when MariaDB MaxScale tries to authenticate users.
|
this might cause conflicts when MariaDB MaxScale tries to authenticate users.
|
||||||
|
|||||||
@ -54,6 +54,8 @@ If your system does not support systemd you can start MariaDB MaxScale using the
|
|||||||
service maxscale start
|
service maxscale start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Starting with version 2.0.3, MaxScale also supports Upstart.
|
||||||
|
|
||||||
An example configuration file is installed into the `/etc/` folder. This file should be changed according to your needs.
|
An example configuration file is installed into the `/etc/` folder. This file should be changed according to your needs.
|
||||||
|
|
||||||
## Install MariaDB MaxScale Using a Tarball
|
## Install MariaDB MaxScale Using a Tarball
|
||||||
|
|||||||
48
Documentation/Release-Notes/MaxScale-2.0.3-Release-Notes.md
Normal file
48
Documentation/Release-Notes/MaxScale-2.0.3-Release-Notes.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# MariaDB MaxScale 2.0.3 Release Notes
|
||||||
|
|
||||||
|
Release 2.0.3 is a GA release.
|
||||||
|
|
||||||
|
This document describes the changes in release 2.0.3, when compared to
|
||||||
|
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
|
||||||
|
notes of release [2.0.0](./MaxScale-2.0.0-Release-Notes.md) and
|
||||||
|
release [2.0.1](./MaxScale-2.0.1-Release-Notes.md).
|
||||||
|
|
||||||
|
For any problems you encounter, please submit a bug report at
|
||||||
|
[Jira](https://jira.mariadb.org).
|
||||||
|
|
||||||
|
## Updated Features
|
||||||
|
|
||||||
|
### [MXS-1027] (https://jira.mariadb.org/browse/MXS-1027) Add Upstart support (including respawn) for MaxScale
|
||||||
|
|
||||||
|
MaxScale now provides an Upstart configuration file for systems that do not
|
||||||
|
support systemd.
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
is a list of bugs fixed since the release of MaxScale 2.0.1.
|
||||||
|
|
||||||
|
* [MXS-1009](https://jira.mariadb.org/browse/MXS-1009): maxinfo sigsegv in spinlock_release
|
||||||
|
|
||||||
|
## Known Issues and Limitations
|
||||||
|
|
||||||
|
There are some limitations and known issues within this version of MaxScale.
|
||||||
|
For more information, please refer to the [Limitations](../About/Limitations.md) document.
|
||||||
|
|
||||||
|
## Packaging
|
||||||
|
|
||||||
|
RPM and Debian packages are provided for the Linux distributions supported
|
||||||
|
by MariaDB Enterprise.
|
||||||
|
|
||||||
|
Packages can be downloaded [here](https://mariadb.com/resources/downloads).
|
||||||
|
|
||||||
|
## Source Code
|
||||||
|
|
||||||
|
The source code of MaxScale is tagged at GitHub with a tag, which is derived
|
||||||
|
from the version of MaxScale. For instance, the tag of version `X.Y.Z` of MaxScale
|
||||||
|
is `maxscale-X.Y.Z`.
|
||||||
|
|
||||||
|
The source code is available [here](https://github.com/mariadb-corporation/MaxScale).
|
||||||
|
|
||||||
@ -23,14 +23,18 @@ 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")
|
||||||
message(STATUS "systemd service files will unpack to to: /usr/lib/systemd/system")
|
message(STATUS "systemd service files will unpack to to: /usr/lib/systemd/system")
|
||||||
|
message(STATUS "upstart files will unpack to: /etc/init/")
|
||||||
install_file(${CMAKE_BINARY_DIR}/maxscale core)
|
install_file(${CMAKE_BINARY_DIR}/maxscale core)
|
||||||
install_file(${CMAKE_BINARY_DIR}/maxscale.conf core)
|
install_file(${CMAKE_BINARY_DIR}/maxscale.conf core)
|
||||||
install_file(${CMAKE_BINARY_DIR}/maxscale.service core)
|
install_file(${CMAKE_BINARY_DIR}/maxscale.service core)
|
||||||
|
install_file(${CMAKE_BINARY_DIR}/upstart/maxscale.conf core)
|
||||||
else()
|
else()
|
||||||
install(PROGRAMS ${CMAKE_BINARY_DIR}/maxscale DESTINATION /etc/init.d COMPONENT core)
|
install(PROGRAMS ${CMAKE_BINARY_DIR}/maxscale DESTINATION /etc/init.d COMPONENT core)
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/maxscale.conf DESTINATION /etc/ld.so.conf.d COMPONENT core)
|
install(FILES ${CMAKE_BINARY_DIR}/maxscale.conf DESTINATION /etc/ld.so.conf.d COMPONENT core)
|
||||||
install(FILES ${CMAKE_BINARY_DIR}/maxscale.service DESTINATION /usr/lib/systemd/system COMPONENT core)
|
install(FILES ${CMAKE_BINARY_DIR}/maxscale.service DESTINATION /usr/lib/systemd/system COMPONENT core)
|
||||||
|
install(FILES ${CMAKE_BINARY_DIR}/upstart/maxscale.conf DESTINATION /etc/init/)
|
||||||
message(STATUS "Installing maxscale.conf to: /etc/ld.so.conf.d")
|
message(STATUS "Installing maxscale.conf to: /etc/ld.so.conf.d")
|
||||||
message(STATUS "Installing startup scripts to: /etc/init.d")
|
message(STATUS "Installing startup scripts to: /etc/init.d")
|
||||||
message(STATUS "Installing systemd service files to: /usr/lib/systemd/system")
|
message(STATUS "Installing systemd service files to: /usr/lib/systemd/system")
|
||||||
|
message(STATUS "Installing upstart files to: /etc/init/")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -50,6 +50,11 @@ then
|
|||||||
systemctl daemon-reload
|
systemctl daemon-reload
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
if [ -d "/etc/init/" ]
|
||||||
|
then
|
||||||
|
cp @CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf /etc/init/
|
||||||
|
fi
|
||||||
|
|
||||||
# If systemd is not present, use init.d scripts
|
# If systemd is not present, use init.d scripts
|
||||||
if [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/maxscale" ]
|
if [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/maxscale" ]
|
||||||
then
|
then
|
||||||
|
|||||||
26
etc/upstart/maxscale.conf.in
Normal file
26
etc/upstart/maxscale.conf.in
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# MaxScale service
|
||||||
|
|
||||||
|
description "MariaDB MaxScale"
|
||||||
|
|
||||||
|
start on stopped rc RUNLEVEL=[2345]
|
||||||
|
stop on starting rc runlevel [!2345]
|
||||||
|
|
||||||
|
# Respawn the process on abnormal exits
|
||||||
|
respawn
|
||||||
|
|
||||||
|
# Uncomment this to limit respawns to two every five minutes
|
||||||
|
# respawn limit 2 5
|
||||||
|
|
||||||
|
# Unlimited open files
|
||||||
|
limit nofile unlimited unlimited
|
||||||
|
|
||||||
|
# Make sure /var/run/maxscale exists
|
||||||
|
pre-start exec /usr/bin/install -d -o maxscale -g maxscale @MAXSCALE_VARDIR@/run/maxscale
|
||||||
|
|
||||||
|
# Change the user to maxscale:maxscale
|
||||||
|
setuid maxscale
|
||||||
|
setgid maxscale
|
||||||
|
|
||||||
|
# Start MaxScale
|
||||||
|
expect fork
|
||||||
|
exec /usr/bin/maxscale
|
||||||
@ -1075,6 +1075,11 @@ bool disable_signals(void)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!delete_signal(&sigset, SIGCHLD, "SIGCHLD"))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef SIGBUS
|
#ifdef SIGBUS
|
||||||
if (!delete_signal(&sigset, SIGBUS, "SIGBUS"))
|
if (!delete_signal(&sigset, SIGBUS, "SIGBUS"))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -33,6 +33,9 @@
|
|||||||
#include <maxscale/buffer.h>
|
#include <maxscale/buffer.h>
|
||||||
#include <maxscale/users.h>
|
#include <maxscale/users.h>
|
||||||
|
|
||||||
|
/** MXS-1026: Without MySQL protocol data structures, the NullAuth authenticator will crash. */
|
||||||
|
#include <maxscale/protocol/mysql.h>
|
||||||
|
|
||||||
/* @see function load_module in load_utils.c for explanation of the following
|
/* @see function load_module in load_utils.c for explanation of the following
|
||||||
* lint directives.
|
* lint directives.
|
||||||
*/
|
*/
|
||||||
@ -130,6 +133,11 @@ null_auth_authenticate(DCB *dcb)
|
|||||||
static int
|
static int
|
||||||
null_auth_set_protocol_data(DCB *dcb, GWBUF *buf)
|
null_auth_set_protocol_data(DCB *dcb, GWBUF *buf)
|
||||||
{
|
{
|
||||||
|
/** MXS-1026: This will just prevent a crash when the NullAuth authenticator
|
||||||
|
* is used. This does not provide a way to use MaxScale with no authentication. */
|
||||||
|
dcb->data = calloc(1, sizeof(MYSQL_session));
|
||||||
|
dcb->protocol = mysql_protocol_init(dcb, dcb->fd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -447,7 +447,7 @@ cdc_protocol_done(DCB* dcb)
|
|||||||
static void
|
static void
|
||||||
write_auth_ack(DCB *dcb)
|
write_auth_ack(DCB *dcb)
|
||||||
{
|
{
|
||||||
dcb_printf(dcb, "OK");
|
dcb_printf(dcb, "OK\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,6 +459,6 @@ write_auth_ack(DCB *dcb)
|
|||||||
static void
|
static void
|
||||||
write_auth_err(DCB *dcb)
|
write_auth_err(DCB *dcb)
|
||||||
{
|
{
|
||||||
dcb_printf(dcb, "ERR, code 11, msg: abcd");
|
dcb_printf(dcb, "ERROR: Authentication failed\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -78,7 +78,7 @@ avro_client_handle_request(AVRO_INSTANCE *router, AVRO_CLIENT *client, GWBUF *qu
|
|||||||
if (avro_client_do_registration(router, client, queue) == 0)
|
if (avro_client_do_registration(router, client, queue) == 0)
|
||||||
{
|
{
|
||||||
client->state = AVRO_CLIENT_ERRORED;
|
client->state = AVRO_CLIENT_ERRORED;
|
||||||
dcb_printf(client->dcb, "ERR, code 12, msg: Registration failed");
|
dcb_printf(client->dcb, "ERR, code 12, msg: Registration failed\n");
|
||||||
/* force disconnection */
|
/* force disconnection */
|
||||||
dcb_close(client->dcb);
|
dcb_close(client->dcb);
|
||||||
rval = 0;
|
rval = 0;
|
||||||
@ -86,7 +86,7 @@ avro_client_handle_request(AVRO_INSTANCE *router, AVRO_CLIENT *client, GWBUF *qu
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Send OK ack to client */
|
/* Send OK ack to client */
|
||||||
dcb_printf(client->dcb, "OK");
|
dcb_printf(client->dcb, "OK\n");
|
||||||
|
|
||||||
client->state = AVRO_CLIENT_REGISTERED;
|
client->state = AVRO_CLIENT_REGISTERED;
|
||||||
MXS_INFO("%s: Client [%s] has completed REGISTRATION action",
|
MXS_INFO("%s: Client [%s] has completed REGISTRATION action",
|
||||||
@ -503,7 +503,7 @@ avro_client_process_command(AVRO_INSTANCE *router, AVRO_CLIENT *client, GWBUF *q
|
|||||||
{
|
{
|
||||||
GWBUF *reply = gwbuf_alloc(5);
|
GWBUF *reply = gwbuf_alloc(5);
|
||||||
memcpy(GWBUF_DATA(reply), "ECHO:", 5);
|
memcpy(GWBUF_DATA(reply), "ECHO:", 5);
|
||||||
reply = gwbuf_append(reply, queue);
|
reply = gwbuf_append(reply, gwbuf_clone(queue));
|
||||||
client->dcb->func.write(client->dcb, reply);
|
client->dcb->func.write(client->dcb, reply);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -556,11 +556,15 @@ const char* get_avrofile_name(const char *file_ptr, int data_len, char *dest)
|
|||||||
static int send_row(DCB *dcb, json_t* row)
|
static int send_row(DCB *dcb, json_t* row)
|
||||||
{
|
{
|
||||||
char *json = json_dumps(row, JSON_PRESERVE_ORDER);
|
char *json = json_dumps(row, JSON_PRESERVE_ORDER);
|
||||||
GWBUF *buf;
|
size_t len = strlen(json);
|
||||||
|
GWBUF *buf = gwbuf_alloc(len + 1);
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
if (json && (buf = gwbuf_alloc_and_load(strlen(json), (void*)json)))
|
if (json && buf)
|
||||||
{
|
{
|
||||||
|
uint8_t *data = GWBUF_DATA(buf);
|
||||||
|
memcpy(data, json, len);
|
||||||
|
data[len] = '\n';
|
||||||
rc = dcb->func.write(dcb, buf);
|
rc = dcb->func.write(dcb, buf);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@ -433,10 +433,10 @@ blr_write_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint32_t size,
|
|||||||
router->binlog_name,
|
router->binlog_name,
|
||||||
strerror_r(errno, err_msg, sizeof(err_msg)));
|
strerror_r(errno, err_msg, sizeof(err_msg)));
|
||||||
/* Remove any partial event that was written */
|
/* Remove any partial event that was written */
|
||||||
if (ftruncate(router->binlog_fd, router->last_written))
|
if (ftruncate(router->binlog_fd, router->binlog_position))
|
||||||
{
|
{
|
||||||
MXS_ERROR("%s: Failed to truncate binlog record at %lu of %s, %s. ",
|
MXS_ERROR("%s: Failed to truncate binlog record at %lu of %s, %s. ",
|
||||||
router->service->name, router->last_written,
|
router->service->name, router->binlog_position,
|
||||||
router->binlog_name,
|
router->binlog_name,
|
||||||
strerror_r(errno, err_msg, sizeof(err_msg)));
|
strerror_r(errno, err_msg, sizeof(err_msg)));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -398,9 +398,20 @@ static void closeSession(ROUTER *instance, void *router_session)
|
|||||||
}
|
}
|
||||||
bref_clear_state(bref, BREF_IN_USE);
|
bref_clear_state(bref, BREF_IN_USE);
|
||||||
bref_set_state(bref, BREF_CLOSED);
|
bref_set_state(bref, BREF_CLOSED);
|
||||||
dcb_close(dcb);
|
|
||||||
|
|
||||||
/** Decrease server reference connection count */
|
RW_CHK_DCB(bref, dcb);
|
||||||
|
|
||||||
|
/** MXS-956: This will prevent closed DCBs from being closed twice.
|
||||||
|
* It should not happen but for currently unknown reasons, a DCB
|
||||||
|
* gets closed twice; first in handleError and a second time here. */
|
||||||
|
if (dcb && dcb->state == DCB_STATE_POLLING)
|
||||||
|
{
|
||||||
|
dcb_close(dcb);
|
||||||
|
}
|
||||||
|
|
||||||
|
RW_CLOSE_BREF(bref);
|
||||||
|
|
||||||
|
/** decrease server current connection counters */
|
||||||
atomic_add(&bref->ref->connections, -1);
|
atomic_add(&bref->ref->connections, -1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1282,6 +1293,13 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
|
|
||||||
CHK_DCB(problem_dcb);
|
CHK_DCB(problem_dcb);
|
||||||
|
|
||||||
|
if (!rses_begin_locked_router_action(rses))
|
||||||
|
{
|
||||||
|
/** Session is already closed */
|
||||||
|
*succp = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/** Don't handle same error twice on same DCB */
|
/** Don't handle same error twice on same DCB */
|
||||||
if (problem_dcb->dcb_errhandle_called)
|
if (problem_dcb->dcb_errhandle_called)
|
||||||
{
|
{
|
||||||
@ -1291,6 +1309,7 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
* be safe with the code as it stands on 9 Sept 2015 - MNB
|
* be safe with the code as it stands on 9 Sept 2015 - MNB
|
||||||
*/
|
*/
|
||||||
*succp = true;
|
*succp = true;
|
||||||
|
rses_end_locked_router_action(rses);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1300,6 +1319,7 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
session = problem_dcb->session;
|
session = problem_dcb->session;
|
||||||
|
|
||||||
bool close_dcb = true;
|
bool close_dcb = true;
|
||||||
|
backend_ref_t *bref = get_bref_from_dcb(rses, problem_dcb);
|
||||||
|
|
||||||
if (session == NULL || rses == NULL)
|
if (session == NULL || rses == NULL)
|
||||||
{
|
{
|
||||||
@ -1318,15 +1338,6 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
{
|
{
|
||||||
case ERRACT_NEW_CONNECTION:
|
case ERRACT_NEW_CONNECTION:
|
||||||
{
|
{
|
||||||
if (!rses_begin_locked_router_action(rses))
|
|
||||||
{
|
|
||||||
close_dcb = false; /* With the assumption that if the router session is closed,
|
|
||||||
* then so is the dcb.
|
|
||||||
*/
|
|
||||||
*succp = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If master has lost its Master status error can't be
|
* If master has lost its Master status error can't be
|
||||||
* handled so that session could continue.
|
* handled so that session could continue.
|
||||||
@ -1334,7 +1345,6 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
if (rses->rses_master_ref && rses->rses_master_ref->bref_dcb == problem_dcb)
|
if (rses->rses_master_ref && rses->rses_master_ref->bref_dcb == problem_dcb)
|
||||||
{
|
{
|
||||||
SERVER *srv = rses->rses_master_ref->ref->server;
|
SERVER *srv = rses->rses_master_ref->ref->server;
|
||||||
backend_ref_t *bref = get_bref_from_dcb(rses, problem_dcb);
|
|
||||||
bool can_continue = false;
|
bool can_continue = false;
|
||||||
|
|
||||||
if (rses->rses_config.rw_master_failure_mode != RW_FAIL_INSTANTLY &&
|
if (rses->rses_config.rw_master_failure_mode != RW_FAIL_INSTANTLY &&
|
||||||
@ -1372,18 +1382,56 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
"corresponding backend ref.", srv->name, srv->port);
|
"corresponding backend ref.", srv->name, srv->port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (bref)
|
||||||
{
|
{
|
||||||
/**
|
/** We should reconnect only if we find a backend for this
|
||||||
* This is called in hope of getting replacement for
|
* DCB. If this DCB is an older DCB that has been closed,
|
||||||
* failed slave(s).
|
* we can ignore it. */
|
||||||
*/
|
|
||||||
*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)
|
||||||
|
{
|
||||||
|
/** This is a valid DCB for a backend ref */
|
||||||
|
|
||||||
|
if (!BREF_IS_IN_USE(bref) || bref->bref_dcb != problem_dcb)
|
||||||
|
{
|
||||||
|
/** The backend is closed or the reference was replaced */
|
||||||
dcb_close(problem_dcb);
|
dcb_close(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *remote = problem_dcb->state == DCB_STATE_POLLING &&
|
||||||
|
problem_dcb->server ? problem_dcb->server->unique_name : "CLOSED";
|
||||||
|
|
||||||
|
MXS_ERROR("DCB connected to '%s' is not in use by the router "
|
||||||
|
"session, not closing it. DCB is in state '%s'",
|
||||||
|
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;
|
close_dcb = false;
|
||||||
rses_end_locked_router_action(rses);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1404,8 +1452,11 @@ static void handleError(ROUTER *instance, void *router_session,
|
|||||||
|
|
||||||
if (close_dcb)
|
if (close_dcb)
|
||||||
{
|
{
|
||||||
|
RW_CHK_DCB(bref, problem_dcb);
|
||||||
dcb_close(problem_dcb);
|
dcb_close(problem_dcb);
|
||||||
|
RW_CLOSE_BREF(bref);
|
||||||
}
|
}
|
||||||
|
rses_end_locked_router_action(rses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1428,11 +1479,6 @@ static void handle_error_reply_client(SESSION *ses, ROUTER_CLIENT_SES *rses,
|
|||||||
client_dcb = ses->client_dcb;
|
client_dcb = ses->client_dcb;
|
||||||
spinlock_release(&ses->ses_lock);
|
spinlock_release(&ses->ses_lock);
|
||||||
|
|
||||||
if (rses_begin_locked_router_action(rses))
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* If bref exists, mark it closed
|
|
||||||
*/
|
|
||||||
if ((bref = get_bref_from_dcb(rses, backend_dcb)) != NULL)
|
if ((bref = get_bref_from_dcb(rses, backend_dcb)) != NULL)
|
||||||
{
|
{
|
||||||
CHK_BACKEND_REF(bref);
|
CHK_BACKEND_REF(bref);
|
||||||
@ -1440,7 +1486,9 @@ static void handle_error_reply_client(SESSION *ses, ROUTER_CLIENT_SES *rses,
|
|||||||
if (BREF_IS_IN_USE(bref))
|
if (BREF_IS_IN_USE(bref))
|
||||||
{
|
{
|
||||||
close_failed_bref(bref, false);
|
close_failed_bref(bref, false);
|
||||||
|
RW_CHK_DCB(bref, backend_dcb);
|
||||||
dcb_close(backend_dcb);
|
dcb_close(backend_dcb);
|
||||||
|
RW_CLOSE_BREF(bref);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1449,14 +1497,6 @@ static void handle_error_reply_client(SESSION *ses, ROUTER_CLIENT_SES *rses,
|
|||||||
ss_dassert(!true);
|
ss_dassert(!true);
|
||||||
}
|
}
|
||||||
|
|
||||||
rses_end_locked_router_action(rses);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// The session has already been closed, hence the dcb has been
|
|
||||||
// closed as well.
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sesstate == SESSION_STATE_ROUTER_READY)
|
if (sesstate == SESSION_STATE_ROUTER_READY)
|
||||||
{
|
{
|
||||||
CHK_DCB(client_dcb);
|
CHK_DCB(client_dcb);
|
||||||
|
|||||||
@ -200,6 +200,7 @@ typedef struct backend_ref_st
|
|||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t bref_chk_tail;
|
skygw_chk_t bref_chk_tail;
|
||||||
#endif
|
#endif
|
||||||
|
int closed_at; /** DEBUG: Line number where this backend reference was closed */
|
||||||
} backend_ref_t;
|
} backend_ref_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -31,6 +31,16 @@ MXS_BEGIN_DECLS
|
|||||||
*/
|
*/
|
||||||
#include <maxscale/protocol/mysql.h>
|
#include <maxscale/protocol/mysql.h>
|
||||||
|
|
||||||
|
#define RW_CHK_DCB(bref, dcb) \
|
||||||
|
do{ \
|
||||||
|
if(dcb->state == DCB_STATE_DISCONNECTED){ \
|
||||||
|
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__); \
|
||||||
|
} \
|
||||||
|
}while (false)
|
||||||
|
|
||||||
|
#define RW_CLOSE_BREF(b) do{ if (bref){ bref->closed_at = __LINE__; } } while (false)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following are implemented in rwsplit_mysql.c
|
* The following are implemented in rwsplit_mysql.c
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -301,7 +301,9 @@ bool select_connect_backend_servers(backend_ref_t **p_master_ref,
|
|||||||
|
|
||||||
/** Decrease backend's connection counter. */
|
/** Decrease backend's connection counter. */
|
||||||
atomic_add(&backend_ref[i].ref->connections, -1);
|
atomic_add(&backend_ref[i].ref->connections, -1);
|
||||||
|
RW_CHK_DCB(&backend_ref[i], backend_ref[i].bref_dcb);
|
||||||
dcb_close(backend_ref[i].bref_dcb);
|
dcb_close(backend_ref[i].bref_dcb);
|
||||||
|
RW_CLOSE_BREF(&backend_ref[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,6 +413,7 @@ static bool connect_server(backend_ref_t *bref, SESSION *session, bool execute_h
|
|||||||
if (bref->bref_dcb != NULL)
|
if (bref->bref_dcb != NULL)
|
||||||
{
|
{
|
||||||
bref_clear_state(bref, BREF_CLOSED);
|
bref_clear_state(bref, BREF_CLOSED);
|
||||||
|
bref->closed_at = 0;
|
||||||
|
|
||||||
if (!execute_history || execute_sescmd_history(bref))
|
if (!execute_history || execute_sescmd_history(bref))
|
||||||
{
|
{
|
||||||
@ -429,7 +432,9 @@ static bool connect_server(backend_ref_t *bref, SESSION *session, bool execute_h
|
|||||||
bref->ref->server->unique_name,
|
bref->ref->server->unique_name,
|
||||||
bref->ref->server->name,
|
bref->ref->server->name,
|
||||||
bref->ref->server->port);
|
bref->ref->server->port);
|
||||||
|
RW_CHK_DCB(bref, bref->bref_dcb);
|
||||||
dcb_close(bref->bref_dcb);
|
dcb_close(bref->bref_dcb);
|
||||||
|
RW_CLOSE_BREF(bref);
|
||||||
bref->bref_dcb = NULL;
|
bref->bref_dcb = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -176,10 +176,9 @@ GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf,
|
|||||||
bref->ref->server->unique_name);
|
bref->ref->server->unique_name);
|
||||||
close_failed_bref(bref, true);
|
close_failed_bref(bref, true);
|
||||||
|
|
||||||
if (bref->bref_dcb)
|
RW_CHK_DCB(bref, bref->bref_dcb);
|
||||||
{
|
|
||||||
dcb_close(bref->bref_dcb);
|
dcb_close(bref->bref_dcb);
|
||||||
}
|
RW_CLOSE_BREF(bref);
|
||||||
*reconnect = true;
|
*reconnect = true;
|
||||||
gwbuf_free(replybuf);
|
gwbuf_free(replybuf);
|
||||||
replybuf = NULL;
|
replybuf = NULL;
|
||||||
@ -217,7 +216,9 @@ GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf,
|
|||||||
|
|
||||||
if (ses->rses_backend_ref[i].bref_dcb)
|
if (ses->rses_backend_ref[i].bref_dcb)
|
||||||
{
|
{
|
||||||
|
RW_CHK_DCB(&ses->rses_backend_ref[i], ses->rses_backend_ref[i].bref_dcb);
|
||||||
dcb_close(ses->rses_backend_ref[i].bref_dcb);
|
dcb_close(ses->rses_backend_ref[i].bref_dcb);
|
||||||
|
RW_CLOSE_BREF(&ses->rses_backend_ref[i]);
|
||||||
}
|
}
|
||||||
*reconnect = true;
|
*reconnect = true;
|
||||||
MXS_INFO("Disabling slave %s:%d, result differs from "
|
MXS_INFO("Disabling slave %s:%d, result differs from "
|
||||||
|
|||||||
Reference in New Issue
Block a user