Merge branch 'develop' into binlog_server_waitdata_encryption

This commit is contained in:
MassimilianoPinto 2016-12-06 14:57:06 +01:00
commit 76a2475c33
19 changed files with 216 additions and 56 deletions

View File

@ -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}/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/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)
set(FLAGS "-Wall -Wno-unused-variable -Wno-unused-function -Werror -fPIC" CACHE STRING "Compilation flags")

View File

@ -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.
`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.

View File

@ -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
(`\`) 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
this might cause conflicts when MariaDB MaxScale tries to authenticate users.

View File

@ -54,6 +54,8 @@ If your system does not support systemd you can start MariaDB MaxScale using the
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.
## Install MariaDB MaxScale Using a Tarball

View 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).

View File

@ -23,14 +23,18 @@ if(PACKAGE)
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 "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.conf core)
install_file(${CMAKE_BINARY_DIR}/maxscale.service core)
install_file(${CMAKE_BINARY_DIR}/upstart/maxscale.conf core)
else()
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.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 startup scripts to: /etc/init.d")
message(STATUS "Installing systemd service files to: /usr/lib/systemd/system")
message(STATUS "Installing upstart files to: /etc/init/")
endif()

View File

@ -50,6 +50,11 @@ then
systemctl daemon-reload
fi
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 [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/maxscale" ]
then

View 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

View File

@ -1075,6 +1075,11 @@ bool disable_signals(void)
return false;
}
if (!delete_signal(&sigset, SIGCHLD, "SIGCHLD"))
{
return false;
}
#ifdef SIGBUS
if (!delete_signal(&sigset, SIGBUS, "SIGBUS"))
{

View File

@ -33,6 +33,9 @@
#include <maxscale/buffer.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
* lint directives.
*/
@ -130,6 +133,11 @@ null_auth_authenticate(DCB *dcb)
static int
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;
}

View File

@ -447,7 +447,7 @@ cdc_protocol_done(DCB* dcb)
static void
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
write_auth_err(DCB *dcb)
{
dcb_printf(dcb, "ERR, code 11, msg: abcd");
dcb_printf(dcb, "ERROR: Authentication failed\n");
}

View File

@ -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)
{
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 */
dcb_close(client->dcb);
rval = 0;
@ -86,7 +86,7 @@ avro_client_handle_request(AVRO_INSTANCE *router, AVRO_CLIENT *client, GWBUF *qu
else
{
/* Send OK ack to client */
dcb_printf(client->dcb, "OK");
dcb_printf(client->dcb, "OK\n");
client->state = AVRO_CLIENT_REGISTERED;
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);
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);
}
}
@ -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)
{
char *json = json_dumps(row, JSON_PRESERVE_ORDER);
GWBUF *buf;
size_t len = strlen(json);
GWBUF *buf = gwbuf_alloc(len + 1);
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);
}
else

View File

@ -565,7 +565,7 @@ blr_write_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint32_t size,
if (ftruncate(router->binlog_fd, router->binlog_position))
{
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,
strerror_r(errno, err_msg, sizeof(err_msg)));
}

View File

@ -1335,7 +1335,7 @@ blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt)
db_name_len = ptr[4 + 20 + 4 + 4];
var_block_len = ptr[4 + 20 + 4 + 4 + 1 + 2];
statement_len = len - (4 + 20 + 4 + 4 + 1 + 2 + 2 + var_block_len + 1 + db_name_len) - semisync_bytes;
statement_len = len - (4 + 20 + 4 + 4 + 1 + 2 + 2 + var_block_len + 1 + db_name_len);
statement_sql = MXS_CALLOC(1, statement_len + 1);
MXS_ABORT_IF_NULL(statement_sql);
memcpy(statement_sql,
@ -1470,7 +1470,7 @@ blr_handle_binlog_record(ROUTER_INSTANCE *router, GWBUF *pkt)
/* Check for rotate event */
if (hdr.event_type == ROTATE_EVENT)
{
if (!blr_rotate_event(router, ptr, &hdr))
if (!blr_rotate_event(router, ptr + offset, &hdr))
{
gwbuf_free(pkt);
blr_master_close(router);

View File

@ -398,9 +398,20 @@ static void closeSession(ROUTER *instance, void *router_session)
}
bref_clear_state(bref, BREF_IN_USE);
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);
}
else
@ -1282,6 +1293,13 @@ static void handleError(ROUTER *instance, void *router_session,
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 */
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
*/
*succp = true;
rses_end_locked_router_action(rses);
return;
}
else
@ -1300,6 +1319,7 @@ static void handleError(ROUTER *instance, void *router_session,
session = problem_dcb->session;
bool close_dcb = true;
backend_ref_t *bref = get_bref_from_dcb(rses, problem_dcb);
if (session == NULL || rses == NULL)
{
@ -1318,15 +1338,6 @@ static void handleError(ROUTER *instance, void *router_session,
{
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
* 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)
{
SERVER *srv = rses->rses_master_ref->ref->server;
backend_ref_t *bref = get_bref_from_dcb(rses, problem_dcb);
bool can_continue = false;
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);
}
}
else
else if (bref)
{
/**
* This is called in hope of getting replacement for
* failed slave(s).
*/
/** We should reconnect only if we find a backend for this
* DCB. If this DCB is an older DCB that has been closed,
* we can ignore it. */
*succp = handle_error_new_connection(inst, &rses, problem_dcb, errmsgbuf);
}
dcb_close(problem_dcb);
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);
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;
rses_end_locked_router_action(rses);
break;
}
@ -1404,8 +1452,11 @@ 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);
}
/**
@ -1428,33 +1479,22 @@ static void handle_error_reply_client(SESSION *ses, ROUTER_CLIENT_SES *rses,
client_dcb = ses->client_dcb;
spinlock_release(&ses->ses_lock);
if (rses_begin_locked_router_action(rses))
if ((bref = get_bref_from_dcb(rses, backend_dcb)) != NULL)
{
/**
* If bref exists, mark it closed
*/
if ((bref = get_bref_from_dcb(rses, backend_dcb)) != NULL)
{
CHK_BACKEND_REF(bref);
CHK_BACKEND_REF(bref);
if (BREF_IS_IN_USE(bref))
{
close_failed_bref(bref, false);
dcb_close(backend_dcb);
}
}
else
if (BREF_IS_IN_USE(bref))
{
// All dcbs should be associated with a backend reference.
ss_dassert(!true);
close_failed_bref(bref, false);
RW_CHK_DCB(bref, backend_dcb);
dcb_close(backend_dcb);
RW_CLOSE_BREF(bref);
}
rses_end_locked_router_action(rses);
}
else
{
// The session has already been closed, hence the dcb has been
// closed as well.
// All dcbs should be associated with a backend reference.
ss_dassert(!true);
}
if (sesstate == SESSION_STATE_ROUTER_READY)

View File

@ -200,6 +200,7 @@ typedef struct backend_ref_st
#if defined(SS_DEBUG)
skygw_chk_t bref_chk_tail;
#endif
int closed_at; /** DEBUG: Line number where this backend reference was closed */
} backend_ref_t;
/**

View File

@ -30,7 +30,17 @@ MXS_BEGIN_DECLS
* rwsplit_tmp_table_multi functions
*/
#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
*/

View File

@ -301,7 +301,9 @@ bool select_connect_backend_servers(backend_ref_t **p_master_ref,
/** Decrease backend's connection counter. */
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);
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)
{
bref_clear_state(bref, BREF_CLOSED);
bref->closed_at = 0;
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->name,
bref->ref->server->port);
RW_CHK_DCB(bref, bref->bref_dcb);
dcb_close(bref->bref_dcb);
RW_CLOSE_BREF(bref);
bref->bref_dcb = NULL;
}
}

View File

@ -176,10 +176,9 @@ GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf,
bref->ref->server->unique_name);
close_failed_bref(bref, true);
if (bref->bref_dcb)
{
dcb_close(bref->bref_dcb);
}
RW_CHK_DCB(bref, bref->bref_dcb);
dcb_close(bref->bref_dcb);
RW_CLOSE_BREF(bref);
*reconnect = true;
gwbuf_free(replybuf);
replybuf = NULL;
@ -217,7 +216,9 @@ GWBUF *sescmd_cursor_process_replies(GWBUF *replybuf,
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);
RW_CLOSE_BREF(&ses->rses_backend_ref[i]);
}
*reconnect = true;
MXS_INFO("Disabling slave %s:%d, result differs from "