log_manager.cc:
State update for filewriter was missing and that caused Maxscale to fail if opening of any log file failed. dcb.c: Added EAGAIN and EWOULDBLOCK handling to dcb_read. If dcb_close is called for freshly created dcb, dcb is only freed. gateway.c: Added file_write_footer and write_footer of which the latter is called at exit time. It simply draws a line to screen. gw_utils.c: Some macros for helping comparison between gw_read_gwbuff and dcb_read, which overlap. poll.c: Some macros to help enable/disable mutexing in poll_waitevents service.c: Check return value of listen and session_alloc and behave accordingly. mysql_client.c: If ioctl returned successfully with b==0 it earlier caused closing the client and backend dcbs. Since that doesn't reliably indicate that client has closed socket on its side, Maxscale doesn't close its sockets either. mysql_common.c: In gw_receive_backend_auth, if dcb_read returns n==0, it is not considered as an error anymore. The implemented behavior is not yet complete and correct. Result should be successful but the protocol state shouldn't change to MYSQL_IDLE before backend return is received. In gw_send_authentication_to_backend protocol state was always set to MYSQL_AUTH_RECV even if gw_rwite had failed. Now, return value is read and state is set in caller's context basen on the return value. skygw_utils.cc: Removed ss_dassert from skyge_file_init because it prevented from returning meaningful error meassage to the client.:
This commit is contained in:
@ -210,6 +210,7 @@ dcb_add_to_zombieslist(DCB *dcb)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Free a DCB and remove it from the chain of all DCBs
|
||||
*
|
||||
@ -221,8 +222,6 @@ dcb_add_to_zombieslist(DCB *dcb)
|
||||
static void
|
||||
dcb_final_free(DCB *dcb)
|
||||
{
|
||||
SERVICE *service;
|
||||
void* rsession = NULL;
|
||||
CHK_DCB(dcb);
|
||||
ss_info_dassert(dcb->state == DCB_STATE_DISCONNECTED,
|
||||
"dcb not in DCB_STATE_DISCONNECTED state.");
|
||||
@ -542,9 +541,9 @@ int eno = 0;
|
||||
while (true)
|
||||
{
|
||||
int bufsize;
|
||||
|
||||
|
||||
rc = ioctl(dcb->fd, FIONREAD, &b);
|
||||
|
||||
|
||||
if (rc == -1) {
|
||||
eno = errno;
|
||||
errno = 0;
|
||||
@ -562,7 +561,7 @@ int eno = 0;
|
||||
}
|
||||
/** Nothing to read - leave */
|
||||
if (b == 0) {
|
||||
n = 0;
|
||||
n = 0;
|
||||
goto return_n;
|
||||
}
|
||||
bufsize = MIN(b, MAX_BUFFER_SIZE);
|
||||
@ -593,20 +592,21 @@ int eno = 0;
|
||||
{
|
||||
int eno = errno;
|
||||
errno = 0;
|
||||
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Read failed, dcb %p in state %s "
|
||||
"fd %d, due %d, %s.",
|
||||
dcb,
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
eno,
|
||||
strerror(eno));
|
||||
|
||||
if (eno != EAGAIN && eno != EWOULDBLOCK) {
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Read failed, dcb %p in state "
|
||||
"%s fd %d, due %d, %s.",
|
||||
dcb,
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd,
|
||||
eno,
|
||||
strerror(eno));
|
||||
}
|
||||
gwbuf_free(buffer);
|
||||
goto return_n;
|
||||
}
|
||||
|
||||
skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
"%lu [dcb_read] Read %d bytes from dcb %p in state %s "
|
||||
@ -638,7 +638,7 @@ int w, saved_errno = 0;
|
||||
ss_dassert(queue != NULL);
|
||||
spinlock_acquire(&dcb->writeqlock);
|
||||
|
||||
if (dcb->writeq)
|
||||
if (dcb->writeq != NULL)
|
||||
{
|
||||
/*
|
||||
* We have some queued data, so add our data to
|
||||
@ -677,26 +677,24 @@ int w, saved_errno = 0;
|
||||
if (dcb->dcb_role == DCB_ROLE_REQUEST_HANDLER &&
|
||||
dcb->session != NULL)
|
||||
{
|
||||
if (dcb_isclient(dcb)) {
|
||||
if (fail_next_client_fd) {
|
||||
dcb_fake_write_errno[dcb->fd] = 32;
|
||||
dcb_fake_write_ev[dcb->fd] = 29;
|
||||
fail_next_client_fd = false;
|
||||
}
|
||||
} else {
|
||||
if (fail_next_backend_fd) {
|
||||
dcb_fake_write_errno[dcb->fd] = 32;
|
||||
dcb_fake_write_ev[dcb->fd] = 29;
|
||||
fail_next_backend_fd = false;
|
||||
}
|
||||
if (dcb_isclient(dcb) && fail_next_client_fd) {
|
||||
dcb_fake_write_errno[dcb->fd] = 32;
|
||||
dcb_fake_write_ev[dcb->fd] = 29;
|
||||
fail_next_client_fd = false;
|
||||
} else if (!dcb_isclient(dcb) &&
|
||||
fail_next_backend_fd)
|
||||
{
|
||||
dcb_fake_write_errno[dcb->fd] = 32;
|
||||
dcb_fake_write_ev[dcb->fd] = 29;
|
||||
fail_next_backend_fd = false;
|
||||
}
|
||||
}
|
||||
#endif /* SS_DEBUG */
|
||||
len = GWBUF_LENGTH(queue);
|
||||
GW_NOINTR_CALL(w = gw_write(dcb->fd,
|
||||
GWBUF_DATA(queue),
|
||||
len);
|
||||
dcb->stats.n_writes++);
|
||||
GW_NOINTR_CALL(
|
||||
w = gw_write(dcb->fd, GWBUF_DATA(queue), len);
|
||||
dcb->stats.n_writes++;
|
||||
);
|
||||
saved_errno = errno;
|
||||
errno = 0;
|
||||
|
||||
@ -728,7 +726,6 @@ int w, saved_errno = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pull the number of bytes we have written from
|
||||
* queue with have.
|
||||
@ -757,12 +754,10 @@ int w, saved_errno = 0;
|
||||
{
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Writing to dcb %p in state %s fd %d "
|
||||
"failed.",
|
||||
dcb,
|
||||
STRDCBSTATE(dcb->state),
|
||||
dcb->fd);
|
||||
/* We had a real write failure that we must deal with */
|
||||
"Error : Writing to %s socket failed due %d, %s.",
|
||||
dcb_isclient(dcb) ? "client" : "backend server",
|
||||
saved_errno,
|
||||
strerror(saved_errno));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@ -859,6 +854,16 @@ dcb_close(DCB *dcb)
|
||||
int rc;
|
||||
CHK_DCB(dcb);
|
||||
|
||||
/**
|
||||
* dcb_close may be called for freshly created dcb, in which case
|
||||
* it only needs to be freed.
|
||||
*/
|
||||
if (dcb->state == DCB_STATE_ALLOC) {
|
||||
dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
|
||||
dcb_final_free(dcb);
|
||||
return;
|
||||
}
|
||||
|
||||
ss_dassert(dcb->state == DCB_STATE_POLLING ||
|
||||
dcb->state == DCB_STATE_NOPOLLING ||
|
||||
dcb->state == DCB_STATE_ZOMBIE);
|
||||
|
||||
@ -98,6 +98,9 @@ static void log_flush_shutdown(void);
|
||||
static void log_flush_cb(void* arg);
|
||||
static void libmysqld_done(void);
|
||||
static bool file_write_header(FILE* outfile);
|
||||
static bool file_write_footer(FILE* outfile);
|
||||
static void write_footer(void);
|
||||
|
||||
/**
|
||||
* Handler for SIGHUP signal. Reload the configuration for the
|
||||
* gateway.
|
||||
@ -211,7 +214,28 @@ return_home:
|
||||
}
|
||||
#endif
|
||||
|
||||
static void write_footer(void)
|
||||
{
|
||||
file_write_footer(stdout);
|
||||
}
|
||||
|
||||
static bool file_write_footer(
|
||||
FILE* outfile)
|
||||
{
|
||||
bool succp = false;
|
||||
size_t wbytes1;
|
||||
size_t len1;
|
||||
const char* header_buf1;
|
||||
|
||||
header_buf1 = "------------------------------------------------------"
|
||||
"\n\n";
|
||||
len1 = strlen(header_buf1);
|
||||
wbytes1=fwrite((void*)header_buf1, len1, 1, outfile);
|
||||
|
||||
succp = true;
|
||||
|
||||
return succp;
|
||||
}
|
||||
static bool file_write_header(
|
||||
FILE* outfile)
|
||||
{
|
||||
@ -303,10 +327,11 @@ main(int argc, char **argv)
|
||||
l = atexit(skygw_logmanager_exit);
|
||||
|
||||
if (l != 0) {
|
||||
fprintf(stderr, "Couldn't register exit function.\n");
|
||||
fprintf(stderr, "* Couldn't register exit function.\n");
|
||||
}
|
||||
atexit(datadir_cleanup);
|
||||
|
||||
atexit(write_footer);
|
||||
|
||||
for (n = 0; n < argc; n++)
|
||||
{
|
||||
if (strcmp(argv[n], "-d") == 0)
|
||||
@ -327,8 +352,8 @@ main(int argc, char **argv)
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Fatal : Unable to find a MaxScale "
|
||||
"configuration file, either install one in "
|
||||
"/etc/MaxScale.cnf, "
|
||||
"configuration file, either install one "
|
||||
"in /etc/MaxScale.cnf, "
|
||||
"$MAXSCALE_HOME/etc/MaxScale.cnf "
|
||||
"or use the -c option. Exiting.");
|
||||
}
|
||||
@ -469,7 +494,7 @@ main(int argc, char **argv)
|
||||
"file, either install one in /etc/MaxScale.cnf, "
|
||||
"$MAXSCALE_HOME/etc/MaxScale.cnf "
|
||||
"or use the -c option. Exiting.");
|
||||
fprintf(stderr, "Unable to find MaxScale configuration file. "
|
||||
fprintf(stderr, "* Unable to find MaxScale configuration file. "
|
||||
"Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
@ -483,7 +508,7 @@ main(int argc, char **argv)
|
||||
server_options[i] = ddopt;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mysql_library_init(num_elements, server_options, server_groups))
|
||||
{
|
||||
skygw_log_write_flush(
|
||||
@ -499,20 +524,20 @@ main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
libmysqld_started = TRUE;
|
||||
|
||||
|
||||
if (!config_load(cnf_file))
|
||||
{
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Fatal : Failed to load MaxScale configuration file %s. "
|
||||
"Error : Failed to load MaxScale configuration file %s. "
|
||||
"Exiting.",
|
||||
cnf_file);
|
||||
fprintf(stderr,
|
||||
"Failed to load MaxScale configuration file. "
|
||||
"* Failed to load MaxScale configuration file. "
|
||||
"Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
skygw_log_write(
|
||||
LOGFILE_MESSAGE,
|
||||
"SkySQL MaxScale (C) SkySQL Ab 2013");
|
||||
@ -534,7 +559,7 @@ main(int argc, char **argv)
|
||||
"Fatal : Failed to start any MaxScale services. "
|
||||
"Exiting.");
|
||||
fprintf(stderr,
|
||||
"Failed to start any MaxScale services. Exiting.\n");
|
||||
"* Failed to start any MaxScale services. Exiting.\n");
|
||||
exit(1);
|
||||
}
|
||||
skygw_log_write(
|
||||
|
||||
@ -135,7 +135,9 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) {
|
||||
|
||||
if (b <= 0) {
|
||||
//fprintf(stderr, "||| read_gwbuff called with 0 bytes for %i, closing\n", dcb->fd);
|
||||
#if 0
|
||||
dcb->func.close(dcb);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -152,11 +154,11 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) {
|
||||
|
||||
if (n < 0) {
|
||||
if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
|
||||
fprintf(stderr, "Client connection %i: continue for %i, %s\n", dcb->fd, errno, strerror(errno));
|
||||
/* fprintf(stderr, "Client connection %i: continue for %i, %s\n", dcb->fd, errno, strerror(errno)); */
|
||||
gwbuf_free(buffer);
|
||||
return 1;
|
||||
} else {
|
||||
fprintf(stderr, "Client connection %i error: %i, %s\n", dcb->fd, errno, strerror(errno));;
|
||||
/* fprintf(stderr, "Client connection %i error: %i, %s\n", dcb->fd, errno, strerror(errno)); */
|
||||
gwbuf_free(buffer);
|
||||
(dcb->func).close(dcb);
|
||||
return 1;
|
||||
@ -165,9 +167,11 @@ int gw_read_gwbuff(DCB *dcb, GWBUF **head, int b) {
|
||||
|
||||
if (n == 0) {
|
||||
// socket closed
|
||||
fprintf(stderr, "Client connection %i closed: %i, %s\n", dcb->fd, errno, strerror(errno));
|
||||
/* fprintf(stderr, "Client connection %i closed: %i, %s\n", dcb->fd, errno, strerror(errno)); */
|
||||
gwbuf_free(buffer);
|
||||
#if 1
|
||||
(dcb->func).close(dcb);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@ -397,6 +397,7 @@ poll_waitevents(void *arg)
|
||||
eno = gw_getsockerrno(dcb->fd);
|
||||
|
||||
if (eno == 0) {
|
||||
#if 1
|
||||
simple_mutex_lock(
|
||||
&dcb->dcb_write_lock,
|
||||
true);
|
||||
@ -404,11 +405,14 @@ poll_waitevents(void *arg)
|
||||
!dcb->dcb_write_active,
|
||||
"Write already active");
|
||||
dcb->dcb_write_active = TRUE;
|
||||
#endif
|
||||
atomic_add(&pollStats.n_write, 1);
|
||||
dcb->func.write_ready(dcb);
|
||||
#if 1
|
||||
dcb->dcb_write_active = FALSE;
|
||||
simple_mutex_unlock(
|
||||
&dcb->dcb_write_lock);
|
||||
#endif
|
||||
} else {
|
||||
skygw_log_write(
|
||||
LOGFILE_TRACE,
|
||||
@ -424,12 +428,13 @@ poll_waitevents(void *arg)
|
||||
}
|
||||
if (ev & EPOLLIN)
|
||||
{
|
||||
#if 1
|
||||
simple_mutex_lock(&dcb->dcb_read_lock,
|
||||
true);
|
||||
ss_info_dassert(!dcb->dcb_read_active,
|
||||
"Read already active");
|
||||
dcb->dcb_read_active = TRUE;
|
||||
|
||||
#endif
|
||||
if (dcb->state == DCB_STATE_LISTENING)
|
||||
{
|
||||
skygw_log_write(
|
||||
@ -454,9 +459,11 @@ poll_waitevents(void *arg)
|
||||
atomic_add(&pollStats.n_read, 1);
|
||||
dcb->func.read(dcb);
|
||||
}
|
||||
#if 1
|
||||
dcb->dcb_read_active = FALSE;
|
||||
simple_mutex_unlock(
|
||||
&dcb->dcb_read_lock);
|
||||
#endif
|
||||
}
|
||||
} /**< for */
|
||||
no_op = FALSE;
|
||||
|
||||
@ -112,7 +112,7 @@ GWPROTOCOL *funcs;
|
||||
int loaded = load_mysql_users(service);
|
||||
skygw_log_write(
|
||||
LOGFILE_MESSAGE,
|
||||
"MySQL Users loaded: %i.",
|
||||
"Loaded %d MySQL Users.",
|
||||
loaded);
|
||||
}
|
||||
|
||||
@ -132,11 +132,26 @@ GWPROTOCOL *funcs;
|
||||
memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
|
||||
port->listener->session = NULL;
|
||||
sprintf(config_bind, "0.0.0.0:%d", port->port);
|
||||
if (port->listener->func.listen(port->listener, config_bind))
|
||||
listeners++;
|
||||
port->listener->session = session_alloc(service, port->listener);
|
||||
port->listener->session->state = SESSION_STATE_LISTENER;
|
||||
|
||||
if (port->listener->func.listen(port->listener, config_bind)) {
|
||||
port->listener->session = session_alloc(service, port->listener);
|
||||
|
||||
if (port->listener->session != NULL) {
|
||||
port->listener->session->state = SESSION_STATE_LISTENER;
|
||||
listeners += 1;
|
||||
} else {
|
||||
dcb_close(port->listener);
|
||||
}
|
||||
} else {
|
||||
dcb_close(port->listener);
|
||||
|
||||
skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
"Error : Unable to start to listen port %d for %s %s.",
|
||||
port->port,
|
||||
port->protocol,
|
||||
service->name);
|
||||
}
|
||||
return listeners;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user