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.
|
||||
|
||||
|
@ -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
|
||||
URL http://ftpmirror.gnu.org/libmicrohttpd/libmicrohttpd-0.9.54.tar.gz
|
||||
URL ${LIBMICROHTTPD_URL}
|
||||
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/
|
||||
BINARY_DIR ${CMAKE_BINARY_DIR}/libmicrohttpd/
|
||||
|
@ -237,6 +237,24 @@ bool serviceAddBackend(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
|
||||
*
|
||||
|
@ -3499,6 +3499,15 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
char *authenticator_options = config_get_value(obj->parameters, CN_AUTHENTICATOR_OPTIONS);
|
||||
|
||||
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];
|
||||
strcpy(service_name, raw_service_name);
|
||||
@ -3507,13 +3516,25 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
SERVICE *service = service_find(service_name);
|
||||
if (service)
|
||||
{
|
||||
SERV_LISTENER *listener;
|
||||
SSL_LISTENER *ssl_info = make_ssl_structure(obj, true, &error_count);
|
||||
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.",
|
||||
obj->object, service_name, socket);
|
||||
MXS_WARNING("In the definition of the listener `%s', the value of "
|
||||
"'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++;
|
||||
}
|
||||
else
|
||||
@ -3525,12 +3546,13 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
|
||||
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.",
|
||||
obj->object,
|
||||
service_name,
|
||||
port);
|
||||
MXS_ERROR("Creation of listener '%s' for service '%s' failed, because "
|
||||
"listener '%s' already listens on the port %s.",
|
||||
obj->object, raw_service_name, listener->name, port);
|
||||
error_count++;
|
||||
}
|
||||
else
|
||||
@ -3552,10 +3574,11 @@ int create_new_listener(CONFIG_CONTEXT *obj)
|
||||
error_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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++;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <maxscale/debug.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
#include "internal/worker.hh"
|
||||
@ -27,11 +26,9 @@ namespace
|
||||
static struct
|
||||
{
|
||||
bool initialized;
|
||||
int pipe_flags;
|
||||
} this_unit =
|
||||
{
|
||||
false,
|
||||
O_NONBLOCK | O_CLOEXEC
|
||||
false
|
||||
};
|
||||
|
||||
}
|
||||
@ -67,63 +64,6 @@ bool MessageQueue::init()
|
||||
{
|
||||
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;
|
||||
|
||||
return this_unit.initialized;
|
||||
@ -141,10 +81,45 @@ MessageQueue* MessageQueue::create(Handler* pHandler)
|
||||
{
|
||||
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;
|
||||
|
||||
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 write_fd = fds[1];
|
||||
|
@ -806,6 +806,46 @@ SERV_LISTENER* serviceCreateListener(SERVICE *service, const char *name, const c
|
||||
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
|
||||
*
|
||||
|
@ -228,7 +228,6 @@ bool Worker::init()
|
||||
{
|
||||
ss_dassert(!this_unit.initialized);
|
||||
|
||||
this_unit.n_workers = config_threadcount();
|
||||
this_unit.number_poll_spins = config_nbpolls();
|
||||
this_unit.max_poll_sleep = config_pollsleep();
|
||||
|
||||
@ -236,33 +235,37 @@ bool Worker::init()
|
||||
|
||||
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);
|
||||
|
||||
if (pWorker)
|
||||
{
|
||||
this_unit.ppWorkers[i] = pWorker;
|
||||
ppWorkers[i] = pWorker;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = i - 1; j >= 0; --j)
|
||||
{
|
||||
delete this_unit.ppWorkers[j];
|
||||
delete ppWorkers[j];
|
||||
}
|
||||
|
||||
delete this_unit.ppWorkers;
|
||||
this_unit.ppWorkers = NULL;
|
||||
delete [] ppWorkers;
|
||||
ppWorkers = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this_unit.ppWorkers)
|
||||
if (ppWorkers)
|
||||
{
|
||||
this_unit.ppWorkers = ppWorkers;
|
||||
this_unit.n_workers = n_workers;
|
||||
|
||||
this_unit.initialized = true;
|
||||
}
|
||||
}
|
||||
@ -977,10 +980,12 @@ void Worker::shutdown()
|
||||
void Worker::shutdown_all()
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
Worker* pWorker = this_unit.ppWorkers[i];
|
||||
ss_dassert(pWorker);
|
||||
|
||||
pWorker->shutdown();
|
||||
}
|
||||
|
@ -1173,7 +1173,7 @@ bool do_show_slave_status(MariaDBMonitor* mon,
|
||||
* root master server.
|
||||
* 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 */
|
||||
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_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,
|
||||
querytype, len, sql, hint, hint_type);
|
||||
|
||||
|
Reference in New Issue
Block a user