Merge branch 'develop' into firewall
This commit is contained in:
commit
4a8f97d2e2
@ -152,7 +152,7 @@ add_custom_target(buildtests
|
|||||||
add_custom_target(testall
|
add_custom_target(testall
|
||||||
COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR}
|
COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR}
|
||||||
COMMAND make install
|
COMMAND make install
|
||||||
COMMAND cp ${CMAKE_SOURCE_DIR}/server/test/MaxScale_test.cnf ${CMAKE_BINARY_DIR}/etc/MaxScale.cnf
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/server/test/MaxScale_test.cnf ${CMAKE_BINARY_DIR}/etc/MaxScale.cnf
|
||||||
COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null"
|
COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null"
|
||||||
COMMAND /bin/sh -c "make test || echo \"Test results written to: ${CMAKE_BINARY_DIR}/Testing/Temporary/\""
|
COMMAND /bin/sh -c "make test || echo \"Test results written to: ${CMAKE_BINARY_DIR}/Testing/Temporary/\""
|
||||||
COMMAND killall maxscale
|
COMMAND killall maxscale
|
||||||
|
@ -276,6 +276,8 @@ static bool check_file_and_path(
|
|||||||
bool* writable);
|
bool* writable);
|
||||||
|
|
||||||
static bool file_is_symlink(char* filename);
|
static bool file_is_symlink(char* filename);
|
||||||
|
static int skygw_log_disable_raw(logfile_id_t id, bool emergency); /*< no locking */
|
||||||
|
|
||||||
|
|
||||||
const char* get_suffix_default(void)
|
const char* get_suffix_default(void)
|
||||||
{
|
{
|
||||||
@ -1185,25 +1187,36 @@ return_err:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int skygw_log_disable(
|
int skygw_log_disable(
|
||||||
logfile_id_t id)
|
logfile_id_t id) /*< no locking */
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = skygw_log_disable_raw(id, false);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int skygw_log_disable_raw(
|
||||||
|
logfile_id_t id,
|
||||||
|
bool emergency) /*< no locking */
|
||||||
{
|
{
|
||||||
bool err = 0;
|
bool err = 0;
|
||||||
|
|
||||||
if (!logmanager_register(true)) {
|
if (!logmanager_register(true))
|
||||||
//fprintf(stderr, "ERROR: Can't register to logmanager\n");
|
{
|
||||||
err = -1;
|
err = -1;
|
||||||
goto return_err;
|
goto return_err;
|
||||||
}
|
}
|
||||||
CHK_LOGMANAGER(lm);
|
CHK_LOGMANAGER(lm);
|
||||||
|
|
||||||
if (logfile_set_enabled(id, false)) {
|
if (emergency || logfile_set_enabled(id, false))
|
||||||
lm->lm_enabled_logfiles &= ~id;
|
{
|
||||||
/**
|
lm->lm_enabled_logfiles &= ~id;
|
||||||
* Set global variable
|
/**
|
||||||
*/
|
* Set global variable
|
||||||
lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles;
|
*/
|
||||||
|
lm_enabled_logfiles_bitmask = lm->lm_enabled_logfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
logmanager_unregister();
|
logmanager_unregister();
|
||||||
@ -2403,6 +2416,7 @@ static bool filewriter_init(
|
|||||||
skygw_message_t* logmes)
|
skygw_message_t* logmes)
|
||||||
{
|
{
|
||||||
bool succp = false;
|
bool succp = false;
|
||||||
|
int err;
|
||||||
logfile_t* lf;
|
logfile_t* lf;
|
||||||
logfile_id_t id;
|
logfile_id_t id;
|
||||||
int i;
|
int i;
|
||||||
@ -2456,10 +2470,22 @@ static bool filewriter_init(
|
|||||||
} else {
|
} else {
|
||||||
start_msg_str = strdup("---\tLogging is disabled.\n");
|
start_msg_str = strdup("---\tLogging is disabled.\n");
|
||||||
}
|
}
|
||||||
skygw_file_write(fw->fwr_file[id],
|
err = skygw_file_write(fw->fwr_file[id],
|
||||||
(void *)start_msg_str,
|
(void *)start_msg_str,
|
||||||
strlen(start_msg_str),
|
strlen(start_msg_str),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
|
if (err != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error : writing to file %s failed due to %d, %s. "
|
||||||
|
"Exiting MaxScale.\n",
|
||||||
|
lf->lf_full_file_name,
|
||||||
|
err,
|
||||||
|
strerror(err));
|
||||||
|
succp = false;
|
||||||
|
goto return_succp;
|
||||||
|
}
|
||||||
free(start_msg_str);
|
free(start_msg_str);
|
||||||
}
|
}
|
||||||
fw->fwr_state = RUN;
|
fw->fwr_state = RUN;
|
||||||
@ -2603,7 +2629,10 @@ static void* thr_filewriter_fun(
|
|||||||
#endif
|
#endif
|
||||||
node = bb_list->mlist_first;
|
node = bb_list->mlist_first;
|
||||||
|
|
||||||
while (node != NULL) {
|
while (node != NULL)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
CHK_MLIST_NODE(node);
|
CHK_MLIST_NODE(node);
|
||||||
bb = (blockbuf_t *)node->mlnode_data;
|
bb = (blockbuf_t *)node->mlnode_data;
|
||||||
CHK_BLOCKBUF(bb);
|
CHK_BLOCKBUF(bb);
|
||||||
@ -2630,11 +2659,25 @@ static void* thr_filewriter_fun(
|
|||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
skygw_file_write(file,
|
err = skygw_file_write(
|
||||||
(void *)bb->bb_buf,
|
file,
|
||||||
bb->bb_buf_used,
|
(void *)bb->bb_buf,
|
||||||
(flush_logfile ||
|
bb->bb_buf_used,
|
||||||
flushall_logfiles));
|
(flush_logfile ||
|
||||||
|
flushall_logfiles));
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error : Write to %s log "
|
||||||
|
": %s failed due to %d, "
|
||||||
|
"%s. Disabling the log.",
|
||||||
|
STRLOGNAME((logfile_id_t)i),
|
||||||
|
lf->lf_full_file_name,
|
||||||
|
err,
|
||||||
|
strerror(err));
|
||||||
|
/** Force log off */
|
||||||
|
skygw_log_disable_raw((logfile_id_t)i, true);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Reset buffer's counters and mark
|
* Reset buffer's counters and mark
|
||||||
* not full.
|
* not full.
|
||||||
|
@ -57,7 +57,7 @@ int main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
fgets(readbuff,4092,infile);
|
fgets(readbuff,4092,infile);
|
||||||
psize = strlen(readbuff);
|
psize = strlen(readbuff);
|
||||||
if(psize < 0 || psize > 4092){
|
if(psize > 4092){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
qbuff = gwbuf_alloc(psize + 7);
|
qbuff = gwbuf_alloc(psize + 7);
|
||||||
|
@ -1393,11 +1393,11 @@ SERVER *server;
|
|||||||
user,
|
user,
|
||||||
auth);
|
auth);
|
||||||
if (enable_root_user)
|
if (enable_root_user)
|
||||||
serviceEnableRootUser(service, atoi(enable_root_user));
|
serviceEnableRootUser(obj->element, atoi(enable_root_user));
|
||||||
|
|
||||||
if (allow_localhost_match_wildcard_host && service)
|
if (allow_localhost_match_wildcard_host)
|
||||||
serviceEnableLocalhostMatchWildcardHost(
|
serviceEnableLocalhostMatchWildcardHost(
|
||||||
service,
|
obj->element,
|
||||||
atoi(allow_localhost_match_wildcard_host));
|
atoi(allow_localhost_match_wildcard_host));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,8 +121,8 @@ DCB *rval;
|
|||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
rval->dcb_chk_top = CHK_NUM_DCB;
|
rval->dcb_chk_top = CHK_NUM_DCB;
|
||||||
rval->dcb_chk_tail = CHK_NUM_DCB;
|
rval->dcb_chk_tail = CHK_NUM_DCB;
|
||||||
rval->dcb_errhandle_called = false;
|
|
||||||
#endif
|
#endif
|
||||||
|
rval->dcb_errhandle_called = false;
|
||||||
rval->dcb_role = role;
|
rval->dcb_role = role;
|
||||||
spinlock_init(&rval->dcb_initlock);
|
spinlock_init(&rval->dcb_initlock);
|
||||||
spinlock_init(&rval->writeqlock);
|
spinlock_init(&rval->writeqlock);
|
||||||
@ -862,7 +862,7 @@ int below_water;
|
|||||||
while (queue != NULL)
|
while (queue != NULL)
|
||||||
{
|
{
|
||||||
int qlen;
|
int qlen;
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
if (dcb->dcb_role == DCB_ROLE_REQUEST_HANDLER &&
|
if (dcb->dcb_role == DCB_ROLE_REQUEST_HANDLER &&
|
||||||
dcb->session != NULL)
|
dcb->session != NULL)
|
||||||
{
|
{
|
||||||
@ -878,7 +878,7 @@ int below_water;
|
|||||||
fail_next_backend_fd = false;
|
fail_next_backend_fd = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* SS_DEBUG */
|
#endif /* FAKE_CODE */
|
||||||
qlen = GWBUF_LENGTH(queue);
|
qlen = GWBUF_LENGTH(queue);
|
||||||
GW_NOINTR_CALL(
|
GW_NOINTR_CALL(
|
||||||
w = gw_write(
|
w = gw_write(
|
||||||
@ -1684,7 +1684,7 @@ int gw_write(
|
|||||||
size_t nbytes)
|
size_t nbytes)
|
||||||
{
|
{
|
||||||
int w;
|
int w;
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
if (dcb_fake_write_errno[fd] != 0) {
|
if (dcb_fake_write_errno[fd] != 0) {
|
||||||
ss_dassert(dcb_fake_write_ev[fd] != 0);
|
ss_dassert(dcb_fake_write_ev[fd] != 0);
|
||||||
w = write(fd, buf, nbytes/2); /*< leave peer to read missing bytes */
|
w = write(fd, buf, nbytes/2); /*< leave peer to read missing bytes */
|
||||||
@ -1698,7 +1698,7 @@ int gw_write(
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
w = write(fd, buf, nbytes);
|
w = write(fd, buf, nbytes);
|
||||||
#endif /* SS_DEBUG && SS_TEST */
|
#endif /* FAKE_CODE */
|
||||||
|
|
||||||
#if defined(SS_DEBUG_MYSQL)
|
#if defined(SS_DEBUG_MYSQL)
|
||||||
{
|
{
|
||||||
|
@ -1025,7 +1025,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
progname = *argv;
|
progname = *argv;
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
memset(conn_open, 0, sizeof(bool)*10240);
|
memset(conn_open, 0, sizeof(bool)*10240);
|
||||||
memset(dcb_fake_write_errno, 0, sizeof(unsigned char)*10240);
|
memset(dcb_fake_write_errno, 0, sizeof(unsigned char)*10240);
|
||||||
memset(dcb_fake_write_ev, 0, sizeof(__int32_t)*10240);
|
memset(dcb_fake_write_ev, 0, sizeof(__int32_t)*10240);
|
||||||
@ -1033,7 +1033,7 @@ int main(int argc, char **argv)
|
|||||||
fail_next_client_fd = false;
|
fail_next_client_fd = false;
|
||||||
fail_next_accept = 0;
|
fail_next_accept = 0;
|
||||||
fail_accept_errno = 0;
|
fail_accept_errno = 0;
|
||||||
#endif
|
#endif /* FAKE_CODE */
|
||||||
file_write_header(stderr);
|
file_write_header(stderr);
|
||||||
/*<
|
/*<
|
||||||
* Register functions which are called at exit except libmysqld-related,
|
* Register functions which are called at exit except libmysqld-related,
|
||||||
|
@ -625,7 +625,7 @@ uint32_t ev;
|
|||||||
thread_data[thread_id].event = ev;
|
thread_data[thread_id].event = ev;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
if (dcb_fake_write_ev[dcb->fd] != 0) {
|
if (dcb_fake_write_ev[dcb->fd] != 0) {
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
@ -637,7 +637,7 @@ uint32_t ev;
|
|||||||
ev |= dcb_fake_write_ev[dcb->fd];
|
ev |= dcb_fake_write_ev[dcb->fd];
|
||||||
dcb_fake_write_ev[dcb->fd] = 0;
|
dcb_fake_write_ev[dcb->fd] = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* FAKE_CODE */
|
||||||
ss_debug(spinlock_acquire(&dcb->dcb_initlock);)
|
ss_debug(spinlock_acquire(&dcb->dcb_initlock);)
|
||||||
ss_dassert(dcb->state != DCB_STATE_ALLOC);
|
ss_dassert(dcb->state != DCB_STATE_ALLOC);
|
||||||
ss_dassert(dcb->state != DCB_STATE_DISCONNECTED);
|
ss_dassert(dcb->state != DCB_STATE_DISCONNECTED);
|
||||||
@ -735,7 +735,7 @@ uint32_t ev;
|
|||||||
if (ev & EPOLLERR)
|
if (ev & EPOLLERR)
|
||||||
{
|
{
|
||||||
int eno = gw_getsockerrno(dcb->fd);
|
int eno = gw_getsockerrno(dcb->fd);
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
if (eno == 0) {
|
if (eno == 0) {
|
||||||
eno = dcb_fake_write_errno[dcb->fd];
|
eno = dcb_fake_write_errno[dcb->fd];
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
@ -748,7 +748,7 @@ uint32_t ev;
|
|||||||
strerror(eno))));
|
strerror(eno))));
|
||||||
}
|
}
|
||||||
dcb_fake_write_errno[dcb->fd] = 0;
|
dcb_fake_write_errno[dcb->fd] = 0;
|
||||||
#endif
|
#endif /* FAKE_CODE */
|
||||||
if (eno != 0) {
|
if (eno != 0) {
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
|
@ -145,6 +145,7 @@ SERVICE *service;
|
|||||||
service->filters = NULL;
|
service->filters = NULL;
|
||||||
service->n_filters = 0;
|
service->n_filters = 0;
|
||||||
service->weightby = 0;
|
service->weightby = 0;
|
||||||
|
service->users = NULL;
|
||||||
service->resources = NULL;
|
service->resources = NULL;
|
||||||
spinlock_init(&service->spin);
|
spinlock_init(&service->spin);
|
||||||
spinlock_init(&service->users_table_spin);
|
spinlock_init(&service->users_table_spin);
|
||||||
@ -213,42 +214,46 @@ GWPROTOCOL *funcs;
|
|||||||
if (strcmp(port->protocol, "MySQLClient") == 0) {
|
if (strcmp(port->protocol, "MySQLClient") == 0) {
|
||||||
int loaded;
|
int loaded;
|
||||||
|
|
||||||
/*
|
if (service->users == NULL) {
|
||||||
* Allocate specific data for MySQL users
|
/*
|
||||||
* including hosts and db names
|
* Allocate specific data for MySQL users
|
||||||
*/
|
* including hosts and db names
|
||||||
service->users = mysql_users_alloc();
|
*/
|
||||||
|
service->users = mysql_users_alloc();
|
||||||
|
|
||||||
if ((loaded = load_mysql_users(service)) < 0)
|
if ((loaded = load_mysql_users(service)) < 0)
|
||||||
{
|
{
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Error : Unable to load users from %s:%d for "
|
"Error : Unable to load users from %s:%d for "
|
||||||
"service %s.",
|
"service %s.",
|
||||||
port->address,
|
port->address,
|
||||||
port->port,
|
port->port,
|
||||||
service->name)));
|
service->name)));
|
||||||
hashtable_free(service->users->data);
|
hashtable_free(service->users->data);
|
||||||
free(service->users);
|
free(service->users);
|
||||||
dcb_free(port->listener);
|
dcb_free(port->listener);
|
||||||
port->listener = NULL;
|
port->listener = NULL;
|
||||||
goto retblock;
|
goto retblock;
|
||||||
|
}
|
||||||
|
/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
|
||||||
|
* This way MaxScale could try reloading users' just after startup
|
||||||
|
*/
|
||||||
|
service->rate_limit.last=time(NULL) - USERS_REFRESH_TIME;
|
||||||
|
service->rate_limit.nloads=1;
|
||||||
|
|
||||||
|
LOGIF(LM, (skygw_log_write(
|
||||||
|
LOGFILE_MESSAGE,
|
||||||
|
"Loaded %d MySQL Users for service [%s].",
|
||||||
|
loaded, service->name)));
|
||||||
}
|
}
|
||||||
/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
|
|
||||||
* This way MaxScale could try reloading users' just after startup
|
|
||||||
*/
|
|
||||||
service->rate_limit.last=time(NULL) - USERS_REFRESH_TIME;
|
|
||||||
service->rate_limit.nloads=1;
|
|
||||||
|
|
||||||
LOGIF(LM, (skygw_log_write(
|
|
||||||
LOGFILE_MESSAGE,
|
|
||||||
"Loaded %d MySQL Users for service [%s].",
|
|
||||||
loaded, service->name)));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Generic users table */
|
if (service->users == NULL) {
|
||||||
service->users = users_alloc();
|
/* Generic users table */
|
||||||
|
service->users = users_alloc();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((funcs=(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL))
|
if ((funcs=(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL))
|
||||||
|
@ -134,7 +134,8 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
service->router->newSession(service->router_instance,
|
service->router->newSession(service->router_instance,
|
||||||
session);
|
session);
|
||||||
|
|
||||||
if (session->router_session == NULL) {
|
if (session->router_session == NULL)
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Inform other threads that session is closing.
|
* Inform other threads that session is closing.
|
||||||
*/
|
*/
|
||||||
@ -153,7 +154,6 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
|
|
||||||
goto return_session;
|
goto return_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pending filter chain being setup set the head of the chain to
|
* Pending filter chain being setup set the head of the chain to
|
||||||
* be the router. As filters are inserted the current head will
|
* be the router. As filters are inserted the current head will
|
||||||
@ -196,11 +196,12 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_acquire(&session_spin);
|
spinlock_acquire(&session->ses_lock);
|
||||||
|
|
||||||
if (session->state != SESSION_STATE_READY)
|
if (session->state != SESSION_STATE_READY)
|
||||||
{
|
{
|
||||||
session_free(session);
|
spinlock_release(&session->ses_lock);
|
||||||
|
session_free(session);
|
||||||
client_dcb->session = NULL;
|
client_dcb->session = NULL;
|
||||||
session = NULL;
|
session = NULL;
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
@ -212,10 +213,13 @@ session_alloc(SERVICE *service, DCB *client_dcb)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
session->state = SESSION_STATE_ROUTER_READY;
|
session->state = SESSION_STATE_ROUTER_READY;
|
||||||
session->next = allSessions;
|
spinlock_release(&session->ses_lock);
|
||||||
|
spinlock_acquire(&session_spin);
|
||||||
|
session->next = allSessions;
|
||||||
allSessions = session;
|
allSessions = session;
|
||||||
spinlock_release(&session_spin);
|
spinlock_release(&session_spin);
|
||||||
atomic_add(&service->stats.n_sessions, 1);
|
|
||||||
|
atomic_add(&service->stats.n_sessions, 1);
|
||||||
atomic_add(&service->stats.n_current, 1);
|
atomic_add(&service->stats.n_current, 1);
|
||||||
CHK_SESSION(session);
|
CHK_SESSION(session);
|
||||||
}
|
}
|
||||||
|
@ -205,9 +205,9 @@ typedef struct dcb_callback {
|
|||||||
typedef struct dcb {
|
typedef struct dcb {
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t dcb_chk_top;
|
skygw_chk_t dcb_chk_top;
|
||||||
bool dcb_errhandle_called;
|
|
||||||
#endif
|
#endif
|
||||||
dcb_role_t dcb_role;
|
bool dcb_errhandle_called; /*< this can be called only once */
|
||||||
|
dcb_role_t dcb_role;
|
||||||
SPINLOCK dcb_initlock;
|
SPINLOCK dcb_initlock;
|
||||||
DCBEVENTQ evq; /**< The event queue for this DCB */
|
DCBEVENTQ evq; /**< The event queue for this DCB */
|
||||||
int fd; /**< The descriptor */
|
int fd; /**< The descriptor */
|
||||||
@ -252,14 +252,14 @@ typedef struct dcb {
|
|||||||
#endif
|
#endif
|
||||||
} DCB;
|
} DCB;
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
unsigned char dcb_fake_write_errno[10240];
|
unsigned char dcb_fake_write_errno[10240];
|
||||||
__int32_t dcb_fake_write_ev[10240];
|
__int32_t dcb_fake_write_ev[10240];
|
||||||
bool fail_next_backend_fd;
|
bool fail_next_backend_fd;
|
||||||
bool fail_next_client_fd;
|
bool fail_next_client_fd;
|
||||||
int fail_next_accept;
|
int fail_next_accept;
|
||||||
int fail_accept_errno;
|
int fail_accept_errno;
|
||||||
#endif
|
#endif /* FAKE_CODE */
|
||||||
|
|
||||||
/* A few useful macros */
|
/* A few useful macros */
|
||||||
#define DCB_SESSION(x) (x)->session
|
#define DCB_SESSION(x) (x)->session
|
||||||
|
@ -110,6 +110,10 @@ typedef enum
|
|||||||
MONITOR_WRITE_TIMEOUT = 2
|
MONITOR_WRITE_TIMEOUT = 2
|
||||||
} monitor_timeouts_t;
|
} monitor_timeouts_t;
|
||||||
|
|
||||||
|
#define DEFAULT_CONNECT_TIMEOUT 3
|
||||||
|
#define DEFAULT_READ_TIMEOUT 1
|
||||||
|
#define DEFAULT_WRITE_TIMEOUT 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of the running monitor.
|
* Representation of the running monitor.
|
||||||
*/
|
*/
|
||||||
|
@ -550,7 +550,7 @@ HINT_TOKEN *tok;
|
|||||||
else if (!inword && inquote == '\0' && **ptr == '=')
|
else if (!inword && inquote == '\0' && **ptr == '=')
|
||||||
{
|
{
|
||||||
*dest = **ptr;
|
*dest = **ptr;
|
||||||
*dest++;
|
dest++;
|
||||||
(*ptr)++;
|
(*ptr)++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -748,9 +748,12 @@ int load_filter(FILTERCHAIN* fc, CONFIG* cnf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int x;
|
int x;
|
||||||
for(x = 0;x<paramc;x++){
|
|
||||||
free(fparams[x]->name);
|
if(fparams){
|
||||||
free(fparams[x]->value);
|
for(x = 0;x<paramc;x++){
|
||||||
|
free(fparams[x]->name);
|
||||||
|
free(fparams[x]->value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fparams);
|
free(fparams);
|
||||||
@ -769,15 +772,18 @@ FILTERCHAIN* load_filter_module(char* str)
|
|||||||
flt_ptr->next = instance.head;
|
flt_ptr->next = instance.head;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((flt_ptr->instance = (FILTER_OBJECT*)load_module(str, MODULE_FILTER)) == NULL)
|
if(flt_ptr){
|
||||||
{
|
if( (flt_ptr->instance = (FILTER_OBJECT*)load_module(str, MODULE_FILTER)) == NULL)
|
||||||
printf("Error: Module loading failed: %s\n",str);
|
{
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error: Module loading failed: %s\n",str);
|
printf("Error: Module loading failed: %s\n",str);
|
||||||
free(flt_ptr->down);
|
skygw_log_write(LOGFILE_ERROR,"Error: Module loading failed: %s\n",str);
|
||||||
free(flt_ptr);
|
free(flt_ptr->down);
|
||||||
return NULL;
|
free(flt_ptr);
|
||||||
}
|
return NULL;
|
||||||
flt_ptr->name = strdup(str);
|
}
|
||||||
|
flt_ptr->name = strdup(str);
|
||||||
|
}
|
||||||
|
|
||||||
return flt_ptr;
|
return flt_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -925,14 +931,35 @@ GWBUF* gen_packet(PACKET pkt)
|
|||||||
|
|
||||||
int process_opts(int argc, char** argv)
|
int process_opts(int argc, char** argv)
|
||||||
{
|
{
|
||||||
unsigned int fd = open_file("harness.cnf",1), buffsize = 1024;
|
int fd, buffsize = 1024;
|
||||||
int rd,rdsz;
|
int rd,rdsz, rval;
|
||||||
unsigned int fsize;
|
size_t fsize;
|
||||||
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
|
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
|
||||||
|
|
||||||
/**Parse 'harness.cnf' file*/
|
/**Parse 'harness.cnf' file*/
|
||||||
fsize = lseek(fd,0,SEEK_END);
|
|
||||||
lseek(fd,0,SEEK_SET);
|
if(buff == NULL){
|
||||||
|
printf("Error: Call to malloc() failed.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((fd = open_file("harness.cnf",1)) < 0){
|
||||||
|
printf("Failed to open configuration file.\n");
|
||||||
|
free(buff);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( (rval = lseek(fd,0,SEEK_END)) < 0 ||
|
||||||
|
lseek(fd,0,SEEK_SET) < 0){
|
||||||
|
printf("Error: Cannot seek file.\n");
|
||||||
|
close(fd);
|
||||||
|
free(buff);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fsize = (size_t)rval;
|
||||||
|
|
||||||
instance.thrcount = 1;
|
instance.thrcount = 1;
|
||||||
instance.session_count = 1;
|
instance.session_count = 1;
|
||||||
rdsz = read(fd,buff,fsize);
|
rdsz = read(fd,buff,fsize);
|
||||||
|
@ -281,6 +281,7 @@ typedef struct {
|
|||||||
* created or received */
|
* created or received */
|
||||||
unsigned long tid; /*< MySQL Thread ID, in
|
unsigned long tid; /*< MySQL Thread ID, in
|
||||||
* handshake */
|
* handshake */
|
||||||
|
unsigned int charset; /*< MySQL character set at connect time */
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
skygw_chk_t protocol_chk_tail;
|
skygw_chk_t protocol_chk_tail;
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
* 03/06/14 Mark Riddoch Add support for maintenance mode
|
* 03/06/14 Mark Riddoch Add support for maintenance mode
|
||||||
* 24/06/14 Massimiliano Pinto Added depth level 0 for each node
|
* 24/06/14 Massimiliano Pinto Added depth level 0 for each node
|
||||||
* 30/10/14 Massimiliano Pinto Added disableMasterFailback feature
|
* 30/10/14 Massimiliano Pinto Added disableMasterFailback feature
|
||||||
|
* 10/11/14 Massimiliano Pinto Added setNetworkTimeout for connect,read,write
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -53,7 +54,7 @@ extern int lm_enabled_logfiles_bitmask;
|
|||||||
|
|
||||||
static void monitorMain(void *);
|
static void monitorMain(void *);
|
||||||
|
|
||||||
static char *version_str = "V1.3.0";
|
static char *version_str = "V1.4.0";
|
||||||
|
|
||||||
MODULE_INFO info = {
|
MODULE_INFO info = {
|
||||||
MODULE_API_MONITOR,
|
MODULE_API_MONITOR,
|
||||||
@ -69,9 +70,10 @@ static void unregisterServer(void *, SERVER *);
|
|||||||
static void defaultUsers(void *, char *, char *);
|
static void defaultUsers(void *, char *, char *);
|
||||||
static void diagnostics(DCB *, void *);
|
static void diagnostics(DCB *, void *);
|
||||||
static void setInterval(void *, size_t);
|
static void setInterval(void *, size_t);
|
||||||
static MONITOR_SERVERS *get_candidate_master(MONITOR_SERVERS *);
|
static MONITOR_SERVERS *get_candidate_master(MONITOR_SERVERS *);
|
||||||
static MONITOR_SERVERS *set_cluster_master(MONITOR_SERVERS *, MONITOR_SERVERS *, int);
|
static MONITOR_SERVERS *set_cluster_master(MONITOR_SERVERS *, MONITOR_SERVERS *, int);
|
||||||
static void disableMasterFailback(void *, int);
|
static void disableMasterFailback(void *, int);
|
||||||
|
static void setNetworkTimeout(void *arg, int type, int value);
|
||||||
|
|
||||||
static MONITOR_OBJECT MyObject = {
|
static MONITOR_OBJECT MyObject = {
|
||||||
startMonitor,
|
startMonitor,
|
||||||
@ -81,7 +83,7 @@ static MONITOR_OBJECT MyObject = {
|
|||||||
defaultUsers,
|
defaultUsers,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
setInterval,
|
setInterval,
|
||||||
NULL,
|
setNetworkTimeout,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@ -155,6 +157,9 @@ MYSQL_MONITOR *handle;
|
|||||||
handle->interval = MONITOR_INTERVAL;
|
handle->interval = MONITOR_INTERVAL;
|
||||||
handle->disableMasterFailback = 0;
|
handle->disableMasterFailback = 0;
|
||||||
handle->master = NULL;
|
handle->master = NULL;
|
||||||
|
handle->connect_timeout=DEFAULT_CONNECT_TIMEOUT;
|
||||||
|
handle->read_timeout=DEFAULT_READ_TIMEOUT;
|
||||||
|
handle->write_timeout=DEFAULT_READ_TIMEOUT;
|
||||||
spinlock_init(&handle->lock);
|
spinlock_init(&handle->lock);
|
||||||
}
|
}
|
||||||
handle->tid = (THREAD)thread_start(monitorMain, handle);
|
handle->tid = (THREAD)thread_start(monitorMain, handle);
|
||||||
@ -273,6 +278,9 @@ char *sep;
|
|||||||
|
|
||||||
dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", handle->interval);
|
dcb_printf(dcb,"\tSampling interval:\t%lu milliseconds\n", handle->interval);
|
||||||
dcb_printf(dcb,"\tMaster Failback:\t%s\n", (handle->disableMasterFailback == 1) ? "off" : "on");
|
dcb_printf(dcb,"\tMaster Failback:\t%s\n", (handle->disableMasterFailback == 1) ? "off" : "on");
|
||||||
|
dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", handle->connect_timeout);
|
||||||
|
dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", handle->read_timeout);
|
||||||
|
dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", handle->write_timeout);
|
||||||
dcb_printf(dcb, "\tMonitored servers: ");
|
dcb_printf(dcb, "\tMonitored servers: ");
|
||||||
|
|
||||||
db = handle->databases;
|
db = handle->databases;
|
||||||
@ -310,16 +318,18 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
|||||||
/**
|
/**
|
||||||
* Monitor an individual server
|
* Monitor an individual server
|
||||||
*
|
*
|
||||||
* @param database The database to probe
|
* @param handle The MySQL Monitor object
|
||||||
|
* @param database The database to probe
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
monitorDatabase(MONITOR_SERVERS *database, char *defaultUser, char *defaultPasswd)
|
monitorDatabase(MYSQL_MONITOR *handle, MONITOR_SERVERS *database)
|
||||||
{
|
{
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
MYSQL_RES *result;
|
MYSQL_RES *result;
|
||||||
int num_fields;
|
int num_fields;
|
||||||
int isjoined = 0;
|
int isjoined = 0;
|
||||||
char *uname = defaultUser, *passwd = defaultPasswd;
|
char *uname = handle->defaultUser;
|
||||||
|
char *passwd = handle->defaultPasswd;
|
||||||
unsigned long int server_version = 0;
|
unsigned long int server_version = 0;
|
||||||
char *server_string;
|
char *server_string;
|
||||||
|
|
||||||
@ -339,12 +349,15 @@ char *server_string;
|
|||||||
{
|
{
|
||||||
char *dpwd = decryptPassword(passwd);
|
char *dpwd = decryptPassword(passwd);
|
||||||
int rc;
|
int rc;
|
||||||
int read_timeout = 1;
|
int connect_timeout = handle->connect_timeout;
|
||||||
int connect_timeout = 2;
|
int read_timeout = handle->read_timeout;
|
||||||
|
int write_timeout = handle->write_timeout;;
|
||||||
|
|
||||||
database->con = mysql_init(NULL);
|
database->con = mysql_init(NULL);
|
||||||
|
|
||||||
rc = mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);
|
rc = mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);
|
||||||
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
|
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
|
||||||
|
rc = mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout);
|
||||||
|
|
||||||
if (mysql_real_connect(database->con, database->server->name,
|
if (mysql_real_connect(database->con, database->server->name,
|
||||||
uname, dpwd, NULL, database->server->port, NULL, 0) == NULL)
|
uname, dpwd, NULL, database->server->port, NULL, 0) == NULL)
|
||||||
@ -487,7 +500,7 @@ int master_stickiness = handle->disableMasterFailback;
|
|||||||
{
|
{
|
||||||
unsigned int prev_status = ptr->server->status;
|
unsigned int prev_status = ptr->server->status;
|
||||||
|
|
||||||
monitorDatabase(ptr, handle->defaultUser, handle->defaultPasswd);
|
monitorDatabase(handle, ptr);
|
||||||
|
|
||||||
/* clear bits for non member nodes */
|
/* clear bits for non member nodes */
|
||||||
if ( ! SERVER_IN_MAINT(ptr->server) && (ptr->server->node_id < 0 || ! SERVER_IS_JOINED(ptr->server))) {
|
if ( ! SERVER_IN_MAINT(ptr->server) && (ptr->server->node_id < 0 || ! SERVER_IS_JOINED(ptr->server))) {
|
||||||
@ -662,3 +675,56 @@ MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
|||||||
memcpy(&handle->disableMasterFailback, &disable, sizeof(int));
|
memcpy(&handle->disableMasterFailback, &disable, sizeof(int));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
setNetworkTimeout(void *arg, int type, int value)
|
||||||
|
{
|
||||||
|
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
||||||
|
int max_timeout = (int)(handle->interval/1000);
|
||||||
|
int new_timeout = max_timeout -1;
|
||||||
|
|
||||||
|
if (new_timeout <= 0)
|
||||||
|
new_timeout = DEFAULT_CONNECT_TIMEOUT;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case MONITOR_CONNECT_TIMEOUT:
|
||||||
|
if (value < max_timeout) {
|
||||||
|
memcpy(&handle->connect_timeout, &value, sizeof(int));
|
||||||
|
} else {
|
||||||
|
memcpy(&handle->connect_timeout, &new_timeout, sizeof(int));
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"warning : Monitor Connect Timeout %i is greater than monitor interval ~%i seconds"
|
||||||
|
", lowering to %i seconds", value, max_timeout, new_timeout)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MONITOR_READ_TIMEOUT:
|
||||||
|
if (value < max_timeout) {
|
||||||
|
memcpy(&handle->read_timeout, &value, sizeof(int));
|
||||||
|
} else {
|
||||||
|
memcpy(&handle->read_timeout, &new_timeout, sizeof(int));
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"warning : Monitor Read Timeout %i is greater than monitor interval ~%i seconds"
|
||||||
|
", lowering to %i seconds", value, max_timeout, new_timeout)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MONITOR_WRITE_TIMEOUT:
|
||||||
|
if (value < max_timeout) {
|
||||||
|
memcpy(&handle->write_timeout, &value, sizeof(int));
|
||||||
|
} else {
|
||||||
|
memcpy(&handle->write_timeout, &new_timeout, sizeof(int));
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"warning : Monitor Write Timeout %i is greater than monitor interval ~%i seconds"
|
||||||
|
", lowering to %i seconds", value, max_timeout, new_timeout)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Monitor setNetworkTimeout received an unsupported action type %i", type)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
* 28/08/14 Massimiliano Pinto Added detectStaleMaster feature: previous detected master will be used again, even if the replication is stopped.
|
* 28/08/14 Massimiliano Pinto Added detectStaleMaster feature: previous detected master will be used again, even if the replication is stopped.
|
||||||
* This means both IO and SQL threads are not working on slaves.
|
* This means both IO and SQL threads are not working on slaves.
|
||||||
* This option is not enabled by default.
|
* This option is not enabled by default.
|
||||||
|
* 10/11/14 Massimiliano Pinto Addition of setNetworkTimeout for connect, read, write
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -65,7 +66,7 @@ extern int lm_enabled_logfiles_bitmask;
|
|||||||
|
|
||||||
static void monitorMain(void *);
|
static void monitorMain(void *);
|
||||||
|
|
||||||
static char *version_str = "V1.3.0";
|
static char *version_str = "V1.4.0";
|
||||||
|
|
||||||
MODULE_INFO info = {
|
MODULE_INFO info = {
|
||||||
MODULE_API_MONITOR,
|
MODULE_API_MONITOR,
|
||||||
@ -104,7 +105,7 @@ static MONITOR_OBJECT MyObject = {
|
|||||||
defaultUser,
|
defaultUser,
|
||||||
diagnostics,
|
diagnostics,
|
||||||
setInterval,
|
setInterval,
|
||||||
NULL,
|
setNetworkTimeout,
|
||||||
defaultId,
|
defaultId,
|
||||||
replicationHeartbeat,
|
replicationHeartbeat,
|
||||||
detectStaleMaster,
|
detectStaleMaster,
|
||||||
@ -180,6 +181,9 @@ MYSQL_MONITOR *handle;
|
|||||||
handle->replicationHeartbeat = 0;
|
handle->replicationHeartbeat = 0;
|
||||||
handle->detectStaleMaster = 0;
|
handle->detectStaleMaster = 0;
|
||||||
handle->master = NULL;
|
handle->master = NULL;
|
||||||
|
handle->connect_timeout=DEFAULT_CONNECT_TIMEOUT;
|
||||||
|
handle->read_timeout=DEFAULT_READ_TIMEOUT;
|
||||||
|
handle->write_timeout=DEFAULT_WRITE_TIMEOUT;
|
||||||
spinlock_init(&handle->lock);
|
spinlock_init(&handle->lock);
|
||||||
}
|
}
|
||||||
handle->tid = (THREAD)thread_start(monitorMain, handle);
|
handle->tid = (THREAD)thread_start(monitorMain, handle);
|
||||||
@ -326,6 +330,9 @@ char *sep;
|
|||||||
dcb_printf(dcb,"\tMaxScale MonitorId:\t%lu\n", handle->id);
|
dcb_printf(dcb,"\tMaxScale MonitorId:\t%lu\n", handle->id);
|
||||||
dcb_printf(dcb,"\tReplication lag:\t%s\n", (handle->replicationHeartbeat == 1) ? "enabled" : "disabled");
|
dcb_printf(dcb,"\tReplication lag:\t%s\n", (handle->replicationHeartbeat == 1) ? "enabled" : "disabled");
|
||||||
dcb_printf(dcb,"\tDetect Stale Master:\t%s\n", (handle->detectStaleMaster == 1) ? "enabled" : "disabled");
|
dcb_printf(dcb,"\tDetect Stale Master:\t%s\n", (handle->detectStaleMaster == 1) ? "enabled" : "disabled");
|
||||||
|
dcb_printf(dcb,"\tConnect Timeout:\t%i seconds\n", handle->connect_timeout);
|
||||||
|
dcb_printf(dcb,"\tRead Timeout:\t\t%i seconds\n", handle->read_timeout);
|
||||||
|
dcb_printf(dcb,"\tWrite Timeout:\t\t%i seconds\n", handle->write_timeout);
|
||||||
dcb_printf(dcb, "\tMonitored servers: ");
|
dcb_printf(dcb, "\tMonitored servers: ");
|
||||||
|
|
||||||
db = handle->databases;
|
db = handle->databases;
|
||||||
@ -381,11 +388,15 @@ char *server_string;
|
|||||||
{
|
{
|
||||||
char *dpwd = decryptPassword(passwd);
|
char *dpwd = decryptPassword(passwd);
|
||||||
int rc;
|
int rc;
|
||||||
int read_timeout = 1;
|
int connect_timeout = handle->connect_timeout;
|
||||||
|
int read_timeout = handle->read_timeout;
|
||||||
|
int write_timeout = handle->write_timeout;
|
||||||
|
|
||||||
database->con = mysql_init(NULL);
|
database->con = mysql_init(NULL);
|
||||||
|
|
||||||
|
rc = mysql_options(database->con, MYSQL_OPT_CONNECT_TIMEOUT, (void *)&connect_timeout);
|
||||||
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
|
rc = mysql_options(database->con, MYSQL_OPT_READ_TIMEOUT, (void *)&read_timeout);
|
||||||
|
rc = mysql_options(database->con, MYSQL_OPT_WRITE_TIMEOUT, (void *)&write_timeout);
|
||||||
|
|
||||||
if (mysql_real_connect(database->con,
|
if (mysql_real_connect(database->con,
|
||||||
database->server->name,
|
database->server->name,
|
||||||
@ -867,6 +878,13 @@ static void set_master_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *databas
|
|||||||
char heartbeat_insert_query[512]="";
|
char heartbeat_insert_query[512]="";
|
||||||
char heartbeat_purge_query[512]="";
|
char heartbeat_purge_query[512]="";
|
||||||
|
|
||||||
|
if (handle->master == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"[mysql_mon]: set_master_heartbeat called without an available Master server")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* create the maxscale_schema database */
|
/* create the maxscale_schema database */
|
||||||
if (mysql_query(database->con, "CREATE DATABASE IF NOT EXISTS maxscale_schema")) {
|
if (mysql_query(database->con, "CREATE DATABASE IF NOT EXISTS maxscale_schema")) {
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
@ -972,6 +990,13 @@ static void set_slave_heartbeat(MYSQL_MONITOR *handle, MONITOR_SERVERS *database
|
|||||||
MYSQL_RES *result;
|
MYSQL_RES *result;
|
||||||
int num_fields;
|
int num_fields;
|
||||||
|
|
||||||
|
if (handle->master == NULL) {
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"[mysql_mon]: set_slave_heartbeat called without an available Master server")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the master_timestamp value from maxscale_schema.replication_heartbeat table */
|
/* Get the master_timestamp value from maxscale_schema.replication_heartbeat table */
|
||||||
|
|
||||||
sprintf(select_heartbeat_query, "SELECT master_timestamp "
|
sprintf(select_heartbeat_query, "SELECT master_timestamp "
|
||||||
@ -1210,11 +1235,61 @@ monitor_clear_pending_status(MONITOR_SERVERS *ptr, int bit)
|
|||||||
/**
|
/**
|
||||||
* Set the default id to use in the monitor.
|
* Set the default id to use in the monitor.
|
||||||
*
|
*
|
||||||
* @param arg The handle allocated by startMonitor
|
* @param arg The handle allocated by startMonitor
|
||||||
* @param id The id to set in monitor struct
|
* @param type The connect timeout type
|
||||||
|
* @param value The timeout value to set
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
setNetworkTimeout(void *arg, int type, int value)
|
setNetworkTimeout(void *arg, int type, int value)
|
||||||
{
|
{
|
||||||
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
||||||
|
int max_timeout = (int)(handle->interval/1000);
|
||||||
|
int new_timeout = max_timeout -1;
|
||||||
|
|
||||||
|
if (new_timeout <= 0)
|
||||||
|
new_timeout = DEFAULT_CONNECT_TIMEOUT;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case MONITOR_CONNECT_TIMEOUT:
|
||||||
|
if (value < max_timeout) {
|
||||||
|
memcpy(&handle->connect_timeout, &value, sizeof(int));
|
||||||
|
} else {
|
||||||
|
memcpy(&handle->connect_timeout, &new_timeout, sizeof(int));
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"warning : Monitor Connect Timeout %i is greater than monitor interval ~%i seconds"
|
||||||
|
", lowering to %i seconds", value, max_timeout, new_timeout)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MONITOR_READ_TIMEOUT:
|
||||||
|
if (value < max_timeout) {
|
||||||
|
memcpy(&handle->read_timeout, &value, sizeof(int));
|
||||||
|
} else {
|
||||||
|
memcpy(&handle->read_timeout, &new_timeout, sizeof(int));
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"warning : Monitor Read Timeout %i is greater than monitor interval ~%i seconds"
|
||||||
|
", lowering to %i seconds", value, max_timeout, new_timeout)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MONITOR_WRITE_TIMEOUT:
|
||||||
|
if (value < max_timeout) {
|
||||||
|
memcpy(&handle->write_timeout, &value, sizeof(int));
|
||||||
|
} else {
|
||||||
|
memcpy(&handle->write_timeout, &new_timeout, sizeof(int));
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"warning : Monitor Write Timeout %i is greater than monitor interval ~%i seconds"
|
||||||
|
", lowering to %i seconds", value, max_timeout, new_timeout)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Monitor setNetworkTimeout received an unsupported action type %i", type)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
* 28/05/14 Massimiliano Pinto Addition of new fields in MYSQL_MONITOR struct
|
* 28/05/14 Massimiliano Pinto Addition of new fields in MYSQL_MONITOR struct
|
||||||
* 24/06/14 Massimiliano Pinto Addition of master field in MYSQL_MONITOR struct and MONITOR_MAX_NUM_SLAVES
|
* 24/06/14 Massimiliano Pinto Addition of master field in MYSQL_MONITOR struct and MONITOR_MAX_NUM_SLAVES
|
||||||
* 28/08/14 Massimiliano Pinto Addition of detectStaleMaster
|
* 28/08/14 Massimiliano Pinto Addition of detectStaleMaster
|
||||||
|
* 30/10/14 Massimiliano Pinto Addition of disableMasterFailback
|
||||||
|
* 07/11/14 Massimiliano Pinto Addition of NetworkTimeout: connect, read, write
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -68,6 +70,13 @@ typedef struct {
|
|||||||
int disableMasterFailback; /**< Monitor flag for Galera Cluster Master failback */
|
int disableMasterFailback; /**< Monitor flag for Galera Cluster Master failback */
|
||||||
MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */
|
MONITOR_SERVERS *master; /**< Master server for MySQL Master/Slave replication */
|
||||||
MONITOR_SERVERS *databases; /**< Linked list of servers to monitor */
|
MONITOR_SERVERS *databases; /**< Linked list of servers to monitor */
|
||||||
|
int connect_timeout; /**< Connect timeout in seconds for mysql_real_connect */
|
||||||
|
int read_timeout; /**< Timeout in seconds to read from the server.
|
||||||
|
* There are retries and the total effective timeout value is three times the option value.
|
||||||
|
*/
|
||||||
|
int write_timeout; /**< Timeout in seconds for each attempt to write to the server.
|
||||||
|
* There are retries and the total effective timeout value is two times the option value.
|
||||||
|
*/
|
||||||
} MYSQL_MONITOR;
|
} MYSQL_MONITOR;
|
||||||
|
|
||||||
#define MONITOR_RUNNING 1
|
#define MONITOR_RUNNING 1
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
* 12/09/2013 Massimiliano Pinto Added checks in gw_read_backend_event() for gw_read_backend_handshake
|
* 12/09/2013 Massimiliano Pinto Added checks in gw_read_backend_event() for gw_read_backend_handshake
|
||||||
* 27/09/2013 Massimiliano Pinto Changed in gw_read_backend_event the check for dcb_read(), now is if rc < 0
|
* 27/09/2013 Massimiliano Pinto Changed in gw_read_backend_event the check for dcb_read(), now is if rc < 0
|
||||||
* 24/10/2014 Massimiliano Pinto Added Mysql user@host @db authentication support
|
* 24/10/2014 Massimiliano Pinto Added Mysql user@host @db authentication support
|
||||||
|
* 10/11/2014 Massimiliano Pinto Client charset is passed to backend
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <modinfo.h>
|
#include <modinfo.h>
|
||||||
@ -378,7 +379,6 @@ static int gw_read_backend_event(DCB *dcb) {
|
|||||||
ERRACT_REPLY_CLIENT,
|
ERRACT_REPLY_CLIENT,
|
||||||
&succp);
|
&succp);
|
||||||
gwbuf_free(errbuf);
|
gwbuf_free(errbuf);
|
||||||
ss_dassert(!succp);
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [gw_read_backend_event] "
|
"%lu [gw_read_backend_event] "
|
||||||
@ -854,8 +854,12 @@ static int gw_error_backend_event(DCB *dcb)
|
|||||||
&succp);
|
&succp);
|
||||||
gwbuf_free(errbuf);
|
gwbuf_free(errbuf);
|
||||||
|
|
||||||
/** There are not required backends available, close session. */
|
/**
|
||||||
if (!succp) {
|
* If error handler fails it means that routing session can't continue
|
||||||
|
* and it must be closed. In success, only this DCB is closed.
|
||||||
|
*/
|
||||||
|
if (!succp)
|
||||||
|
{
|
||||||
spinlock_acquire(&session->ses_lock);
|
spinlock_acquire(&session->ses_lock);
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
spinlock_release(&session->ses_lock);
|
spinlock_release(&session->ses_lock);
|
||||||
@ -909,6 +913,9 @@ static int gw_create_backend_connection(
|
|||||||
/** Copy client flags to backend protocol */
|
/** Copy client flags to backend protocol */
|
||||||
protocol->client_capabilities =
|
protocol->client_capabilities =
|
||||||
((MySQLProtocol *)(backend_dcb->session->client->protocol))->client_capabilities;
|
((MySQLProtocol *)(backend_dcb->session->client->protocol))->client_capabilities;
|
||||||
|
/** Copy client charset to backend protocol */
|
||||||
|
protocol->charset =
|
||||||
|
((MySQLProtocol *)(backend_dcb->session->client->protocol))->charset;
|
||||||
|
|
||||||
/*< if succeed, fd > 0, -1 otherwise */
|
/*< if succeed, fd > 0, -1 otherwise */
|
||||||
rv = gw_do_connect_to_backend(server->name, server->port, &fd);
|
rv = gw_do_connect_to_backend(server->name, server->port, &fd);
|
||||||
@ -1082,8 +1089,8 @@ gw_backend_close(DCB *dcb)
|
|||||||
mysql_protocol_done(dcb);
|
mysql_protocol_done(dcb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If session->state is set to STOPPING the client and the session must
|
* If session->state is STOPPING, start closing client session.
|
||||||
* be closed too.
|
* Otherwise only this backend connection is closed.
|
||||||
*/
|
*/
|
||||||
if (session != NULL && session->state == SESSION_STATE_STOPPING)
|
if (session != NULL && session->state == SESSION_STATE_STOPPING)
|
||||||
{
|
{
|
||||||
@ -1258,6 +1265,16 @@ static int gw_change_user(
|
|||||||
/* get new database name */
|
/* get new database name */
|
||||||
strcpy(database, (char *)client_auth_packet);
|
strcpy(database, (char *)client_auth_packet);
|
||||||
|
|
||||||
|
/* get character set */
|
||||||
|
if (strlen(database)) {
|
||||||
|
client_auth_packet += strlen(database) + 1;
|
||||||
|
} else {
|
||||||
|
client_auth_packet++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_auth_packet && *client_auth_packet)
|
||||||
|
memcpy(&backend_protocol->charset, client_auth_packet, sizeof(int));
|
||||||
|
|
||||||
/* save current_database name */
|
/* save current_database name */
|
||||||
strcpy(current_database, current_session->db);
|
strcpy(current_database, current_session->db);
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
* 07/05/2014 Massimiliano Pinto Added: specific version string in server handshake
|
* 07/05/2014 Massimiliano Pinto Added: specific version string in server handshake
|
||||||
* 09/09/2014 Massimiliano Pinto Added: 777 permission for socket path
|
* 09/09/2014 Massimiliano Pinto Added: 777 permission for socket path
|
||||||
* 13/10/2014 Massimiliano Pinto Added: dbname authentication check
|
* 13/10/2014 Massimiliano Pinto Added: dbname authentication check
|
||||||
|
* 10/11/2014 Massimiliano Pinto Added: client charset added to protocol struct
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <skygw_utils.h>
|
#include <skygw_utils.h>
|
||||||
@ -444,6 +445,9 @@ static int gw_mysql_do_authentication(DCB *dcb, GWBUF *queue) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get charset */
|
||||||
|
memcpy(&protocol->charset, client_auth_packet + 4 + 4 + 4, sizeof (int));
|
||||||
|
|
||||||
/* get the auth token len */
|
/* get the auth token len */
|
||||||
memcpy(&auth_token_len,
|
memcpy(&auth_token_len,
|
||||||
client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1,
|
client_auth_packet + 4 + 4 + 4 + 1 + 23 + strlen(username) + 1,
|
||||||
@ -836,9 +840,6 @@ int gw_read_client_event(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GWBUF* errbuf;
|
|
||||||
bool succp;
|
|
||||||
|
|
||||||
modutil_send_mysql_err_packet(dcb,
|
modutil_send_mysql_err_packet(dcb,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
@ -850,7 +851,6 @@ int gw_read_client_event(
|
|||||||
"Error : Routing the query failed. "
|
"Error : Routing the query failed. "
|
||||||
"Session will be closed.")));
|
"Session will be closed.")));
|
||||||
|
|
||||||
|
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1109,7 +1109,7 @@ int gw_MySQLAccept(DCB *listener)
|
|||||||
|
|
||||||
retry_accept:
|
retry_accept:
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
if (fail_next_accept > 0)
|
if (fail_next_accept > 0)
|
||||||
{
|
{
|
||||||
c_sock = -1;
|
c_sock = -1;
|
||||||
@ -1117,16 +1117,16 @@ int gw_MySQLAccept(DCB *listener)
|
|||||||
fail_next_accept -= 1;
|
fail_next_accept -= 1;
|
||||||
} else {
|
} else {
|
||||||
fail_accept_errno = 0;
|
fail_accept_errno = 0;
|
||||||
#endif /* SS_DEBUG */
|
#endif /* FAKE_CODE */
|
||||||
// new connection from client
|
// new connection from client
|
||||||
c_sock = accept(listener->fd,
|
c_sock = accept(listener->fd,
|
||||||
(struct sockaddr *) &client_conn,
|
(struct sockaddr *) &client_conn,
|
||||||
&client_len);
|
&client_len);
|
||||||
eno = errno;
|
eno = errno;
|
||||||
errno = 0;
|
errno = 0;
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
}
|
}
|
||||||
#endif /* SS_DEBUG */
|
#endif /* FAKE_CODE */
|
||||||
|
|
||||||
if (c_sock == -1) {
|
if (c_sock == -1) {
|
||||||
|
|
||||||
@ -1363,7 +1363,6 @@ gw_client_close(DCB *dcb)
|
|||||||
SESSION* session;
|
SESSION* session;
|
||||||
ROUTER_OBJECT* router;
|
ROUTER_OBJECT* router;
|
||||||
void* router_instance;
|
void* router_instance;
|
||||||
void* rsession;
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(SS_DEBUG)
|
||||||
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
MySQLProtocol* protocol = (MySQLProtocol *)dcb->protocol;
|
||||||
if (dcb->state == DCB_STATE_POLLING ||
|
if (dcb->state == DCB_STATE_POLLING ||
|
||||||
@ -1389,13 +1388,22 @@ gw_client_close(DCB *dcb)
|
|||||||
{
|
{
|
||||||
session->state = SESSION_STATE_STOPPING;
|
session->state = SESSION_STATE_STOPPING;
|
||||||
}
|
}
|
||||||
spinlock_release(&session->ses_lock);
|
|
||||||
|
|
||||||
router = session->service->router;
|
|
||||||
router_instance = session->service->router_instance;
|
router_instance = session->service->router_instance;
|
||||||
rsession = session->router_session;
|
router = session->service->router;
|
||||||
/** Close router session and all its connections */
|
/**
|
||||||
router->closeSession(router_instance, rsession);
|
* If router session is being created concurrently router
|
||||||
|
* session might be NULL and it shouldn't be closed.
|
||||||
|
*/
|
||||||
|
if (session->router_session != NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
/** Close router session and all its connections */
|
||||||
|
router->closeSession(router_instance, session->router_session);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spinlock_release(&session->ses_lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
* x.y.z.%, x.y.%.%, x.%.%.%
|
* x.y.z.%, x.y.%.%, x.%.%.%
|
||||||
* 03/10/2014 Massimiliano Pinto Added netmask for wildcard in IPv4 hosts.
|
* 03/10/2014 Massimiliano Pinto Added netmask for wildcard in IPv4 hosts.
|
||||||
* 24/10/2014 Massimiliano Pinto Added Mysql user@host @db authentication support
|
* 24/10/2014 Massimiliano Pinto Added Mysql user@host @db authentication support
|
||||||
|
* 10/11/2014 Massimiliano Pinto Charset at connect is passed to backend during authentication
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -563,6 +564,7 @@ int gw_send_authentication_to_backend(
|
|||||||
|
|
||||||
char *curr_db = NULL;
|
char *curr_db = NULL;
|
||||||
uint8_t *curr_passwd = NULL;
|
uint8_t *curr_passwd = NULL;
|
||||||
|
unsigned int charset;
|
||||||
|
|
||||||
if (strlen(dbname))
|
if (strlen(dbname))
|
||||||
curr_db = dbname;
|
curr_db = dbname;
|
||||||
@ -574,7 +576,10 @@ int gw_send_authentication_to_backend(
|
|||||||
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
||||||
|
|
||||||
/** Copy client's flags to backend */
|
/** Copy client's flags to backend */
|
||||||
final_capabilities |= conn->client_capabilities;;
|
final_capabilities |= conn->client_capabilities;
|
||||||
|
|
||||||
|
/* get charset the client sent and use it for connection auth */
|
||||||
|
charset = conn->charset;
|
||||||
|
|
||||||
if (compress) {
|
if (compress) {
|
||||||
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
||||||
@ -668,7 +673,7 @@ int gw_send_authentication_to_backend(
|
|||||||
|
|
||||||
// set the charset
|
// set the charset
|
||||||
payload += 4;
|
payload += 4;
|
||||||
*payload = '\x08';
|
*payload = charset;
|
||||||
|
|
||||||
payload++;
|
payload++;
|
||||||
|
|
||||||
@ -768,9 +773,43 @@ int gw_do_connect_to_backend(
|
|||||||
setipaddress(&serv_addr.sin_addr, host);
|
setipaddress(&serv_addr.sin_addr, host);
|
||||||
serv_addr.sin_port = htons(port);
|
serv_addr.sin_port = htons(port);
|
||||||
bufsize = GW_BACKEND_SO_SNDBUF;
|
bufsize = GW_BACKEND_SO_SNDBUF;
|
||||||
setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
|
|
||||||
|
if(setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize)) != 0)
|
||||||
|
{
|
||||||
|
int eno = errno;
|
||||||
|
errno = 0;
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error: Failed to set socket options "
|
||||||
|
"%s:%d failed.\n\t\t Socket configuration failed "
|
||||||
|
"due %d, %s.",
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
eno,
|
||||||
|
strerror(eno))));
|
||||||
|
rv = -1;
|
||||||
|
goto return_rv;
|
||||||
|
}
|
||||||
|
|
||||||
bufsize = GW_BACKEND_SO_RCVBUF;
|
bufsize = GW_BACKEND_SO_RCVBUF;
|
||||||
setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize));
|
|
||||||
|
if(setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(bufsize)) != 0)
|
||||||
|
{
|
||||||
|
int eno = errno;
|
||||||
|
errno = 0;
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error: Failed to set socket options "
|
||||||
|
"%s:%d failed.\n\t\t Socket configuration failed "
|
||||||
|
"due %d, %s.",
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
eno,
|
||||||
|
strerror(eno))));
|
||||||
|
rv = -1;
|
||||||
|
goto return_rv;
|
||||||
|
}
|
||||||
|
|
||||||
/* set socket to as non-blocking here */
|
/* set socket to as non-blocking here */
|
||||||
setnonblocking(so);
|
setnonblocking(so);
|
||||||
rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
|
||||||
@ -1050,6 +1089,7 @@ int gw_send_change_user_to_backend(
|
|||||||
|
|
||||||
char *curr_db = NULL;
|
char *curr_db = NULL;
|
||||||
uint8_t *curr_passwd = NULL;
|
uint8_t *curr_passwd = NULL;
|
||||||
|
unsigned int charset;
|
||||||
|
|
||||||
if (strlen(dbname))
|
if (strlen(dbname))
|
||||||
curr_db = dbname;
|
curr_db = dbname;
|
||||||
@ -1062,7 +1102,10 @@ int gw_send_change_user_to_backend(
|
|||||||
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
final_capabilities = gw_mysql_get_byte4((uint8_t *)&server_capabilities);
|
||||||
|
|
||||||
/** Copy client's flags to backend */
|
/** Copy client's flags to backend */
|
||||||
final_capabilities |= conn->client_capabilities;;
|
final_capabilities |= conn->client_capabilities;
|
||||||
|
|
||||||
|
/* get charset the client sent and use it for connection auth */
|
||||||
|
charset = conn->charset;
|
||||||
|
|
||||||
if (compress) {
|
if (compress) {
|
||||||
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
final_capabilities |= GW_MYSQL_CAPABILITIES_COMPRESS;
|
||||||
@ -1188,7 +1231,7 @@ int gw_send_change_user_to_backend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the charset, 2 bytes!!!!
|
// set the charset, 2 bytes!!!!
|
||||||
*payload = '\x08';
|
*payload = charset;
|
||||||
payload++;
|
payload++;
|
||||||
*payload = '\x00';
|
*payload = '\x00';
|
||||||
payload++;
|
payload++;
|
||||||
|
@ -414,7 +414,7 @@ struct subcommand disableoptions[] = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
|
|
||||||
static void fail_backendfd(void);
|
static void fail_backendfd(void);
|
||||||
static void fail_clientfd(void);
|
static void fail_clientfd(void);
|
||||||
@ -456,7 +456,7 @@ struct subcommand failoptions[] = {
|
|||||||
{0, 0, 0}
|
{0, 0, 0}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif /* SS_DEBUG */
|
#endif /* FAKE_CODE */
|
||||||
|
|
||||||
static void telnetdAddUser(DCB *, char *, char *);
|
static void telnetdAddUser(DCB *, char *, char *);
|
||||||
/**
|
/**
|
||||||
@ -502,9 +502,9 @@ static struct {
|
|||||||
{ "clear", clearoptions },
|
{ "clear", clearoptions },
|
||||||
{ "disable", disableoptions },
|
{ "disable", disableoptions },
|
||||||
{ "enable", enableoptions },
|
{ "enable", enableoptions },
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
{ "fail", failoptions },
|
{ "fail", failoptions },
|
||||||
#endif
|
#endif /* FAKE_CODE */
|
||||||
{ "list", listoptions },
|
{ "list", listoptions },
|
||||||
{ "reload", reloadoptions },
|
{ "reload", reloadoptions },
|
||||||
{ "remove", removeoptions },
|
{ "remove", removeoptions },
|
||||||
@ -1113,7 +1113,7 @@ static void disable_log_action(DCB *dcb, char *arg1) {
|
|||||||
skygw_log_disable(type);
|
skygw_log_disable(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(SS_DEBUG)
|
#if defined(FAKE_CODE)
|
||||||
static void fail_backendfd(void)
|
static void fail_backendfd(void)
|
||||||
{
|
{
|
||||||
fail_next_backend_fd = true;
|
fail_next_backend_fd = true;
|
||||||
@ -1157,4 +1157,4 @@ static void fail_accept(
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* FAKE_CODE */
|
||||||
|
@ -828,6 +828,17 @@ static void handleError(
|
|||||||
SESSION *session = backend_dcb->session;
|
SESSION *session = backend_dcb->session;
|
||||||
session_state_t sesstate;
|
session_state_t sesstate;
|
||||||
|
|
||||||
|
/** Don't handle same error twice on same DCB */
|
||||||
|
if (backend_dcb->dcb_errhandle_called)
|
||||||
|
{
|
||||||
|
/** we optimistically assume that previous call succeed */
|
||||||
|
*succp = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backend_dcb->dcb_errhandle_called = true;
|
||||||
|
}
|
||||||
spinlock_acquire(&session->ses_lock);
|
spinlock_acquire(&session->ses_lock);
|
||||||
sesstate = session->state;
|
sesstate = session->state;
|
||||||
client_dcb = session->client;
|
client_dcb = session->client;
|
||||||
|
@ -830,8 +830,16 @@ static void* newSession(
|
|||||||
* Find a backend servers to connect to.
|
* Find a backend servers to connect to.
|
||||||
* This command requires that rsession's lock is held.
|
* This command requires that rsession's lock is held.
|
||||||
*/
|
*/
|
||||||
rses_begin_locked_router_action(client_rses);
|
|
||||||
|
|
||||||
|
succp = rses_begin_locked_router_action(client_rses);
|
||||||
|
|
||||||
|
if(!succp)
|
||||||
|
{
|
||||||
|
free(client_rses->rses_backend_ref);
|
||||||
|
free(client_rses);
|
||||||
|
client_rses = NULL;
|
||||||
|
goto return_rses;
|
||||||
|
}
|
||||||
succp = select_connect_backend_servers(&master_ref,
|
succp = select_connect_backend_servers(&master_ref,
|
||||||
backend_ref,
|
backend_ref,
|
||||||
router_nservers,
|
router_nservers,
|
||||||
@ -1029,6 +1037,9 @@ static void freeSession(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide the router with a pointer to a suitable backend dcb.
|
* Provide the router with a pointer to a suitable backend dcb.
|
||||||
|
*
|
||||||
|
* As of Nov. 2014, slave which has least connections is always chosen.
|
||||||
|
*
|
||||||
* Detect failures in server statuses and reselect backends if necessary.
|
* Detect failures in server statuses and reselect backends if necessary.
|
||||||
* If name is specified, server name becomes primary selection criteria.
|
* If name is specified, server name becomes primary selection criteria.
|
||||||
*
|
*
|
||||||
@ -1610,8 +1621,12 @@ void check_create_tmp_table(
|
|||||||
rses_prop_tmp->rses_prop_type = RSES_PROP_TYPE_TMPTABLES;
|
rses_prop_tmp->rses_prop_type = RSES_PROP_TYPE_TMPTABLES;
|
||||||
router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES] = rses_prop_tmp;
|
router_cli_ses->rses_properties[RSES_PROP_TYPE_TMPTABLES] = rses_prop_tmp;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,"Error : Call to malloc() failed.")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if(rses_prop_tmp){
|
||||||
if (rses_prop_tmp->rses_prop_data.temp_tables == NULL)
|
if (rses_prop_tmp->rses_prop_data.temp_tables == NULL)
|
||||||
{
|
{
|
||||||
h = hashtable_alloc(7, hashkeyfun, hashcmpfun);
|
h = hashtable_alloc(7, hashkeyfun, hashcmpfun);
|
||||||
@ -1619,10 +1634,13 @@ void check_create_tmp_table(
|
|||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
{
|
{
|
||||||
rses_prop_tmp->rses_prop_data.temp_tables = h;
|
rses_prop_tmp->rses_prop_data.temp_tables = h;
|
||||||
}
|
}else{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,"Error : Failed to allocate a new hashtable.")));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hkey &&
|
if (hkey && rses_prop_tmp->rses_prop_data.temp_tables &&
|
||||||
hashtable_add(rses_prop_tmp->rses_prop_data.temp_tables,
|
hashtable_add(rses_prop_tmp->rses_prop_data.temp_tables,
|
||||||
(void *)hkey,
|
(void *)hkey,
|
||||||
(void *)is_temp) == 0) /*< Conflict in hash table */
|
(void *)is_temp) == 0) /*< Conflict in hash table */
|
||||||
@ -1647,6 +1665,8 @@ void check_create_tmp_table(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
free(hkey);
|
free(hkey);
|
||||||
free(tblname);
|
free(tblname);
|
||||||
}
|
}
|
||||||
@ -2074,14 +2094,11 @@ static int routeQuery(
|
|||||||
"route to master "
|
"route to master "
|
||||||
"but couldn't find "
|
"but couldn't find "
|
||||||
"master in a "
|
"master in a "
|
||||||
"suitable state "
|
"suitable state.")));
|
||||||
"failed.")));
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Master has changed. Set the dcb pointer NULL and
|
* Master has changed. Return with error indicator.
|
||||||
* return with error indicator.
|
|
||||||
*/
|
*/
|
||||||
router_cli_ses->rses_master_ref->bref_dcb = NULL;
|
|
||||||
rses_end_locked_router_action(router_cli_ses);
|
rses_end_locked_router_action(router_cli_ses);
|
||||||
succp = false;
|
succp = false;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -2655,7 +2672,7 @@ static bool select_connect_backend_servers(
|
|||||||
const int min_nslaves = 0; /*< not configurable at the time */
|
const int min_nslaves = 0; /*< not configurable at the time */
|
||||||
bool is_synced_master;
|
bool is_synced_master;
|
||||||
int (*p)(const void *, const void *);
|
int (*p)(const void *, const void *);
|
||||||
BACKEND* master_host = NULL;
|
BACKEND* master_host;
|
||||||
|
|
||||||
if (p_master_ref == NULL || backend_ref == NULL)
|
if (p_master_ref == NULL || backend_ref == NULL)
|
||||||
{
|
{
|
||||||
@ -2667,46 +2684,32 @@ static bool select_connect_backend_servers(
|
|||||||
/* get the root Master */
|
/* get the root Master */
|
||||||
master_host = get_root_master(backend_ref, router_nservers);
|
master_host = get_root_master(backend_ref, router_nservers);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Master is already chosen and connected. It means that the function
|
* Existing session : master is already chosen and connected.
|
||||||
* was called from error handling function or from some other similar
|
* The function was called because new slave must be selected to replace
|
||||||
* function where session was already established but new slaves needed
|
* failed one.
|
||||||
* to be selected.
|
|
||||||
*/
|
*/
|
||||||
if (*p_master_ref != NULL &&
|
if (*p_master_ref != NULL)
|
||||||
BREF_IS_IN_USE((*p_master_ref)))
|
{
|
||||||
{
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [select_connect_backend_servers] Master %p fd %d found.",
|
|
||||||
pthread_self(),
|
|
||||||
(*p_master_ref)->bref_dcb,
|
|
||||||
(*p_master_ref)->bref_dcb->fd)));
|
|
||||||
|
|
||||||
master_found = true;
|
|
||||||
master_connected = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure that *p_master_ref and master_host point to same backend
|
* Ensure that backend reference is in use, stored master is
|
||||||
* and it has a master role.
|
* still current root master.
|
||||||
*/
|
*/
|
||||||
ss_dassert(master_host &&
|
if (!BREF_IS_IN_USE((*p_master_ref)) ||
|
||||||
((*p_master_ref)->bref_backend->backend_server ==
|
!SERVER_IS_MASTER((*p_master_ref)->bref_backend->backend_server) ||
|
||||||
master_host->backend_server) &&
|
master_host != (*p_master_ref)->bref_backend)
|
||||||
(master_host->backend_server->status &
|
{
|
||||||
(SERVER_MASTER|SERVER_MAINT)) == SERVER_MASTER);
|
succp = false;
|
||||||
}
|
goto return_succp;
|
||||||
/** New session or master failure case */
|
}
|
||||||
|
master_found = true;
|
||||||
|
master_connected = true;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* New session : select master and slaves
|
||||||
|
*/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGIF(LD, (skygw_log_write(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [select_connect_backend_servers] Session %p doesn't "
|
|
||||||
"currently have a master chosen. Proceeding to master "
|
|
||||||
"selection.",
|
|
||||||
pthread_self(),
|
|
||||||
session)));
|
|
||||||
|
|
||||||
master_found = false;
|
master_found = false;
|
||||||
master_connected = false;
|
master_connected = false;
|
||||||
}
|
}
|
||||||
@ -2745,11 +2748,6 @@ static bool select_connect_backend_servers(
|
|||||||
b->backend_conn_count)));
|
b->backend_conn_count)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* assert with master_host */
|
|
||||||
ss_dassert(!master_connected ||
|
|
||||||
(master_host &&
|
|
||||||
((*p_master_ref)->bref_backend->backend_server == master_host->backend_server) &&
|
|
||||||
SERVER_MASTER));
|
|
||||||
/**
|
/**
|
||||||
* Sort the pointer list to servers according to connection counts. As
|
* Sort the pointer list to servers according to connection counts. As
|
||||||
* a consequence those backends having least connections are in the
|
* a consequence those backends having least connections are in the
|
||||||
@ -2840,8 +2838,10 @@ static bool select_connect_backend_servers(
|
|||||||
(max_slave_rlag == MAX_RLAG_UNDEFINED ||
|
(max_slave_rlag == MAX_RLAG_UNDEFINED ||
|
||||||
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
(b->backend_server->rlag != MAX_RLAG_NOT_AVAILABLE &&
|
||||||
b->backend_server->rlag <= max_slave_rlag)) &&
|
b->backend_server->rlag <= max_slave_rlag)) &&
|
||||||
(SERVER_IS_SLAVE(b->backend_server) || SERVER_IS_RELAY_SERVER(b->backend_server)) &&
|
(SERVER_IS_SLAVE(b->backend_server) ||
|
||||||
(master_host != NULL && (b->backend_server != master_host->backend_server)))
|
SERVER_IS_RELAY_SERVER(b->backend_server)) &&
|
||||||
|
(master_host != NULL &&
|
||||||
|
(b->backend_server != master_host->backend_server)))
|
||||||
{
|
{
|
||||||
slaves_found += 1;
|
slaves_found += 1;
|
||||||
|
|
||||||
@ -2903,6 +2903,12 @@ static bool select_connect_backend_servers(
|
|||||||
else if (master_host &&
|
else if (master_host &&
|
||||||
(b->backend_server == master_host->backend_server))
|
(b->backend_server == master_host->backend_server))
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* *p_master_ref must be assigned with this
|
||||||
|
* backend_ref pointer because its original value
|
||||||
|
* may have been lost when backend references were
|
||||||
|
* sorted (qsort).
|
||||||
|
*/
|
||||||
*p_master_ref = &backend_ref[i];
|
*p_master_ref = &backend_ref[i];
|
||||||
|
|
||||||
if (master_connected)
|
if (master_connected)
|
||||||
@ -4072,7 +4078,6 @@ static void rwsplit_process_router_options(
|
|||||||
* Even if succp == true connecting to new slave may have failed. succp is to
|
* Even if succp == true connecting to new slave may have failed. succp is to
|
||||||
* tell whether router has enough master/slave connections to continue work.
|
* tell whether router has enough master/slave connections to continue work.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void handleError (
|
static void handleError (
|
||||||
ROUTER* instance,
|
ROUTER* instance,
|
||||||
void* router_session,
|
void* router_session,
|
||||||
@ -4086,10 +4091,17 @@ static void handleError (
|
|||||||
ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES *)router_session;
|
ROUTER_CLIENT_SES* rses = (ROUTER_CLIENT_SES *)router_session;
|
||||||
|
|
||||||
CHK_DCB(backend_dcb);
|
CHK_DCB(backend_dcb);
|
||||||
#if defined(SS_DEBUG)
|
/** Don't handle same error twice on same DCB */
|
||||||
ss_dassert(!backend_dcb->dcb_errhandle_called);
|
if (backend_dcb->dcb_errhandle_called)
|
||||||
backend_dcb->dcb_errhandle_called = true;
|
{
|
||||||
#endif
|
/** we optimistically assume that previous call succeed */
|
||||||
|
*succp = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backend_dcb->dcb_errhandle_called = true;
|
||||||
|
}
|
||||||
session = backend_dcb->session;
|
session = backend_dcb->session;
|
||||||
|
|
||||||
if (session != NULL)
|
if (session != NULL)
|
||||||
@ -4107,7 +4119,8 @@ static void handleError (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rses->rses_master_ref->bref_dcb == backend_dcb)
|
if (rses->rses_master_ref->bref_dcb == backend_dcb &&
|
||||||
|
!SERVER_IS_MASTER(rses->rses_master_ref->bref_backend->backend_server))
|
||||||
{
|
{
|
||||||
/** Master failed, can't recover */
|
/** Master failed, can't recover */
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
@ -4206,6 +4219,11 @@ static bool handle_error_new_connection(
|
|||||||
}
|
}
|
||||||
CHK_BACKEND_REF(bref);
|
CHK_BACKEND_REF(bref);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If query was sent through the bref and it is waiting for reply from
|
||||||
|
* the backend server it is necessary to send an error to the client
|
||||||
|
* because it is waiting for reply.
|
||||||
|
*/
|
||||||
if (BREF_IS_WAITING_RESULT(bref))
|
if (BREF_IS_WAITING_RESULT(bref))
|
||||||
{
|
{
|
||||||
DCB* client_dcb;
|
DCB* client_dcb;
|
||||||
@ -4473,6 +4491,10 @@ static backend_ref_t* get_bref_from_dcb(
|
|||||||
return bref;
|
return bref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls hang-up function for DCB if it is not both running and in
|
||||||
|
* master/slave/joined/ndb role. Called by DCB's callback routine.
|
||||||
|
*/
|
||||||
static int router_handle_state_switch(
|
static int router_handle_state_switch(
|
||||||
DCB* dcb,
|
DCB* dcb,
|
||||||
DCB_REASON reason,
|
DCB_REASON reason,
|
||||||
@ -4513,6 +4535,7 @@ return_rc:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static sescmd_cursor_t* backend_ref_get_sescmd_cursor (
|
static sescmd_cursor_t* backend_ref_get_sescmd_cursor (
|
||||||
backend_ref_t* bref)
|
backend_ref_t* bref)
|
||||||
{
|
{
|
||||||
@ -4634,7 +4657,7 @@ static BACKEND *get_root_master(
|
|||||||
* Servers are checked even if they are in 'maintenance'
|
* Servers are checked even if they are in 'maintenance'
|
||||||
*
|
*
|
||||||
* @param rses pointer to router session
|
* @param rses pointer to router session
|
||||||
* @return pointer to backend reference of the root master
|
* @return pointer to backend reference of the root master or NULL
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static backend_ref_t* get_root_master_bref(
|
static backend_ref_t* get_root_master_bref(
|
||||||
@ -4664,6 +4687,14 @@ static backend_ref_t* get_root_master_bref(
|
|||||||
bref++;
|
bref++;
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
if (candidate_bref == NULL)
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"Error : Could not find master among the backend "
|
||||||
|
"servers. Previous master state : %s",
|
||||||
|
STRSRVSTATUS(BREFSRV(rses->rses_master_ref)))));
|
||||||
|
}
|
||||||
return candidate_bref;
|
return candidate_bref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
if(MYSQLCLIENT_FOUND)
|
if(MYSQLCLIENT_FOUND)
|
||||||
add_executable(testconnect testconnect.c)
|
add_executable(testconnect testconnect.c)
|
||||||
message(STATUS "Linking against: ${MYSQLCLIENT_LIBRARIES}")
|
message(STATUS "Linking against: ${MYSQLCLIENT_LIBRARIES}")
|
||||||
target_link_libraries(testconnect ${MYSQLCLIENT_LIBRARIES} ssl crypto dl z m)
|
target_link_libraries(testconnect ${MYSQLCLIENT_LIBRARIES} ssl crypto dl z m rt pthread)
|
||||||
add_test(NAME ReadConnRouterLoginTest COMMAND $<TARGET_FILE:testconnect> 10000 ${TEST_HOST} ${MASTER_PORT} ${TEST_HOST} ${TEST_PORT} 1.10)
|
add_test(NAME ReadConnRouterLoginTest COMMAND $<TARGET_FILE:testconnect> 10000 ${TEST_HOST} ${MASTER_PORT} ${TEST_HOST} ${TEST_PORT} 1.10)
|
||||||
endif()
|
endif()
|
@ -4,24 +4,40 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
MYSQL* server;
|
MYSQL* server;
|
||||||
char *host;
|
char *host = NULL, *str_baseline = NULL,*str_test = NULL, *errmsg = NULL;
|
||||||
unsigned int port;
|
unsigned int port;
|
||||||
int rval, iterations,i;
|
int rval, iterations,i;
|
||||||
clock_t begin,end;
|
clock_t begin,end;
|
||||||
double baseline,test, ratio, result, minimum;
|
size_t offset;
|
||||||
|
struct timeval real_begin,real_end,real_baseline,real_test;
|
||||||
|
time_t time;
|
||||||
|
double baseline, test, ratio, result;
|
||||||
|
|
||||||
if(argc < 7){
|
if(argc < 7){
|
||||||
fprintf(stderr,"Usage: %s <iterations> <baseline host> <baseline port> <test host> <test port> <max result ratio>\n",argv[0]);
|
fprintf(stderr,"Usage: %s <iterations> <baseline host> <baseline port> <test host> <test port> <max result ratio>\n",argv[0]);
|
||||||
fprintf(stderr,"The ratio is measured as:\ntest CPU time / baseline CPU time\n");
|
fprintf(stderr,"The ratio is measured as:\ntest time / baseline time\n");
|
||||||
fprintf(stderr,"The test fails if this ratio is exceeded.\n");
|
fprintf(stderr,"The test fails if this ratio is exceeded.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
if((str_baseline = calloc(256,sizeof(char))) == NULL){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((str_test = calloc(256,sizeof(char))) == NULL){
|
||||||
|
free(str_baseline);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
iterations = atoi(argv[1]);
|
iterations = atoi(argv[1]);
|
||||||
host = strdup(argv[2]);
|
host = strdup(argv[2]);
|
||||||
port = atoi(argv[3]);
|
port = atoi(argv[3]);
|
||||||
@ -35,24 +51,36 @@ int main(int argc, char** argv)
|
|||||||
/**Testing direct connection to master*/
|
/**Testing direct connection to master*/
|
||||||
|
|
||||||
printf("Connecting to MySQL server through %s:%d.\n",host,port);
|
printf("Connecting to MySQL server through %s:%d.\n",host,port);
|
||||||
|
gettimeofday(&real_begin,NULL);
|
||||||
begin = clock();
|
begin = clock();
|
||||||
|
|
||||||
|
if((server = mysql_init(NULL)) == NULL){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_real_connect(server,host,"maxuser","maxpwd",NULL,port,NULL,0) == NULL){
|
||||||
|
rval = 1;
|
||||||
|
printf( "Failed to connect to database: Error: %s\n",
|
||||||
|
mysql_error(server));
|
||||||
|
goto report;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0;i<iterations;i++)
|
for(i = 0;i<iterations;i++)
|
||||||
{
|
{
|
||||||
if((server = mysql_init(NULL)) == NULL){
|
if(mysql_change_user(server,"maxuser","maxpwd",NULL)){
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(mysql_real_connect(server,host,"maxuser","maxpwd",NULL,port,NULL,0) == NULL){
|
|
||||||
fprintf(stderr, "Failed to connect to database: Error: %s\n",
|
|
||||||
mysql_error(server));
|
|
||||||
rval = 1;
|
rval = 1;
|
||||||
break;
|
printf( "Failed to change user: Error: %s\n",
|
||||||
|
mysql_error(server));
|
||||||
|
goto report;
|
||||||
}
|
}
|
||||||
mysql_close(server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mysql_close(server);
|
||||||
|
|
||||||
end = clock();
|
end = clock();
|
||||||
|
gettimeofday(&real_end,NULL);
|
||||||
baseline = (double)(end - begin)/CLOCKS_PER_SEC;
|
baseline = (double)(end - begin)/CLOCKS_PER_SEC;
|
||||||
|
timersub(&real_end,&real_begin,&real_baseline);
|
||||||
|
|
||||||
free(host);
|
free(host);
|
||||||
host = strdup(argv[4]);
|
host = strdup(argv[4]);
|
||||||
@ -61,37 +89,73 @@ int main(int argc, char** argv)
|
|||||||
/**Testing connection to master through MaxScale*/
|
/**Testing connection to master through MaxScale*/
|
||||||
|
|
||||||
printf("Connecting to MySQL server through %s:%d.\n",host,port);
|
printf("Connecting to MySQL server through %s:%d.\n",host,port);
|
||||||
|
gettimeofday(&real_begin,NULL);
|
||||||
begin = clock();
|
begin = clock();
|
||||||
|
|
||||||
|
if((server = mysql_init(NULL)) == NULL){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_real_connect(server,host,"maxuser","maxpwd",NULL,port,NULL,0) == NULL){
|
||||||
|
rval = 1;
|
||||||
|
printf("Failed to connect to database: Error: %s\n",
|
||||||
|
mysql_error(server));
|
||||||
|
goto report;
|
||||||
|
}
|
||||||
|
|
||||||
for(i = 0;i<iterations;i++)
|
for(i = 0;i<iterations;i++)
|
||||||
{
|
{
|
||||||
if((server = mysql_init(NULL)) == NULL){
|
if(mysql_change_user(server,"maxuser","maxpwd",NULL)){
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(mysql_real_connect(server,host,"maxuser","maxpwd",NULL,port,NULL,0) == NULL){
|
|
||||||
rval = 1;
|
rval = 1;
|
||||||
fprintf(stderr, "Failed to connect to database: Error: %s\n",
|
printf("Failed to change user: Error: %s\n",
|
||||||
mysql_error(server));
|
mysql_error(server));
|
||||||
break;
|
goto report;
|
||||||
}
|
}
|
||||||
mysql_close(server);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mysql_close(server);
|
||||||
|
|
||||||
end = clock();
|
end = clock();
|
||||||
|
gettimeofday(&real_end,NULL);
|
||||||
|
|
||||||
test = (double)(end - begin)/CLOCKS_PER_SEC;
|
test = (double)(end - begin)/CLOCKS_PER_SEC;
|
||||||
|
timersub(&real_end,&real_begin,&real_test);
|
||||||
|
|
||||||
printf("CPU time used in seconds:\nDirect connection: %f\nThrough MaxScale: %f\n",baseline,test);
|
report:
|
||||||
|
|
||||||
result = test / baseline;
|
|
||||||
if(rval){
|
if(rval){
|
||||||
printf("Test failed: Errors during test run.");
|
|
||||||
}else if(result > ratio){
|
|
||||||
printf("Test failed: CPU time ratio was %f which exceeded the limit of %f.\n", result, ratio);
|
|
||||||
rval = 1;
|
|
||||||
}else{
|
|
||||||
printf("Test passed: CPU time ratio was %f.\n",result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
printf("\nTest failed: Errors during test run.\n");
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
struct tm *tm;
|
||||||
|
time = real_baseline.tv_sec;
|
||||||
|
tm = localtime(&time);
|
||||||
|
offset = strftime(str_baseline,256*sizeof(char),"%S",tm);
|
||||||
|
sprintf(str_baseline + offset,".%06d",(int)real_baseline.tv_usec);
|
||||||
|
time = real_test.tv_sec;
|
||||||
|
tm = localtime(&time);
|
||||||
|
offset = strftime(str_test,256*sizeof(char),"%S",tm);
|
||||||
|
sprintf(str_test + offset,".%06d",(int)real_test.tv_usec);
|
||||||
|
|
||||||
|
printf("\n\tCPU time in seconds\n\nDirect connection: %f\nThrough MaxScale: %f\n",baseline,test);
|
||||||
|
printf("\n\tReal time in seconds\n\nDirect connection: %s\nThrough MaxScale: %s\n",str_baseline,str_test);
|
||||||
|
|
||||||
|
double base_res = real_baseline.tv_sec + (real_baseline.tv_usec / 1000000.0);
|
||||||
|
double test_res = real_test.tv_sec + (real_test.tv_usec / 1000000.0);
|
||||||
|
result = test_res/base_res;
|
||||||
|
|
||||||
|
if(result > ratio){
|
||||||
|
printf("\nTest failed: Time ratio was %f which exceeded the limit of %f.\n", result, ratio);
|
||||||
|
rval = 1;
|
||||||
|
}else{
|
||||||
|
printf("\nTest passed: Time ratio was %f.\n",result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(str_baseline);
|
||||||
|
free(str_test);
|
||||||
free(host);
|
free(host);
|
||||||
|
free(errmsg);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
@ -263,6 +263,9 @@ typedef enum skygw_chk_t {
|
|||||||
(SERVER_IS_RELAY_SERVER(s) ? "RUNNING RELAY" : \
|
(SERVER_IS_RELAY_SERVER(s) ? "RUNNING RELAY" : \
|
||||||
(SERVER_IS_RUNNING(s) ? "RUNNING (only)" : "NO STATUS")))))))
|
(SERVER_IS_RUNNING(s) ? "RUNNING (only)" : "NO STATUS")))))))
|
||||||
|
|
||||||
|
#define BREFSRV(b) (b->bref_backend->backend_server)
|
||||||
|
|
||||||
|
|
||||||
#define STRHINTTYPE(t) (t == HINT_ROUTE_TO_MASTER ? "HINT_ROUTE_TO_MASTER" : \
|
#define STRHINTTYPE(t) (t == HINT_ROUTE_TO_MASTER ? "HINT_ROUTE_TO_MASTER" : \
|
||||||
((t) == HINT_ROUTE_TO_SLAVE ? "HINT_ROUTE_TO_SLAVE" : \
|
((t) == HINT_ROUTE_TO_SLAVE ? "HINT_ROUTE_TO_SLAVE" : \
|
||||||
((t) == HINT_ROUTE_TO_NAMED_SERVER ? "HINT_ROUTE_TO_NAMED_SERVER" : \
|
((t) == HINT_ROUTE_TO_NAMED_SERVER ? "HINT_ROUTE_TO_NAMED_SERVER" : \
|
||||||
|
@ -1749,14 +1749,23 @@ return_succp:
|
|||||||
return succp;
|
return succp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
bool skygw_file_write(
|
* Write data to a file.
|
||||||
|
*
|
||||||
|
* @param file write target
|
||||||
|
* @param data pointer to contiguous memory buffer
|
||||||
|
* @param nbytes amount of bytes to be written
|
||||||
|
* @param flush ensure that write is permanent
|
||||||
|
*
|
||||||
|
* @return 0 if succeed, errno if failed.
|
||||||
|
*/
|
||||||
|
int skygw_file_write(
|
||||||
skygw_file_t* file,
|
skygw_file_t* file,
|
||||||
void* data,
|
void* data,
|
||||||
size_t nbytes,
|
size_t nbytes,
|
||||||
bool flush)
|
bool flush)
|
||||||
{
|
{
|
||||||
bool succp = false;
|
int rc;
|
||||||
#if !defined(LAPTOP_TEST)
|
#if !defined(LAPTOP_TEST)
|
||||||
int err = 0;
|
int err = 0;
|
||||||
size_t nwritten;
|
size_t nwritten;
|
||||||
@ -1771,13 +1780,14 @@ bool skygw_file_write(
|
|||||||
nwritten = fwrite(data, nbytes, 1, file->sf_file);
|
nwritten = fwrite(data, nbytes, 1, file->sf_file);
|
||||||
|
|
||||||
if (nwritten != 1) {
|
if (nwritten != 1) {
|
||||||
|
rc = errno;
|
||||||
perror("Logfile write.\n");
|
perror("Logfile write.\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"* Writing %ld bytes, %s to %s failed.\n",
|
"* Writing %ld bytes,\n%s\n to %s failed.\n",
|
||||||
nbytes,
|
nbytes,
|
||||||
(char *)data,
|
(char *)data,
|
||||||
file->sf_fname);
|
file->sf_fname);
|
||||||
goto return_succp;
|
goto return_rc;
|
||||||
}
|
}
|
||||||
writecount += 1;
|
writecount += 1;
|
||||||
|
|
||||||
@ -1789,10 +1799,10 @@ bool skygw_file_write(
|
|||||||
writecount = 0;
|
writecount = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
succp = true;
|
rc = 0;
|
||||||
CHK_FILE(file);
|
CHK_FILE(file);
|
||||||
return_succp:
|
return_rc:
|
||||||
return succp;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
skygw_file_t* skygw_file_init(
|
skygw_file_t* skygw_file_init(
|
||||||
|
@ -146,7 +146,7 @@ EXTERN_C_BLOCK_END
|
|||||||
/** Skygw file routines */
|
/** Skygw file routines */
|
||||||
skygw_file_t* skygw_file_init(char* fname, char* symlinkname);
|
skygw_file_t* skygw_file_init(char* fname, char* symlinkname);
|
||||||
void skygw_file_done(skygw_file_t* file);
|
void skygw_file_done(skygw_file_t* file);
|
||||||
bool skygw_file_write(
|
int skygw_file_write(
|
||||||
skygw_file_t* file,
|
skygw_file_t* file,
|
||||||
void* data,
|
void* data,
|
||||||
size_t nbytes,
|
size_t nbytes,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user