Merge remote-tracking branch 'origin/develop' into MXS-329-develop-20151111
# Conflicts: # server/core/CMakeLists.txt # server/core/buffer.c # server/core/service.c # server/modules/filter/tee.c # server/modules/monitor/mysql_mon.c # server/modules/routing/binlog/blr.c # server/modules/routing/binlog/blr_slave.c # server/modules/routing/debugcmd.c # server/modules/routing/readwritesplit/readwritesplit.c # utils/skygw_utils.cc - resolved.
This commit is contained in:
@ -52,14 +52,9 @@
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
|
||||
#include <mysqlmon.h>
|
||||
#include <dcb.h>
|
||||
|
||||
/** Defined in log_manager.cc */
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
extern size_t log_ses_count[];
|
||||
extern __thread log_info_t tls_log_info;
|
||||
#include <modutil.h>
|
||||
|
||||
static void monitorMain(void *);
|
||||
|
||||
@ -83,7 +78,10 @@ static void set_master_heartbeat(MYSQL_MONITOR *, MONITOR_SERVERS *);
|
||||
static void set_slave_heartbeat(MONITOR *, MONITOR_SERVERS *);
|
||||
static int add_slave_to_master(long *, int, long);
|
||||
bool isMySQLEvent(monitor_event_t event);
|
||||
void check_maxscale_schema_replication(MONITOR *monitor);
|
||||
static bool report_version_err = true;
|
||||
static const char* hb_table_name = "maxscale_schema.replication_heartbeat";
|
||||
|
||||
static MONITOR_OBJECT MyObject = {
|
||||
startMonitor,
|
||||
stopMonitor,
|
||||
@ -221,6 +219,7 @@ startMonitor(void *arg, void* opt)
|
||||
{
|
||||
memset(handle->events,true,sizeof(handle->events));
|
||||
}
|
||||
|
||||
handle->tid = (THREAD)thread_start(monitorMain, monitor);
|
||||
return handle;
|
||||
}
|
||||
@ -289,40 +288,6 @@ static void diagnostics(DCB *dcb, void *arg)
|
||||
}
|
||||
dcb_printf(dcb, "\n");
|
||||
}
|
||||
/**
|
||||
* Connect to a database
|
||||
* @param mon Monitor
|
||||
* @param database Monitored database
|
||||
* @return true if connection was successful, false if there was an error
|
||||
*/
|
||||
static inline bool connect_to_db(MONITOR* mon,MONITOR_SERVERS *database)
|
||||
{
|
||||
char *uname = mon->user;
|
||||
char *passwd = mon->password;
|
||||
char *dpwd = decryptPassword(passwd);
|
||||
int connect_timeout = mon->connect_timeout;
|
||||
int read_timeout = mon->read_timeout;
|
||||
int write_timeout = mon->write_timeout;
|
||||
|
||||
if(database->con)
|
||||
mysql_close(database->con);
|
||||
database->con = mysql_init(NULL);
|
||||
|
||||
mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);
|
||||
mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
|
||||
mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout);
|
||||
|
||||
bool result = (mysql_real_connect(database->con,
|
||||
database->server->name,
|
||||
uname,
|
||||
dpwd,
|
||||
NULL,
|
||||
database->server->port,
|
||||
NULL,
|
||||
0) != NULL);
|
||||
free(dpwd);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void monitor_mysql100_db(MONITOR_SERVERS* database)
|
||||
{
|
||||
@ -643,7 +608,8 @@ monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
|
||||
|
||||
if (database->con == NULL || mysql_ping(database->con) != 0)
|
||||
{
|
||||
if(connect_to_db(mon,database))
|
||||
connect_result_t rval;
|
||||
if ((rval = mon_connect_to_db(mon, database)) == MONITOR_CONN_OK)
|
||||
{
|
||||
server_clear_status(database->server, SERVER_AUTH_ERROR);
|
||||
monitor_clear_pending_status(database, SERVER_AUTH_ERROR);
|
||||
@ -677,15 +643,9 @@ monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
|
||||
|
||||
/* Log connect failure only once */
|
||||
if (mon_status_changed(database) && mon_print_fail_status(database))
|
||||
{
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Monitor was unable to connect to "
|
||||
"server %s:%d : \"%s\"",
|
||||
database->server->name,
|
||||
database->server->port,
|
||||
mysql_error(database->con))));
|
||||
}
|
||||
{
|
||||
mon_log_connect_error(database, rval);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -775,6 +735,7 @@ int num_servers=0;
|
||||
MONITOR_SERVERS *root_master = NULL;
|
||||
size_t nrounds = 0;
|
||||
int log_no_master = 1;
|
||||
bool heartbeat_checked = false;
|
||||
|
||||
spinlock_acquire(&mon->lock);
|
||||
handle = (MYSQL_MONITOR *)mon->handle;
|
||||
@ -803,6 +764,13 @@ detect_stale_master = handle->detectStaleMaster;
|
||||
}
|
||||
/** Wait base interval */
|
||||
thread_millisleep(MON_BASE_INTERVAL_MS);
|
||||
|
||||
if (handle->replicationHeartbeat && !heartbeat_checked)
|
||||
{
|
||||
check_maxscale_schema_replication(mon);
|
||||
heartbeat_checked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate how far away the monitor interval is from its full
|
||||
* cycle and if monitor interval time further than the base
|
||||
@ -1505,3 +1473,223 @@ bool isMySQLEvent(monitor_event_t event)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if replicate_ignore_table is defined and if maxscale_schema.replication_hearbeat
|
||||
* table is in the list.
|
||||
* @param database Server to check
|
||||
* @return False if the table is not replicated or an error occurred when querying
|
||||
* the server
|
||||
*/
|
||||
bool check_replicate_ignore_table(MONITOR_SERVERS* database)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_ignore_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
if (strlen(row[1]) > 0 &&
|
||||
strcasestr(row[1], hb_table_name))
|
||||
{
|
||||
skygw_log_write(LE, "Warning: 'replicate_ignore_table' is "
|
||||
"defined on server '%s' and '%s' was found in it. ",
|
||||
database->server->unique_name, hb_table_name);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE, "Error: Failed to query server %s for "
|
||||
"'replicate_ignore_table': %s",
|
||||
database->server->unique_name,
|
||||
mysql_error(database->con));
|
||||
rval = false;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if replicate_do_table is defined and if maxscale_schema.replication_hearbeat
|
||||
* table is not in the list.
|
||||
* @param database Server to check
|
||||
* @return False if the table is not replicated or an error occurred when querying
|
||||
* the server
|
||||
*/
|
||||
bool check_replicate_do_table(MONITOR_SERVERS* database)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_do_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
if (strlen(row[1]) > 0 &&
|
||||
strcasestr(row[1], hb_table_name) == NULL)
|
||||
{
|
||||
skygw_log_write(LE, "Warning: 'replicate_do_table' is "
|
||||
"defined on server '%s' and '%s' was not found in it. ",
|
||||
database->server->unique_name, hb_table_name);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE, "Error: Failed to query server %s for "
|
||||
"'replicate_do_table': %s",
|
||||
database->server->unique_name,
|
||||
mysql_error(database->con));
|
||||
rval = false;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if replicate_wild_do_table is defined and if it doesn't match
|
||||
* maxscale_schema.replication_heartbeat.
|
||||
* @param database Database server
|
||||
* @return False if the table is not replicated or an error occurred when trying to
|
||||
* query the server.
|
||||
*/
|
||||
bool check_replicate_wild_do_table(MONITOR_SERVERS* database)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_wild_do_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
if (strlen(row[1]) > 0)
|
||||
{
|
||||
mxs_pcre2_result_t rc = modutil_mysql_wildcard_match(row[1], hb_table_name);
|
||||
if (rc == MXS_PCRE2_NOMATCH)
|
||||
{
|
||||
skygw_log_write(LE, "Warning: 'replicate_wild_do_table' is "
|
||||
"defined on server '%s' and '%s' does not match it. ",
|
||||
database->server->unique_name,
|
||||
hb_table_name);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE, "Error: Failed to query server %s for "
|
||||
"'replicate_wild_do_table': %s",
|
||||
database->server->unique_name,
|
||||
mysql_error(database->con));
|
||||
rval = false;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if replicate_wild_ignore_table is defined and if it matches
|
||||
* maxscale_schema.replication_heartbeat.
|
||||
* @param database Database server
|
||||
* @return False if the table is not replicated or an error occurred when trying to
|
||||
* query the server.
|
||||
*/
|
||||
bool check_replicate_wild_ignore_table(MONITOR_SERVERS* database)
|
||||
{
|
||||
MYSQL_RES *result;
|
||||
bool rval = true;
|
||||
|
||||
if (mysql_query(database->con,
|
||||
"show variables like 'replicate_wild_ignore_table'") == 0 &&
|
||||
(result = mysql_store_result(database->con)) &&
|
||||
mysql_num_fields(result) > 1)
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
|
||||
while ((row = mysql_fetch_row(result)))
|
||||
{
|
||||
if (strlen(row[1]) > 0)
|
||||
{
|
||||
mxs_pcre2_result_t rc = modutil_mysql_wildcard_match(row[1], hb_table_name);
|
||||
if (rc == MXS_PCRE2_MATCH)
|
||||
{
|
||||
skygw_log_write(LE, "Warning: 'replicate_wild_ignore_table' is "
|
||||
"defined on server '%s' and '%s' matches it. ",
|
||||
database->server->unique_name,
|
||||
hb_table_name);
|
||||
rval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
mysql_free_result(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
skygw_log_write(LE, "Error: Failed to query server %s for "
|
||||
"'replicate_wild_do_table': %s",
|
||||
database->server->unique_name,
|
||||
mysql_error(database->con));
|
||||
rval = false;
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the maxscale_schema.replication_heartbeat table is replicated on all
|
||||
* servers and log a warning if problems were found.
|
||||
* @param monitor Monitor structure
|
||||
*/
|
||||
void check_maxscale_schema_replication(MONITOR *monitor)
|
||||
{
|
||||
MONITOR_SERVERS* database = monitor->databases;
|
||||
bool err = false;
|
||||
|
||||
while (database)
|
||||
{
|
||||
connect_result_t rval = mon_connect_to_db(monitor, database);
|
||||
if (rval == MONITOR_CONN_OK)
|
||||
{
|
||||
if (!check_replicate_ignore_table(database) ||
|
||||
!check_replicate_do_table(database) ||
|
||||
!check_replicate_wild_do_table(database) ||
|
||||
!check_replicate_wild_ignore_table(database))
|
||||
{
|
||||
err = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mon_log_connect_error(database, rval);
|
||||
}
|
||||
database = database->next;
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
skygw_log_write(LE, "Warning: Problems were encountered when "
|
||||
"checking if '%s' is replicated. Make sure that the table is "
|
||||
"replicated to all slaves.", hb_table_name);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user