Fix to bug #662, http://bugs.mariadb.com/show_bug.cgi?id=662
dbusers.c: Added function for setting read, write and connection timeout values. Set default timeouts for getUsers. Defaults are listed in service.c gateway.c:shutdown_server is called whenever MaxScale is to be shut down. Added call for service_shutdown to shutdown_server. service.c:service_alloc: replaced malloc with calloc and removed unnecessary zero/NULL initialization statements as a consequence. serviceStart: Exit serviceStartPort loop if shutdown flag is set for the service. serviceStartAll: Exit serviceStart loop if shutdown flag is set for the service. service.c: Added service_shutdown which sets shutdown flag for each service found in allServices list. service.h: Added prototype for service_shutdown
This commit is contained in:
@ -52,6 +52,10 @@
|
|||||||
#include <mysqld_error.h>
|
#include <mysqld_error.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DEFAULT_CONNECT_TIMEOUT 3
|
||||||
|
#define DEFAULT_READ_TIMEOUT 1
|
||||||
|
#define DEFAULT_WRITE_TIMEOUT 2
|
||||||
|
|
||||||
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
|
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -105,6 +109,11 @@ void *resource_fetch(HASHTABLE *, char *);
|
|||||||
int resource_add(HASHTABLE *, char *, char *);
|
int resource_add(HASHTABLE *, char *, char *);
|
||||||
int resource_hash(char *);
|
int resource_hash(char *);
|
||||||
static int normalize_hostname(char *input_host, char *output_host);
|
static int normalize_hostname(char *input_host, char *output_host);
|
||||||
|
static int gw_mysql_set_timeouts(
|
||||||
|
MYSQL* handle,
|
||||||
|
int read_timeout,
|
||||||
|
int write_timeout,
|
||||||
|
int connect_timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the user/passwd form mysql.user table into the service users' hashtable
|
* Load the user/passwd form mysql.user table into the service users' hashtable
|
||||||
@ -429,7 +438,8 @@ getDatabases(SERVICE *service, MYSQL *con)
|
|||||||
*
|
*
|
||||||
* @param service The current service
|
* @param service The current service
|
||||||
* @param users The users table into which to load the users
|
* @param users The users table into which to load the users
|
||||||
* @return -1 on any error or the number of users inserted (0 means no users at all)
|
* @return -1 on any error or the number of users inserted
|
||||||
|
* (0 means no users at all)
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
getUsers(SERVICE *service, USERS *users)
|
getUsers(SERVICE *service, USERS *users)
|
||||||
@ -446,15 +456,19 @@ getUsers(SERVICE *service, USERS *users)
|
|||||||
unsigned char hash[SHA_DIGEST_LENGTH]="";
|
unsigned char hash[SHA_DIGEST_LENGTH]="";
|
||||||
char *users_data = NULL;
|
char *users_data = NULL;
|
||||||
int nusers = 0;
|
int nusers = 0;
|
||||||
int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN + sizeof(char) + MYSQL_DATABASE_MAXLEN;
|
int users_data_row_len = MYSQL_USER_MAXLEN +
|
||||||
|
MYSQL_HOST_MAXLEN +
|
||||||
|
MYSQL_PASSWORD_LEN +
|
||||||
|
sizeof(char) +
|
||||||
|
MYSQL_DATABASE_MAXLEN;
|
||||||
int dbnames = 0;
|
int dbnames = 0;
|
||||||
int db_grants = 0;
|
int db_grants = 0;
|
||||||
|
|
||||||
serviceGetUser(service, &service_user, &service_passwd);
|
if (serviceGetUser(service, &service_user, &service_passwd) == 0)
|
||||||
|
{
|
||||||
if (service_user == NULL || service_passwd == NULL)
|
ss_dassert(service_passwd == NULL || service_user == NULL);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
con = mysql_init(NULL);
|
con = mysql_init(NULL);
|
||||||
|
|
||||||
if (con == NULL) {
|
if (con == NULL) {
|
||||||
@ -464,13 +478,26 @@ getUsers(SERVICE *service, USERS *users)
|
|||||||
mysql_error(con))));
|
mysql_error(con))));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/** Set read, write and connect timeout values */
|
||||||
|
if (gw_mysql_set_timeouts(con,
|
||||||
|
DEFAULT_READ_TIMEOUT,
|
||||||
|
DEFAULT_WRITE_TIMEOUT,
|
||||||
|
DEFAULT_CONNECT_TIMEOUT))
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : failed to set timeout values for backend "
|
||||||
|
"connection.")));
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) {
|
if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) {
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Error : failed to set external connection. "
|
"Error : failed to set external connection. "
|
||||||
"It is needed for backend server connections. "
|
"It is needed for backend server connections.")));
|
||||||
"Exiting.")));
|
mysql_close(con);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -486,12 +513,26 @@ getUsers(SERVICE *service, USERS *users)
|
|||||||
server = server->nextdb;
|
server = server->nextdb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (service->svc_do_shutdown)
|
||||||
|
{
|
||||||
|
free(dpwd);
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Try loading data from master server */
|
/* Try loading data from master server */
|
||||||
if (server != NULL && (mysql_real_connect(con, server->name, service_user, dpwd, NULL, server->port, NULL, 0) != NULL)) {
|
if (server != NULL &&
|
||||||
|
(mysql_real_connect(con,
|
||||||
|
server->name, service_user,
|
||||||
|
dpwd,
|
||||||
|
NULL,
|
||||||
|
server->port,
|
||||||
|
NULL, 0) != NULL))
|
||||||
|
{
|
||||||
LOGIF(LD, (skygw_log_write_flush(
|
LOGIF(LD, (skygw_log_write_flush(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"Dbusers : Loading data from backend database with Master role [%s:%i] "
|
"Dbusers : Loading data from backend database with "
|
||||||
"for service [%s]",
|
"Master role [%s:%i] for service [%s]",
|
||||||
server->name,
|
server->name,
|
||||||
server->port,
|
server->port,
|
||||||
service->name)));
|
service->name)));
|
||||||
@ -499,7 +540,9 @@ getUsers(SERVICE *service, USERS *users)
|
|||||||
/* load data from other servers via loop */
|
/* load data from other servers via loop */
|
||||||
server = service->databases;
|
server = service->databases;
|
||||||
|
|
||||||
while (server != NULL && (mysql_real_connect(con,
|
while (!service->svc_do_shutdown &&
|
||||||
|
server != NULL &&
|
||||||
|
(mysql_real_connect(con,
|
||||||
server->name,
|
server->name,
|
||||||
service_user,
|
service_user,
|
||||||
dpwd,
|
dpwd,
|
||||||
@ -511,11 +554,18 @@ getUsers(SERVICE *service, USERS *users)
|
|||||||
server = server->nextdb;
|
server = server->nextdb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (service->svc_do_shutdown)
|
||||||
|
{
|
||||||
|
free(dpwd);
|
||||||
|
mysql_close(con);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (server != NULL) {
|
if (server != NULL) {
|
||||||
LOGIF(LD, (skygw_log_write_flush(
|
LOGIF(LD, (skygw_log_write_flush(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"Dbusers : Loading data from backend database [%s:%i] "
|
"Dbusers : Loading data from backend database "
|
||||||
"for service [%s]",
|
"[%s:%i] for service [%s]",
|
||||||
server->name,
|
server->name,
|
||||||
server->port,
|
server->port,
|
||||||
service->name)));
|
service->name)));
|
||||||
@ -535,9 +585,7 @@ getUsers(SERVICE *service, USERS *users)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* count users */
|
/** Count users. Start with users and db grants for users */
|
||||||
|
|
||||||
/* start with users and db grants for users */
|
|
||||||
if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
|
if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
|
||||||
if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
|
if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
|
||||||
/* This is an error we cannot handle, return */
|
/* This is an error we cannot handle, return */
|
||||||
@ -1213,3 +1261,58 @@ int useorig = 0;
|
|||||||
|
|
||||||
return netmask;
|
return netmask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set read, write and connect timeout values for MySQL database connection.
|
||||||
|
*
|
||||||
|
* @param handle MySQL handle
|
||||||
|
* @param read_timeout Read timeout value in seconds
|
||||||
|
* @param write_timeout Write timeout value in seconds
|
||||||
|
* @param connect_timeout Connect timeout value in seconds
|
||||||
|
*
|
||||||
|
* @return 0 if succeed, 1 if failed
|
||||||
|
*/
|
||||||
|
static int gw_mysql_set_timeouts(
|
||||||
|
MYSQL* handle,
|
||||||
|
int read_timeout,
|
||||||
|
int write_timeout,
|
||||||
|
int connect_timeout)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((rc = mysql_options(handle,
|
||||||
|
MYSQL_OPT_READ_TIMEOUT,
|
||||||
|
(void *)&read_timeout)))
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : failed to set read timeout for backend "
|
||||||
|
"connection.")));
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = mysql_options(handle,
|
||||||
|
MYSQL_OPT_CONNECT_TIMEOUT,
|
||||||
|
(void *)&connect_timeout)))
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : failed to set connect timeout for backend "
|
||||||
|
"connection.")));
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = mysql_options(handle,
|
||||||
|
MYSQL_OPT_WRITE_TIMEOUT,
|
||||||
|
(void *)&write_timeout)))
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : failed to set write timeout for backend "
|
||||||
|
"connection.")));
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
retblock:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
@ -56,6 +56,7 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <housekeeper.h>
|
#include <housekeeper.h>
|
||||||
|
#include <service.h>
|
||||||
#include <memlog.h>
|
#include <memlog.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -1837,6 +1838,7 @@ return_main:
|
|||||||
void
|
void
|
||||||
shutdown_server()
|
shutdown_server()
|
||||||
{
|
{
|
||||||
|
service_shutdown();
|
||||||
poll_shutdown();
|
poll_shutdown();
|
||||||
hkshutdown();
|
hkshutdown();
|
||||||
memlog_flush_all();
|
memlog_flush_all();
|
||||||
|
|||||||
@ -87,7 +87,6 @@ static void service_add_qualified_param(
|
|||||||
SERVICE* svc,
|
SERVICE* svc,
|
||||||
CONFIG_PARAMETER* param);
|
CONFIG_PARAMETER* param);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a new service for the gateway to support
|
* Allocate a new service for the gateway to support
|
||||||
*
|
*
|
||||||
@ -102,7 +101,7 @@ service_alloc(const char *servname, const char *router)
|
|||||||
{
|
{
|
||||||
SERVICE *service;
|
SERVICE *service;
|
||||||
|
|
||||||
if ((service = (SERVICE *)malloc(sizeof(SERVICE))) == NULL)
|
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((service->router = load_module(router, MODULE_ROUTER)) == NULL)
|
if ((service->router = load_module(router, MODULE_ROUTER)) == NULL)
|
||||||
{
|
{
|
||||||
@ -132,27 +131,10 @@ SERVICE *service;
|
|||||||
free(service);
|
free(service);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
service->version_string = NULL;
|
|
||||||
memset(&service->stats, 0, sizeof(SERVICE_STATS));
|
|
||||||
service->ports = NULL;
|
|
||||||
service->stats.started = time(0);
|
service->stats.started = time(0);
|
||||||
service->state = SERVICE_STATE_ALLOC;
|
service->state = SERVICE_STATE_ALLOC;
|
||||||
service->credentials.name = NULL;
|
|
||||||
service->credentials.authdata = NULL;
|
|
||||||
service->enable_root = 0;
|
|
||||||
service->localhost_match_wildcard_host = 0;
|
|
||||||
service->routerOptions = NULL;
|
|
||||||
service->databases = NULL;
|
|
||||||
service->svc_config_param = NULL;
|
|
||||||
service->svc_config_version = 0;
|
|
||||||
service->filters = NULL;
|
|
||||||
service->n_filters = 0;
|
|
||||||
service->weightby = 0;
|
|
||||||
service->users = NULL;
|
|
||||||
service->resources = NULL;
|
|
||||||
spinlock_init(&service->spin);
|
spinlock_init(&service->spin);
|
||||||
spinlock_init(&service->users_table_spin);
|
spinlock_init(&service->users_table_spin);
|
||||||
memset(&service->rate_limit, 0, sizeof(SERVICE_REFRESH_RATE));
|
|
||||||
|
|
||||||
spinlock_acquire(&service_spin);
|
spinlock_acquire(&service_spin);
|
||||||
service->next = allServices;
|
service->next = allServices;
|
||||||
@ -360,7 +342,7 @@ int listeners = 0;
|
|||||||
}
|
}
|
||||||
|
|
||||||
port = service->ports;
|
port = service->ports;
|
||||||
while (port)
|
while (!service->svc_do_shutdown && port)
|
||||||
{
|
{
|
||||||
listeners += serviceStartPort(service, port);
|
listeners += serviceStartPort(service, port);
|
||||||
port = port->next;
|
port = port->next;
|
||||||
@ -408,7 +390,7 @@ SERVICE *ptr;
|
|||||||
int n = 0,i;
|
int n = 0,i;
|
||||||
|
|
||||||
ptr = allServices;
|
ptr = allServices;
|
||||||
while (ptr)
|
while (ptr && !ptr->svc_do_shutdown)
|
||||||
{
|
{
|
||||||
n += (i = serviceStart(ptr));
|
n += (i = serviceStart(ptr));
|
||||||
|
|
||||||
@ -1422,3 +1404,16 @@ serviceEnableLocalhostMatchWildcardHost(SERVICE *service, int action)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void service_shutdown()
|
||||||
|
{
|
||||||
|
SERVICE* svc;
|
||||||
|
spinlock_acquire(&service_spin);
|
||||||
|
svc = allServices;
|
||||||
|
while (svc != NULL)
|
||||||
|
{
|
||||||
|
svc->svc_do_shutdown = true;
|
||||||
|
svc = svc->next;
|
||||||
|
}
|
||||||
|
spinlock_release(&service_spin);
|
||||||
|
}
|
||||||
@ -130,6 +130,7 @@ typedef struct service {
|
|||||||
CONFIG_PARAMETER*
|
CONFIG_PARAMETER*
|
||||||
svc_config_param; /*< list of config params and values */
|
svc_config_param; /*< list of config params and values */
|
||||||
int svc_config_version; /*< Version number of configuration */
|
int svc_config_version; /*< Version number of configuration */
|
||||||
|
bool svc_do_shutdown; /*< tells the service to exit loops etc. */
|
||||||
SPINLOCK
|
SPINLOCK
|
||||||
users_table_spin; /**< The spinlock for users data refresh */
|
users_table_spin; /**< The spinlock for users data refresh */
|
||||||
SERVICE_REFRESH_RATE
|
SERVICE_REFRESH_RATE
|
||||||
@ -186,4 +187,5 @@ extern void dprintService(DCB *, SERVICE *);
|
|||||||
extern void dListServices(DCB *);
|
extern void dListServices(DCB *);
|
||||||
extern void dListListeners(DCB *);
|
extern void dListListeners(DCB *);
|
||||||
char* service_get_name(SERVICE* svc);
|
char* service_get_name(SERVICE* svc);
|
||||||
|
void service_shutdown();
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user