Merge branch 'develop' into MAX-324

Conflicts:
	macros.cmake
	server/core/config.c
	server/core/service.c
	server/modules/routing/CMakeLists.txt
This commit is contained in:
Markus Makela
2015-02-24 06:26:55 +02:00
36 changed files with 9590 additions and 308 deletions

View File

@ -40,6 +40,7 @@
* internal router suppression of messages
* 30/10/14 Massimiliano Pinto Added disable_master_failback parameter
* 07/11/14 Massimiliano Pinto Addition of monitor timeouts for connect/read/write
* 20/02/15 Markus Mäkelä Added connection_timeout parameter for services
*
* @endverbatim
*/
@ -278,29 +279,41 @@ int error_count = 0;
char *user;
char *auth;
char *enable_root_user;
char *auth_all_servers;
char *connection_timeout;
char *auth_all_servers;
char *strip_db_esc;
char *weightby;
char *version_string;
bool is_rwsplit = false;
bool is_schemarouter = false;
char *allow_localhost_match_wildcard_host;
obj->element = service_alloc(obj->object, router);
user = config_get_value(obj->parameters, "user");
auth = config_get_value(obj->parameters, "passwd");
enable_root_user = config_get_value(
obj->parameters,
"enable_root_user");
auth_all_servers = config_get_value(
obj->parameters,
"auth_all_servers");
strip_db_esc = config_get_value(
obj->parameters,
"strip_db_esc");
connection_timeout =
config_get_value(
obj->parameters,
"connection_timeout");
auth_all_servers =
config_get_value(
obj->parameters,
"auth_all_servers");
strip_db_esc =
config_get_value(
obj->parameters,
"strip_db_esc");
allow_localhost_match_wildcard_host =
config_get_value(obj->parameters,
"localhost_match_wildcard_host");
weightby = config_get_value(obj->parameters, "weightby");
version_string = config_get_value(obj->parameters,
@ -310,14 +323,10 @@ int error_count = 0;
{
is_rwsplit = true;
}
else if (strncasecmp(router, "schemarouter", strlen("schemarouter")+1) == 0)
{
is_schemarouter = true;
}
else if(strncasecmp(router, "shardrouter", strlen("schemarouter")+1) == 0)
{
is_schemarouter = true;
}
char *allow_localhost_match_wildcard_host =
config_get_value(obj->parameters, "localhost_match_wildcard_host");
if (obj->element == NULL) /*< if module load failed */
{
LOGIF(LE, (skygw_log_write_flush(
@ -331,41 +340,36 @@ int error_count = 0;
continue; /*< process next obj */
}
if (version_string != NULL)
{
((SERVICE *)(obj->element))->version_string =
strdup(version_string);
}
else
{
if (gateway.version_string != NULL)
{
((SERVICE *)(obj->element))->version_string =
strdup(gateway.version_string);
}
if (version_string) {
((SERVICE *)(obj->element))->version_string = strdup(version_string);
} else {
if (gateway.version_string)
((SERVICE *)(obj->element))->version_string = strdup(gateway.version_string);
}
if (is_rwsplit)
{
max_slave_conn_str =
config_get_value(obj->parameters,
"max_slave_connections");
max_slave_rlag_str =
config_get_value(obj->parameters,
"max_slave_replication_lag");
}
max_slave_conn_str =
config_get_value(obj->parameters,
"max_slave_connections");
max_slave_rlag_str =
config_get_value(obj->parameters,
"max_slave_replication_lag");
if (enable_root_user)
serviceEnableRootUser(
obj->element,
config_truth_value(enable_root_user));
if(auth_all_servers)
serviceAuthAllServers(obj->element,
config_truth_value(auth_all_servers));
if (connection_timeout)
serviceSetTimeout(
obj->element,
atoi(connection_timeout));
if(auth_all_servers)
serviceAuthAllServers(obj->element,
config_truth_value(auth_all_servers));
if(strip_db_esc)
serviceStripDbEsc(obj->element,
config_truth_value(strip_db_esc));
serviceStripDbEsc(obj->element,
config_truth_value(strip_db_esc));
if (weightby)
serviceWeightBy(obj->element, weightby);
@ -380,7 +384,9 @@ int error_count = 0;
if (obj->element && user && auth)
{
serviceSetUser(obj->element, user, auth);
serviceSetUser(obj->element,
user,
auth);
}
else if (user && auth == NULL)
{
@ -392,7 +398,7 @@ int error_count = 0;
obj->object)));
}
/** Read, validate and set max_slave_connections */
if (is_rwsplit && max_slave_conn_str != NULL)
if (max_slave_conn_str != NULL)
{
CONFIG_PARAMETER* param;
bool succp;
@ -430,7 +436,7 @@ int error_count = 0;
}
}
/** Read, validate and set max_slave_replication_lag */
if (is_rwsplit && max_slave_rlag_str != NULL)
if (max_slave_rlag_str != NULL)
{
CONFIG_PARAMETER* param;
bool succp;
@ -466,58 +472,6 @@ int error_count = 0;
param->value)));
}
}
if(is_schemarouter)
{
CONFIG_PARAMETER* param = NULL;
char* subservices;
bool succp = true;
subservices =
config_get_value(obj->parameters,
"subservices");
if (subservices != NULL)
{
param = config_get_param(
obj->parameters,
"subservices");
if (param == NULL)
{
succp = false;
}
else
{
param->qfd.valstr = strdup(param->value);
param->qfd_param_type = STRING_TYPE;
succp = service_set_param_value(
obj->element,
param,
subservices,
COUNT_NONE,
STRING_TYPE);
}
}
if (!succp)
{
if(param){
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"* Warning : invalid value type "
"for parameter \'%s.%s = %s\'\n\tExpected "
"type is [master|all] for "
"use sql variables in.",
((SERVICE*)obj->element)->name,
param->name,
param->value)));
}else{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : parameter was NULL")));
}
}
}
/** Parameters for rwsplit router only */
if (is_rwsplit)
{
@ -1365,32 +1319,32 @@ SERVER *server;
char *user;
char *auth;
char *enable_root_user;
char* auth_all_servers;
char *connection_timeout;
char* auth_all_servers;
char* strip_db_esc;
char* max_slave_conn_str;
char* max_slave_rlag_str;
char* max_slave_conn_str;
char* max_slave_rlag_str;
char *version_string;
char *allow_localhost_match_wildcard_host;
enable_root_user = config_get_value(obj->parameters, "enable_root_user");
user = config_get_value(obj->parameters,
connection_timeout = config_get_value(obj->parameters, "connection_timeout");
user = config_get_value(obj->parameters,
"user");
auth = config_get_value(obj->parameters,
"passwd");
auth_all_servers = config_get_value(obj->parameters, "auth_all_servers");
strip_db_esc = config_get_value(obj->parameters, "strip_db_esc");
auth_all_servers = config_get_value(obj->parameters, "auth_all_servers");
strip_db_esc = config_get_value(obj->parameters, "strip_db_esc");
version_string = config_get_value(obj->parameters, "version_string");
allow_localhost_match_wildcard_host = config_get_value(obj->parameters, "localhost_match_wildcard_host");
allow_localhost_match_wildcard_host =
config_get_value(obj->parameters,
"localhost_match_wildcard_host");
if (version_string)
{
if (service->version_string)
{
if (version_string) {
if (service->version_string) {
free(service->version_string);
}
service->version_string = strdup(version_string);
@ -1402,10 +1356,16 @@ SERVER *server;
auth);
if (enable_root_user)
serviceEnableRootUser(service, atoi(enable_root_user));
if (connection_timeout)
serviceSetTimeout(service, atoi(connection_timeout));
if(auth_all_servers)
serviceAuthAllServers(service, atoi(auth_all_servers));
if(strip_db_esc)
serviceStripDbEsc(service, atoi(strip_db_esc));
if (allow_localhost_match_wildcard_host)
serviceEnableLocalhostMatchWildcardHost(
service,
@ -1484,24 +1444,21 @@ SERVER *server;
if (!succp)
{
if(param)
{
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"* Warning : invalid value type "
"for parameter \'%s.%s = %s\'\n\tExpected "
"type is <int> for maximum "
"slave replication lag.",
((SERVICE*)obj->element)->name,
param->name,
param->value)));
}
else
{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : parameter was NULL")));
}
if(param){
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"* Warning : invalid value type "
"for parameter \'%s.%s = %s\'\n\tExpected "
"type is <int> for maximum "
"slave replication lag.",
((SERVICE*)obj->element)->name,
param->name,
param->value)));
}else{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : parameter was NULL")));
}
}
}
}
@ -1510,53 +1467,58 @@ SERVER *server;
}
else
{
char *user;
char *user;
char *auth;
char *enable_root_user;
char *connection_timeout;
char *allow_localhost_match_wildcard_host;
char *auth_all_servers;
char *strip_db_esc;
char *auth_all_servers;
char *strip_db_esc;
enable_root_user =
config_get_value(obj->parameters,
"enable_root_user");
connection_timeout = config_get_value(obj->parameters,
"connection_timeout");
auth_all_servers =
config_get_value(obj->parameters,
"auth_all_servers");
strip_db_esc =
config_get_value(obj->parameters,
"strip_db_esc");
allow_localhost_match_wildcard_host =
config_get_value(obj->parameters,
"localhost_match_wildcard_host");
user = config_get_value(obj->parameters,
"user");
config_get_value(obj->parameters, "localhost_match_wildcard_host");
user = config_get_value(obj->parameters,
"user");
auth = config_get_value(obj->parameters,
"passwd");
"passwd");
obj->element = service_alloc(obj->object,
router);
router);
if (obj->element && user && auth)
{
serviceSetUser(obj->element,
user,
auth);
if (enable_root_user)
serviceEnableRootUser(obj->element,
atoi(enable_root_user));
if(auth_all_servers)
serviceAuthAllServers(obj->element, atoi(auth_all_servers));
if(strip_db_esc)
serviceStripDbEsc(obj->element, atoi(strip_db_esc));
serviceEnableRootUser(obj->element, atoi(enable_root_user));
if (connection_timeout)
serviceSetTimeout(obj->element, atoi(connection_timeout));
if (allow_localhost_match_wildcard_host)
serviceEnableLocalhostMatchWildcardHost(
obj->element,
atoi(allow_localhost_match_wildcard_host));
}
}
} /*< if router */
}
else
{
obj->element = NULL;
@ -1772,17 +1734,18 @@ static char *service_params[] =
"servers",
"user",
"passwd",
"enable_root_user",
"enable_root_user",
"connection_timeout",
"auth_all_servers",
"strip_db_esc",
"localhost_match_wildcard_host",
"strip_db_esc",
"localhost_match_wildcard_host",
"max_slave_connections",
"max_slave_replication_lag",
"use_sql_variables_in", /*< rwsplit only */
"subservices",
"version_string",
"filters",
"weightby",
"use_sql_variables_in", /*< rwsplit only */
"subservices",
"version_string",
"filters",
"weightby",
NULL
};

View File

@ -70,6 +70,7 @@
#include <skygw_utils.h>
#include <log_manager.h>
#include <hashtable.h>
#include <hk_heartbeat.h>
/** Defined in log_manager.cc */
extern int lm_enabled_logfiles_bitmask;
@ -816,6 +817,9 @@ int dcb_read(
n = 0;
goto return_n;
}
dcb->last_read = hkheartbeat;
bufsize = MIN(b, MAX_BUFFER_SIZE);
if ((buffer = gwbuf_alloc(bufsize)) == NULL)

View File

@ -632,7 +632,8 @@ static bool resolve_maxscale_homedir(
* 3. if /etc/MaxScale/MaxScale.cnf didn't exist or wasn't accessible, home
* isn't specified. Thus, try to access $PWD/MaxScale.cnf .
*/
tmp = strndup(getenv("PWD"), PATH_MAX);
char *pwd = getenv("PWD");
tmp = strndup(pwd ? pwd : "PWD_NOT_SET", PATH_MAX);
tmp2 = get_expanded_pathname(p_home_dir, tmp, default_cnf_fname);
free(tmp2); /*< full path isn't needed so simply free it */

View File

@ -57,6 +57,7 @@
#include <log_manager.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <housekeeper.h>
/** Defined in log_manager.cc */
extern int lm_enabled_logfiles_bitmask;
@ -250,7 +251,7 @@ GWPROTOCOL *funcs;
else
{
/* Save authentication data to file cache */
char *ptr, path[4096];
char *ptr, path[4097];
int mkdir_rval = 0;
strcpy(path, "/usr/local/skysql/MaxScale");
if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
@ -431,6 +432,12 @@ int listeners = 0;
service->stats.started = time(0);
}
/** Add the task that monitors session timeouts */
if(service->conn_timeout > 0)
{
hktask_add("connection_timeout",session_close_timeouts,NULL,5);
}
return listeners;
}
@ -839,6 +846,25 @@ int serviceStripDbEsc(SERVICE* service, int action)
return 1;
}
/**
* Sets the session timeout for the service.
* @param service Service to configure
* @param val Timeout in seconds
* @return 1 on success, 0 when the value is invalid
*/
int
serviceSetTimeout(SERVICE *service, int val)
{
if(val < 0)
return 0;
service->conn_timeout = val;
return 1;
}
/**
* Trim whitespace from the from an rear of a string
*

View File

@ -42,6 +42,7 @@
#include <atomic.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <housekeeper.h>
/** Defined in log_manager.cc */
extern int lm_enabled_logfiles_bitmask;
@ -909,3 +910,35 @@ SESSION *get_all_sessions()
{
return allSessions;
}
/**
* Close sessions that have been idle for too long.
*
* If the time since a session last sent data is grater than the set value in the
* service, it is disconnected. The default value for the timeout for a service is 0.
* This means that connections are never timed out.
* @param data NULL, this is only here to satisfy the housekeeper function requirements.
*/
void session_close_timeouts(void* data)
{
SESSION* ses;
spinlock_acquire(&session_spin);
ses = get_all_sessions();
spinlock_release(&session_spin);
while(ses)
{
if(ses->client && ses->client->state == DCB_STATE_POLLING &&
ses->service->conn_timeout > 0 &&
hkheartbeat - ses->client->last_read > ses->service->conn_timeout * 10)
{
ses->client->func.hangup(ses->client);
}
spinlock_acquire(&session_spin);
ses = ses->next;
spinlock_release(&session_spin);
}
}

View File

@ -33,6 +33,17 @@
#include <maxscale_test.h>
#include <service.h>
#include <poll.h>
#include <dcb.h>
#include "housekeeper.h"
static bool success = false;
int hup(DCB* dcb)
{
success = true;
}
/**
* test1 Allocate a service and do lots of other things
*
@ -40,19 +51,24 @@
static int
test1()
{
SERVICE *service;
int result;
int argc = 3;
char buffer[1024];
sprintf(buffer,"%s",TEST_LOG_DIR);
char* argv[] = {
"log_manager",
"-j",
buffer,
NULL
SERVICE *service;
SESSION *session;
DCB *dcb;
int result;
int argc = 3;
char* argv[] =
{
"log_manager",
"-j",
TEST_LOG_DIR,
NULL
};
skygw_logmanager_init(argc,argv);
poll_init();
hkinit();
/* Service tests */
ss_dfprintf(stderr,
"testservice : creating service called MyService with router nonexistent");
@ -66,10 +82,10 @@ poll_init();
ss_info_dassert(NULL != service, "New service with valid router must not be null");
ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
ss_info_dassert(0 == strcmp("MyService", service_get_name(service)), "Service must have given name");
ss_dfprintf(stderr, "\t..done\nAdding protocol HTTPD.");
ss_info_dassert(0 != serviceAddProtocol(service, "HTTPD", "localhost", 9876), "Add Protocol should succeed");
ss_info_dassert(0 != serviceHasProtocol(service, "HTTPD", 9876), "Service should have new protocol as requested");
serviceStartProtocol(service, "HTTPD", 9876);
ss_dfprintf(stderr, "\t..done\nAdding protocol testprotocol.");
ss_info_dassert(0 != serviceAddProtocol(service, "testprotocol", "localhost", 9876), "Add Protocol should succeed");
ss_info_dassert(0 != serviceHasProtocol(service, "testprotocol", 9876), "Service should have new protocol as requested");
serviceStartProtocol(service, "testprotocol", 9876);
skygw_log_sync_all();
ss_dfprintf(stderr, "\t..done\nStarting Service.");
result = serviceStart(service);
@ -81,13 +97,41 @@ poll_init();
result = serviceStartAll();
skygw_log_sync_all();
ss_info_dassert(0 != result, "Start all should succeed");
ss_dfprintf(stderr, "\t..done\nTiming out a session.");
service->conn_timeout = 1;
result = serviceStart(service);
skygw_log_sync_all();
ss_info_dassert(0 != result, "Start should succeed");
result = serviceStop(service);
skygw_log_sync_all();
ss_info_dassert(0 != result, "Stop should succeed");
dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
ss_info_dassert(dcb != NULL, "DCB allocation failed");
session = session_alloc(service,dcb);
ss_info_dassert(session != NULL, "Session allocation failed");
session->client->state = DCB_STATE_POLLING;
session->client->func.hangup = hup;
sleep(15);
ss_info_dassert(success, "Session timeout failed");
ss_dfprintf(stderr, "\t..done\nStopping Service.");
ss_info_dassert(0 != serviceStop(service), "Stop should succeed");
ss_dfprintf(stderr, "\t..done\n");
/** This is never used in MaxScale and will always fail due to service's
* stats.n_current value never being decremented */
/*
ss_dfprintf(stderr, "\t..done\nFreeing Service.");
ss_info_dassert(0 != service_free(service), "Free should succeed");
ss_dfprintf(stderr, "\t..done\n");
*/
return 0;
}