Moved common monitor functionality to the MONITOR type

Common variables, like databases, timeouts and interval, and functionality was moved to the MONITOR type.
This reduces the redundant functionality of the monitor API's functions like registerServer and setInterval.
This commit is contained in:
Markus Makela
2015-05-09 03:54:54 +03:00
parent da6d597987
commit 5a3ed0de9b
9 changed files with 323 additions and 936 deletions

View File

@ -80,7 +80,13 @@ MONITOR *mon;
} }
mon->handle = NULL; mon->handle = NULL;
mon->databases = NULL;
mon->name = NULL;
mon->password = NULL;
mon->read_timeout = DEFAULT_READ_TIMEOUT;
mon->write_timeout = DEFAULT_WRITE_TIMEOUT;
mon->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
spinlock_init(&mon->lock);
spinlock_acquire(&monLock); spinlock_acquire(&monLock);
mon->next = allMonitors; mon->next = allMonitors;
allMonitors = mon; allMonitors = mon;
@ -100,7 +106,7 @@ monitor_free(MONITOR *mon)
{ {
MONITOR *ptr; MONITOR *ptr;
mon->module->stopMonitor(mon->handle); mon->module->stopMonitor(mon);
mon->state = MONITOR_STATE_FREED; mon->state = MONITOR_STATE_FREED;
spinlock_acquire(&monLock); spinlock_acquire(&monLock);
if (allMonitors == mon) if (allMonitors == mon)
@ -127,7 +133,7 @@ MONITOR *ptr;
void void
monitorStart(MONITOR *monitor, void* params) monitorStart(MONITOR *monitor, void* params)
{ {
monitor->handle = (*monitor->module->startMonitor)(monitor->handle,params); monitor->handle = (*monitor->module->startMonitor)(monitor,params);
monitor->state = MONITOR_STATE_RUNNING; monitor->state = MONITOR_STATE_RUNNING;
} }
@ -142,7 +148,7 @@ monitorStop(MONITOR *monitor)
if(monitor->state != MONITOR_STATE_STOPPED) if(monitor->state != MONITOR_STATE_STOPPED)
{ {
monitor->state = MONITOR_STATE_STOPPING; monitor->state = MONITOR_STATE_STOPPING;
monitor->module->stopMonitor(monitor->handle); monitor->module->stopMonitor(monitor);
monitor->state = MONITOR_STATE_STOPPED; monitor->state = MONITOR_STATE_STOPPED;
} }
} }
@ -175,7 +181,30 @@ MONITOR *ptr;
void void
monitorAddServer(MONITOR *mon, SERVER *server) monitorAddServer(MONITOR *mon, SERVER *server)
{ {
mon->module->registerServer(mon->handle, server); MONITOR_SERVERS *ptr, *db;
if ((db = (MONITOR_SERVERS *)malloc(sizeof(MONITOR_SERVERS))) == NULL)
return;
db->server = server;
db->con = NULL;
db->next = NULL;
db->mon_err_count = 0;
db->mon_prev_status = 0;
/* pending status is updated by get_replication_tree */
db->pending_status = 0;
spinlock_acquire(&mon->lock);
if (mon->databases == NULL)
mon->databases = db;
else
{
ptr = mon->databases;
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = db;
}
spinlock_release(&mon->lock);
} }
/** /**
@ -189,7 +218,9 @@ monitorAddServer(MONITOR *mon, SERVER *server)
void void
monitorAddUser(MONITOR *mon, char *user, char *passwd) monitorAddUser(MONITOR *mon, char *user, char *passwd)
{ {
mon->module->defaultUser(mon->handle, user, passwd); mon->user = strdup(user);
mon->password = strdup(passwd);
//mon->module->defaultUser(mon->handle, user, passwd);
} }
/** /**
@ -288,10 +319,7 @@ MONITOR *ptr;
void void
monitorSetInterval (MONITOR *mon, unsigned long interval) monitorSetInterval (MONITOR *mon, unsigned long interval)
{ {
if (mon->module->setInterval != NULL) {
mon->interval = interval; mon->interval = interval;
mon->module->setInterval(mon->handle, interval);
}
} }
/** /**
@ -303,8 +331,54 @@ monitorSetInterval (MONITOR *mon, unsigned long interval)
*/ */
void void
monitorSetNetworkTimeout(MONITOR *mon, int type, int value) { monitorSetNetworkTimeout(MONITOR *mon, int type, int value) {
if (mon->module->setNetworkTimeout != NULL) {
mon->module->setNetworkTimeout(mon->handle, type, value); int max_timeout = (int)(mon->interval/1000);
int new_timeout = max_timeout -1;
if (new_timeout <= 0)
new_timeout = DEFAULT_CONNECT_TIMEOUT;
switch(type) {
case MONITOR_CONNECT_TIMEOUT:
if (value < max_timeout) {
memcpy(&mon->connect_timeout, &value, sizeof(int));
} else {
memcpy(&mon->connect_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Connect Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_READ_TIMEOUT:
if (value < max_timeout) {
memcpy(&mon->read_timeout, &value, sizeof(int));
} else {
memcpy(&mon->read_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Read Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_WRITE_TIMEOUT:
if (value < max_timeout) {
memcpy(&mon->write_timeout, &value, sizeof(int));
} else {
memcpy(&mon->write_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Write Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
default:
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Monitor setNetworkTimeout received an unsupported action type %i", type)));
break;
} }
} }

View File

@ -17,6 +17,7 @@
* *
* Copyright MariaDB Corporation Ab 2013-2014 * Copyright MariaDB Corporation Ab 2013-2014
*/ */
#include <mysql.h>
#include <server.h> #include <server.h>
#include <dcb.h> #include <dcb.h>
#include <resultset.h> #include <resultset.h>
@ -69,19 +70,14 @@
typedef struct { typedef struct {
void *(*startMonitor)(void *, void*); void *(*startMonitor)(void *, void*);
void (*stopMonitor)(void *); void (*stopMonitor)(void *);
void (*registerServer)(void *, SERVER *);
void (*unregisterServer)(void *, SERVER *);
void (*defaultUser)(void *, char *, char *);
void (*diagnostics)(DCB *, void *); void (*diagnostics)(DCB *, void *);
void (*setInterval)(void *, size_t);
void (*setNetworkTimeout)(void *, int, int);
} MONITOR_OBJECT; } MONITOR_OBJECT;
/** /**
* The monitor API version number. Any change to the monitor module API * The monitor API version number. Any change to the monitor module API
* must change these versions usign the rules defined in modinfo.h * must change these versions usign the rules defined in modinfo.h
*/ */
#define MONITOR_VERSION {2, 0, 0} #define MONITOR_VERSION {3, 0, 0}
/** Monitor's poll frequency */ /** Monitor's poll frequency */
#define MON_BASE_INTERVAL_MS 100 #define MON_BASE_INTERVAL_MS 100
@ -112,12 +108,46 @@ typedef enum
#define DEFAULT_READ_TIMEOUT 1 #define DEFAULT_READ_TIMEOUT 1
#define DEFAULT_WRITE_TIMEOUT 2 #define DEFAULT_WRITE_TIMEOUT 2
#define MONITOR_RUNNING 1
#define MONITOR_STOPPING 2
#define MONITOR_STOPPED 3
#define MONITOR_INTERVAL 10000 // in milliseconds
#define MONITOR_DEFAULT_ID 1UL // unsigned long value
#define MONITOR_MAX_NUM_SLAVES 20 //number of MySQL slave servers associated to a MySQL master server
/**
* The linked list of servers that are being monitored by the monitor module.
*/
typedef struct monitor_servers {
SERVER *server; /**< The server being monitored */
MYSQL *con; /**< The MySQL connection */
int mon_err_count;
unsigned int mon_prev_status;
unsigned int pending_status; /**< Pending Status flag bitmap */
struct monitor_servers
*next; /**< The next server in the list */
} MONITOR_SERVERS;
/** /**
* Representation of the running monitor. * Representation of the running monitor.
*/ */
typedef struct monitor { typedef struct monitor {
char *name; /**< The name of the monitor module */ char *name; /**< The name of the monitor module */
char* user; /*< Monitor username */
char* password; /*< Monitor password */
SPINLOCK lock;
MONITOR_SERVERS* databases; /*< List of databases the monitor monitors */
monitor_state_t state; /**< The state of the monitor */ monitor_state_t state; /**< The state of the monitor */
int connect_timeout; /**< Connect timeout in seconds for mysql_real_connect */
int read_timeout; /**< Timeout in seconds to read from the server.
* There are retries and the total effective timeout value is three times the option value.
*/
int write_timeout; /**< Timeout in seconds for each attempt to write to the server.
* There are retries and the total effective timeout value is two times the option value.
*/
MONITOR_OBJECT *module; /**< The "monitor object" */ MONITOR_OBJECT *module; /**< The "monitor object" */
void *handle; /**< Handle returned from startMonitor */ void *handle; /**< Handle returned from startMonitor */
size_t interval; /**< The monitor interval */ size_t interval; /**< The monitor interval */

View File

@ -60,7 +60,7 @@ extern __thread log_info_t tls_log_info;
static void monitorMain(void *); static void monitorMain(void *);
static char *version_str = "V1.5.0"; static char *version_str = "V2.0.0";
MODULE_INFO info = { MODULE_INFO info = {
MODULE_API_MONITOR, MODULE_API_MONITOR,
@ -86,12 +86,7 @@ static bool mon_print_fail_status(MONITOR_SERVERS* mon_srv);
static MONITOR_OBJECT MyObject = { static MONITOR_OBJECT MyObject = {
startMonitor, startMonitor,
stopMonitor, stopMonitor,
registerServer, diagnostics
unregisterServer,
defaultUsers,
diagnostics,
setInterval,
setNetworkTimeout
}; };
/** /**
@ -142,30 +137,23 @@ GetModuleObject()
static void * static void *
startMonitor(void *arg,void* opt) startMonitor(void *arg,void* opt)
{ {
GALERA_MONITOR *handle; MONITOR* mon = arg;
GALERA_MONITOR *handle = mon->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt; CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
if (arg != NULL) if (handle != NULL)
{ {
handle = (GALERA_MONITOR *)arg;
handle->shutdown = 0; handle->shutdown = 0;
} }
else else
{ {
if ((handle = (GALERA_MONITOR *)malloc(sizeof(GALERA_MONITOR))) == NULL) if ((handle = (GALERA_MONITOR *)malloc(sizeof(GALERA_MONITOR))) == NULL)
return NULL; return NULL;
handle->databases = NULL;
handle->shutdown = 0; handle->shutdown = 0;
handle->defaultUser = NULL;
handle->defaultPasswd = NULL;
handle->id = MONITOR_DEFAULT_ID; handle->id = MONITOR_DEFAULT_ID;
handle->interval = MONITOR_INTERVAL;
handle->disableMasterFailback = 0; handle->disableMasterFailback = 0;
handle->availableWhenDonor = 0; handle->availableWhenDonor = 0;
handle->disableMasterRoleSetting = 0; handle->disableMasterRoleSetting = 0;
handle->master = NULL; handle->master = NULL;
handle->connect_timeout=DEFAULT_CONNECT_TIMEOUT;
handle->read_timeout=DEFAULT_READ_TIMEOUT;
handle->write_timeout=DEFAULT_WRITE_TIMEOUT;
handle->master_down_script = NULL; handle->master_down_script = NULL;
spinlock_init(&handle->lock); spinlock_init(&handle->lock);
} }
@ -200,82 +188,13 @@ CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
static void static void
stopMonitor(void *arg) stopMonitor(void *arg)
{ {
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
GALERA_MONITOR *handle = (GALERA_MONITOR *)mon->handle;
handle->shutdown = 1; handle->shutdown = 1;
thread_wait((void *)handle->tid); thread_wait((void *)handle->tid);
} }
/**
* Register a server that must be added to the monitored servers for
* a monitoring module.
*
* @param arg A handle on the running monitor module
* @param server The server to add
*/
static void
registerServer(void *arg, SERVER *server)
{
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
MONITOR_SERVERS *ptr, *db;
if ((db = (MONITOR_SERVERS *)malloc(sizeof(MONITOR_SERVERS))) == NULL)
return;
db->server = server;
db->con = NULL;
db->next = NULL;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
handle->databases = db;
else
{
ptr = handle->databases;
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = db;
}
spinlock_release(&handle->lock);
}
/**
* Remove a server from those being monitored by a monitoring module
*
* @param arg A handle on the running monitor module
* @param server The server to remove
*/
static void
unregisterServer(void *arg, SERVER *server)
{
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
MONITOR_SERVERS *ptr, *lptr;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
{
spinlock_release(&handle->lock);
return;
}
if (handle->databases->server == server)
{
ptr = handle->databases;
handle->databases = handle->databases->next;
free(ptr);
}
else
{
ptr = handle->databases;
while (ptr->next != NULL && ptr->next->server != server)
ptr = ptr->next;
if (ptr->next)
{
lptr = ptr->next;
ptr->next = ptr->next->next;
free(lptr);
}
}
spinlock_release(&handle->lock);
}
/** /**
* Diagnostic interface * Diagnostic interface
* *
@ -285,7 +204,8 @@ MONITOR_SERVERS *ptr, *lptr;
static void static void
diagnostics(DCB *dcb, void *arg) diagnostics(DCB *dcb, void *arg)
{ {
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
GALERA_MONITOR *handle = (GALERA_MONITOR *)mon->handle;
MONITOR_SERVERS *db; MONITOR_SERVERS *db;
char *sep; char *sep;
@ -302,16 +222,16 @@ char *sep;
break; break;
} }
dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", handle->interval); dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", mon->interval);
dcb_printf(dcb,"\tMaster Failback:\t%s\n", (handle->disableMasterFailback == 1) ? "off" : "on"); dcb_printf(dcb,"\tMaster Failback:\t%s\n", (handle->disableMasterFailback == 1) ? "off" : "on");
dcb_printf(dcb,"\tAvailable when Donor:\t%s\n", (handle->availableWhenDonor == 1) ? "on" : "off"); dcb_printf(dcb,"\tAvailable when Donor:\t%s\n", (handle->availableWhenDonor == 1) ? "on" : "off");
dcb_printf(dcb,"\tMaster Role Setting Disabled:\t%s\n", (handle->disableMasterRoleSetting == 1) ? "on" : "off"); dcb_printf(dcb,"\tMaster Role Setting Disabled:\t%s\n", (handle->disableMasterRoleSetting == 1) ? "on" : "off");
dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", handle->connect_timeout); dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", mon->connect_timeout);
dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", handle->read_timeout); dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", mon->read_timeout);
dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", handle->write_timeout); dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", mon->write_timeout);
dcb_printf(dcb, "\tMonitored servers: "); dcb_printf(dcb, "\tMonitored servers: ");
db = handle->databases; db = mon->databases;
sep = ""; sep = "";
while (db) while (db)
{ {
@ -322,27 +242,6 @@ char *sep;
dcb_printf(dcb, "\n"); dcb_printf(dcb, "\n");
} }
/**
* Set the default username and password to use to monitor if the server does not
* override this.
*
* @param arg The handle allocated by startMonitor
* @param uname The default user name
* @param passwd The default password
*/
static void
defaultUsers(void *arg, char *uname, char *passwd)
{
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
if (handle->defaultUser)
free(handle->defaultUser);
if (handle->defaultPasswd)
free(handle->defaultPasswd);
handle->defaultUser = strdup(uname);
handle->defaultPasswd = strdup(passwd);
}
/** /**
* Monitor an individual server * Monitor an individual server
* *
@ -350,14 +249,14 @@ GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
* @param database The database to probe * @param database The database to probe
*/ */
static void static void
monitorDatabase(GALERA_MONITOR *handle, MONITOR_SERVERS *database) monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
{ {
GALERA_MONITOR* handle = (GALERA_MONITOR*)mon->handle;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL_RES *result; MYSQL_RES *result;
int num_fields;
int isjoined = 0; int isjoined = 0;
char *uname = handle->defaultUser; char *uname = mon->user;
char *passwd = handle->defaultPasswd; char *passwd = mon->password;
unsigned long int server_version = 0; unsigned long int server_version = 0;
char *server_string; char *server_string;
@ -379,16 +278,15 @@ char *server_string;
if (database->con == NULL || mysql_ping(database->con) != 0) if (database->con == NULL || mysql_ping(database->con) != 0)
{ {
char *dpwd = decryptPassword(passwd); char *dpwd = decryptPassword(passwd);
int rc; int connect_timeout = mon->connect_timeout;
int connect_timeout = handle->connect_timeout; int read_timeout = mon->read_timeout;
int read_timeout = handle->read_timeout; int write_timeout = mon->write_timeout;
int write_timeout = handle->write_timeout;
database->con = mysql_init(NULL); database->con = mysql_init(NULL);
rc = mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout); mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout); mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
rc = mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout); mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout);
if (mysql_real_connect(database->con, database->server->name, if (mysql_real_connect(database->con, database->server->name,
uname, dpwd, NULL, database->server->port, NULL, 0) == NULL) uname, dpwd, NULL, database->server->port, NULL, 0) == NULL)
@ -433,9 +331,6 @@ char *server_string;
/* If we get this far then we have a working connection */ /* If we get this far then we have a working connection */
server_set_status(database->server, SERVER_RUNNING); server_set_status(database->server, SERVER_RUNNING);
/* get server version from current server */
server_version = mysql_get_server_version(database->con);
/* get server version string */ /* get server version string */
server_string = (char *)mysql_get_server_info(database->con); server_string = (char *)mysql_get_server_info(database->con);
if (server_string) { if (server_string) {
@ -448,7 +343,6 @@ char *server_string;
if (mysql_query(database->con, "SHOW STATUS LIKE 'wsrep_local_state'") == 0 if (mysql_query(database->con, "SHOW STATUS LIKE 'wsrep_local_state'") == 0
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
if (strcmp(row[1], "4") == 0) if (strcmp(row[1], "4") == 0)
@ -459,7 +353,6 @@ char *server_string;
if (mysql_query(database->con, "SHOW VARIABLES LIKE 'wsrep_sst_method'") == 0 if (mysql_query(database->con, "SHOW VARIABLES LIKE 'wsrep_sst_method'") == 0
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
if (strncmp(row[1], "xtrabackup", 10) == 0) if (strncmp(row[1], "xtrabackup", 10) == 0)
@ -476,7 +369,6 @@ char *server_string;
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
long local_index = -1; long local_index = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
local_index = strtol(row[1], NULL, 10); local_index = strtol(row[1], NULL, 10);
@ -504,7 +396,8 @@ char *server_string;
static void static void
monitorMain(void *arg) monitorMain(void *arg)
{ {
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
GALERA_MONITOR *handle = (GALERA_MONITOR *)mon->handle;
MONITOR_SERVERS *ptr; MONITOR_SERVERS *ptr;
size_t nrounds = 0; size_t nrounds = 0;
MONITOR_SERVERS *candidate_master = NULL; MONITOR_SERVERS *candidate_master = NULL;
@ -540,7 +433,7 @@ int log_no_members = 1;
* round. * round.
*/ */
if (nrounds != 0 && ((nrounds*MON_BASE_INTERVAL_MS)%handle->interval) >= MON_BASE_INTERVAL_MS) if (nrounds != 0 && ((nrounds*MON_BASE_INTERVAL_MS)%mon->interval) >= MON_BASE_INTERVAL_MS)
{ {
nrounds += 1; nrounds += 1;
continue; continue;
@ -551,11 +444,11 @@ int log_no_members = 1;
/* reset cluster members counter */ /* reset cluster members counter */
is_cluster=0; is_cluster=0;
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {
monitorDatabase(handle, ptr); monitorDatabase(mon, ptr);
if(ptr->mon_prev_status & SERVER_MASTER && if(ptr->mon_prev_status & SERVER_MASTER &&
SERVER_IS_DOWN(ptr->server)) SERVER_IS_DOWN(ptr->server))
@ -619,7 +512,7 @@ int log_no_members = 1;
*/ */
/* get the candidate master, following MIN(node_id) rule */ /* get the candidate master, following MIN(node_id) rule */
candidate_master = get_candidate_master(handle->databases); candidate_master = get_candidate_master(mon->databases);
/* Select the master, based on master_stickiness */ /* Select the master, based on master_stickiness */
if (1 == handle->disableMasterRoleSetting) { if (1 == handle->disableMasterRoleSetting) {
@ -629,7 +522,7 @@ int log_no_members = 1;
handle->master = set_cluster_master(handle->master, candidate_master, master_stickiness); handle->master = set_cluster_master(handle->master, candidate_master, master_stickiness);
} }
ptr = handle->databases; ptr = mon->databases;
while (ptr) { while (ptr) {
if (!SERVER_IS_JOINED(ptr->server) || SERVER_IN_MAINT(ptr->server)) { if (!SERVER_IS_JOINED(ptr->server) || SERVER_IN_MAINT(ptr->server)) {
@ -681,19 +574,6 @@ int log_no_members = 1;
} }
} }
/**
* Set the monitor sampling interval.
*
* @param arg The handle allocated by startMonitor
* @param interval The interval to set in monitor struct, in milliseconds
*/
static void
setInterval(void *arg, size_t interval)
{
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
memcpy(&handle->interval, &interval, sizeof(unsigned long));
}
/** /**
* get candidate master from all nodes * get candidate master from all nodes
* *
@ -796,67 +676,6 @@ GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
memcpy(&handle->availableWhenDonor, &disable, sizeof(int)); memcpy(&handle->availableWhenDonor, &disable, sizeof(int));
} }
/**
* Set the timeouts to use in the monitor.
*
* @param arg The handle allocated by startMonitor
* @param type The connect timeout type
* @param value The timeout value to set
*/
static void
setNetworkTimeout(void *arg, int type, int value)
{
GALERA_MONITOR *handle = (GALERA_MONITOR *)arg;
int max_timeout = (int)(handle->interval/1000);
int new_timeout = max_timeout -1;
if (new_timeout <= 0)
new_timeout = DEFAULT_CONNECT_TIMEOUT;
switch(type) {
case MONITOR_CONNECT_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->connect_timeout, &value, sizeof(int));
} else {
memcpy(&handle->connect_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Connect Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_READ_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->read_timeout, &value, sizeof(int));
} else {
memcpy(&handle->read_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Read Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_WRITE_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->write_timeout, &value, sizeof(int));
} else {
memcpy(&handle->write_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Write Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
default:
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Monitor setNetworkTimeout received an unsupported action type %i", type)));
break;
}
}
/** /**
* Check if current monitored server status has changed * Check if current monitored server status has changed
* *
@ -890,9 +709,6 @@ static bool mon_print_fail_status(
{ {
bool succp; bool succp;
int errcount = mon_srv->mon_err_count; int errcount = mon_srv->mon_err_count;
uint8_t modval;
modval = 1<<(MIN(errcount/10, 7));
if (SERVER_IS_DOWN(mon_srv->server) && errcount == 0) if (SERVER_IS_DOWN(mon_srv->server) && errcount == 0)
{ {

View File

@ -42,23 +42,12 @@ typedef struct {
pthread_t tid; /**< id of monitor thread */ pthread_t tid; /**< id of monitor thread */
int shutdown; /**< Flag to shutdown the monitor thread */ int shutdown; /**< Flag to shutdown the monitor thread */
int status; /**< Monitor status */ int status; /**< Monitor status */
char *defaultUser; /**< Default username for monitoring */
char *defaultPasswd; /**< Default password for monitoring */
unsigned long interval; /**< Monitor sampling interval */
unsigned long id; /**< Monitor ID */ unsigned long id; /**< Monitor ID */
int detectStaleMaster; /**< Monitor flag for MySQL replication Stale Master detection */ int detectStaleMaster; /**< Monitor flag for MySQL replication Stale Master detection */
int disableMasterFailback; /**< Monitor flag for Galera Cluster Master failback */ int disableMasterFailback; /**< Monitor flag for Galera Cluster Master failback */
int availableWhenDonor; /**< Monitor flag for Galera Cluster Donor availability */ int availableWhenDonor; /**< Monitor flag for Galera Cluster Donor availability */
int disableMasterRoleSetting; /**< Monitor flag to disable setting master role */ int disableMasterRoleSetting; /**< Monitor flag to disable setting master role */
MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */ MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */
MONITOR_SERVERS *databases; /**< Linked list of servers to monitor */
int connect_timeout; /**< Connect timeout in seconds for mysql_real_connect */
int read_timeout; /**< Timeout in seconds to read from the server.
* There are retries and the total effective timeout value is three times the option value.
*/
int write_timeout; /**< Timeout in seconds for each attempt to write to the server.
* There are retries and the total effective timeout value is two times the option value.
*/
EXTERNCMD* master_down_script; EXTERNCMD* master_down_script;
} GALERA_MONITOR; } GALERA_MONITOR;

View File

@ -49,7 +49,7 @@ extern __thread log_info_t tls_log_info;
static void monitorMain(void *); static void monitorMain(void *);
static char *version_str = "V1.0.1"; static char *version_str = "V1.1.1";
MODULE_INFO info = { MODULE_INFO info = {
MODULE_API_MONITOR, MODULE_API_MONITOR,
@ -60,26 +60,18 @@ MODULE_INFO info = {
static void *startMonitor(void *,void*); static void *startMonitor(void *,void*);
static void stopMonitor(void *); static void stopMonitor(void *);
static void registerServer(void *, SERVER *);
static void unregisterServer(void *, SERVER *);
static void defaultUser(void *, char *, char *);
static void diagnostics(DCB *, void *); static void diagnostics(DCB *, void *);
static void setInterval(void *, size_t);
static void detectStaleMaster(void *, int); static void detectStaleMaster(void *, int);
static bool mon_status_changed(MONITOR_SERVERS* mon_srv); static bool mon_status_changed(MONITOR_SERVERS* mon_srv);
static bool mon_print_fail_status(MONITOR_SERVERS* mon_srv); static bool mon_print_fail_status(MONITOR_SERVERS* mon_srv);
static MONITOR_SERVERS *get_current_master(MYSQL_MONITOR *); static MONITOR_SERVERS *get_current_master(MONITOR *);
static void monitor_set_pending_status(MONITOR_SERVERS *, int); static void monitor_set_pending_status(MONITOR_SERVERS *, int);
static void monitor_clear_pending_status(MONITOR_SERVERS *, int); static void monitor_clear_pending_status(MONITOR_SERVERS *, int);
static MONITOR_OBJECT MyObject = { static MONITOR_OBJECT MyObject = {
startMonitor, startMonitor,
stopMonitor, stopMonitor,
registerServer, diagnostics
unregisterServer,
defaultUser,
diagnostics,
setInterval
}; };
/** /**
@ -131,23 +123,19 @@ GetModuleObject()
static void * static void *
startMonitor(void *arg,void* opt) startMonitor(void *arg,void* opt)
{ {
MYSQL_MONITOR *handle; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = mon->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt; CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
if (arg) if (handle)
{ {
handle = arg; /* Must be a restart */
handle->shutdown = 0; handle->shutdown = 0;
} }
else else
{ {
if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL)
return NULL; return NULL;
handle->databases = NULL;
handle->shutdown = 0; handle->shutdown = 0;
handle->defaultUser = NULL;
handle->defaultPasswd = NULL;
handle->id = MONITOR_DEFAULT_ID; handle->id = MONITOR_DEFAULT_ID;
handle->interval = MONITOR_INTERVAL;
handle->replicationHeartbeat = 0; handle->replicationHeartbeat = 0;
handle->detectStaleMaster = 0; handle->detectStaleMaster = 0;
handle->master = NULL; handle->master = NULL;
@ -179,103 +167,6 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
thread_wait((void *)handle->tid); thread_wait((void *)handle->tid);
} }
/**
* Register a server that must be added to the monitored servers for
* a monitoring module.
*
* @param arg A handle on the running monitor module
* @param server The server to add
*/
static void
registerServer(void *arg, SERVER *server)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
MONITOR_SERVERS *ptr, *db;
if ((db = (MONITOR_SERVERS *)malloc(sizeof(MONITOR_SERVERS))) == NULL)
return;
db->server = server;
db->con = NULL;
db->next = NULL;
db->mon_err_count = 0;
db->mon_prev_status = 0;
/* pending status is updated by monitorMain */
db->pending_status = 0;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
handle->databases = db;
else
{
ptr = handle->databases;
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = db;
}
spinlock_release(&handle->lock);
}
/**
* Remove a server from those being monitored by a monitoring module
*
* @param arg A handle on the running monitor module
* @param server The server to remove
*/
static void
unregisterServer(void *arg, SERVER *server)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
MONITOR_SERVERS *ptr, *lptr;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
{
spinlock_release(&handle->lock);
return;
}
if (handle->databases->server == server)
{
ptr = handle->databases;
handle->databases = handle->databases->next;
free(ptr);
}
else
{
ptr = handle->databases;
while (ptr->next != NULL && ptr->next->server != server)
ptr = ptr->next;
if (ptr->next)
{
lptr = ptr->next;
ptr->next = ptr->next->next;
free(lptr);
}
}
spinlock_release(&handle->lock);
}
/**
* Set the default username and password to use to monitor if the server does not
* override this.
*
* @param arg The handle allocated by startMonitor
* @param uname The default user name
* @param passwd The default password
*/
static void
defaultUser(void *arg, char *uname, char *passwd)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
if (handle->defaultUser)
free(handle->defaultUser);
if (handle->defaultPasswd)
free(handle->defaultPasswd);
handle->defaultUser = strdup(uname);
handle->defaultPasswd = strdup(passwd);
}
/** /**
* Daignostic interface * Daignostic interface
* *
@ -284,7 +175,8 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
*/ */
static void diagnostics(DCB *dcb, void *arg) static void diagnostics(DCB *dcb, void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
MONITOR_SERVERS *db; MONITOR_SERVERS *db;
char *sep; char *sep;
@ -301,11 +193,11 @@ char *sep;
break; break;
} }
dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", handle->interval); dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", mon->interval);
dcb_printf(dcb,"\tDetect Stale Master:\t%s\n", (handle->detectStaleMaster == 1) ? "enabled" : "disabled"); dcb_printf(dcb,"\tDetect Stale Master:\t%s\n", (handle->detectStaleMaster == 1) ? "enabled" : "disabled");
dcb_printf(dcb, "\tMonitored servers: "); dcb_printf(dcb, "\tMonitored servers: ");
db = handle->databases; db = mon->databases;
sep = ""; sep = "";
while (db) while (db)
{ {
@ -327,15 +219,16 @@ char *sep;
* @param database The database to probe * @param database The database to probe
*/ */
static void static void
monitorDatabase(MYSQL_MONITOR *handle, MONITOR_SERVERS *database) monitorDatabase(MONITOR* mon, MONITOR_SERVERS *database)
{ {
MYSQL_MONITOR *handle = mon->handle;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL_RES *result; MYSQL_RES *result;
int num_fields; int num_fields;
int isslave = 0; int isslave = 0;
int ismaster = 0; int ismaster = 0;
char *uname = handle->defaultUser; char *uname = mon->user;
char *passwd = handle->defaultPasswd; char *passwd = mon->password;
unsigned long int server_version = 0; unsigned long int server_version = 0;
char *server_string; char *server_string;
@ -358,12 +251,11 @@ char *server_string;
if (database->con == NULL || mysql_ping(database->con) != 0) if (database->con == NULL || mysql_ping(database->con) != 0)
{ {
char *dpwd = decryptPassword(passwd); char *dpwd = decryptPassword(passwd);
int rc;
int read_timeout = 1; int read_timeout = 1;
database->con = mysql_init(NULL); database->con = mysql_init(NULL);
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout); mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
if (mysql_real_connect(database->con, if (mysql_real_connect(database->con,
database->server->name, database->server->name,
@ -437,7 +329,7 @@ char *server_string;
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
long server_id = -1; long server_id = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
server_id = strtol(row[0], NULL, 10); server_id = strtol(row[0], NULL, 10);
@ -463,7 +355,7 @@ char *server_string;
{ {
int i = 0; int i = 0;
long master_id = -1; long master_id = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
/* get Slave_IO_Running and Slave_SQL_Running values*/ /* get Slave_IO_Running and Slave_SQL_Running values*/
@ -502,7 +394,7 @@ char *server_string;
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
long master_id = -1; long master_id = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
/* get Slave_IO_Running and Slave_SQL_Running values*/ /* get Slave_IO_Running and Slave_SQL_Running values*/
@ -534,7 +426,7 @@ char *server_string;
if (mysql_query(database->con, "SHOW GLOBAL VARIABLES LIKE 'read_only'") == 0 if (mysql_query(database->con, "SHOW GLOBAL VARIABLES LIKE 'read_only'") == 0
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
if (strncasecmp(row[1], "OFF", 3) == 0) { if (strncasecmp(row[1], "OFF", 3) == 0) {
@ -584,7 +476,8 @@ char *server_string;
static void static void
monitorMain(void *arg) monitorMain(void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
MONITOR_SERVERS *ptr; MONITOR_SERVERS *ptr;
int detect_stale_master = handle->detectStaleMaster; int detect_stale_master = handle->detectStaleMaster;
MONITOR_SERVERS *root_master; MONITOR_SERVERS *root_master;
@ -619,7 +512,7 @@ size_t nrounds = 0;
* round. * round.
*/ */
if (nrounds != 0 && if (nrounds != 0 &&
((nrounds*MON_BASE_INTERVAL_MS)%handle->interval) >= ((nrounds*MON_BASE_INTERVAL_MS)%mon->interval) >=
MON_BASE_INTERVAL_MS) MON_BASE_INTERVAL_MS)
{ {
nrounds += 1; nrounds += 1;
@ -628,7 +521,7 @@ size_t nrounds = 0;
nrounds += 1; nrounds += 1;
/* start from the first server in the list */ /* start from the first server in the list */
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {
@ -636,7 +529,7 @@ size_t nrounds = 0;
ptr->pending_status = ptr->server->status; ptr->pending_status = ptr->server->status;
/* monitor current node */ /* monitor current node */
monitorDatabase(handle, ptr); monitorDatabase(mon, ptr);
if (mon_status_changed(ptr)) if (mon_status_changed(ptr))
{ {
@ -668,11 +561,11 @@ size_t nrounds = 0;
} }
/* Get Master server pointer */ /* Get Master server pointer */
root_master = get_current_master(handle); root_master = get_current_master(mon);
/* Update server status from monitor pending status on that server*/ /* Update server status from monitor pending status on that server*/
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {
if (! SERVER_IN_MAINT(ptr->server)) { if (! SERVER_IN_MAINT(ptr->server)) {
@ -692,19 +585,6 @@ size_t nrounds = 0;
} }
} }
/**
* Set the monitor sampling interval.
*
* @param arg The handle allocated by startMonitor
* @param interval The interval to set in monitor struct, in milliseconds
*/
static void
setInterval(void *arg, size_t interval)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
memcpy(&handle->interval, &interval, sizeof(unsigned long));
}
/** /**
* Enable/Disable the MySQL Replication Stale Master dectection, allowing a previouvsly detected master to still act as a Master. * Enable/Disable the MySQL Replication Stale Master dectection, allowing a previouvsly detected master to still act as a Master.
* This option must be enabled in order to keep the Master when the replication is stopped or removed from slaves. * This option must be enabled in order to keep the Master when the replication is stopped or removed from slaves.
@ -716,7 +596,8 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
static void static void
detectStaleMaster(void *arg, int enable) detectStaleMaster(void *arg, int enable)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
memcpy(&handle->detectStaleMaster, &enable, sizeof(int)); memcpy(&handle->detectStaleMaster, &enable, sizeof(int));
} }
@ -790,10 +671,11 @@ monitor_clear_pending_status(MONITOR_SERVERS *ptr, int bit)
* @return The server at root level with SERVER_MASTER bit * @return The server at root level with SERVER_MASTER bit
*/ */
static MONITOR_SERVERS *get_current_master(MYSQL_MONITOR *handle) { static MONITOR_SERVERS *get_current_master(MONITOR *mon) {
MYSQL_MONITOR* handle = mon->handle;
MONITOR_SERVERS *ptr; MONITOR_SERVERS *ptr;
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {

View File

@ -31,27 +31,4 @@
* @endverbatim * @endverbatim
*/ */
#define MONITOR_RUNNING 1
#define MONITOR_STOPPING 2
#define MONITOR_STOPPED 3
#define MONITOR_INTERVAL 10000 // in milliseconds
#define MONITOR_DEFAULT_ID 1UL // unsigned long value
#define MONITOR_MAX_NUM_SLAVES 20 //number of MySQL slave servers associated to a MySQL master server
/**
* The linked list of servers that are being monitored by the MySQL
* Monitor module.
*/
typedef struct monitor_servers {
SERVER *server; /**< The server being monitored */
MYSQL *con; /**< The MySQL connection */
int mon_err_count;
unsigned int mon_prev_status;
unsigned int pending_status; /**< Pending Status flag bitmap */
struct monitor_servers
*next; /**< The next server in the list */
} MONITOR_SERVERS;
#endif #endif

View File

@ -84,20 +84,15 @@ MODULE_INFO info = {
static void *startMonitor(void *,void*); static void *startMonitor(void *,void*);
static void stopMonitor(void *); static void stopMonitor(void *);
static void registerServer(void *, SERVER *);
static void unregisterServer(void *, SERVER *);
static void defaultUser(void *, char *, char *);
static void diagnostics(DCB *, void *); static void diagnostics(DCB *, void *);
static void setInterval(void *, size_t);
static void defaultId(void *, unsigned long); static void defaultId(void *, unsigned long);
static void setNetworkTimeout(void *, int, int);
static bool mon_status_changed(MONITOR_SERVERS* mon_srv); static bool mon_status_changed(MONITOR_SERVERS* mon_srv);
static bool mon_print_fail_status(MONITOR_SERVERS* mon_srv); static bool mon_print_fail_status(MONITOR_SERVERS* mon_srv);
static MONITOR_SERVERS *getServerByNodeId(MONITOR_SERVERS *, long); static MONITOR_SERVERS *getServerByNodeId(MONITOR_SERVERS *, long);
static MONITOR_SERVERS *getSlaveOfNodeId(MONITOR_SERVERS *, long); static MONITOR_SERVERS *getSlaveOfNodeId(MONITOR_SERVERS *, long);
static MONITOR_SERVERS *get_replication_tree(MYSQL_MONITOR *, int); static MONITOR_SERVERS *get_replication_tree(MONITOR *, int);
static void set_master_heartbeat(MYSQL_MONITOR *, MONITOR_SERVERS *); static void set_master_heartbeat(MYSQL_MONITOR *, MONITOR_SERVERS *);
static void set_slave_heartbeat(MYSQL_MONITOR *, MONITOR_SERVERS *); static void set_slave_heartbeat(MONITOR *, MONITOR_SERVERS *);
static int add_slave_to_master(long *, int, long); static int add_slave_to_master(long *, int, long);
static void monitor_set_pending_status(MONITOR_SERVERS *, int); static void monitor_set_pending_status(MONITOR_SERVERS *, int);
static void monitor_clear_pending_status(MONITOR_SERVERS *, int); static void monitor_clear_pending_status(MONITOR_SERVERS *, int);
@ -105,12 +100,7 @@ static void monitor_clear_pending_status(MONITOR_SERVERS *, int);
static MONITOR_OBJECT MyObject = { static MONITOR_OBJECT MyObject = {
startMonitor, startMonitor,
stopMonitor, stopMonitor,
registerServer, diagnostics
unregisterServer,
defaultUser,
diagnostics,
setInterval,
setNetworkTimeout
}; };
/** /**
@ -157,12 +147,14 @@ GetModuleObject()
* This function creates a thread to execute the actual monitoring. * This function creates a thread to execute the actual monitoring.
* *
* @param arg The current handle - NULL if first start * @param arg The current handle - NULL if first start
* @param opt Configuration parameters
* @return A handle to use when interacting with the monitor * @return A handle to use when interacting with the monitor
*/ */
static void * static void *
startMonitor(void *arg, void* opt) startMonitor(void *arg, void* opt)
{ {
MYSQL_MONITOR *handle; MONITOR* monitor = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR*)monitor->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt; CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
if (arg) if (arg)
{ {
@ -173,18 +165,11 @@ CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
{ {
if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL)
return NULL; return NULL;
handle->databases = NULL;
handle->shutdown = 0; handle->shutdown = 0;
handle->defaultUser = NULL;
handle->defaultPasswd = NULL;
handle->id = config_get_gateway_id(); handle->id = config_get_gateway_id();
handle->interval = MONITOR_INTERVAL;
handle->replicationHeartbeat = 0; handle->replicationHeartbeat = 0;
handle->detectStaleMaster = 0; handle->detectStaleMaster = 0;
handle->master = NULL; handle->master = NULL;
handle->connect_timeout=DEFAULT_CONNECT_TIMEOUT;
handle->read_timeout=DEFAULT_READ_TIMEOUT;
handle->write_timeout=DEFAULT_WRITE_TIMEOUT;
handle->master_down_script = NULL; handle->master_down_script = NULL;
spinlock_init(&handle->lock); spinlock_init(&handle->lock);
} }
@ -216,109 +201,13 @@ CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
static void static void
stopMonitor(void *arg) stopMonitor(void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
handle->shutdown = 1; handle->shutdown = 1;
thread_wait((void *)handle->tid); thread_wait((void *)handle->tid);
} }
/**
* Register a server that must be added to the monitored servers for
* a monitoring module.
*
* @param arg A handle on the running monitor module
* @param server The server to add
*/
static void
registerServer(void *arg, SERVER *server)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
MONITOR_SERVERS *ptr, *db;
if ((db = (MONITOR_SERVERS *)malloc(sizeof(MONITOR_SERVERS))) == NULL)
return;
db->server = server;
db->con = NULL;
db->next = NULL;
db->mon_err_count = 0;
db->mon_prev_status = 0;
/* pending status is updated by get_replication_tree */
db->pending_status = 0;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
handle->databases = db;
else
{
ptr = handle->databases;
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = db;
}
spinlock_release(&handle->lock);
}
/**
* Remove a server from those being monitored by a monitoring module
*
* @param arg A handle on the running monitor module
* @param server The server to remove
*/
static void
unregisterServer(void *arg, SERVER *server)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
MONITOR_SERVERS *ptr, *lptr;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
{
spinlock_release(&handle->lock);
return;
}
if (handle->databases->server == server)
{
ptr = handle->databases;
handle->databases = handle->databases->next;
free(ptr);
}
else
{
ptr = handle->databases;
while (ptr->next != NULL && ptr->next->server != server)
ptr = ptr->next;
if (ptr->next)
{
lptr = ptr->next;
ptr->next = ptr->next->next;
free(lptr);
}
}
spinlock_release(&handle->lock);
}
/**
* Set the default username and password to use to monitor if the server does not
* override this.
*
* @param arg The handle allocated by startMonitor
* @param uname The default user name
* @param passwd The default password
*/
static void
defaultUser(void *arg, char *uname, char *passwd)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
if (handle->defaultUser)
free(handle->defaultUser);
if (handle->defaultPasswd)
free(handle->defaultPasswd);
handle->defaultUser = strdup(uname);
handle->defaultPasswd = strdup(passwd);
}
/** /**
* Daignostic interface * Daignostic interface
* *
@ -327,7 +216,8 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
*/ */
static void diagnostics(DCB *dcb, void *arg) static void diagnostics(DCB *dcb, void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
MONITOR_SERVERS *db; MONITOR_SERVERS *db;
char *sep; char *sep;
@ -344,16 +234,16 @@ char *sep;
break; break;
} }
dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", handle->interval); dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", mon->interval);
dcb_printf(dcb,"\tMaxScale MonitorId:\t%lu\n", handle->id); dcb_printf(dcb,"\tMaxScale MonitorId:\t%lu\n", handle->id);
dcb_printf(dcb,"\tReplication lag:\t%s\n", (handle->replicationHeartbeat == 1) ? "enabled" : "disabled"); dcb_printf(dcb,"\tReplication lag:\t%s\n", (handle->replicationHeartbeat == 1) ? "enabled" : "disabled");
dcb_printf(dcb,"\tDetect Stale Master:\t%s\n", (handle->detectStaleMaster == 1) ? "enabled" : "disabled"); dcb_printf(dcb,"\tDetect Stale Master:\t%s\n", (handle->detectStaleMaster == 1) ? "enabled" : "disabled");
dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", handle->connect_timeout); dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", mon->connect_timeout);
dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", handle->read_timeout); dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", mon->read_timeout);
dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", handle->write_timeout); dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", mon->write_timeout);
dcb_printf(dcb, "\tMonitored servers: "); dcb_printf(dcb, "\tMonitored servers: ");
db = handle->databases; db = mon->databases;
sep = ""; sep = "";
while (db) while (db)
{ {
@ -375,14 +265,14 @@ char *sep;
* @param database The database to probe * @param database The database to probe
*/ */
static void static void
monitorDatabase(MYSQL_MONITOR *handle, MONITOR_SERVERS *database) monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
{ {
MYSQL_MONITOR* handle = mon->handle;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL_RES *result; MYSQL_RES *result;
int num_fields;
int isslave = 0; int isslave = 0;
char *uname = handle->defaultUser; char *uname = mon->user;
char *passwd = handle->defaultPasswd; char *passwd = mon->password;
unsigned long int server_version = 0; unsigned long int server_version = 0;
char *server_string; char *server_string;
@ -405,16 +295,15 @@ char *server_string;
if (database->con == NULL || mysql_ping(database->con) != 0) if (database->con == NULL || mysql_ping(database->con) != 0)
{ {
char *dpwd = decryptPassword(passwd); char *dpwd = decryptPassword(passwd);
int rc; int connect_timeout = mon->connect_timeout;
int connect_timeout = handle->connect_timeout; int read_timeout = mon->read_timeout;
int read_timeout = handle->read_timeout; int write_timeout = mon->write_timeout;
int write_timeout = handle->write_timeout;
database->con = mysql_init(NULL); database->con = mysql_init(NULL);
rc = mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout); mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout); mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
rc = mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout); mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout);
if (mysql_real_connect(database->con, if (mysql_real_connect(database->con,
database->server->name, database->server->name,
@ -493,7 +382,6 @@ char *server_string;
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
long server_id = -1; long server_id = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
server_id = strtol(row[0], NULL, 10); server_id = strtol(row[0], NULL, 10);
@ -519,7 +407,6 @@ char *server_string;
{ {
int i = 0; int i = 0;
long master_id = -1; long master_id = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
/* get Slave_IO_Running and Slave_SQL_Running values*/ /* get Slave_IO_Running and Slave_SQL_Running values*/
@ -558,7 +445,6 @@ char *server_string;
&& (result = mysql_store_result(database->con)) != NULL) && (result = mysql_store_result(database->con)) != NULL)
{ {
long master_id = -1; long master_id = -1;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) while ((row = mysql_fetch_row(result)))
{ {
/* get Slave_IO_Running and Slave_SQL_Running values*/ /* get Slave_IO_Running and Slave_SQL_Running values*/
@ -615,7 +501,8 @@ char *server_string;
static void static void
monitorMain(void *arg) monitorMain(void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*) arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
MONITOR_SERVERS *ptr; MONITOR_SERVERS *ptr;
int replication_heartbeat = handle->replicationHeartbeat; int replication_heartbeat = handle->replicationHeartbeat;
int detect_stale_master = handle->detectStaleMaster; int detect_stale_master = handle->detectStaleMaster;
@ -652,7 +539,7 @@ int log_no_master = 1;
* round. * round.
*/ */
if (nrounds != 0 && if (nrounds != 0 &&
((nrounds*MON_BASE_INTERVAL_MS)%handle->interval) >= ((nrounds*MON_BASE_INTERVAL_MS)%mon->interval) >=
MON_BASE_INTERVAL_MS) MON_BASE_INTERVAL_MS)
{ {
nrounds += 1; nrounds += 1;
@ -663,7 +550,7 @@ int log_no_master = 1;
num_servers = 0; num_servers = 0;
/* start from the first server in the list */ /* start from the first server in the list */
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {
@ -671,7 +558,7 @@ int log_no_master = 1;
ptr->pending_status = ptr->server->status; ptr->pending_status = ptr->server->status;
/* monitor current node */ /* monitor current node */
monitorDatabase(handle, ptr); monitorDatabase(mon, ptr);
/* reset the slave list of current node */ /* reset the slave list of current node */
if (ptr->server->slaves) { if (ptr->server->slaves) {
@ -753,7 +640,7 @@ int log_no_master = 1;
ptr = ptr->next; ptr = ptr->next;
} }
ptr = handle->databases; ptr = mon->databases;
/* if only one server is configured, that's is Master */ /* if only one server is configured, that's is Master */
if (num_servers == 1) { if (num_servers == 1) {
if (SERVER_IS_RUNNING(ptr->server)) { if (SERVER_IS_RUNNING(ptr->server)) {
@ -770,12 +657,12 @@ int log_no_master = 1;
} }
} else { } else {
/* Compute the replication tree */ /* Compute the replication tree */
root_master = get_replication_tree(handle, num_servers); root_master = get_replication_tree(mon, num_servers);
} }
/* Update server status from monitor pending status on that server*/ /* Update server status from monitor pending status on that server*/
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {
if (! SERVER_IN_MAINT(ptr->server)) { if (! SERVER_IN_MAINT(ptr->server)) {
@ -852,7 +739,7 @@ int log_no_master = 1;
SERVER_IS_RELAY_SERVER(root_master->server))) SERVER_IS_RELAY_SERVER(root_master->server)))
{ {
set_master_heartbeat(handle, root_master); set_master_heartbeat(handle, root_master);
ptr = handle->databases; ptr = mon->databases;
while (ptr) { while (ptr) {
if( (! SERVER_IN_MAINT(ptr->server)) && SERVER_IS_RUNNING(ptr->server)) if( (! SERVER_IN_MAINT(ptr->server)) && SERVER_IS_RUNNING(ptr->server))
@ -861,7 +748,7 @@ int log_no_master = 1;
(SERVER_IS_SLAVE(ptr->server) || (SERVER_IS_SLAVE(ptr->server) ||
SERVER_IS_RELAY_SERVER(ptr->server))) SERVER_IS_RELAY_SERVER(ptr->server)))
{ {
set_slave_heartbeat(handle, ptr); set_slave_heartbeat(mon, ptr);
} }
} }
ptr = ptr->next; ptr = ptr->next;
@ -883,19 +770,6 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
memcpy(&handle->id, &id, sizeof(unsigned long)); memcpy(&handle->id, &id, sizeof(unsigned long));
} }
/**
* Set the monitor sampling interval.
*
* @param arg The handle allocated by startMonitor
* @param interval The interval to set in monitor struct, in milliseconds
*/
static void
setInterval(void *arg, size_t interval)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
memcpy(&handle->interval, &interval, sizeof(unsigned long));
}
/** /**
* Enable/Disable the MySQL Replication hearbeat, detecting slave lag behind master. * Enable/Disable the MySQL Replication hearbeat, detecting slave lag behind master.
* *
@ -957,9 +831,6 @@ static bool mon_print_fail_status(
{ {
bool succp; bool succp;
int errcount = mon_srv->mon_err_count; int errcount = mon_srv->mon_err_count;
uint8_t modval;
modval = 1<<(MIN(errcount/10, 7));
if (SERVER_IS_DOWN(mon_srv->server) && errcount == 0) if (SERVER_IS_DOWN(mon_srv->server) && errcount == 0)
{ {
@ -1133,13 +1004,13 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *databas
* @param handle The monitor handle * @param handle The monitor handle
* @param database The number database server * @param database The number database server
*/ */
static void set_slave_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *database) { static void set_slave_heartbeat(MONITOR* mon, MONITOR_SERVERS *database) {
MYSQL_MONITOR *handle = (MYSQL_MONITOR*)mon->handle;
unsigned long id = handle->id; unsigned long id = handle->id;
time_t heartbeat; time_t heartbeat;
char select_heartbeat_query[256] = ""; char select_heartbeat_query[256] = "";
MYSQL_ROW row; MYSQL_ROW row;
MYSQL_RES *result; MYSQL_RES *result;
int num_fields;
if (handle->master == NULL) { if (handle->master == NULL) {
LOGIF(LE, (skygw_log_write_flush( LOGIF(LE, (skygw_log_write_flush(
@ -1159,7 +1030,6 @@ static void set_slave_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *database
if (handle->master !=NULL && (mysql_query(database->con, select_heartbeat_query) == 0 if (handle->master !=NULL && (mysql_query(database->con, select_heartbeat_query) == 0
&& (result = mysql_store_result(database->con)) != NULL)) { && (result = mysql_store_result(database->con)) != NULL)) {
int rows_found = 0; int rows_found = 0;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result))) { while ((row = mysql_fetch_row(result))) {
int rlag = -1; int rlag = -1;
@ -1184,7 +1054,7 @@ static void set_slave_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *database
if (rlag >= 0) { if (rlag >= 0) {
/* store rlag only if greater than monitor sampling interval */ /* store rlag only if greater than monitor sampling interval */
database->server->rlag = (rlag > (handle->interval / 1000)) ? rlag : 0; database->server->rlag = (rlag > (mon->interval / 1000)) ? rlag : 0;
} else { } else {
database->server->rlag = -1; database->server->rlag = -1;
} }
@ -1238,7 +1108,8 @@ static void set_slave_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *database
* @return The server at root level with SERVER_MASTER bit * @return The server at root level with SERVER_MASTER bit
*/ */
static MONITOR_SERVERS *get_replication_tree(MYSQL_MONITOR *handle, int num_servers) { static MONITOR_SERVERS *get_replication_tree(MONITOR *mon, int num_servers) {
MYSQL_MONITOR* handle = (MYSQL_MONITOR*)mon->handle;
MONITOR_SERVERS *ptr; MONITOR_SERVERS *ptr;
MONITOR_SERVERS *backend; MONITOR_SERVERS *backend;
SERVER *current; SERVER *current;
@ -1246,7 +1117,7 @@ static MONITOR_SERVERS *get_replication_tree(MYSQL_MONITOR *handle, int num_serv
long node_id; long node_id;
int root_level; int root_level;
ptr = handle->databases; ptr = mon->databases;
root_level = num_servers; root_level = num_servers;
while (ptr) while (ptr)
@ -1265,7 +1136,7 @@ static MONITOR_SERVERS *get_replication_tree(MYSQL_MONITOR *handle, int num_serv
node_id = current->master_id; node_id = current->master_id;
if (node_id < 1) { if (node_id < 1) {
MONITOR_SERVERS *find_slave; MONITOR_SERVERS *find_slave;
find_slave = getSlaveOfNodeId(handle->databases, current->node_id); find_slave = getSlaveOfNodeId(mon->databases, current->node_id);
if (find_slave == NULL) { if (find_slave == NULL) {
current->depth = -1; current->depth = -1;
@ -1285,7 +1156,7 @@ static MONITOR_SERVERS *get_replication_tree(MYSQL_MONITOR *handle, int num_serv
root_level = current->depth; root_level = current->depth;
handle->master = ptr; handle->master = ptr;
} }
backend = getServerByNodeId(handle->databases, node_id); backend = getServerByNodeId(mon->databases, node_id);
if (backend) { if (backend) {
node_id = backend->server->master_id; node_id = backend->server->master_id;
@ -1301,7 +1172,7 @@ static MONITOR_SERVERS *get_replication_tree(MYSQL_MONITOR *handle, int num_serv
MONITOR_SERVERS *master; MONITOR_SERVERS *master;
current->depth = depth; current->depth = depth;
master = getServerByNodeId(handle->databases, current->master_id); master = getServerByNodeId(mon->databases, current->master_id);
if (master && master->server && master->server->node_id > 0) { if (master && master->server && master->server->node_id > 0) {
add_slave_to_master(master->server->slaves, MONITOR_MAX_NUM_SLAVES, current->node_id); add_slave_to_master(master->server->slaves, MONITOR_MAX_NUM_SLAVES, current->node_id);
master->server->depth = current->depth -1; master->server->depth = current->depth -1;
@ -1383,65 +1254,3 @@ monitor_clear_pending_status(MONITOR_SERVERS *ptr, int bit)
{ {
ptr->pending_status &= ~bit; ptr->pending_status &= ~bit;
} }
/**
* Set the default id to use in the monitor.
*
* @param arg The handle allocated by startMonitor
* @param type The connect timeout type
* @param value The timeout value to set
*/
static void
setNetworkTimeout(void *arg, int type, int value)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
int max_timeout = (int)(handle->interval/1000);
int new_timeout = max_timeout -1;
if (new_timeout <= 0)
new_timeout = DEFAULT_CONNECT_TIMEOUT;
switch(type) {
case MONITOR_CONNECT_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->connect_timeout, &value, sizeof(int));
} else {
memcpy(&handle->connect_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Connect Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_READ_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->read_timeout, &value, sizeof(int));
} else {
memcpy(&handle->read_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Read Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_WRITE_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->write_timeout, &value, sizeof(int));
} else {
memcpy(&handle->write_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Write Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
default:
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Monitor setNetworkTimeout received an unsupported action type %i", type)));
break;
}
}

View File

@ -49,9 +49,6 @@ typedef struct {
pthread_t tid; /**< id of monitor thread */ pthread_t tid; /**< id of monitor thread */
int shutdown; /**< Flag to shutdown the monitor thread */ int shutdown; /**< Flag to shutdown the monitor thread */
int status; /**< Monitor status */ int status; /**< Monitor status */
char *defaultUser; /**< Default username for monitoring */
char *defaultPasswd; /**< Default password for monitoring */
unsigned long interval; /**< Monitor sampling interval */
unsigned long id; /**< Monitor ID */ unsigned long id; /**< Monitor ID */
int replicationHeartbeat; /**< Monitor flag for MySQL replication heartbeat */ int replicationHeartbeat; /**< Monitor flag for MySQL replication heartbeat */
int detectStaleMaster; /**< Monitor flag for MySQL replication Stale Master detection */ int detectStaleMaster; /**< Monitor flag for MySQL replication Stale Master detection */
@ -59,14 +56,6 @@ typedef struct {
int availableWhenDonor; /**< Monitor flag for Galera Cluster Donor availability */ int availableWhenDonor; /**< Monitor flag for Galera Cluster Donor availability */
int disableMasterRoleSetting; /**< Monitor flag to disable setting master role */ int disableMasterRoleSetting; /**< Monitor flag to disable setting master role */
MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */ MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */
MONITOR_SERVERS *databases; /**< Linked list of servers to monitor */
int connect_timeout; /**< Connect timeout in seconds for mysql_real_connect */
int read_timeout; /**< Timeout in seconds to read from the server.
* There are retries and the total effective timeout value is three times the option value.
*/
int write_timeout; /**< Timeout in seconds for each attempt to write to the server.
* There are retries and the total effective timeout value is two times the option value.
*/
EXTERNCMD* master_down_script; EXTERNCMD* master_down_script;
} MYSQL_MONITOR; } MYSQL_MONITOR;

View File

@ -50,7 +50,7 @@ extern __thread log_info_t tls_log_info;
static void monitorMain(void *); static void monitorMain(void *);
static char *version_str = "V1.1.0"; static char *version_str = "V2.1.0";
MODULE_INFO info = { MODULE_INFO info = {
MODULE_API_MONITOR, MODULE_API_MONITOR,
@ -61,22 +61,12 @@ MODULE_INFO info = {
static void *startMonitor(void *,void*); static void *startMonitor(void *,void*);
static void stopMonitor(void *); static void stopMonitor(void *);
static void registerServer(void *, SERVER *);
static void unregisterServer(void *, SERVER *);
static void defaultUsers(void *, char *, char *);
static void diagnostics(DCB *, void *); static void diagnostics(DCB *, void *);
static void setInterval(void *, size_t);
static void setNetworkTimeout(void *arg, int type, int value);
static MONITOR_OBJECT MyObject = { static MONITOR_OBJECT MyObject = {
startMonitor, startMonitor,
stopMonitor, stopMonitor,
registerServer, diagnostics
unregisterServer,
defaultUsers,
diagnostics,
setInterval,
setNetworkTimeout
}; };
/** /**
@ -127,26 +117,19 @@ GetModuleObject()
static void * static void *
startMonitor(void *arg,void* opt) startMonitor(void *arg,void* opt)
{ {
MYSQL_MONITOR *handle; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = mon->handle;
CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt; CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
if (arg != NULL) if (handle != NULL)
{ {
handle = (MYSQL_MONITOR *)arg;
handle->shutdown = 0; handle->shutdown = 0;
} }
else else
{ {
if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL) if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL)
return NULL; return NULL;
handle->databases = NULL;
handle->shutdown = 0; handle->shutdown = 0;
handle->defaultUser = NULL;
handle->defaultPasswd = NULL;
handle->id = MONITOR_DEFAULT_ID; handle->id = MONITOR_DEFAULT_ID;
handle->interval = MONITOR_INTERVAL;
handle->connect_timeout=DEFAULT_CONNECT_TIMEOUT;
handle->read_timeout=DEFAULT_READ_TIMEOUT;
handle->write_timeout=DEFAULT_WRITE_TIMEOUT;
spinlock_init(&handle->lock); spinlock_init(&handle->lock);
} }
@ -162,82 +145,13 @@ CONFIG_PARAMETER* params = (CONFIG_PARAMETER*)opt;
static void static void
stopMonitor(void *arg) stopMonitor(void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = (MONITOR*)arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
handle->shutdown = 1; handle->shutdown = 1;
thread_wait((void *)handle->tid); thread_wait((void *)handle->tid);
} }
/**
* Register a server that must be added to the monitored servers for
* a monitoring module.
*
* @param arg A handle on the running monitor module
* @param server The server to add
*/
static void
registerServer(void *arg, SERVER *server)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
MONITOR_SERVERS *ptr, *db;
if ((db = (MONITOR_SERVERS *)malloc(sizeof(MONITOR_SERVERS))) == NULL)
return;
db->server = server;
db->con = NULL;
db->next = NULL;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
handle->databases = db;
else
{
ptr = handle->databases;
while (ptr->next != NULL)
ptr = ptr->next;
ptr->next = db;
}
spinlock_release(&handle->lock);
}
/**
* Remove a server from those being monitored by a monitoring module
*
* @param arg A handle on the running monitor module
* @param server The server to remove
*/
static void
unregisterServer(void *arg, SERVER *server)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
MONITOR_SERVERS *ptr, *lptr;
spinlock_acquire(&handle->lock);
if (handle->databases == NULL)
{
spinlock_release(&handle->lock);
return;
}
if (handle->databases->server == server)
{
ptr = handle->databases;
handle->databases = handle->databases->next;
free(ptr);
}
else
{
ptr = handle->databases;
while (ptr->next != NULL && ptr->next->server != server)
ptr = ptr->next;
if (ptr->next)
{
lptr = ptr->next;
ptr->next = ptr->next->next;
free(lptr);
}
}
spinlock_release(&handle->lock);
}
/** /**
* Diagnostic interface * Diagnostic interface
* *
@ -247,7 +161,8 @@ MONITOR_SERVERS *ptr, *lptr;
static void static void
diagnostics(DCB *dcb, void *arg) diagnostics(DCB *dcb, void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
MONITOR_SERVERS *db; MONITOR_SERVERS *db;
char *sep; char *sep;
@ -264,13 +179,13 @@ char *sep;
break; break;
} }
dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", handle->interval); dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", mon->interval);
dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", handle->connect_timeout); dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", mon->connect_timeout);
dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", handle->read_timeout); dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", mon->read_timeout);
dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", handle->write_timeout); dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", mon->write_timeout);
dcb_printf(dcb, "\tMonitored servers: "); dcb_printf(dcb, "\tMonitored servers: ");
db = handle->databases; db = mon->databases;
sep = ""; sep = "";
while (db) while (db)
{ {
@ -281,35 +196,15 @@ char *sep;
dcb_printf(dcb, "\n"); dcb_printf(dcb, "\n");
} }
/**
* Set the default username and password to use to monitor if the server does not
* override this.
*
* @param arg The handle allocated by startMonitor
* @param uname The default user name
* @param passwd The default password
*/
static void
defaultUsers(void *arg, char *uname, char *passwd)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
if (handle->defaultUser)
free(handle->defaultUser);
if (handle->defaultPasswd)
free(handle->defaultPasswd);
handle->defaultUser = strdup(uname);
handle->defaultPasswd = strdup(passwd);
}
/** /**
* Monitor an individual server * Monitor an individual server
* *
* @param database The database to probe * @param database The database to probe
*/ */
static void static void
monitorDatabase(MONITOR_SERVERS *database, char *defaultUser, char *defaultPasswd, MYSQL_MONITOR *handle) monitorDatabase(MONITOR_SERVERS *database, char *defaultUser, char *defaultPasswd, MONITOR *mon)
{ {
MYSQL_MONITOR* handle = mon->handle;
MYSQL_ROW row; MYSQL_ROW row;
MYSQL_RES *result; MYSQL_RES *result;
int num_fields; int num_fields;
@ -334,9 +229,9 @@ char *server_string;
{ {
char *dpwd = decryptPassword(passwd); char *dpwd = decryptPassword(passwd);
int rc; int rc;
int connect_timeout = handle->connect_timeout; int connect_timeout = mon->connect_timeout;
int read_timeout = handle->read_timeout; int read_timeout = mon->read_timeout;
int write_timeout = handle->write_timeout; int write_timeout = mon->write_timeout;
database->con = mysql_init(NULL); database->con = mysql_init(NULL);
@ -433,7 +328,8 @@ char *server_string;
static void static void
monitorMain(void *arg) monitorMain(void *arg)
{ {
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg; MONITOR* mon = arg;
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)mon->handle;
MONITOR_SERVERS *ptr; MONITOR_SERVERS *ptr;
long master_id; long master_id;
size_t nrounds = 0; size_t nrounds = 0;
@ -467,7 +363,7 @@ size_t nrounds = 0;
* round. * round.
*/ */
if (nrounds != 0 && if (nrounds != 0 &&
((nrounds*MON_BASE_INTERVAL_MS)%handle->interval) >= ((nrounds*MON_BASE_INTERVAL_MS)%mon->interval) >=
MON_BASE_INTERVAL_MS) MON_BASE_INTERVAL_MS)
{ {
nrounds += 1; nrounds += 1;
@ -475,12 +371,12 @@ size_t nrounds = 0;
} }
nrounds += 1; nrounds += 1;
master_id = -1; master_id = -1;
ptr = handle->databases; ptr = mon->databases;
while (ptr) while (ptr)
{ {
unsigned int prev_status = ptr->server->status; unsigned int prev_status = ptr->server->status;
monitorDatabase(ptr, handle->defaultUser, handle->defaultPasswd,handle); monitorDatabase(ptr, mon->user, mon->password,mon);
if (ptr->server->status != prev_status || if (ptr->server->status != prev_status ||
SERVER_IS_DOWN(ptr->server)) SERVER_IS_DOWN(ptr->server))
@ -497,78 +393,3 @@ size_t nrounds = 0;
} }
} }
} }
/**
* Set the monitor sampling interval.
*
* @param arg The handle allocated by startMonitor
* @param interval The interval to set in monitor struct, in milliseconds
*/
static void
setInterval(void *arg, size_t interval)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
memcpy(&handle->interval, &interval, sizeof(unsigned long));
}
/**
* Set the timeouts to use in the monitor.
*
* @param arg The handle allocated by startMonitor
* @param type The connect timeout type
* @param value The timeout value to set
*/
static void
setNetworkTimeout(void *arg, int type, int value)
{
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
int max_timeout = (int)(handle->interval/1000);
int new_timeout = max_timeout -1;
if (new_timeout <= 0)
new_timeout = DEFAULT_CONNECT_TIMEOUT;
switch(type) {
case MONITOR_CONNECT_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->connect_timeout, &value, sizeof(int));
} else {
memcpy(&handle->connect_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Connect Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_READ_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->read_timeout, &value, sizeof(int));
} else {
memcpy(&handle->read_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Read Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
case MONITOR_WRITE_TIMEOUT:
if (value < max_timeout) {
memcpy(&handle->write_timeout, &value, sizeof(int));
} else {
memcpy(&handle->write_timeout, &new_timeout, sizeof(int));
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"warning : Monitor Write Timeout %i is greater than monitor interval ~%i seconds"
", lowering to %i seconds", value, max_timeout, new_timeout)));
}
break;
default:
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Monitor setNetworkTimeout received an unsupported action type %i", type)));
break;
}
}