Merge branch '2.2' into develop

This commit is contained in:
Johan Wikman
2018-02-12 14:00:40 +02:00
31 changed files with 900 additions and 352 deletions

View File

@ -58,7 +58,7 @@ int atomic_load_int(const int *variable)
#ifdef MXS_USE_ATOMIC_BUILTINS
return __atomic_load_n(variable, __ATOMIC_SEQ_CST);
#else
return __sync_fetch_and_or(variable, 0);
return __sync_fetch_and_or((int*)variable, 0);
#endif
}
@ -67,7 +67,7 @@ int32_t atomic_load_int32(const int32_t *variable)
#ifdef MXS_USE_ATOMIC_BUILTINS
return __atomic_load_n(variable, __ATOMIC_SEQ_CST);
#else
return __sync_fetch_and_or(variable, 0);
return __sync_fetch_and_or((int32_t*)variable, 0);
#endif
}
@ -76,7 +76,7 @@ int64_t atomic_load_int64(const int64_t *variable)
#ifdef MXS_USE_ATOMIC_BUILTINS
return __atomic_load_n(variable, __ATOMIC_SEQ_CST);
#else
return __sync_fetch_and_or(variable, 0);
return __sync_fetch_and_or((int64_t*)variable, 0);
#endif
}
@ -85,7 +85,7 @@ uint32_t atomic_load_uint32(const uint32_t *variable)
#ifdef MXS_USE_ATOMIC_BUILTINS
return __atomic_load_n(variable, __ATOMIC_SEQ_CST);
#else
return __sync_fetch_and_or(variable, 0);
return __sync_fetch_and_or((uint32_t*)variable, 0);
#endif
}
@ -94,7 +94,7 @@ uint64_t atomic_load_uint64(const uint64_t *variable)
#ifdef MXS_USE_ATOMIC_BUILTINS
return __atomic_load_n(variable, __ATOMIC_SEQ_CST);
#else
return __sync_fetch_and_or(variable, 0);
return __sync_fetch_and_or((uint64_t*)variable, 0);
#endif
}

View File

@ -146,6 +146,7 @@ const char CN_TYPE[] = "type";
const char CN_UNIX[] = "unix";
const char CN_USER[] = "user";
const char CN_USERS[] = "users";
const char CN_USERS_REFRESH_TIME[] = "users_refresh_time";
const char CN_VERSION_STRING[] = "version_string";
const char CN_WEIGHTBY[] = "weightby";
const char CN_SESSION_TRACK_TRX_STATE[] = "session_track_trx_state";
@ -1668,6 +1669,44 @@ handle_global_item(const char *name, const char *value)
{
gateway.local_address = MXS_STRDUP_A(value);
}
else if (strcmp(name, CN_USERS_REFRESH_TIME) == 0)
{
char* endptr;
long users_refresh_time = strtol(value, &endptr, 0);
if (*endptr == '\0')
{
if (users_refresh_time < 0)
{
MXS_NOTICE("Value of '%s' is less than 0, users will "
"not be automatically refreshed.", CN_USERS_REFRESH_TIME);
// Strictly speaking they will be refreshed once every 68 years,
// but I just don't beleave the uptime will be that long.
users_refresh_time = INT32_MAX;
}
else if (users_refresh_time < USERS_REFRESH_TIME_MIN)
{
MXS_WARNING("%s is less than the allowed minimum value of %d for the "
"configuration option '%s', using the minimum value.",
value, USERS_REFRESH_TIME_MIN, CN_USERS_REFRESH_TIME);
users_refresh_time = USERS_REFRESH_TIME_MIN;
}
if (users_refresh_time > INT32_MAX)
{
// To ensure that there will be no overflows when
// we later do arithmetic.
users_refresh_time = INT32_MAX;
}
gateway.users_refresh_time = users_refresh_time;
}
else
{
MXS_ERROR("%s is an invalid value for '%s', using default %d instead.",
value, CN_USERS_REFRESH_TIME, USERS_REFRESH_TIME_DEFAULT);
gateway.users_refresh_time = USERS_REFRESH_TIME_DEFAULT;
}
}
else
{
for (i = 0; lognames[i].name; i++)

View File

@ -515,15 +515,15 @@ monitorShow(DCB *dcb, MXS_MONITOR *monitor)
break;
}
dcb_printf(dcb, "Monitor: %p\n", monitor);
dcb_printf(dcb, "Name: %s\n", monitor->name);
dcb_printf(dcb, "State: %s\n", state);
dcb_printf(dcb, "Sampling interval: %lu milliseconds\n", monitor->interval);
dcb_printf(dcb, "Connect Timeout: %i seconds\n", monitor->connect_timeout);
dcb_printf(dcb, "Read Timeout: %i seconds\n", monitor->read_timeout);
dcb_printf(dcb, "Write Timeout: %i seconds\n", monitor->write_timeout);
dcb_printf(dcb, "Connect attempts: %i \n", monitor->connect_attempts);
dcb_printf(dcb, "Monitored servers: ");
dcb_printf(dcb, "Monitor: %p\n", monitor);
dcb_printf(dcb, "Name: %s\n", monitor->name);
dcb_printf(dcb, "State: %s\n", state);
dcb_printf(dcb, "Sampling interval: %lu milliseconds\n", monitor->interval);
dcb_printf(dcb, "Connect Timeout: %i seconds\n", monitor->connect_timeout);
dcb_printf(dcb, "Read Timeout: %i seconds\n", monitor->read_timeout);
dcb_printf(dcb, "Write Timeout: %i seconds\n", monitor->write_timeout);
dcb_printf(dcb, "Connect attempts: %i \n", monitor->connect_attempts);
dcb_printf(dcb, "Monitored servers: ");
const char *sep = "";
@ -543,12 +543,12 @@ monitorShow(DCB *dcb, MXS_MONITOR *monitor)
}
else
{
dcb_printf(dcb, "\t(no diagnostics)\n");
dcb_printf(dcb, " (no diagnostics)\n");
}
}
else
{
dcb_printf(dcb, "\tMonitor failed\n");
dcb_printf(dcb, " Monitor failed\n");
}
dcb_printf(dcb, "\n");
}
@ -2444,41 +2444,41 @@ MXS_MONITORED_SERVER* mon_get_monitored_server(const MXS_MONITOR* mon, SERVER* s
int mon_config_get_servers(const MXS_CONFIG_PARAMETER* params, const char* key, const MXS_MONITOR* mon,
MXS_MONITORED_SERVER*** monitored_servers_out)
{
ss_dassert(*monitored_servers_out == NULL);
ss_dassert(monitored_servers_out != NULL && *monitored_servers_out == NULL);
SERVER** servers = NULL;
int servers_size = config_get_server_list(params, key, &servers);
int rval = 0;
int found = 0;
// All servers in the array must be monitored by the given monitor.
if (servers_size > 0)
{
MXS_MONITORED_SERVER** monitored_array =
(MXS_MONITORED_SERVER**)MXS_CALLOC(servers_size, sizeof(MXS_MONITORED_SERVER*));
bool error = false;
for (int i = 0; i < servers_size && !error; i++)
for (int i = 0; i < servers_size; i++)
{
MXS_MONITORED_SERVER* mon_serv = mon_get_monitored_server(mon, servers[i]);
if (mon_serv != NULL)
{
monitored_array[i] = mon_serv;
monitored_array[found++] = mon_serv;
}
else
{
MXS_ERROR("Server '%s' is not monitored by monitor '%s'.", servers[i]->unique_name, mon->name);
error = true;
MXS_WARNING("Server '%s' is not monitored by monitor '%s'.",
servers[i]->unique_name, mon->name);
}
}
MXS_FREE(servers);
if (error)
ss_dassert(found <= servers_size);
if (found == 0)
{
MXS_FREE(monitored_array);
rval = -1;
monitored_array = NULL;
}
else
else if (found < servers_size)
{
*monitored_servers_out = monitored_array;
rval = servers_size;
monitored_array = (MXS_MONITORED_SERVER**)MXS_REALLOC(monitored_array, found);
}
*monitored_servers_out = monitored_array;
}
return rval;
}
return found;
}

View File

@ -335,6 +335,34 @@ serviceStartPort(SERVICE *service, SERV_LISTENER *port)
}
}
MXS_CONFIG* config = config_get_global_options();
time_t last;
bool warned;
/**
* At service start last update is set to config->users_refresh_time seconds earlier.
* This way MaxScale could try reloading users just after startup. But only if user
* refreshing has not been turned off.
*/
if (config->users_refresh_time == INT32_MAX)
{
last = time(NULL);
warned = true; // So that there will not be a refresh rate warning.
}
else
{
last = time(NULL) - config->users_refresh_time;
warned = false;
}
int nthreads = config_threadcount();
for (int i = 0; i < nthreads; ++i)
{
service->rate_limits[i].last = last;
service->rate_limits[i].warned = warned;
}
if (port->listener->func.listen(port->listener, config_bind))
{
port->listener->session = session_alloc(service, port->listener);
@ -1629,22 +1657,24 @@ int service_refresh_users(SERVICE *service)
self = 0;
}
MXS_CONFIG* config = config_get_global_options();
/* Check if refresh rate limit has been exceeded */
if ((now < service->rate_limits[self].last + USERS_REFRESH_TIME) ||
(service->rate_limits[self].nloads >= USERS_REFRESH_MAX_PER_TIME))
if (now < service->rate_limits[self].last + config->users_refresh_time)
{
MXS_ERROR("[%s] Refresh rate limit exceeded for load of users' table.", service->name);
if (!service->rate_limits[self].warned)
{
MXS_WARNING("[%s] Refresh rate limit (once every %ld seconds) exceeded for "
"load of users' table.",
service->name, config->users_refresh_time);
service->rate_limits[self].warned = true;
}
}
else
{
service->rate_limits[self].nloads++;
service->rate_limits[self].last = now;
service->rate_limits[self].warned = false;
/** If we have reached the limit on users refreshes, reset refresh time and count */
if (service->rate_limits[self].nloads >= USERS_REFRESH_MAX_PER_TIME)
{
service->rate_limits[self].nloads = 0;
service->rate_limits[self].last = now;
}
ret = 0;
LISTENER_ITERATOR iter;