Merge from develop

Merge from develop
This commit is contained in:
MassimilianoPinto
2015-10-28 09:38:31 +01:00
354 changed files with 275256 additions and 408 deletions

View File

@ -7,7 +7,7 @@ if(BUILD_RABBITMQ)
endif()
add_library(regexfilter SHARED regexfilter.c)
target_link_libraries(regexfilter log_manager)
target_link_libraries(regexfilter log_manager ${PCRE2_LIBRARIES})
install(TARGETS regexfilter DESTINATION ${MAXSCALE_LIBDIR})
add_library(testfilter SHARED testfilter.c)

View File

@ -15,6 +15,7 @@
*
* Copyright MariaDB Corporation Ab 2014
*/
#define PCRE2_CODE_UNIT_WIDTH 8
#include <stdio.h>
#include <filter.h>
#include <modinfo.h>
@ -22,7 +23,7 @@
#include <skygw_utils.h>
#include <log_manager.h>
#include <string.h>
#include <regex.h>
#include <pcre2.h>
#include <atomic.h>
#include "maxconfig.h"
@ -65,7 +66,7 @@ static void setDownstream(FILTER *instance, void *fsession, DOWNSTREAM *downstre
static int routeQuery(FILTER *instance, void *fsession, GWBUF *queue);
static void diagnostic(FILTER *instance, void *fsession, DCB *dcb);
static char *regex_replace(char *sql, regex_t *re, char *replace);
static char *regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *study, const char *replace);
static FILTER_OBJECT MyObject = {
createInstance,
@ -82,25 +83,28 @@ static FILTER_OBJECT MyObject = {
/**
* Instance structure
*/
typedef struct {
char *source; /* Source address to restrict matches */
char *user; /* User name to restrict matches */
char *match; /* Regular expression to match */
char *replace; /* Replacement text */
regex_t re; /* Compiled regex text */
FILE* logfile;
bool log_trace;
typedef struct
{
char *source; /*< Source address to restrict matches */
char *user; /*< User name to restrict matches */
char *match; /*< Regular expression to match */
char *replace; /*< Replacement text */
pcre2_code *re; /*< Compiled regex text */
pcre2_match_data *match_data; /*< Matching data used by the compiled regex */
FILE* logfile; /*< Log file */
bool log_trace; /*< Whether messages should be printed to tracelog */
} REGEX_INSTANCE;
/**
* The session structure for this regex filter
*/
typedef struct {
DOWNSTREAM down; /* The downstream filter */
SPINLOCK lock;
int no_change; /* No. of unchanged requests */
int replacements; /* No. of changed requests */
int active; /* Is filter active */
typedef struct
{
DOWNSTREAM down; /* The downstream filter */
SPINLOCK lock;
int no_change; /* No. of unchanged requests */
int replacements; /* No. of changed requests */
int active; /* Is filter active */
} REGEX_SESSION;
void log_match(REGEX_INSTANCE* inst,char* re, char* old, char* new);
@ -140,6 +144,32 @@ GetModuleObject()
return &MyObject;
}
/**
* Free a regexfilter instance.
* @param instance instance to free
*/
void free_instance(REGEX_INSTANCE *instance)
{
if (instance)
{
if (instance->re)
{
pcre2_code_free(instance->re);
}
if (instance->match_data)
{
pcre2_match_data_free(instance->match_data);
}
free(instance->match);
free(instance->replace);
free(instance->source);
free(instance->user);
free(instance);
}
}
/**
* Create an instance of the filter for a particular service
* within MaxScale.
@ -152,9 +182,12 @@ GetModuleObject()
static FILTER *
createInstance(char **options, FILTER_PARAMETER **params)
{
REGEX_INSTANCE *my_instance;
int i, cflags = REG_ICASE;
char *logfile = NULL;
REGEX_INSTANCE *my_instance;
int i, errnumber, cflags = PCRE2_CASELESS;
PCRE2_SIZE erroffset;
char *logfile = NULL;
const char *errmsg;
if ((my_instance = calloc(1, sizeof(REGEX_INSTANCE))) != NULL)
{
my_instance->match = NULL;
@ -193,11 +226,11 @@ char *logfile = NULL;
{
if (!strcasecmp(options[i], "ignorecase"))
{
cflags |= REG_ICASE;
cflags |= PCRE2_CASELESS;
}
else if (!strcasecmp(options[i], "case"))
{
cflags &= ~REG_ICASE;
cflags &= ~PCRE2_CASELESS;
}
else
{
@ -207,45 +240,56 @@ char *logfile = NULL;
options[i])));
}
}
}
}
if (logfile != NULL)
{
if ((my_instance->logfile = fopen(logfile, "a")) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"regexfilter: Failed to open file '%s'.\n",
logfile)));
free_instance(my_instance);
free(logfile);
return NULL;
}
fprintf(my_instance->logfile, "\nOpened regex filter log\n");
fflush(my_instance->logfile);
}
free(logfile);
if (my_instance->match == NULL || my_instance->replace == NULL)
{
free(my_instance);
free(logfile);
free_instance(my_instance);
return NULL;
}
if (regcomp(&my_instance->re, my_instance->match, REG_ICASE))
if ((my_instance->re = pcre2_compile((PCRE2_SPTR)my_instance->match,
PCRE2_ZERO_TERMINATED,
cflags,
&errnumber,
&erroffset,
NULL)) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"regexfilter: Invalid regular expression '%s'.\n",
my_instance->match)));
free(my_instance->match);
free(my_instance->replace);
free(my_instance);
free(logfile);
return NULL;
}
char errbuffer[1024];
pcre2_get_error_message(errnumber, (PCRE2_UCHAR*) & errbuffer, sizeof(errbuffer));
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"Error: regexfilter: Compiling regular expression '%s' failed at %d: %s\n",
my_instance->match, erroffset, errbuffer)));
free_instance(my_instance);
return NULL;
}
if(logfile != NULL)
{
if((my_instance->logfile = fopen(logfile,"a")) == NULL)
{
if((my_instance->match_data = pcre2_match_data_create_from_pattern(
my_instance->re, NULL)) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"regexfilter: Failed to open file '%s'.\n",
logfile)));
free(my_instance->match);
free(my_instance->replace);
free(my_instance);
free(logfile);
return NULL;
}
fprintf(my_instance->logfile,"\nOpened regex filter log\n");
fflush(my_instance->logfile);
}
free(logfile);
"Error: regexfilter: Failure to create PCRE2 matching data. "
"This is most likely caused by a lack of available memory.")));
free_instance(my_instance);
return NULL;
}
}
return (FILTER *)my_instance;
}
@ -351,8 +395,10 @@ char *sql, *newsql;
}
if ((sql = modutil_get_SQL(queue)) != NULL)
{
newsql = regex_replace(sql, &my_instance->re,
my_instance->replace);
newsql = regex_replace(sql,
my_instance->re,
my_instance->match_data,
my_instance->replace);
if (newsql)
{
queue = modutil_replace_SQL(queue, newsql);
@ -415,76 +461,42 @@ REGEX_SESSION *my_session = (REGEX_SESSION *)fsession;
}
/**
* Perform a regular expression match and subsititution on the SQL
* Perform a regular expression match and substitution on the SQL
*
* @param sql The original SQL text
* @param re The compiled regular expression
* @param match_data The PCRE2 matching data buffer
* @param replace The replacement text
* @return The replaced text or NULL if no replacement was done.
*/
static char *
regex_replace(char *sql, regex_t *re, char *replace)
regex_replace(const char *sql, pcre2_code *re, pcre2_match_data *match_data, const char *replace)
{
char *orig, *result, *ptr;
int i, res_size, res_length, rep_length;
int last_match, length;
regmatch_t match[10];
char *result = NULL;
size_t result_size;
if (regexec(re, sql, 10, match, 0))
{
return NULL;
}
length = strlen(sql);
res_size = 2 * length;
result = (char *)malloc(res_size);
res_length = 0;
rep_length = strlen(replace);
last_match = 0;
for (i = 0; i < 10; i++)
{
if (match[i].rm_so != -1)
{
ptr = &result[res_length];
if (last_match < match[i].rm_so)
{
int to_copy = match[i].rm_so - last_match;
if (last_match + to_copy > res_size)
{
res_size = last_match + to_copy + length;
result = (char *)realloc(result, res_size);
}
memcpy(ptr, &sql[last_match], to_copy);
res_length += to_copy;
}
last_match = match[i].rm_eo;
if (res_length + rep_length > res_size)
{
res_size += rep_length;
result = (char *)realloc(result, res_size);
}
ptr = &result[res_length];
memcpy(ptr, replace, rep_length);
res_length += rep_length;
}
}
/** This should never fail with rc == 0 because we used pcre2_match_data_create_from_pattern() */
if (pcre2_match(re, (PCRE2_SPTR)sql, PCRE2_ZERO_TERMINATED, 0, 0, match_data, NULL))
{
result_size = strlen(sql) + strlen(replace);
result = malloc(result_size);
if (last_match < length)
{
int to_copy = length - last_match;
if (last_match + to_copy > res_size)
{
res_size = last_match + to_copy + 1;
result = (char *)realloc(result, res_size);
}
ptr = &result[res_length];
memcpy(ptr, &sql[last_match], to_copy);
res_length += to_copy;
}
result[res_length] = 0;
return result;
while (result &&
pcre2_substitute(re, (PCRE2_SPTR)sql, PCRE2_ZERO_TERMINATED, 0,
PCRE2_SUBSTITUTE_GLOBAL, match_data, NULL,
(PCRE2_SPTR)replace, PCRE2_ZERO_TERMINATED,
(PCRE2_UCHAR*)result, (PCRE2_SIZE*)&result_size) == PCRE2_ERROR_NOMEMORY)
{
char *tmp;
if ((tmp = realloc(result, (result_size *= 1.5))) == NULL)
{
free(result);
result = NULL;
}
result = tmp;
}
}
return result;
}
/**
@ -525,4 +537,4 @@ void log_nomatch(REGEX_INSTANCE* inst, char* re, char* old)
{
LOGIF(LT,(skygw_log_write(LT,"No match %s: [%s]",re,old)));
}
}
}

View File

@ -285,19 +285,9 @@ monitorDatabase(MONITOR *mon, MONITOR_SERVERS *database)
MYSQL_ROW row;
MYSQL_RES *result,*result2;
int isjoined = 0;
char *uname = mon->user;
char *passwd = mon->password;
unsigned long int server_version = 0;
char *server_string;
if (database->server->monuser != NULL)
{
uname = database->server->monuser;
passwd = database->server->monpw;
}
if (uname == NULL)
return;
/* Don't even probe server flagged as in maintenance */
if (SERVER_IN_MAINT(database->server))
return;
@ -305,60 +295,35 @@ char *server_string;
/** Store previous status */
database->mon_prev_status = database->server->status;
if (database->con == NULL || mysql_ping(database->con) != 0)
{
char *dpwd = decryptPassword(passwd);
int connect_timeout = mon->connect_timeout;
int read_timeout = mon->read_timeout;
int write_timeout = mon->write_timeout;
server_clear_status(database->server, SERVER_RUNNING);
if(database->con)
mysql_close(database->con);
database->con = mysql_init(NULL);
/* Also clear Joined, M/S and Stickiness bits */
server_clear_status(database->server, SERVER_JOINED);
server_clear_status(database->server, SERVER_SLAVE);
server_clear_status(database->server, SERVER_MASTER);
server_clear_status(database->server, SERVER_MASTER_STICKINESS);
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);
connect_result_t rval = mon_connect_to_db(mon, database);
if (rval != MONITOR_CONN_OK)
{
if (mysql_errno(database->con) == ER_ACCESS_DENIED_ERROR)
{
server_set_status(database->server, SERVER_AUTH_ERROR);
}
else
{
server_clear_status(database->server, SERVER_AUTH_ERROR);
}
if (mysql_real_connect(database->con, database->server->name,
uname, dpwd, NULL, database->server->port, NULL, 0) == NULL)
{
free(dpwd);
database->server->node_id = -1;
server_clear_status(database->server, SERVER_RUNNING);
if (mon_status_changed(database) && mon_print_fail_status(database))
{
mon_log_connect_error(database, rval);
}
/* Also clear Joined, M/S and Stickiness bits */
server_clear_status(database->server, SERVER_JOINED);
server_clear_status(database->server, SERVER_SLAVE);
server_clear_status(database->server, SERVER_MASTER);
server_clear_status(database->server, SERVER_MASTER_STICKINESS);
if (mysql_errno(database->con) == ER_ACCESS_DENIED_ERROR)
{
server_set_status(database->server, SERVER_AUTH_ERROR);
}
database->server->node_id = -1;
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))));
}
return;
}
else
{
server_clear_status(database->server, SERVER_AUTH_ERROR);
}
free(dpwd);
}
return;
}
/* If we get this far then we have a working connection */
server_set_status(database->server, SERVER_RUNNING);

View File

@ -260,95 +260,54 @@ char *sep;
static void
monitorDatabase(MONITOR* mon, MONITOR_SERVERS *database)
{
MM_MONITOR *handle = mon->handle;
MYSQL_ROW row;
MYSQL_RES *result;
int isslave = 0;
int ismaster = 0;
char *uname = mon->user;
char *passwd = mon->password;
unsigned long int server_version = 0;
char *server_string;
if (database->server->monuser != NULL)
{
uname = database->server->monuser;
passwd = database->server->monpw;
}
if (uname == NULL)
return;
/* Don't probe servers in maintenance mode */
if (SERVER_IN_MAINT(database->server))
return;
/* Don't probe servers in maintenance mode */
if (SERVER_IN_MAINT(database->server))
return;
/** Store previous status */
database->mon_prev_status = database->server->status;
if (database->con == NULL || mysql_ping(database->con) != 0)
{
char *dpwd = decryptPassword(passwd);
int read_timeout = 1;
if(database->con)
mysql_close(database->con);
database->con = mysql_init(NULL);
/** Store previous status */
database->mon_prev_status = database->server->status;
connect_result_t rval = mon_connect_to_db(mon, database);
mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
if (mysql_real_connect(database->con,
database->server->name,
uname,
dpwd,
NULL,
database->server->port,
NULL,
0) == NULL)
{
free(dpwd);
if (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))));
}
if (rval != MONITOR_CONN_OK)
{
if (mysql_errno(database->con) == ER_ACCESS_DENIED_ERROR)
{
server_set_status(database->server, SERVER_AUTH_ERROR);
monitor_set_pending_status(database, SERVER_AUTH_ERROR);
}
server_clear_status(database->server, SERVER_RUNNING);
monitor_clear_pending_status(database, SERVER_RUNNING);
/* The current server is not running
*
* Store server NOT running in server and monitor server pending struct
*
*/
if (mysql_errno(database->con) == ER_ACCESS_DENIED_ERROR)
{
server_set_status(database->server, SERVER_AUTH_ERROR);
monitor_set_pending_status(database, SERVER_AUTH_ERROR);
}
server_clear_status(database->server, SERVER_RUNNING);
monitor_clear_pending_status(database, SERVER_RUNNING);
/* Also clear M/S state in both server and monitor server pending struct */
server_clear_status(database->server, SERVER_SLAVE);
server_clear_status(database->server, SERVER_MASTER);
monitor_clear_pending_status(database, SERVER_SLAVE);
monitor_clear_pending_status(database, SERVER_MASTER);
/* Also clear M/S state in both server and monitor server pending struct */
server_clear_status(database->server, SERVER_SLAVE);
server_clear_status(database->server, SERVER_MASTER);
monitor_clear_pending_status(database, SERVER_SLAVE);
monitor_clear_pending_status(database, SERVER_MASTER);
/* Clean addition status too */
server_clear_status(database->server, SERVER_STALE_STATUS);
monitor_clear_pending_status(database, SERVER_STALE_STATUS);
/* Clean addition status too */
server_clear_status(database->server, SERVER_STALE_STATUS);
monitor_clear_pending_status(database, SERVER_STALE_STATUS);
if (mon_status_changed(database) && mon_print_fail_status(database))
{
mon_log_connect_error(database, rval);
}
return;
}
else
{
server_clear_status(database->server, SERVER_AUTH_ERROR);
monitor_clear_pending_status(database, SERVER_AUTH_ERROR);
}
return;
} else {
server_clear_status(database->server, SERVER_AUTH_ERROR);
monitor_clear_pending_status(database, SERVER_AUTH_ERROR);
}
free(dpwd);
}
/* Store current status in both server and monitor server pending struct */
/* Store current status in both server and monitor server pending struct */
server_set_status(database->server, SERVER_RUNNING);
monitor_set_pending_status(database, SERVER_RUNNING);

View File

@ -413,3 +413,92 @@ monitor_event_t mon_name_to_event(char* tok)
}
/**
* Connect to a database. This will always leave a valid database handle in the
* database->con pointer. This allows the user to call MySQL C API functions to
* find out the reason of the failure.
* @param mon Monitor
* @param database Monitored database
* @return MONITOR_CONN_OK if the connection is OK else the reason for the failure
*/
connect_result_t mon_connect_to_db(MONITOR* mon, MONITOR_SERVERS *database)
{
connect_result_t rval = MONITOR_CONN_OK;
/** Return if the connection is OK */
if (database->con && mysql_ping(database->con) == 0)
{
return rval;
}
int connect_timeout = mon->connect_timeout;
int read_timeout = mon->read_timeout;
int write_timeout = mon->write_timeout;
char *uname = database->server->monuser ? database->server->monuser : mon->user;
char *passwd = database->server->monpw ? database->server->monpw : mon->password;
char *dpwd = decryptPassword(passwd);
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);
time_t start = time(NULL);
bool result = (mysql_real_connect(database->con,
database->server->name,
uname,
dpwd,
NULL,
database->server->port,
NULL,
0) != NULL);
time_t end = time(NULL);
if (!result)
{
if ((int) difftime(end, start) >= connect_timeout)
{
rval = MONITOR_CONN_TIMEOUT;
}
else
{
rval = MONITOR_CONN_REFUSED;
}
}
free(dpwd);
return rval;
}
/**
* Log an error about the failure to connect to a backend server
* and why it happened.
* @param database Backend database
* @param rval Return value of mon_connect_to_db
*/
void mon_log_connect_error(MONITOR_SERVERS* database, connect_result_t rval)
{
if (rval == MONITOR_CONN_TIMEOUT)
{
skygw_log_write_flush(LOGFILE_ERROR,
"Error : Monitor timed out when connecting to "
"server %s:%d : \"%s\"",
database->server->name,
database->server->port,
mysql_error(database->con));
}
else
{
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));
}
}

View File

@ -23,6 +23,7 @@
#include <monitor.h>
#include <log_manager.h>
#include <externcmd.h>
#include <secrets.h>
/**
* @file monitor_common.h - The generic monitor structures all monitors use
*
@ -63,6 +64,14 @@ typedef enum {
NEW_NDB_EVENT,
MAX_MONITOR_EVENT
}monitor_event_t;
typedef enum
{
MONITOR_CONN_OK,
MONITOR_CONN_REFUSED,
MONITOR_CONN_TIMEOUT
} connect_result_t;
void mon_append_node_names(MONITOR_SERVERS* start,char* str, int len);
monitor_event_t mon_get_event_type(MONITOR_SERVERS* node);
char* mon_get_event_name(MONITOR_SERVERS* node);
@ -72,4 +81,6 @@ bool mon_status_changed(MONITOR_SERVERS* mon_srv);
bool mon_print_fail_status(MONITOR_SERVERS* mon_srv);
void monitor_launch_script(MONITOR* mon,MONITOR_SERVERS* ptr, char* script);
int mon_parse_event_string(bool* events, size_t count,char* string);
connect_result_t mon_connect_to_db(MONITOR* mon, MONITOR_SERVERS *database);
void mon_log_connect_error(MONITOR_SERVERS* database, connect_result_t rval);
#endif

View File

@ -287,40 +287,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)
{
@ -641,7 +607,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);
@ -675,15 +642,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;
}

View File

@ -248,66 +248,35 @@ char *sep;
static void
monitorDatabase(MONITOR_SERVERS *database, char *defaultUser, char *defaultPasswd, MONITOR *mon)
{
MYSQL_MONITOR* handle = mon->handle;
MYSQL_ROW row;
MYSQL_RES *result;
int isjoined = 0;
char *uname = defaultUser, *passwd = defaultPasswd;
char *server_string;
if (database->server->monuser != NULL)
{
uname = database->server->monuser;
passwd = database->server->monpw;
}
if (uname == NULL)
return;
/* Don't even probe server flagged as in maintenance */
if (SERVER_IN_MAINT(database->server))
return;
/* Don't even probe server flagged as in maintenance */
if (SERVER_IN_MAINT(database->server))
return;
connect_result_t rval = mon_connect_to_db(mon, database);
if (rval != MONITOR_CONN_OK)
{
server_clear_status(database->server, SERVER_RUNNING);
if (database->con == NULL || mysql_ping(database->con) != 0)
{
char *dpwd = decryptPassword(passwd);
int connect_timeout = mon->connect_timeout;
int read_timeout = mon->read_timeout;
int write_timeout = mon->write_timeout;
if (mysql_errno(database->con) == ER_ACCESS_DENIED_ERROR)
{
server_set_status(database->server, SERVER_AUTH_ERROR);
}
if(database->con)
mysql_close(database->con);
database->con = mysql_init(NULL);
database->server->node_id = -1;
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);
if (mysql_real_connect(database->con, database->server->name,
uname, dpwd, NULL, database->server->port, NULL, 0) == NULL)
{
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))));
server_clear_status(database->server, SERVER_RUNNING);
if (mysql_errno(database->con) == ER_ACCESS_DENIED_ERROR)
{
server_set_status(database->server, SERVER_AUTH_ERROR);
}
database->server->node_id = -1;
free(dpwd);
return;
}
else
{
server_clear_status(database->server, SERVER_AUTH_ERROR);
}
free(dpwd);
}
if (mon_status_changed(database) && mon_print_fail_status(database))
{
mon_log_connect_error(database, rval);
}
return;
}
server_clear_status(database->server, SERVER_AUTH_ERROR);
/* If we get this far then we have a working connection */
server_set_status(database->server, SERVER_RUNNING);

View File

@ -79,7 +79,7 @@ extern int lm_enabled_logfiles_bitmask;
extern size_t log_ses_count[];
extern __thread log_info_t tls_log_info;
static char *version_str = "V1.2.2";
static char *version_str = "V2.0.0";
/* The router entry points */
static ROUTER *createInstance(SERVICE *service, char **options);
@ -115,6 +115,8 @@ extern int blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debu
void blr_master_close(ROUTER_INSTANCE *);
char * blr_last_event_description(ROUTER_INSTANCE *router);
extern int MaxScaleUptime();
static uint8_t getCapabilities (ROUTER* inst, void* router_session);
char *blr_get_event_description(ROUTER_INSTANCE *router, uint8_t event);
/** The module object definition */
static ROUTER_OBJECT MyObject = {
@ -2059,7 +2061,38 @@ char *event_desc = NULL;
event_desc = event_names_mariadb10[(router->lastEventReceived - MARIADB_NEW_EVENTS_BEGIN)];
}
}
}
return event_desc;
}
/**
* Return the event description
*
* @param router The router instance
* @param event The current event
* @return The event description or NULL
*/
char *
blr_get_event_description(ROUTER_INSTANCE *router, uint8_t event) {
char *event_desc = NULL;
if (!router->mariadb10_compat) {
if (event >= 0 &&
event <= MAX_EVENT_TYPE) {
event_desc = event_names[event];
}
} else {
if (event >= 0 &&
event <= MAX_EVENT_TYPE) {
event_desc = event_names[event];
} else {
/* Check MariaDB 10 new events */
if (event >= MARIADB_NEW_EVENTS_BEGIN &&
event <= MAX_EVENT_TYPE_MARIADB10) {
event_desc = event_names_mariadb10[(event - MARIADB_NEW_EVENTS_BEGIN)];
}
}
}
return event_desc;

View File

@ -78,6 +78,15 @@ int blr_file_write_master_config(ROUTER_INSTANCE *router, char *error);
extern uint32_t extract_field(uint8_t *src, int bits);
static void blr_format_event_size(double *event_size, char *label);
extern int MaxScaleUptime();
extern char *blr_get_event_description(ROUTER_INSTANCE *router, uint8_t event);
typedef struct binlog_event_desc {
unsigned long long event_pos;
uint8_t event_type;
time_t event_time;
} BINLOG_EVENT_DESC;
static void blr_print_binlog_details(ROUTER_INSTANCE *router, BINLOG_EVENT_DESC first_event_time, BINLOG_EVENT_DESC last_event_time);
/**
* Initialise the binlog file for this instance. MaxScale will look
@ -831,6 +840,14 @@ unsigned long event_bytes = 0;
unsigned long max_bytes = 0;
double average_events = 0;
double average_bytes = 0;
BINLOG_EVENT_DESC first_event;
BINLOG_EVENT_DESC last_event;
BINLOG_EVENT_DESC fde_event;
int fde_seen = 0;
memset(&first_event, '\0', sizeof(first_event));
memset(&last_event, '\0', sizeof(last_event));
memset(&fde_event, '\0', sizeof(fde_event));
if (router->binlog_fd == -1) {
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
@ -862,6 +879,13 @@ double average_bytes = 0;
if (n_transactions)
average_bytes = (double)((double)total_bytes / (double)n_transactions) * (1.0);
/* Report Binlog First and Last event */
if (first_event.event_type == 0)
blr_print_binlog_details(router, fde_event, last_event);
else
blr_print_binlog_details(router, first_event, last_event);
/* Report Transaction Summary */
if (n_transactions != 0) {
char total_label[2]="";
char average_label[2]="";
@ -1147,6 +1171,14 @@ double average_bytes = 0;
last_known_commit = pos;
}
/* get firts event timestamp, after FDE */
if (fde_seen) {
first_event.event_time = (unsigned long)hdr.timestamp;
first_event.event_type = hdr.event_type;
first_event.event_pos = pos;
fde_seen = 0;
}
/* get event content */
ptr = data+BINLOG_EVENT_HDR_LEN;
@ -1157,11 +1189,25 @@ double average_bytes = 0;
int n_events;
int check_alg;
uint8_t *checksum;
char buf_t[40];
struct tm tm_t;
fde_seen = 1;
fde_event.event_time = (unsigned long)hdr.timestamp;
fde_event.event_type = hdr.event_type;
fde_event.event_pos = pos;
localtime_r(&fde_event.event_time, &tm_t);
asctime_r(&tm_t, buf_t);
if (buf_t[strlen(buf_t)-1] == '\n') {
buf_t[strlen(buf_t)-1] = '\0';
}
if(debug)
LOGIF(LD, (skygw_log_write_flush(LOGFILE_DEBUG,
"- Format Description event FDE @ %llu, size %lu",
pos, (unsigned long)hdr.event_size)));
"- Format Description event FDE @ %llu, size %lu, time %lu (%s)",
pos, (unsigned long)hdr.event_size, fde_event.event_time, buf_t)));
event_header_length = ptr[2 + 50 + 4];
event_header_ntypes = hdr.event_size - event_header_length - (2 + 50 + 4 + 1);
@ -1208,6 +1254,12 @@ double average_bytes = 0;
}
}
}
/* set last event time, pos and type */
last_event.event_time = (unsigned long)hdr.timestamp;
last_event.event_type = hdr.event_type;
last_event.event_pos = pos;
/* Decode ROTATE EVENT */
if(hdr.event_type == ROTATE_EVENT) {
int len, slen;
@ -1627,3 +1679,48 @@ char err_msg[STRERROR_BUFLEN];
return 0;
}
/** Print Binlog Details
*
* @param router The router instance
* @param first_event First Event details
* @param last_event First Event details
*/
static void
blr_print_binlog_details(ROUTER_INSTANCE *router, BINLOG_EVENT_DESC first_event, BINLOG_EVENT_DESC last_event)
{
char buf_t[40];
struct tm tm_t;
char *event_desc;
/* First Event */
localtime_r(&first_event.event_time, &tm_t);
asctime_r(&tm_t, buf_t);
if (buf_t[strlen(buf_t)-1] == '\n') {
buf_t[strlen(buf_t)-1] = '\0';
}
event_desc = blr_get_event_description(router, first_event.event_type);
LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE,
"%lu @ %llu, %s, (%s), First EventTime",
first_event.event_time, first_event.event_pos,
event_desc != NULL ? event_desc : "unknown", buf_t)));
/* Last Event */
localtime_r(&last_event.event_time, &tm_t);
asctime_r(&tm_t, buf_t);
if (buf_t[strlen(buf_t)-1] == '\n') {
buf_t[strlen(buf_t)-1] = '\0';
}
event_desc = blr_get_event_description(router, last_event.event_type);
LOGIF(LM, (skygw_log_write_flush(LOGFILE_MESSAGE,
"%lu @ %llu, %s, (%s), Last EventTime",
last_event.event_time, last_event.event_pos,
event_desc != NULL ? event_desc : "unknown", buf_t)));
}

View File

@ -80,7 +80,7 @@ static struct option long_options[] = {
{0, 0, 0, 0}
};
char *binlog_check_version = "1.0.0";
char *binlog_check_version = "1.1.0";
int
MaxScaleUptime()