Merge branch 'release-1.0GA' into firewall
Conflicts: log_manager/log_manager.cc
This commit is contained in:
@ -123,7 +123,7 @@ install(DIRECTORY DESTINATION log)
|
||||
# See if we are on a RPM-capable or DEB-capable system
|
||||
find_program(RPMBUILD rpmbuild)
|
||||
find_program(DEBBUILD dpkg-buildpackage)
|
||||
|
||||
set(CPACK_GENERATOR "TGZ")
|
||||
if(NOT ( ${RPMBUILD} STREQUAL "RPMBUILD-NOTFOUND" ) )
|
||||
message(STATUS "Generating RPM packages")
|
||||
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
|
||||
|
BIN
Documentation/Administration Tutorial.pdf
Executable file
BIN
Documentation/Administration Tutorial.pdf
Executable file
Binary file not shown.
BIN
Documentation/Filter Tutorial.pdf
Executable file
BIN
Documentation/Filter Tutorial.pdf
Executable file
Binary file not shown.
BIN
Documentation/Galera Cluster Connection Routing Tutorial.pdf
Executable file
BIN
Documentation/Galera Cluster Connection Routing Tutorial.pdf
Executable file
Binary file not shown.
BIN
Documentation/Galera Cluster Read-Write Splitting Tutorial.pdf
Executable file
BIN
Documentation/Galera Cluster Read-Write Splitting Tutorial.pdf
Executable file
Binary file not shown.
BIN
Documentation/Getting Started With MaxScale.pdf
Executable file
BIN
Documentation/Getting Started With MaxScale.pdf
Executable file
Binary file not shown.
BIN
Documentation/MaxAdmin The MaxScale Administration And Monitoring Client.pdf
Normal file → Executable file
BIN
Documentation/MaxAdmin The MaxScale Administration And Monitoring Client.pdf
Normal file → Executable file
Binary file not shown.
Binary file not shown.
BIN
Documentation/MaxScale Debug And Diagnostic Support.pdf
Normal file → Executable file
BIN
Documentation/MaxScale Debug And Diagnostic Support.pdf
Normal file → Executable file
Binary file not shown.
BIN
Documentation/MaxScale HA with Corosync-Pacemaker.pdf
Executable file
BIN
Documentation/MaxScale HA with Corosync-Pacemaker.pdf
Executable file
Binary file not shown.
BIN
Documentation/MaxScale Known Limitiations.pdf
Executable file
BIN
Documentation/MaxScale Known Limitiations.pdf
Executable file
Binary file not shown.
BIN
Documentation/MySQL Replication Connection Routing Tutorial.pdf
Executable file
BIN
Documentation/MySQL Replication Connection Routing Tutorial.pdf
Executable file
Binary file not shown.
BIN
Documentation/MySQL Replication Read-Write Splitting Tutorial.pdf
Executable file
BIN
Documentation/MySQL Replication Read-Write Splitting Tutorial.pdf
Executable file
Binary file not shown.
BIN
Documentation/filters/Regex Filter.pdf
Normal file → Executable file
BIN
Documentation/filters/Regex Filter.pdf
Normal file → Executable file
Binary file not shown.
BIN
Documentation/filters/Tee Filter.pdf
Normal file → Executable file
BIN
Documentation/filters/Tee Filter.pdf
Normal file → Executable file
Binary file not shown.
BIN
Documentation/filters/Top Filter.pdf
Normal file → Executable file
BIN
Documentation/filters/Top Filter.pdf
Normal file → Executable file
Binary file not shown.
@ -1,3 +1,6 @@
|
||||
if(LOG_DEBUG)
|
||||
add_definitions(-DSS_LOG_DEBUG)
|
||||
endif()
|
||||
add_library(log_manager SHARED log_manager.cc)
|
||||
target_link_libraries(log_manager pthread aio stdc++)
|
||||
install(TARGETS log_manager DESTINATION lib)
|
||||
|
@ -94,7 +94,9 @@ char* syslog_ident_str = NULL;
|
||||
*/
|
||||
static int lmlock;
|
||||
static logmanager_t* lm;
|
||||
|
||||
static bool flushall_flag;
|
||||
static bool flushall_started_flag;
|
||||
static bool flushall_done_flag;
|
||||
|
||||
/** Writer thread structure */
|
||||
struct filewriter_st {
|
||||
@ -286,12 +288,14 @@ static char* add_slash(char* str);
|
||||
|
||||
static bool check_file_and_path(
|
||||
char* filename,
|
||||
bool* writable);
|
||||
bool* writable,
|
||||
bool do_log);
|
||||
|
||||
static bool file_is_symlink(char* filename);
|
||||
static int skygw_log_disable_raw(logfile_id_t id, bool emergency); /*< no locking */
|
||||
static int find_last_seqno(strpart_t* parts, int seqno, int seqnoidx);
|
||||
|
||||
void flushall_logfiles(bool flush);
|
||||
bool thr_flushall_check();
|
||||
|
||||
const char* get_suffix_default(void)
|
||||
{
|
||||
@ -441,17 +445,6 @@ static bool logmanager_init_nomutex(
|
||||
return_succp:
|
||||
if (err != 0)
|
||||
{
|
||||
if (lm != NULL)
|
||||
{
|
||||
if (lm->lm_clientmes != NULL)
|
||||
{
|
||||
skygw_message_done(lm->lm_clientmes);
|
||||
}
|
||||
if (lm->lm_logmes != NULL)
|
||||
{
|
||||
skygw_message_done(lm->lm_logmes);
|
||||
}
|
||||
}
|
||||
/** This releases memory of all created objects */
|
||||
logmanager_done_nomutex();
|
||||
fprintf(stderr, "*\n* Error : Initializing log manager failed.\n*\n");
|
||||
@ -729,10 +722,10 @@ static int logmanager_write_log(
|
||||
/** Length of session id */
|
||||
int sesid_str_len;
|
||||
|
||||
/** 2 braces and 2 spaces */
|
||||
/** 2 braces, 2 spaces and terminating char */
|
||||
if (id == LOGFILE_TRACE && tls_log_info.li_sesid != 0)
|
||||
{
|
||||
sesid_str_len = 2+2+get_decimal_len(tls_log_info.li_sesid);
|
||||
sesid_str_len = 2+2+get_decimal_len(tls_log_info.li_sesid)+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -741,13 +734,13 @@ static int logmanager_write_log(
|
||||
timestamp_len = get_timestamp_len();
|
||||
|
||||
/** Find out how much can be safely written with current block size */
|
||||
if (timestamp_len-1+sesid_str_len+str_len > lf->lf_buf_size)
|
||||
if (timestamp_len-1+MAX(sesid_str_len-1,0)+str_len > lf->lf_buf_size)
|
||||
{
|
||||
safe_str_len = lf->lf_buf_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
safe_str_len = timestamp_len-1+sesid_str_len+str_len;
|
||||
safe_str_len = timestamp_len-1+MAX(sesid_str_len-1,0)+str_len;
|
||||
}
|
||||
/**
|
||||
* Seek write position and register to block buffer.
|
||||
@ -809,6 +802,7 @@ static int logmanager_write_log(
|
||||
sesid_str_len,
|
||||
"[%lu] ",
|
||||
tls_log_info.li_sesid);
|
||||
sesid_str_len -= 1; /*< don't calculate terminating char anymore */
|
||||
}
|
||||
/**
|
||||
* Write next string to overwrite terminating null character
|
||||
@ -1099,7 +1093,7 @@ static char* blockbuf_get_writepos(
|
||||
|
||||
simple_mutex_unlock(&bb->bb_mutex);
|
||||
simple_mutex_lock(&bb_list->mlist_mutex, true);
|
||||
|
||||
node = bb_list->mlist_first;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2052,7 +2046,7 @@ static bool logfile_create(
|
||||
* If file exists but is different type, create fails and
|
||||
* new, increased sequence number is added to file name.
|
||||
*/
|
||||
if (check_file_and_path(lf->lf_full_file_name, &writable))
|
||||
if (check_file_and_path(lf->lf_full_file_name, &writable, true))
|
||||
{
|
||||
/** Found similarly named file which isn't writable */
|
||||
if (!writable || file_is_symlink(lf->lf_full_file_name))
|
||||
@ -2076,13 +2070,11 @@ static bool logfile_create(
|
||||
|
||||
if (store_shmem)
|
||||
{
|
||||
if (check_file_and_path(lf->lf_full_file_name, &writable))
|
||||
if (check_file_and_path(lf->lf_full_link_name, &writable, true))
|
||||
{
|
||||
/** Found similarly named file which isn't writable */
|
||||
if (!writable ||
|
||||
file_is_symlink(lf->lf_full_file_name))
|
||||
/** Found similarly named link which isn't writable */
|
||||
if (!writable)
|
||||
{
|
||||
unlink(lf->lf_full_file_name);
|
||||
nameconflicts = true;
|
||||
}
|
||||
}
|
||||
@ -2213,7 +2205,6 @@ return_succp:
|
||||
*
|
||||
* @return Pointer to filename, of NULL if failed.
|
||||
*
|
||||
*
|
||||
*/
|
||||
static char* form_full_file_name(
|
||||
strpart_t* parts,
|
||||
@ -2230,9 +2221,21 @@ static char* form_full_file_name(
|
||||
|
||||
if (lf->lf_name_seqno != -1)
|
||||
{
|
||||
lf->lf_name_seqno = find_last_seqno(parts,
|
||||
lf->lf_name_seqno,
|
||||
seqnoidx);
|
||||
int file_sn;
|
||||
int link_sn = 0;
|
||||
char* tmp = parts[0].sp_string;
|
||||
|
||||
file_sn = find_last_seqno(parts, lf->lf_name_seqno, seqnoidx);
|
||||
|
||||
if (lf->lf_linkpath != NULL)
|
||||
{
|
||||
tmp = parts[0].sp_string;
|
||||
parts[0].sp_string = lf->lf_linkpath;
|
||||
link_sn = find_last_seqno(parts, lf->lf_name_seqno, seqnoidx);
|
||||
parts[0].sp_string = tmp;
|
||||
}
|
||||
lf->lf_name_seqno = MAX(file_sn, link_sn);
|
||||
|
||||
seqno = lf->lf_name_seqno;
|
||||
s = UINTLEN(seqno);
|
||||
seqnostr = (char *)malloc((int)s+1);
|
||||
@ -2353,7 +2356,8 @@ static char* add_slash(
|
||||
*/
|
||||
static bool check_file_and_path(
|
||||
char* filename,
|
||||
bool* writable)
|
||||
bool* writable,
|
||||
bool do_log)
|
||||
{
|
||||
int fd;
|
||||
bool exists;
|
||||
@ -2380,12 +2384,24 @@ static bool check_file_and_path(
|
||||
fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG);
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
if (do_log && file_is_symlink(filename))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Error : Can't access "
|
||||
"file pointed to by %s due "
|
||||
"to %s.\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
}
|
||||
else if (do_log)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Error : Can't access %s due "
|
||||
"to %s.\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
}
|
||||
if (writable)
|
||||
{
|
||||
*writable = false;
|
||||
@ -2401,12 +2417,25 @@ static bool check_file_and_path(
|
||||
*writable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (do_log &&
|
||||
file_is_symlink(filename))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Error : Can't write to "
|
||||
"file pointed to by %s due to "
|
||||
"%s.\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
}
|
||||
else if (do_log)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Error : Can't write to "
|
||||
"%s due to %s.\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
}
|
||||
*writable = false;
|
||||
}
|
||||
}
|
||||
@ -2415,11 +2444,22 @@ static bool check_file_and_path(
|
||||
exists = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (do_log && file_is_symlink(filename))
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Error : Can't access the file "
|
||||
"pointed to by %s due to %s.\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
}
|
||||
else if (do_log)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Error : Can't access %s due to %s.\n",
|
||||
filename,
|
||||
strerror(errno));
|
||||
}
|
||||
exists = false;
|
||||
|
||||
if (writable)
|
||||
@ -2571,7 +2611,7 @@ static bool logfile_init(
|
||||
logfile_free_memory(logfile);
|
||||
goto return_with_succp;
|
||||
}
|
||||
#if defined(SS_DEBUG)
|
||||
|
||||
if (store_shmem)
|
||||
{
|
||||
fprintf(stderr, "%s\t: %s->%s\n",
|
||||
@ -2585,7 +2625,6 @@ static bool logfile_init(
|
||||
STRLOGNAME(logfile_id),
|
||||
logfile->lf_full_file_name);
|
||||
}
|
||||
#endif
|
||||
succp = true;
|
||||
logfile->lf_state = RUN;
|
||||
CHK_LOGFILE(logfile);
|
||||
@ -2801,13 +2840,15 @@ static void* thr_filewriter_fun(
|
||||
int i;
|
||||
blockbuf_state_t flush_blockbuf; /**< flush single block buffer. */
|
||||
bool flush_logfile; /**< flush logfile */
|
||||
bool flushall_logfiles;/**< flush all logfiles */
|
||||
bool do_flushall = false;
|
||||
bool rotate_logfile; /*< close current and open new file */
|
||||
size_t vn1;
|
||||
size_t vn2;
|
||||
|
||||
thr = (skygw_thread_t *)data;
|
||||
fwr = (filewriter_t *)skygw_thread_get_data(thr);
|
||||
flushall_logfiles(false);
|
||||
|
||||
CHK_FILEWRITER(fwr);
|
||||
ss_debug(skygw_thread_set_state(thr, THR_RUNNING));
|
||||
|
||||
@ -2820,8 +2861,9 @@ static void* thr_filewriter_fun(
|
||||
* Reset message to avoid redundant calls.
|
||||
*/
|
||||
skygw_message_wait(fwr->fwr_logmes);
|
||||
|
||||
flushall_logfiles = skygw_thread_must_exit(thr);
|
||||
if(skygw_thread_must_exit(thr)){
|
||||
flushall_logfiles(true);
|
||||
}
|
||||
|
||||
/** Process all logfiles which have buffered writes. */
|
||||
for (i=LOGFILE_FIRST; i<=LOGFILE_LAST; i <<= 1)
|
||||
@ -2830,6 +2872,10 @@ static void* thr_filewriter_fun(
|
||||
/**
|
||||
* Get file pointer of current logfile.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
do_flushall = thr_flushall_check();
|
||||
file = fwr->fwr_file[i];
|
||||
lf = &lm->lm_logfile[(logfile_id_t)i];
|
||||
|
||||
@ -2900,7 +2946,7 @@ static void* thr_filewriter_fun(
|
||||
if (bb->bb_buf_used != 0 &&
|
||||
(flush_blockbuf == BB_FULL ||
|
||||
flush_logfile ||
|
||||
flushall_logfiles))
|
||||
do_flushall))
|
||||
{
|
||||
/**
|
||||
* buffer is at least half-full
|
||||
@ -2919,7 +2965,7 @@ static void* thr_filewriter_fun(
|
||||
(void *)bb->bb_buf,
|
||||
bb->bb_buf_used,
|
||||
(flush_logfile ||
|
||||
flushall_logfiles));
|
||||
do_flushall));
|
||||
if (err)
|
||||
{
|
||||
fprintf(stderr,
|
||||
@ -2966,13 +3012,28 @@ static void* thr_filewriter_fun(
|
||||
* Loop is restarted to ensure that all logfiles are
|
||||
* flushed.
|
||||
*/
|
||||
if (!flushall_logfiles && skygw_thread_must_exit(thr))
|
||||
|
||||
if(flushall_started_flag){
|
||||
flushall_started_flag = false;
|
||||
flushall_done_flag = true;
|
||||
i = LOGFILE_FIRST;
|
||||
goto retry_flush_on_exit;
|
||||
}
|
||||
|
||||
if (!thr_flushall_check() && skygw_thread_must_exit(thr))
|
||||
{
|
||||
flushall_logfiles = true;
|
||||
flushall_logfiles(true);
|
||||
i = LOGFILE_FIRST;
|
||||
goto retry_flush_on_exit;
|
||||
}
|
||||
}/* for */
|
||||
|
||||
if(flushall_done_flag){
|
||||
flushall_done_flag = false;
|
||||
flushall_logfiles(false);
|
||||
skygw_message_send(fwr->fwr_clientmes);
|
||||
}
|
||||
|
||||
} /* while (!skygw_thread_must_exit) */
|
||||
|
||||
ss_debug(skygw_thread_set_state(thr, THR_STOPPED));
|
||||
@ -3048,11 +3109,11 @@ static int find_last_seqno(
|
||||
|
||||
for (i=0, p=parts; p->sp_string != NULL; i++, p=p->sp_next)
|
||||
{
|
||||
if (snstr != NULL && i == seqnoidx && strnlen(snstr,NAME_MAX) < NAME_MAX)
|
||||
if (snstr != NULL && i == seqnoidx)
|
||||
{
|
||||
strcat(filename, snstr); /*< add sequence number */
|
||||
strncat(filename, snstr, NAME_MAX - 1); /*< add sequence number */
|
||||
}
|
||||
strcat(filename, p->sp_string);
|
||||
strncat(filename, p->sp_string, NAME_MAX - 1);
|
||||
|
||||
if (p->sp_next == NULL)
|
||||
{
|
||||
@ -3060,7 +3121,7 @@ static int find_last_seqno(
|
||||
}
|
||||
}
|
||||
|
||||
if (check_file_and_path(filename, NULL))
|
||||
if (check_file_and_path(filename, NULL, false))
|
||||
{
|
||||
seqno++;
|
||||
}
|
||||
@ -3073,3 +3134,33 @@ static int find_last_seqno(
|
||||
|
||||
return seqno;
|
||||
}
|
||||
|
||||
bool thr_flushall_check()
|
||||
{
|
||||
bool rval = false;
|
||||
simple_mutex_lock(&lm->lm_mutex,true);
|
||||
rval = flushall_flag;
|
||||
if(rval && !flushall_started_flag && !flushall_done_flag){
|
||||
flushall_started_flag = true;
|
||||
}
|
||||
simple_mutex_unlock(&lm->lm_mutex);
|
||||
return rval;
|
||||
}
|
||||
|
||||
void flushall_logfiles(bool flush)
|
||||
{
|
||||
simple_mutex_lock(&lm->lm_mutex,true);
|
||||
flushall_flag = flush;
|
||||
simple_mutex_unlock(&lm->lm_mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush all log files synchronously
|
||||
*/
|
||||
void skygw_log_sync_all(void)
|
||||
{
|
||||
skygw_log_write(LOGFILE_TRACE,"Starting log flushing to disk.");
|
||||
flushall_logfiles(true);
|
||||
skygw_message_send(lm->lm_logmes);
|
||||
skygw_message_wait(lm->lm_clientmes);
|
||||
}
|
||||
|
@ -619,6 +619,7 @@ static skygw_query_type_t resolve_query_type(
|
||||
break;
|
||||
|
||||
case SQLCOM_SELECT:
|
||||
case SQLCOM_SHOW_SLAVE_STAT:
|
||||
type |= QUERY_TYPE_READ;
|
||||
break;
|
||||
|
||||
|
@ -1,89 +1,212 @@
|
||||
## Example MaxScale.cnf configuration file
|
||||
#
|
||||
# Example MaxScale.cnf configuration file
|
||||
# Number of worker threads in MaxScale
|
||||
#
|
||||
#
|
||||
#
|
||||
# Number of server threads
|
||||
# Valid options are:
|
||||
# threads=<number of threads>
|
||||
|
||||
#
|
||||
[maxscale]
|
||||
threads=1
|
||||
threads=4
|
||||
|
||||
# Define a monitor that can be used to determine the state and role of
|
||||
## Define a monitor that can be used to determine the state and role of
|
||||
# the servers.
|
||||
#
|
||||
# Valid options for all monitors are:
|
||||
# Currently valid options for all monitors are:
|
||||
#
|
||||
# module=<name of module to load>
|
||||
# servers=<server name>,<server name>,...
|
||||
# user =<user name - must have slave replication and
|
||||
# slave client privileges>
|
||||
# passwd=<password of the above user, plain text currently>
|
||||
# monitor_interval=<sampling interval in milliseconds,
|
||||
# default value is 10000>
|
||||
# module=[mysqlmon|galeramon]
|
||||
#
|
||||
# List of server names which are being monitored
|
||||
#
|
||||
# servers=<server name 1>,<server name 2>,...,<server name N>
|
||||
#
|
||||
# Username for monitor queries, need slave replication and slave client privileges
|
||||
# Password in plain text format, and monitor's sampling interval in milliseconds.
|
||||
#
|
||||
# user=<username>
|
||||
# passwd=<plain txt password>
|
||||
# monitor_interval=<sampling interval in milliseconds> (default 10000)
|
||||
#
|
||||
# Timeouts for monitor operations in backend servers - optional.
|
||||
#
|
||||
# backend_connect_timeout=<timeout in seconds>
|
||||
# backend_write_timeout=<timeout in seconds>
|
||||
# backend_read_timeout=<timeout in seconds>
|
||||
#
|
||||
## MySQL monitor-specific options:
|
||||
#
|
||||
# Enable detection of replication slaves lag via replication_heartbeat
|
||||
# table - optional.
|
||||
#
|
||||
# detect_replication_lag=[1|0] (default 0)
|
||||
#
|
||||
# Allow previous master to be available even in case of stopped or misconfigured
|
||||
# replication - optional.
|
||||
#
|
||||
# detect_stale_master=[1|0] (default 0)
|
||||
#
|
||||
## Galera monitor-specific options:
|
||||
#
|
||||
# If disable_master_failback is not set, recovery of previously failed master
|
||||
# causes mastership to be switched back to it. Enabling the option prevents it.
|
||||
#
|
||||
# disable_master_failback=[0|1] (default 0)
|
||||
#
|
||||
## Examples:
|
||||
|
||||
[MySQL Monitor]
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
servers=server1,server2,server3
|
||||
user=maxuser
|
||||
passwd=maxpwd
|
||||
#
|
||||
# options for mysql_monitor only
|
||||
#
|
||||
# detect_replication_lag=<enable detection of replication slaves lag
|
||||
# via replication_heartbeat table,
|
||||
# default value is 0>
|
||||
# detect_stale_master=<if the replication is stopped or misconfigured
|
||||
# the previous detected master will be still available
|
||||
# until monitor or MaxSclale restart,
|
||||
# default value is 0>
|
||||
user=myuser
|
||||
passwd=mypwd
|
||||
monitor_interval=10000
|
||||
#backend_connect_timeout=
|
||||
#backend_read_timeout=
|
||||
#backend_write_timeout=
|
||||
#detect_replication_lag=
|
||||
#detect_stale_master=
|
||||
|
||||
# A series of service definition
|
||||
[Galera Monitor]
|
||||
type=monitor
|
||||
module=galeramon
|
||||
servers=server1,server2,server3
|
||||
user=myuser
|
||||
passwd=mypwd
|
||||
monitor_interval=10000
|
||||
#disable_master_failback=
|
||||
|
||||
## Filter definition
|
||||
#
|
||||
# Valid options are:
|
||||
# Type specifies the section
|
||||
#
|
||||
# router=<name of router module>
|
||||
# servers=<server name>,<server name>,...
|
||||
# user=<User to fetch password inforamtion with>
|
||||
# passwd=<Password of the user, plain text currently>
|
||||
# enable_root_user=<0 or 1, default is 0>
|
||||
# version_string=<specific string for server handshake,
|
||||
# default is the MariaDB embedded library version>
|
||||
# type=filter
|
||||
#
|
||||
# Module specifies which module implements the filter function
|
||||
#
|
||||
# module=[qlafilter|regexfilter|topfilter|teefilter]
|
||||
#
|
||||
# Options specify the log file for Query Log Filter
|
||||
#
|
||||
# options=<path to logfile>
|
||||
#
|
||||
# Match and replace are used in regexfilter
|
||||
#
|
||||
# match=fetch
|
||||
# replace=select
|
||||
#
|
||||
# Count and filebase are used with topfilter to specify how many top queries are
|
||||
# listed and where.
|
||||
#
|
||||
# count=<count>
|
||||
# filebase=<path to output file>
|
||||
#
|
||||
# Match and service are used by tee filter to specify what queries should be
|
||||
# duplicated and where the copy should be routed.
|
||||
#
|
||||
# match=insert.*HighScore.*values
|
||||
# service=Cassandra
|
||||
#
|
||||
## Examples:
|
||||
|
||||
[qla]
|
||||
type=filter
|
||||
module=qlafilter
|
||||
options=/tmp/QueryLog
|
||||
|
||||
[fetch]
|
||||
type=filter
|
||||
module=regexfilter
|
||||
match=fetch
|
||||
replace=select
|
||||
|
||||
|
||||
## A series of service definition
|
||||
#
|
||||
# Name of router module, currently valid options are
|
||||
#
|
||||
# router=[readconnroute|readwritesplit|debugcli|CLI]
|
||||
#
|
||||
# List of server names for use of service - mandatory for readconnroute,
|
||||
# readwritesplit, and debugcli
|
||||
#
|
||||
# servers=<server name 1>,<server name 2>,...,<server name N>
|
||||
#
|
||||
# Username to fetch password information with and password in plaintext
|
||||
# format - for readconnroute and readwritesplit
|
||||
#
|
||||
# user=<username>
|
||||
# passwd=<password in plain text format>
|
||||
#
|
||||
# flag for enabling the use of root user - for readconnroute and
|
||||
# readwritesplite - optional.
|
||||
#
|
||||
# enable_root_user=[0|1] (default 0)
|
||||
#
|
||||
# Version string to be used in server handshake. Default value is that of
|
||||
# MariaDB embedded library's - for readconnroute and readwritesplite - optional.
|
||||
#
|
||||
# version_string=<specific version string>
|
||||
#
|
||||
# Filters specify the filters through which the query is transferred and the
|
||||
# order of their appearance on the list corresponds the order they are
|
||||
# used. Values refer to names of filters configured in this file - for
|
||||
# readconnroute and readwritesplit - optional.
|
||||
#
|
||||
# filters=<filter name1|filter name2|...|filter nameN>
|
||||
#
|
||||
## Read Connection Router specific router options.
|
||||
#
|
||||
# router_options specify the role in which the selected server must be.
|
||||
#
|
||||
# router_options=[master|slave|synced]
|
||||
#
|
||||
## Read/Write Split Router specific options.
|
||||
#
|
||||
# use_sql_variables_in specifies where sql variable modifications are
|
||||
# routed - optional.
|
||||
#
|
||||
# use_sql_variables_in=[master|all] (default all)
|
||||
# router_options=<option[=value]>,<option[=value]>,...
|
||||
# where value=[master|slave|synced]
|
||||
#
|
||||
# Read/Write Split Router specific options are:
|
||||
# router_options=slave_selection_criteria specifies the selection criteria for
|
||||
# slaves both in new session creation and when route target is selected - optional.
|
||||
#
|
||||
# router_options=
|
||||
# slave_selection_criteria=[LEAST_CURRENT_OPERATIONS|LEAST_BEHIND_MASTER]
|
||||
#
|
||||
# max_slave_connections specifies how many slaves a router session can
|
||||
# connect to - optional.
|
||||
#
|
||||
# max_slave_connections=<number, or percentage, of all slaves>
|
||||
#
|
||||
# max_slave_replication_lag specifies how much a slave is allowed to be behind
|
||||
# the master and still become chosen routing target - optional, requires that
|
||||
# monitor has detect_replication_lag=1 .
|
||||
#
|
||||
# max_slave_connections=<exact number or percentage of all slaves>
|
||||
# max_slave_replication_lag=<allowed lag in seconds for a slave>
|
||||
# router_options=slave_selection_criteria=[LEAST_CURRENT_OPERATIONS|LEAST_BEHIND_MASTER]
|
||||
#
|
||||
# Valid router modules currently are:
|
||||
# readwritesplit, readconnroute and debugcli
|
||||
# readwritesplit, readconnroute, debugcli and CLI
|
||||
#
|
||||
## Examples:
|
||||
|
||||
[Read Connection Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
servers=server1,server2,server3
|
||||
user=myuser
|
||||
passwd=mypwd
|
||||
router_options=slave
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router=readwritesplit
|
||||
servers=server1,server2,server3
|
||||
user=maxuser
|
||||
passwd=maxpwd
|
||||
use_sql_variables_in=all
|
||||
max_slave_connections=50%
|
||||
max_slave_replication_lag=30
|
||||
router_options=slave_selection_criteria=LEAST_BEHIND_MASTER
|
||||
|
||||
|
||||
[Read Connection Router]
|
||||
type=service
|
||||
router=readconnroute
|
||||
router_options=slave
|
||||
servers=server1,server2,server3
|
||||
user=maxuser
|
||||
passwd=maxpwd
|
||||
user=myuser
|
||||
passwd=mypwd
|
||||
#use_sql_variables_in=
|
||||
#max_slave_connections=100%
|
||||
#max_slave_replication_lag=21
|
||||
#router_options=slave_selection_criteria=
|
||||
#filters=fetch|qla
|
||||
|
||||
[HTTPD Router]
|
||||
type=service
|
||||
@ -94,15 +217,44 @@ servers=server1,server2,server3
|
||||
type=service
|
||||
router=debugcli
|
||||
|
||||
# Listener definitions for the services
|
||||
[CLI]
|
||||
type=service
|
||||
router=CLI
|
||||
|
||||
## Listener definitions for the services
|
||||
#
|
||||
# Valid options are:
|
||||
# Type specifies section as listener one
|
||||
#
|
||||
# type=listener
|
||||
#
|
||||
# Service links the section to one of the service names used in this configuration
|
||||
#
|
||||
# service=<name of service section>
|
||||
#
|
||||
# Protocol is client protocol library name.
|
||||
#
|
||||
# protocol=[MySQLClient|telnetd|HTTPD|maxscaled]
|
||||
#
|
||||
# Port and address specify which port the service listens and the address limits
|
||||
# listening to a specific network interface only. Address is optional.
|
||||
#
|
||||
# service=<name of service defined elsewhere>
|
||||
# protocol=<name of protocol module with which to listen>
|
||||
# port=<Listening port>
|
||||
# address=<Address to bind to>
|
||||
#
|
||||
# Socket is alternative for address. The specified socket path must be writable
|
||||
# by the Unix user MaxScale runs as.
|
||||
#
|
||||
# socket=<Listening socket>
|
||||
#
|
||||
## Examples:
|
||||
|
||||
[Read Connection Listener]
|
||||
type=listener
|
||||
service=Read Connection Router
|
||||
protocol=MySQLClient
|
||||
address=192.168.100.102
|
||||
port=4008
|
||||
#socket=/tmp/readconn.sock
|
||||
|
||||
[RW Split Listener]
|
||||
type=listener
|
||||
@ -111,19 +263,12 @@ protocol=MySQLClient
|
||||
port=4006
|
||||
#socket=/tmp/rwsplit.sock
|
||||
|
||||
[Read Connection Listener]
|
||||
type=listener
|
||||
service=Read Connection Router
|
||||
protocol=MySQLClient
|
||||
port=4008
|
||||
#socket=/tmp/readconn.sock
|
||||
|
||||
[Debug Listener]
|
||||
type=listener
|
||||
service=Debug Interface
|
||||
protocol=telnetd
|
||||
port=4442
|
||||
#address=127.0.0.1
|
||||
port=4442
|
||||
|
||||
[HTTPD Listener]
|
||||
type=listener
|
||||
@ -131,40 +276,51 @@ service=HTTPD Router
|
||||
protocol=HTTPD
|
||||
port=6444
|
||||
|
||||
# Enable the maxadmin interface to MaxScale
|
||||
#
|
||||
# Listen on the default port of 6603 and restrict
|
||||
# to connections from localhost only.
|
||||
# Remove the address=localhost entry to enable
|
||||
# maxadmin connections from any host
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
address=localhost
|
||||
#address=localhost
|
||||
port=6603
|
||||
|
||||
# Definition of the servers
|
||||
## Definition of the servers
|
||||
#
|
||||
# Type specifies the section as server one
|
||||
#
|
||||
# type=server
|
||||
#
|
||||
# The IP address or hostname of the machine running the database server that is
|
||||
# being defined. MaxScale will use this address to connect to the backend
|
||||
# database server.
|
||||
#
|
||||
# address=<IP|hostname>
|
||||
#
|
||||
# The port on which the database listens for incoming connections. MaxScale
|
||||
# will use this port to connect to the database server.
|
||||
#
|
||||
# port=<port>
|
||||
#
|
||||
# The name for the protocol module to use to connect MaxScale to the database.
|
||||
# Currently the only backend protocol supported is the MySQLBackend module.
|
||||
#
|
||||
# protocol=MySQLBackend
|
||||
#
|
||||
## Examples:
|
||||
|
||||
[server1]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
address=192.168.100.101
|
||||
port=3000
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server2]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3001
|
||||
address=192.168.100.102
|
||||
port=3000
|
||||
protocol=MySQLBackend
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=127.0.0.1
|
||||
port=3002
|
||||
address=192.168.100.103
|
||||
port=3000
|
||||
protocol=MySQLBackend
|
||||
|
@ -590,11 +590,12 @@ int error_count = 0;
|
||||
}
|
||||
if (obj->element && options)
|
||||
{
|
||||
char *s = strtok(options, ",");
|
||||
char *lasts;
|
||||
char *s = strtok_r(options, ",", &lasts);
|
||||
while (s)
|
||||
{
|
||||
filterAddOption(obj->element, s);
|
||||
s = strtok(NULL, ",");
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
if (obj->element)
|
||||
@ -640,7 +641,8 @@ int error_count = 0;
|
||||
router = config_get_value(obj->parameters, "router");
|
||||
if (servers && obj->element)
|
||||
{
|
||||
char *s = strtok(servers, ",");
|
||||
char *lasts;
|
||||
char *s = strtok_r(servers, ",", &lasts);
|
||||
while (s)
|
||||
{
|
||||
CONFIG_CONTEXT *obj1 = context;
|
||||
@ -667,7 +669,7 @@ int error_count = 0;
|
||||
"service '%s'.",
|
||||
s, obj->object)));
|
||||
}
|
||||
s = strtok(NULL, ",");
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
else if (servers == NULL && internalService(router) == 0)
|
||||
@ -681,11 +683,12 @@ int error_count = 0;
|
||||
}
|
||||
if (roptions && obj->element)
|
||||
{
|
||||
char *s = strtok(roptions, ",");
|
||||
char *lasts;
|
||||
char *s = strtok_r(roptions, ",", &lasts);
|
||||
while (s)
|
||||
{
|
||||
serviceAddRouterOption(obj->element, s);
|
||||
s = strtok(NULL, ",");
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
if (filters && obj->element)
|
||||
@ -818,7 +821,7 @@ int error_count = 0;
|
||||
obj->element = monitor_alloc(obj->object, module);
|
||||
if (servers && obj->element)
|
||||
{
|
||||
char *s;
|
||||
char *s, *lasts;
|
||||
|
||||
/* if id is not set, compute it now with pid only */
|
||||
if (gateway.id == 0) {
|
||||
@ -853,7 +856,7 @@ int error_count = 0;
|
||||
monitorSetNetworkTimeout(obj->element, MONITOR_WRITE_TIMEOUT, write_timeout);
|
||||
|
||||
/* get the servers to monitor */
|
||||
s = strtok(servers, ",");
|
||||
s = strtok_r(servers, ",", &lasts);
|
||||
while (s)
|
||||
{
|
||||
CONFIG_CONTEXT *obj1 = context;
|
||||
@ -880,7 +883,7 @@ int error_count = 0;
|
||||
"monitor '%s'.",
|
||||
s, obj->object)));
|
||||
|
||||
s = strtok(NULL, ",");
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
if (obj->element && user && passwd)
|
||||
@ -1529,7 +1532,8 @@ SERVER *server;
|
||||
filters = config_get_value(obj->parameters, "filters");
|
||||
if (servers && obj->element)
|
||||
{
|
||||
char *s = strtok(servers, ",");
|
||||
char *lasts;
|
||||
char *s = strtok_r(servers, ",", &lasts);
|
||||
while (s)
|
||||
{
|
||||
CONFIG_CONTEXT *obj1 = context;
|
||||
@ -1559,17 +1563,18 @@ SERVER *server;
|
||||
"service '%s'.",
|
||||
s, obj->object)));
|
||||
}
|
||||
s = strtok(NULL, ",");
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
if (roptions && obj->element)
|
||||
{
|
||||
char *s = strtok(roptions, ",");
|
||||
char *lasts;
|
||||
char *s = strtok_r(roptions, ",", &lasts);
|
||||
serviceClearRouterOptions(obj->element);
|
||||
while (s)
|
||||
{
|
||||
serviceAddRouterOption(obj->element, s);
|
||||
s = strtok(NULL, ",");
|
||||
s = strtok_r(NULL, ",", &lasts);
|
||||
}
|
||||
}
|
||||
if (filters && obj->element)
|
||||
@ -1667,17 +1672,6 @@ static char *service_params[] =
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *server_params[] =
|
||||
{
|
||||
"type",
|
||||
"address",
|
||||
"port",
|
||||
"protocol",
|
||||
"monitorpw",
|
||||
"monitoruser",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *listener_params[] =
|
||||
{
|
||||
"type",
|
||||
|
@ -362,10 +362,11 @@ getDatabases(SERVICE *service, MYSQL *con)
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Warning: Loading DB names for service [%s] returned 0 rows."
|
||||
" SHOW DATABASES grant to user [%s] is required for MaxScale DB Name Authentication",
|
||||
service->name,
|
||||
service_user)));
|
||||
"%s: Unable to load database grant information, MaxScale "
|
||||
"authentication will proceed without including database "
|
||||
"permissions. To correct this GRANT select permission "
|
||||
"on msql.db to the user %s.",
|
||||
service->name, service_user)));
|
||||
}
|
||||
|
||||
/* free resut set */
|
||||
@ -622,7 +623,11 @@ getUsers(SERVICE *service, USERS *users)
|
||||
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error: Loading DB grants failed: GRANT is required on [mysql.db] to user [%s]. Try loading DB users for service [%s] without DB name MaxScale Authentication", service_user, service->name)));
|
||||
"%s: Unable to load database grant information, MaxScale "
|
||||
"authentication will proceed without including database "
|
||||
"permissions. To correct this GRANT select permission "
|
||||
"on msql.db to the user %s.",
|
||||
service->name, service_user)));
|
||||
|
||||
/* check for root user select */
|
||||
if(service->enable_root) {
|
||||
@ -649,8 +654,9 @@ getUsers(SERVICE *service, USERS *users)
|
||||
|
||||
LOGIF(LM, (skygw_log_write_flush(
|
||||
LOGFILE_MESSAGE,
|
||||
"Loading users from [mysql.user] without DB grants from [mysql.db] for service [%s]."
|
||||
" MaxScale Authentication with DBname on connect will not work",
|
||||
"Loading users from [mysql.user] without access to [mysql.db] for "
|
||||
"service [%s]. MaxScale Authentication with DBname on connect "
|
||||
"will not consider database grants.",
|
||||
service->name)));
|
||||
}
|
||||
} else {
|
||||
@ -715,7 +721,23 @@ getUsers(SERVICE *service, USERS *users)
|
||||
|
||||
int rc = 0;
|
||||
char *password = NULL;
|
||||
|
||||
if (row[2] != NULL) {
|
||||
/* detect mysql_old_password (pre 4.1 protocol) */
|
||||
if (strlen(row[2]) == 16) {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"%s: The user %s@%s has on old password in the "
|
||||
"backend database. MaxScale does not support these "
|
||||
"old passwords. This user will not be able to connect "
|
||||
"via MaxScale. Update the users password to correct "
|
||||
"this.",
|
||||
service->name,
|
||||
row[0],
|
||||
row[1])));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen(row[2]) > 1)
|
||||
password = row[2] +1;
|
||||
else
|
||||
@ -752,19 +774,20 @@ getUsers(SERVICE *service, USERS *users)
|
||||
/* Log the user being added with its db grants */
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"Added user %s@%s with DB grants on [%s], for service [%s]",
|
||||
"%s: User %s@%s for database %s added to "
|
||||
"service user table.",
|
||||
service->name,
|
||||
row[0],
|
||||
row[1],
|
||||
dbgrant,
|
||||
service->name)));
|
||||
dbgrant)));
|
||||
} else {
|
||||
/* Log the user being added (without db grants) */
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"Added user %s@%s for service [%s]",
|
||||
"%s: User %s@%s added to service user table.",
|
||||
service->name,
|
||||
row[0],
|
||||
row[1],
|
||||
service->name)));
|
||||
row[1])));
|
||||
}
|
||||
|
||||
/* Append data in the memory area for SHA1 digest */
|
||||
@ -774,7 +797,8 @@ getUsers(SERVICE *service, USERS *users)
|
||||
} else {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Warning: Failed adding user %s@%s for service [%s]",
|
||||
"Warning: Failed to add user %s@%s for service [%s]. "
|
||||
"This user will be unavailable via MaxScale.",
|
||||
row[0],
|
||||
row[1],
|
||||
service->name)));
|
||||
|
@ -293,7 +293,7 @@ GWBUF *modutil_create_mysql_err_msg(
|
||||
const char *msg)
|
||||
{
|
||||
uint8_t *outbuf = NULL;
|
||||
uint8_t mysql_payload_size = 0;
|
||||
uint32_t mysql_payload_size = 0;
|
||||
uint8_t mysql_packet_header[4];
|
||||
uint8_t *mysql_payload = NULL;
|
||||
uint8_t field_count = 0;
|
||||
|
@ -344,8 +344,10 @@ SERVER_PARAM *param;
|
||||
}
|
||||
}
|
||||
if (server->node_ts > 0) {
|
||||
struct tm result;
|
||||
char buf[40];
|
||||
dcb_printf(dcb, "\tLast Repl Heartbeat:\t%s",
|
||||
asctime(localtime(&server->node_ts)));
|
||||
asctime_r(localtime_r((time_t *)(&server->node_ts), &result), buf));
|
||||
}
|
||||
if ((param = server->parameters) != NULL)
|
||||
{
|
||||
|
@ -810,12 +810,15 @@ void
|
||||
printService(SERVICE *service)
|
||||
{
|
||||
SERVER *ptr = service->databases;
|
||||
struct tm result;
|
||||
char time_buf[30];
|
||||
int i;
|
||||
|
||||
printf("Service %p\n", service);
|
||||
printf("\tService: %s\n", service->name);
|
||||
printf("\tRouter: %s (%p)\n", service->routerModule, service->router);
|
||||
printf("\tStarted: %s", asctime(localtime(&service->stats.started)));
|
||||
printf("\tStarted: %s",
|
||||
asctime_r(localtime_r(&service->stats.started, &result), time_buf));
|
||||
printf("\tBackend databases\n");
|
||||
while (ptr)
|
||||
{
|
||||
@ -888,6 +891,8 @@ SERVICE *ptr;
|
||||
void dprintService(DCB *dcb, SERVICE *service)
|
||||
{
|
||||
SERVER *server = service->databases;
|
||||
struct tm result;
|
||||
char timebuf[30];
|
||||
int i;
|
||||
|
||||
dcb_printf(dcb, "Service %p\n", service);
|
||||
@ -898,7 +903,7 @@ int i;
|
||||
if (service->router)
|
||||
service->router->diagnostics(service->router_instance, dcb);
|
||||
dcb_printf(dcb, "\tStarted: %s",
|
||||
asctime(localtime(&service->stats.started)));
|
||||
asctime_r(localtime_r(&service->stats.started, &result), timebuf));
|
||||
dcb_printf(dcb, "\tRoot user access: %s\n",
|
||||
service->enable_root ? "Enabled" : "Disabled");
|
||||
if (service->n_filters)
|
||||
@ -1244,7 +1249,6 @@ bool service_set_param_value (
|
||||
* 0 error
|
||||
* > 0 position in TYPELIB->type_names +1
|
||||
*/
|
||||
|
||||
static int find_type(
|
||||
typelib_t* tl,
|
||||
const char* needle,
|
||||
|
@ -465,11 +465,15 @@ int rval = 0;
|
||||
void
|
||||
printSession(SESSION *session)
|
||||
{
|
||||
struct tm result;
|
||||
char timebuf[40];
|
||||
|
||||
printf("Session %p\n", session);
|
||||
printf("\tState: %s\n", session_state(session->state));
|
||||
printf("\tService: %s (%p)\n", session->service->name, session->service);
|
||||
printf("\tClient DCB: %p\n", session->client);
|
||||
printf("\tConnected: %s", asctime(localtime(&session->stats.connect)));
|
||||
printf("\tConnected: %s",
|
||||
asctime_r(localtime_r(&session->stats.connect, &result), timebuf));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -566,6 +570,8 @@ int norouter = 0;
|
||||
void
|
||||
dprintAllSessions(DCB *dcb)
|
||||
{
|
||||
struct tm result;
|
||||
char timebuf[40];
|
||||
SESSION *ptr;
|
||||
|
||||
spinlock_acquire(&session_spin);
|
||||
@ -578,7 +584,8 @@ SESSION *ptr;
|
||||
dcb_printf(dcb, "\tClient DCB: %p\n", ptr->client);
|
||||
if (ptr->client && ptr->client->remote)
|
||||
dcb_printf(dcb, "\tClient Address: %s\n", ptr->client->remote);
|
||||
dcb_printf(dcb, "\tConnected: %s", asctime(localtime(&ptr->stats.connect)));
|
||||
dcb_printf(dcb, "\tConnected: %s",
|
||||
asctime_r(localtime_r(&ptr->stats.connect, &result), timebuf));
|
||||
ptr = ptr->next;
|
||||
}
|
||||
spinlock_release(&session_spin);
|
||||
@ -596,6 +603,8 @@ SESSION *ptr;
|
||||
void
|
||||
dprintSession(DCB *dcb, SESSION *ptr)
|
||||
{
|
||||
struct tm result;
|
||||
char buf[30];
|
||||
int i;
|
||||
|
||||
dcb_printf(dcb, "Session %d (%p)\n",ptr->ses_id, ptr);
|
||||
@ -604,7 +613,8 @@ int i;
|
||||
dcb_printf(dcb, "\tClient DCB: %p\n", ptr->client);
|
||||
if (ptr->client && ptr->client->remote)
|
||||
dcb_printf(dcb, "\tClient Address: %s\n", ptr->client->remote);
|
||||
dcb_printf(dcb, "\tConnected: %s", asctime(localtime(&ptr->stats.connect)));
|
||||
dcb_printf(dcb, "\tConnected: %s",
|
||||
asctime_r(localtime_r(&ptr->stats.connect, &result), buf));
|
||||
if (ptr->n_filters)
|
||||
{
|
||||
for (i = 0; i < ptr->n_filters; i++)
|
||||
|
@ -231,9 +231,9 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
service->users = mysql_users;
|
||||
|
||||
if (db_from != NULL)
|
||||
strcpy(data->db, db_from);
|
||||
strncpy(data->db, db_from,MYSQL_DATABASE_MAXLEN);
|
||||
else
|
||||
strcpy(data->db, "");
|
||||
strncpy(data->db, "",MYSQL_DATABASE_MAXLEN);
|
||||
|
||||
/* freed by dcb_free(dcb) */
|
||||
dcb->data = data;
|
||||
|
@ -423,7 +423,7 @@ init_conn(MQ_INSTANCE *my_instance)
|
||||
*/
|
||||
char** parse_optstr(char* str, char* tok, int* szstore)
|
||||
{
|
||||
char* tk = str;
|
||||
char *lasts, *tk = str;
|
||||
char **arr;
|
||||
int i = 0, size = 1;
|
||||
while((tk = strpbrk(tk + 1,tok))){
|
||||
@ -440,10 +440,10 @@ char** parse_optstr(char* str, char* tok, int* szstore)
|
||||
}
|
||||
|
||||
*szstore = size;
|
||||
tk = strtok(str,tok);
|
||||
tk = strtok_r(str,tok, &lasts);
|
||||
while(tk && i < size){
|
||||
arr[i++] = strdup(tk);
|
||||
tk = strtok(NULL,tok);
|
||||
tk = strtok_r(NULL,tok,&lasts);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
@ -1052,7 +1052,8 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
||||
|
||||
for(z = 0;z<tbsz;z++){
|
||||
if((tmp = strchr(tblnames[z],'.')) != NULL){
|
||||
tmp = strtok(tblnames[z],".");
|
||||
char *lasts;
|
||||
tmp = strtok_r(tblnames[z],".",&lasts);
|
||||
for(i = 0; i<my_instance->shm_trg->size; i++){
|
||||
|
||||
if(strcmp(tmp,my_instance->shm_trg->objects[i]) == 0){
|
||||
@ -1103,8 +1104,9 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
||||
char* tbnm = NULL;
|
||||
|
||||
if((strchr(sesstbls[j],'.')) != NULL){
|
||||
tbnm = strtok(sesstbls[j],".");
|
||||
tbnm = strtok(NULL,".");
|
||||
char *lasts;
|
||||
tbnm = strtok_r(sesstbls[j],".",&lasts);
|
||||
tbnm = strtok_r(NULL,".",&lasts);
|
||||
}else{
|
||||
tbnm = sesstbls[j];
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ typedef enum {
|
||||
MYSQL_AUTH_SENT,
|
||||
MYSQL_AUTH_RECV,
|
||||
MYSQL_AUTH_FAILED,
|
||||
MYSQL_HANDSHAKE_FAILED,
|
||||
MYSQL_IDLE
|
||||
} mysql_auth_state_t;
|
||||
|
||||
|
@ -752,7 +752,7 @@ int log_no_master = 1;
|
||||
/* log master detection failure od first master becomes available after failure */
|
||||
if (root_master && mon_status_changed(root_master) && !(root_master->server->status & SERVER_STALE_STATUS)) {
|
||||
if (root_master->pending_status & (SERVER_MASTER)) {
|
||||
if (!(root_master->mon_prev_status & SERVER_STALE_STATUS)) {
|
||||
if (!(root_master->mon_prev_status & SERVER_STALE_STATUS) && !(root_master->server->status & SERVER_MAINT)) {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Info: A Master Server is now available: %s:%i",
|
||||
|
@ -374,8 +374,8 @@ int rc;
|
||||
rc = listen(listener->fd, SOMAXCONN);
|
||||
|
||||
if (rc == 0) {
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
LOGIF(LM, (skygw_log_write(
|
||||
LOGFILE_MESSAGE,
|
||||
"Listening maxscale connections at %s\n",
|
||||
config)));
|
||||
} else {
|
||||
|
@ -211,12 +211,13 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
/** Read cached backend handshake */
|
||||
if (gw_read_backend_handshake(backend_protocol) != 0)
|
||||
{
|
||||
backend_protocol->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||
backend_protocol->protocol_auth_state = MYSQL_HANDSHAKE_FAILED;
|
||||
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_backend_event] after "
|
||||
"gw_read_backend_handshake, fd %d, "
|
||||
"state = MYSQL_AUTH_FAILED.",
|
||||
"state = MYSQL_HANDSHAKE_FAILED.",
|
||||
pthread_self(),
|
||||
backend_protocol->owner_dcb->fd)));
|
||||
}
|
||||
@ -256,6 +257,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
* -- handle a previous handshake error
|
||||
*/
|
||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_RECV ||
|
||||
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED ||
|
||||
backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED)
|
||||
{
|
||||
spinlock_acquire(&dcb->authlock);
|
||||
@ -264,6 +266,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
CHK_PROTOCOL(backend_protocol);
|
||||
|
||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_RECV ||
|
||||
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED ||
|
||||
backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED)
|
||||
{
|
||||
ROUTER_OBJECT *router = NULL;
|
||||
@ -286,7 +289,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_RECV)
|
||||
{
|
||||
/**
|
||||
* Read backed's reply to authentication message
|
||||
* Read backend's reply to authentication message
|
||||
*/
|
||||
receive_rc =
|
||||
gw_receive_backend_auth(backend_protocol);
|
||||
@ -340,7 +343,8 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
} /* switch */
|
||||
}
|
||||
|
||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED)
|
||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED ||
|
||||
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED)
|
||||
{
|
||||
/**
|
||||
* protocol state won't change anymore,
|
||||
@ -362,7 +366,9 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
bool succp;
|
||||
|
||||
/* try reload users' table for next connection */
|
||||
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED) {
|
||||
service_refresh_users(dcb->session->service);
|
||||
}
|
||||
#if defined(SS_DEBUG)
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
@ -428,7 +434,7 @@ static int gw_read_backend_event(DCB *dcb) {
|
||||
|
||||
spinlock_release(&dcb->authlock);
|
||||
|
||||
} /* MYSQL_AUTH_RECV || MYSQL_AUTH_FAILED */
|
||||
} /* MYSQL_AUTH_RECV || MYSQL_AUTH_FAILED || MYSQL_HANDSHAKE_FAILED */
|
||||
|
||||
/* reading MySQL command output from backend and writing to the client */
|
||||
{
|
||||
@ -693,6 +699,7 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
|
||||
* return 1.
|
||||
*/
|
||||
switch (backend_protocol->protocol_auth_state) {
|
||||
case MYSQL_HANDSHAKE_FAILED:
|
||||
case MYSQL_AUTH_FAILED:
|
||||
{
|
||||
size_t len;
|
||||
@ -827,15 +834,19 @@ static int gw_error_backend_event(DCB *dcb)
|
||||
char buf[100];
|
||||
|
||||
len = sizeof(error);
|
||||
|
||||
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0)
|
||||
{
|
||||
if (error != 0)
|
||||
{
|
||||
strerror_r(error, buf, 100);
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"DCB in state %s got error '%s'.",
|
||||
gw_dcb_state2string(dcb->state),
|
||||
STRDCBSTATE(dcb->state),
|
||||
buf)));
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
errbuf = mysql_create_custom_error(
|
||||
@ -867,6 +878,8 @@ static int gw_error_backend_event(DCB *dcb)
|
||||
|
||||
len = sizeof(error);
|
||||
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0)
|
||||
{
|
||||
if (error != 0)
|
||||
{
|
||||
strerror_r(error, buf, 100);
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
@ -874,6 +887,7 @@ static int gw_error_backend_event(DCB *dcb)
|
||||
"Error '%s' in session that is not ready for routing.",
|
||||
buf)));
|
||||
}
|
||||
}
|
||||
gwbuf_free(errbuf);
|
||||
goto retblock;
|
||||
}
|
||||
@ -1070,6 +1084,8 @@ gw_backend_hangup(DCB *dcb)
|
||||
|
||||
len = sizeof(error);
|
||||
if (getsockopt(dcb->fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0)
|
||||
{
|
||||
if (error != 0)
|
||||
{
|
||||
strerror_r(error, buf, 100);
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
@ -1078,6 +1094,7 @@ gw_backend_hangup(DCB *dcb)
|
||||
"Error reported is '%s'.",
|
||||
buf)));
|
||||
}
|
||||
}
|
||||
gwbuf_free(errbuf);
|
||||
goto retblock;
|
||||
}
|
||||
@ -1312,7 +1329,7 @@ static int gw_change_user(
|
||||
|
||||
/* now get the user, after 4 bytes header and 1 byte command */
|
||||
client_auth_packet += 5;
|
||||
strcpy(username, (char *)client_auth_packet);
|
||||
strncpy(username, (char *)client_auth_packet,MYSQL_USER_MAXLEN);
|
||||
client_auth_packet += strlen(username) + 1;
|
||||
|
||||
/* get the auth token len */
|
||||
@ -1333,7 +1350,7 @@ static int gw_change_user(
|
||||
}
|
||||
|
||||
/* get new database name */
|
||||
strcpy(database, (char *)client_auth_packet);
|
||||
strncpy(database, (char *)client_auth_packet,MYSQL_DATABASE_MAXLEN);
|
||||
|
||||
/* get character set */
|
||||
if (strlen(database)) {
|
||||
@ -1346,7 +1363,7 @@ static int gw_change_user(
|
||||
memcpy(&backend_protocol->charset, client_auth_packet, sizeof(int));
|
||||
|
||||
/* save current_database name */
|
||||
strcpy(current_database, current_session->db);
|
||||
strncpy(current_database, current_session->db,MYSQL_DATABASE_MAXLEN);
|
||||
|
||||
/*
|
||||
* Now clear database name in dcb as we don't do local authentication on db name for change user.
|
||||
|
@ -214,12 +214,12 @@ int gw_read_backend_handshake(
|
||||
|
||||
if (h_len <= 4) {
|
||||
/* log error this exit point */
|
||||
conn->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||
conn->protocol_auth_state = MYSQL_HANDSHAKE_FAILED;
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_backend_handshake] after "
|
||||
"dcb_read, fd %d, "
|
||||
"state = MYSQL_AUTH_FAILED.",
|
||||
"state = MYSQL_HANDSHAKE_FAILED.",
|
||||
dcb->fd,
|
||||
pthread_self())));
|
||||
|
||||
@ -232,6 +232,8 @@ int gw_read_backend_handshake(
|
||||
uint16_t errcode = MYSQL_GET_ERRCODE(payload);
|
||||
char* bufstr = strndup(&((char *)payload)[7], len-3);
|
||||
|
||||
conn->protocol_auth_state = MYSQL_HANDSHAKE_FAILED;
|
||||
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_receive_backend_auth] Invalid "
|
||||
@ -261,12 +263,14 @@ int gw_read_backend_handshake(
|
||||
* data in buffer less than expected in the
|
||||
* packet. Log error this exit point
|
||||
*/
|
||||
conn->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||
|
||||
conn->protocol_auth_state = MYSQL_HANDSHAKE_FAILED;
|
||||
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_backend_handshake] after "
|
||||
"gw_mysql_get_byte3, fd %d, "
|
||||
"state = MYSQL_AUTH_FAILED.",
|
||||
"state = MYSQL_HANDSHAKE_FAILED.",
|
||||
pthread_self(),
|
||||
dcb->fd,
|
||||
pthread_self())));
|
||||
@ -285,12 +289,13 @@ int gw_read_backend_handshake(
|
||||
* we cannot continue
|
||||
* log error this exit point
|
||||
*/
|
||||
conn->protocol_auth_state = MYSQL_AUTH_FAILED;
|
||||
conn->protocol_auth_state = MYSQL_HANDSHAKE_FAILED;
|
||||
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [gw_read_backend_handshake] after "
|
||||
"gw_decode_mysql_server_handshake, fd %d, "
|
||||
"state = MYSQL_AUTH_FAILED.",
|
||||
"state = MYSQL_HANDSHAKE_FAILED.",
|
||||
pthread_self(),
|
||||
conn->owner_dcb->fd,
|
||||
pthread_self())));
|
||||
@ -577,8 +582,8 @@ int gw_send_authentication_to_backend(
|
||||
dcb = conn->owner_dcb;
|
||||
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
||||
|
||||
/** Copy client's flags to backend */
|
||||
final_capabilities |= conn->client_capabilities;
|
||||
/** Copy client's flags to backend but with the known capabilities mask */
|
||||
final_capabilities |= (conn->client_capabilities & GW_MYSQL_CAPABILITIES_CLIENT);
|
||||
|
||||
/* get charset the client sent and use it for connection auth */
|
||||
charset = conn->charset;
|
||||
@ -964,7 +969,7 @@ GWBUF* mysql_create_custom_error(
|
||||
const char* msg)
|
||||
{
|
||||
uint8_t* outbuf = NULL;
|
||||
uint8_t mysql_payload_size = 0;
|
||||
uint32_t mysql_payload_size = 0;
|
||||
uint8_t mysql_packet_header[4];
|
||||
uint8_t* mysql_payload = NULL;
|
||||
uint8_t field_count = 0;
|
||||
@ -1574,7 +1579,7 @@ mysql_send_auth_error (
|
||||
const char *mysql_message)
|
||||
{
|
||||
uint8_t *outbuf = NULL;
|
||||
uint8_t mysql_payload_size = 0;
|
||||
uint32_t mysql_payload_size = 0;
|
||||
uint8_t mysql_packet_header[4];
|
||||
uint8_t *mysql_payload = NULL;
|
||||
uint8_t field_count = 0;
|
||||
|
@ -1212,7 +1212,9 @@ static bool get_dcb(
|
||||
* backend and update assign it to new candidate if
|
||||
* necessary.
|
||||
*/
|
||||
else if (max_rlag == MAX_RLAG_UNDEFINED ||
|
||||
else if (SERVER_IS_SLAVE(b->backend_server))
|
||||
{
|
||||
if (max_rlag == MAX_RLAG_UNDEFINED ||
|
||||
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
||||
b->backend_server->rlag <= max_rlag))
|
||||
{
|
||||
@ -1231,6 +1233,7 @@ static bool get_dcb(
|
||||
b->backend_server->port,
|
||||
b->backend_server->rlag)));
|
||||
}
|
||||
}
|
||||
} /*< for */
|
||||
/** Assign selected DCB's pointer value */
|
||||
if (candidate_bref != NULL)
|
||||
@ -1473,6 +1476,12 @@ static route_target_t get_route_target (
|
||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_UNKNOWN)));
|
||||
target = TARGET_MASTER;
|
||||
}
|
||||
#if defined(SS_EXTRA_DEBUG)
|
||||
LOGIF(LT, (skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
"Selected target \"%s\"",
|
||||
STRTARGET(target))));
|
||||
#endif
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -2125,6 +2134,14 @@ static int routeQuery(
|
||||
rlag_max);
|
||||
if (succp)
|
||||
{
|
||||
#if defined(SS_EXTRA_DEBUG)
|
||||
LOGIF(LT, (skygw_log_write(LOGFILE_TRACE,
|
||||
"Found DCB for slave.")));
|
||||
#endif
|
||||
ss_dassert(get_bref_from_dcb(router_cli_ses, target_dcb) !=
|
||||
router_cli_ses->rses_master_ref);
|
||||
ss_dassert(get_root_master_bref(router_cli_ses) ==
|
||||
router_cli_ses->rses_master_ref);
|
||||
atomic_add(&inst->stats.n_slave, 1);
|
||||
}
|
||||
else
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
NARGS=7
|
||||
TLOG=$1
|
||||
THOST=$2
|
||||
|
@ -262,6 +262,12 @@ typedef enum skygw_chk_t {
|
||||
(SERVER_IS_RELAY_SERVER(s) ? "RUNNING RELAY" : \
|
||||
(SERVER_IS_RUNNING(s) ? "RUNNING (only)" : "NO STATUS")))))))
|
||||
|
||||
#define STRTARGET(t) (t == TARGET_ALL ? "TARGET_ALL" : \
|
||||
(t == TARGET_MASTER ? "TARGET_MASTER" : \
|
||||
(t == TARGET_SLAVE ? "TARGET_SLAVE" : \
|
||||
(t == TARGET_UNDEFINED ? "TARGET_UNDEFINED" : \
|
||||
"Unknown target value"))))
|
||||
|
||||
#define BREFSRV(b) (b->bref_backend->backend_server)
|
||||
|
||||
|
||||
|
@ -1680,12 +1680,12 @@ static bool file_write_header(
|
||||
|
||||
if (wbytes1 != 1 || wbytes2 != 1 || wbytes3 != 1 || wbytes4 != 1) {
|
||||
fprintf(stderr,
|
||||
"* Writing header %s %s %s to %s failed.\n",
|
||||
"\nError : Writing header %s %s %s %s failed.\n",
|
||||
header_buf1,
|
||||
header_buf2,
|
||||
header_buf3,
|
||||
header_buf4);
|
||||
perror("Logfile header write.\n");
|
||||
perror("Logfile header write");
|
||||
goto return_succp;
|
||||
}
|
||||
#endif
|
||||
@ -1757,11 +1757,11 @@ static bool file_write_footer(
|
||||
if (wbytes1 != 1 || wbytes3 != 1 || wbytes4 != 1)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"* Writing header %s %s to %s failed.\n",
|
||||
"\nError : Writing header %s %s to %s failed.\n",
|
||||
header_buf1,
|
||||
header_buf3,
|
||||
header_buf4);
|
||||
perror("Logfile header write.\n");
|
||||
perror("Logfile header write");
|
||||
goto return_succp;
|
||||
}
|
||||
#endif
|
||||
@ -1875,7 +1875,7 @@ skygw_file_t* skygw_file_init(
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
fprintf(stderr,
|
||||
"* Writing header of log file %s failed due %d, %s.\n",
|
||||
"\nError : Writing header of log file %s failed due %d, %s.\n",
|
||||
file->sf_fname,
|
||||
eno,
|
||||
strerror(eno));
|
||||
|
Reference in New Issue
Block a user