Merge branch '2.2' into develop
This commit is contained in:
@ -1,4 +1,4 @@
|
|||||||
# MariaDB MaxScale 2.2.3 Release Notes
|
# MariaDB MaxScale 2.2.3 Release Notes -- 2018-03-09
|
||||||
|
|
||||||
Release 2.2.3 is a GA release.
|
Release 2.2.3 is a GA release.
|
||||||
|
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
|
set(LIBMICROHTTPD_URL "http://ftpmirror.gnu.org/libmicrohttpd/libmicrohttpd-0.9.54.tar.gz"
|
||||||
|
CACHE STRING "GNU libmicrochttpd source code")
|
||||||
|
|
||||||
ExternalProject_Add(libmicrohttpd
|
ExternalProject_Add(libmicrohttpd
|
||||||
URL http://ftpmirror.gnu.org/libmicrohttpd/libmicrohttpd-0.9.54.tar.gz
|
URL ${LIBMICROHTTPD_URL}
|
||||||
SOURCE_DIR ${CMAKE_BINARY_DIR}/libmicrohttpd/
|
SOURCE_DIR ${CMAKE_BINARY_DIR}/libmicrohttpd/
|
||||||
CONFIGURE_COMMAND ${CMAKE_BINARY_DIR}/libmicrohttpd//configure --prefix=${CMAKE_BINARY_DIR}/libmicrohttpd/ --enable-shared --with-pic --libdir=${CMAKE_BINARY_DIR}/libmicrohttpd/lib/
|
CONFIGURE_COMMAND ${CMAKE_BINARY_DIR}/libmicrohttpd//configure --prefix=${CMAKE_BINARY_DIR}/libmicrohttpd/ --enable-shared --with-pic --libdir=${CMAKE_BINARY_DIR}/libmicrohttpd/lib/
|
||||||
BINARY_DIR ${CMAKE_BINARY_DIR}/libmicrohttpd/
|
BINARY_DIR ${CMAKE_BINARY_DIR}/libmicrohttpd/
|
||||||
|
@ -237,6 +237,24 @@ bool serviceAddBackend(SERVICE *service, SERVER *server);
|
|||||||
*/
|
*/
|
||||||
bool serviceHasBackend(SERVICE *service, SERVER *server);
|
bool serviceHasBackend(SERVICE *service, SERVER *server);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find listener with specified properties.
|
||||||
|
*
|
||||||
|
* @param service Service to check
|
||||||
|
* @param socket Listener socket path
|
||||||
|
* @param address Listener address
|
||||||
|
* @param port Listener port number
|
||||||
|
*
|
||||||
|
* @note Either socket should be NULL and port non-zero or socket
|
||||||
|
* non-NULL and port zero.
|
||||||
|
*
|
||||||
|
* @return True if service has the listener
|
||||||
|
*/
|
||||||
|
SERV_LISTENER* service_find_listener(SERVICE* service,
|
||||||
|
const char* socket,
|
||||||
|
const char* address,
|
||||||
|
unsigned short port);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if a service has a listener
|
* @brief Check if a service has a listener
|
||||||
*
|
*
|
||||||
|
@ -3499,6 +3499,15 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
|||||||
char *authenticator_options = config_get_value(obj->parameters, CN_AUTHENTICATOR_OPTIONS);
|
char *authenticator_options = config_get_value(obj->parameters, CN_AUTHENTICATOR_OPTIONS);
|
||||||
|
|
||||||
if (raw_service_name && protocol && (socket || port))
|
if (raw_service_name && protocol && (socket || port))
|
||||||
|
{
|
||||||
|
if (socket && port)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Creation of listener '%s' for service '%s' failed, because "
|
||||||
|
"both 'socket' and 'port' are defined. Only either one is allowed.",
|
||||||
|
obj->object, raw_service_name);
|
||||||
|
error_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
char service_name[strlen(raw_service_name) + 1];
|
char service_name[strlen(raw_service_name) + 1];
|
||||||
strcpy(service_name, raw_service_name);
|
strcpy(service_name, raw_service_name);
|
||||||
@ -3507,13 +3516,25 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
|||||||
SERVICE *service = service_find(service_name);
|
SERVICE *service = service_find(service_name);
|
||||||
if (service)
|
if (service)
|
||||||
{
|
{
|
||||||
|
SERV_LISTENER *listener;
|
||||||
SSL_LISTENER *ssl_info = make_ssl_structure(obj, true, &error_count);
|
SSL_LISTENER *ssl_info = make_ssl_structure(obj, true, &error_count);
|
||||||
if (socket)
|
if (socket)
|
||||||
{
|
{
|
||||||
if (serviceHasListener(service, obj->object, protocol, address, 0))
|
if (address)
|
||||||
{
|
{
|
||||||
MXS_ERROR("Listener '%s' for service '%s' already has a socket at '%s.",
|
MXS_WARNING("In the definition of the listener `%s', the value of "
|
||||||
obj->object, service_name, socket);
|
"'address' lacks meaning as the listener listens on a "
|
||||||
|
"domain socket ('%s') and not on a port.",
|
||||||
|
obj->object, socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
listener = service_find_listener(service, socket, NULL, 0);
|
||||||
|
|
||||||
|
if (listener)
|
||||||
|
{
|
||||||
|
MXS_ERROR("Creation of listener '%s' for service '%s' failed, because "
|
||||||
|
"listener '%s' already listens on the socket '%s'.",
|
||||||
|
obj->object, raw_service_name, listener->name, socket);
|
||||||
error_count++;
|
error_count++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3525,12 +3546,13 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
|||||||
|
|
||||||
if (port)
|
if (port)
|
||||||
{
|
{
|
||||||
if (serviceHasListener(service, obj->object, protocol, address, atoi(port)))
|
listener = service_find_listener(service, NULL, address, atoi(port));
|
||||||
|
|
||||||
|
if (listener)
|
||||||
{
|
{
|
||||||
MXS_ERROR("Listener '%s', for service '%s', already have port %s.",
|
MXS_ERROR("Creation of listener '%s' for service '%s' failed, because "
|
||||||
obj->object,
|
"listener '%s' already listens on the port %s.",
|
||||||
service_name,
|
obj->object, raw_service_name, listener->name, port);
|
||||||
port);
|
|
||||||
error_count++;
|
error_count++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3552,10 +3574,11 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
|||||||
error_count++;
|
error_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MXS_ERROR("Listener '%s' is missing a required parameter. A Listener "
|
MXS_ERROR("Listener '%s' is missing a required parameter. A Listener "
|
||||||
"must have a service, port and protocol defined.", obj->object);
|
"must have a service, protocol and port (or socket) defined.", obj->object);
|
||||||
error_count++;
|
error_count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <maxscale/debug.h>
|
#include <maxscale/debug.h>
|
||||||
#include <maxscale/log_manager.h>
|
#include <maxscale/log_manager.h>
|
||||||
#include "internal/worker.hh"
|
#include "internal/worker.hh"
|
||||||
@ -27,11 +26,9 @@ namespace
|
|||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
bool initialized;
|
bool initialized;
|
||||||
int pipe_flags;
|
|
||||||
} this_unit =
|
} this_unit =
|
||||||
{
|
{
|
||||||
false,
|
false
|
||||||
O_NONBLOCK | O_CLOEXEC
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -67,63 +64,6 @@ bool MessageQueue::init()
|
|||||||
{
|
{
|
||||||
ss_dassert(!this_unit.initialized);
|
ss_dassert(!this_unit.initialized);
|
||||||
|
|
||||||
/* From "man 7 pipe"
|
|
||||||
* ----
|
|
||||||
*
|
|
||||||
* O_NONBLOCK enabled, n <= PIPE_BUF
|
|
||||||
* If there is room to write n bytes to the pipe, then write(2)
|
|
||||||
* succeeds immediately, writing all n bytes; otherwise write(2)
|
|
||||||
* fails, with errno set to EAGAIN.
|
|
||||||
*
|
|
||||||
* ... (On Linux, PIPE_BUF is 4096 bytes.)
|
|
||||||
*
|
|
||||||
* ----
|
|
||||||
*
|
|
||||||
* As O_NONBLOCK is set and the messages are less than 4096 bytes,
|
|
||||||
* O_DIRECT should not be needed and we should be safe without it.
|
|
||||||
*
|
|
||||||
* However, to be in the safe side, if we run on kernel version >= 3.4
|
|
||||||
* we use it.
|
|
||||||
*/
|
|
||||||
|
|
||||||
utsname u;
|
|
||||||
|
|
||||||
if (uname(&u) == 0)
|
|
||||||
{
|
|
||||||
char* p;
|
|
||||||
char* zMajor = strtok_r(u.release, ".", &p);
|
|
||||||
char* zMinor = strtok_r(NULL, ".", &p);
|
|
||||||
|
|
||||||
if (zMajor && zMinor)
|
|
||||||
{
|
|
||||||
int major = atoi(zMajor);
|
|
||||||
int minor = atoi(zMinor);
|
|
||||||
|
|
||||||
if (major >= 3 && minor >= 4)
|
|
||||||
{
|
|
||||||
// O_DIRECT for pipes is supported from kernel 3.4 onwards.
|
|
||||||
this_unit.pipe_flags |= O_DIRECT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MXS_NOTICE("O_DIRECT is not supported for pipes on Linux kernel %s "
|
|
||||||
"(supported from version 3.4 onwards), NOT using it.",
|
|
||||||
u.release);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MXS_WARNING("Syntax used in utsname.release seems to have changed, "
|
|
||||||
"not able to figure out current kernel version. Assuming "
|
|
||||||
"O_DIRECT is not supported for pipes.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MXS_WARNING("uname() failed, assuming O_DIRECT is not supported for pipes: %s",
|
|
||||||
mxs_strerror(errno));
|
|
||||||
}
|
|
||||||
|
|
||||||
this_unit.initialized = true;
|
this_unit.initialized = true;
|
||||||
|
|
||||||
return this_unit.initialized;
|
return this_unit.initialized;
|
||||||
@ -141,10 +81,45 @@ MessageQueue* MessageQueue::create(Handler* pHandler)
|
|||||||
{
|
{
|
||||||
ss_dassert(this_unit.initialized);
|
ss_dassert(this_unit.initialized);
|
||||||
|
|
||||||
|
/* From "man 7 pipe"
|
||||||
|
* ----
|
||||||
|
*
|
||||||
|
* O_NONBLOCK enabled, n <= PIPE_BUF
|
||||||
|
* If there is room to write n bytes to the pipe, then write(2)
|
||||||
|
* succeeds immediately, writing all n bytes; otherwise write(2)
|
||||||
|
* fails, with errno set to EAGAIN.
|
||||||
|
*
|
||||||
|
* ... (On Linux, PIPE_BUF is 4096 bytes.)
|
||||||
|
*
|
||||||
|
* ----
|
||||||
|
*
|
||||||
|
* As O_NONBLOCK is set and the messages are less than 4096 bytes,
|
||||||
|
* O_DIRECT should not be needed and we should be safe without it.
|
||||||
|
*
|
||||||
|
* However, to be in the safe side, we first try whether it is supported,
|
||||||
|
* and if not, we create the pipe without O_DIRECT.
|
||||||
|
*/
|
||||||
|
|
||||||
MessageQueue* pThis = NULL;
|
MessageQueue* pThis = NULL;
|
||||||
|
|
||||||
int fds[2];
|
int fds[2];
|
||||||
if (pipe2(fds, this_unit.pipe_flags) == 0)
|
|
||||||
|
int rv = pipe2(fds, O_NONBLOCK | O_CLOEXEC | O_DIRECT);
|
||||||
|
|
||||||
|
if ((rv != 0) && (errno == EINVAL))
|
||||||
|
{
|
||||||
|
// Ok, apparently the kernel does not support O_DIRECT. Let's try without.
|
||||||
|
rv = pipe2(fds, O_NONBLOCK | O_CLOEXEC);
|
||||||
|
|
||||||
|
if (rv == 0)
|
||||||
|
{
|
||||||
|
// Succeeded, so apparently it was the missing support for O_DIRECT.
|
||||||
|
MXS_WARNING("Platform does not support O_DIRECT in conjunction with pipes, "
|
||||||
|
"using without.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rv == 0)
|
||||||
{
|
{
|
||||||
int read_fd = fds[0];
|
int read_fd = fds[0];
|
||||||
int write_fd = fds[1];
|
int write_fd = fds[1];
|
||||||
|
@ -806,6 +806,46 @@ SERV_LISTENER* serviceCreateListener(SERVICE *service, const char *name, const c
|
|||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SERV_LISTENER* service_find_listener(SERVICE* service,
|
||||||
|
const char* socket,
|
||||||
|
const char* address, unsigned short port)
|
||||||
|
{
|
||||||
|
LISTENER_ITERATOR iter;
|
||||||
|
|
||||||
|
for (SERV_LISTENER *listener = listener_iterator_init(service, &iter);
|
||||||
|
listener; listener = listener_iterator_next(&iter))
|
||||||
|
{
|
||||||
|
if (listener_is_active(listener))
|
||||||
|
{
|
||||||
|
bool is_same_port = false;
|
||||||
|
|
||||||
|
if (port && (port == listener->port) &&
|
||||||
|
((address && listener->address && strcmp(listener->address, address) == 0) ||
|
||||||
|
(address == NULL && listener->address == NULL)))
|
||||||
|
{
|
||||||
|
is_same_port = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_same_socket = false;
|
||||||
|
|
||||||
|
if (!is_same_port)
|
||||||
|
{
|
||||||
|
if (socket && listener->address && strcmp(listener->address, socket) == 0)
|
||||||
|
{
|
||||||
|
is_same_socket = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_same_port || is_same_socket)
|
||||||
|
{
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a protocol/port pair is part of the service
|
* Check if a protocol/port pair is part of the service
|
||||||
*
|
*
|
||||||
|
@ -228,7 +228,6 @@ bool Worker::init()
|
|||||||
{
|
{
|
||||||
ss_dassert(!this_unit.initialized);
|
ss_dassert(!this_unit.initialized);
|
||||||
|
|
||||||
this_unit.n_workers = config_threadcount();
|
|
||||||
this_unit.number_poll_spins = config_nbpolls();
|
this_unit.number_poll_spins = config_nbpolls();
|
||||||
this_unit.max_poll_sleep = config_pollsleep();
|
this_unit.max_poll_sleep = config_pollsleep();
|
||||||
|
|
||||||
@ -236,33 +235,37 @@ bool Worker::init()
|
|||||||
|
|
||||||
if (this_unit.epoll_listener_fd != -1)
|
if (this_unit.epoll_listener_fd != -1)
|
||||||
{
|
{
|
||||||
this_unit.ppWorkers = new (std::nothrow) Worker* [this_unit.n_workers] (); // Zero initialized array
|
int n_workers = config_threadcount();
|
||||||
|
Worker** ppWorkers = new (std::nothrow) Worker* [n_workers] (); // Zero initialized array
|
||||||
|
|
||||||
if (this_unit.ppWorkers)
|
if (ppWorkers)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < this_unit.n_workers; ++i)
|
for (int i = 0; i < n_workers; ++i)
|
||||||
{
|
{
|
||||||
Worker* pWorker = Worker::create(i, this_unit.epoll_listener_fd);
|
Worker* pWorker = Worker::create(i, this_unit.epoll_listener_fd);
|
||||||
|
|
||||||
if (pWorker)
|
if (pWorker)
|
||||||
{
|
{
|
||||||
this_unit.ppWorkers[i] = pWorker;
|
ppWorkers[i] = pWorker;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (int j = i - 1; j >= 0; --j)
|
for (int j = i - 1; j >= 0; --j)
|
||||||
{
|
{
|
||||||
delete this_unit.ppWorkers[j];
|
delete ppWorkers[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this_unit.ppWorkers;
|
delete [] ppWorkers;
|
||||||
this_unit.ppWorkers = NULL;
|
ppWorkers = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this_unit.ppWorkers)
|
if (ppWorkers)
|
||||||
{
|
{
|
||||||
|
this_unit.ppWorkers = ppWorkers;
|
||||||
|
this_unit.n_workers = n_workers;
|
||||||
|
|
||||||
this_unit.initialized = true;
|
this_unit.initialized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -977,10 +980,12 @@ void Worker::shutdown()
|
|||||||
void Worker::shutdown_all()
|
void Worker::shutdown_all()
|
||||||
{
|
{
|
||||||
// NOTE: No logging here, this function must be signal safe.
|
// NOTE: No logging here, this function must be signal safe.
|
||||||
|
ss_dassert((this_unit.n_workers == 0) || (this_unit.ppWorkers != NULL));
|
||||||
|
|
||||||
for (int i = 0; i < this_unit.n_workers; ++i)
|
for (int i = 0; i < this_unit.n_workers; ++i)
|
||||||
{
|
{
|
||||||
Worker* pWorker = this_unit.ppWorkers[i];
|
Worker* pWorker = this_unit.ppWorkers[i];
|
||||||
|
ss_dassert(pWorker);
|
||||||
|
|
||||||
pWorker->shutdown();
|
pWorker->shutdown();
|
||||||
}
|
}
|
||||||
|
@ -1173,7 +1173,7 @@ bool do_show_slave_status(MariaDBMonitor* mon,
|
|||||||
* root master server.
|
* root master server.
|
||||||
* Please note, there could be no slaves at all if Slave_SQL_Running == 'No'
|
* Please note, there could be no slaves at all if Slave_SQL_Running == 'No'
|
||||||
*/
|
*/
|
||||||
if (server_version != MYSQL_SERVER_VERSION_51)
|
if (serv_info->slave_status.slave_io_running && server_version != MYSQL_SERVER_VERSION_51)
|
||||||
{
|
{
|
||||||
/* Get Master_Server_Id */
|
/* Get Master_Server_Id */
|
||||||
master_server_id = scan_server_id(row[i_master_server_id]);
|
master_server_id = scan_server_id(row[i_master_server_id]);
|
||||||
|
@ -179,7 +179,7 @@ log_transaction_status(RWSplitSession *rses, GWBUF *querybuf, uint32_t qtype)
|
|||||||
const char *hint = querybuf->hint == NULL ? "" : ", Hint:";
|
const char *hint = querybuf->hint == NULL ? "" : ", Hint:";
|
||||||
const char *hint_type = querybuf->hint == NULL ? "" : STRHINTTYPE(querybuf->hint->type);
|
const char *hint_type = querybuf->hint == NULL ? "" : STRHINTTYPE(querybuf->hint->type);
|
||||||
|
|
||||||
MXS_INFO("> Autocommit: %s, trx is %s, cmd: (0x%02x) %s, plen: %u, type: %s, pastmt: %.*s%s %s",
|
MXS_INFO("> Autocommit: %s, trx is %s, cmd: (0x%02x) %s, plen: %u, type: %s, stmt: %.*s%s %s",
|
||||||
autocommit, transaction, command, STRPACKETTYPE(command), plen,
|
autocommit, transaction, command, STRPACKETTYPE(command), plen,
|
||||||
querytype, len, sql, hint, hint_type);
|
querytype, len, sql, hint, hint_type);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user