Merge branch 'develop' of https://github.com/mariadb-corporation/MaxScale into develop
This commit is contained in:
@ -50,6 +50,9 @@
|
|||||||
* 07/05/2014 Mark Riddoch Addition of callback mechanism
|
* 07/05/2014 Mark Riddoch Addition of callback mechanism
|
||||||
* 20/06/2014 Mark Riddoch Addition of dcb_clone
|
* 20/06/2014 Mark Riddoch Addition of dcb_clone
|
||||||
* 29/05/2015 Markus Makela Addition of dcb_write_SSL
|
* 29/05/2015 Markus Makela Addition of dcb_write_SSL
|
||||||
|
* 07/07/2015 Martin Brampton Merged add to zombieslist into dcb_close,
|
||||||
|
* fixes for various error situations,
|
||||||
|
* remove dcb_set_state etc, simplifications.
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -57,6 +60,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <dcb.h>
|
#include <dcb.h>
|
||||||
#include <spinlock.h>
|
#include <spinlock.h>
|
||||||
#include <server.h>
|
#include <server.h>
|
||||||
@ -84,10 +88,6 @@ static SPINLOCK dcbspin = SPINLOCK_INIT;
|
|||||||
static SPINLOCK zombiespin = SPINLOCK_INIT;
|
static SPINLOCK zombiespin = SPINLOCK_INIT;
|
||||||
|
|
||||||
static void dcb_final_free(DCB *dcb);
|
static void dcb_final_free(DCB *dcb);
|
||||||
static bool dcb_set_state_nomutex(
|
|
||||||
DCB* dcb,
|
|
||||||
const dcb_state_t new_state,
|
|
||||||
dcb_state_t* old_state);
|
|
||||||
static void dcb_call_callback(DCB *dcb, DCB_REASON reason);
|
static void dcb_call_callback(DCB *dcb, DCB_REASON reason);
|
||||||
static DCB* dcb_get_next (DCB* dcb);
|
static DCB* dcb_get_next (DCB* dcb);
|
||||||
static int dcb_null_write(DCB *dcb, GWBUF *buf);
|
static int dcb_null_write(DCB *dcb, GWBUF *buf);
|
||||||
@ -252,51 +252,6 @@ dcb_free(DCB *dcb)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add the DCB to the end of zombies list.
|
|
||||||
*
|
|
||||||
* Adding to list occurs once per DCB. This is ensured by changing the
|
|
||||||
* state of DCB to DCB_STATE_ZOMBIE after addition. Prior insertion, DCB state
|
|
||||||
* is checked and operation proceeds only if state differs from DCB_STATE_ZOMBIE.
|
|
||||||
* @param dcb The DCB to add to the zombie list
|
|
||||||
* @return none
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
dcb_add_to_zombieslist(DCB *dcb)
|
|
||||||
{
|
|
||||||
bool succp = false;
|
|
||||||
dcb_state_t prev_state = DCB_STATE_UNDEFINED;
|
|
||||||
|
|
||||||
CHK_DCB(dcb);
|
|
||||||
|
|
||||||
/*<
|
|
||||||
* Protect zombies list access.
|
|
||||||
*/
|
|
||||||
spinlock_acquire(&zombiespin);
|
|
||||||
/*<
|
|
||||||
* If dcb is already added to zombies list, return.
|
|
||||||
*/
|
|
||||||
if (dcb->state != DCB_STATE_NOPOLLING) {
|
|
||||||
ss_dassert(dcb->state != DCB_STATE_POLLING &&
|
|
||||||
dcb->state != DCB_STATE_LISTENING);
|
|
||||||
spinlock_release(&zombiespin);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/*<
|
|
||||||
* Add closing dcb to the top of the list.
|
|
||||||
*/
|
|
||||||
dcb->memdata.next = zombies;
|
|
||||||
zombies = dcb;
|
|
||||||
/*<
|
|
||||||
* Set state which indicates that it has been added to zombies
|
|
||||||
* list.
|
|
||||||
*/
|
|
||||||
succp = dcb_set_state(dcb, DCB_STATE_ZOMBIE, &prev_state);
|
|
||||||
ss_info_dassert(succp, "Failed to set DCB_STATE_ZOMBIE");
|
|
||||||
|
|
||||||
spinlock_release(&zombiespin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clone a DCB for internal use, mostly used for specialist filters
|
* Clone a DCB for internal use, mostly used for specialist filters
|
||||||
* to create dummy clients based on real clients.
|
* to create dummy clients based on real clients.
|
||||||
@ -533,14 +488,13 @@ bool succp = false;
|
|||||||
/*<
|
/*<
|
||||||
* Move dcb to linked list of victim dcbs.
|
* Move dcb to linked list of victim dcbs.
|
||||||
*/
|
*/
|
||||||
|
ptr->memdata.next = NULL;
|
||||||
if (dcb_list == NULL) {
|
if (dcb_list == NULL) {
|
||||||
dcb_list = ptr;
|
dcb_list = ptr;
|
||||||
dcb = dcb_list;
|
|
||||||
} else {
|
} else {
|
||||||
dcb->memdata.next = ptr;
|
dcb->memdata.next = ptr;
|
||||||
dcb = dcb->memdata.next;
|
|
||||||
}
|
}
|
||||||
dcb->memdata.next = NULL;
|
dcb = ptr;
|
||||||
ptr = tptr;
|
ptr = tptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -604,8 +558,7 @@ bool succp = false;
|
|||||||
&tls_log_info.li_sesid,
|
&tls_log_info.li_sesid,
|
||||||
&tls_log_info.li_enabled_logs)));
|
&tls_log_info.li_enabled_logs)));
|
||||||
|
|
||||||
succp = dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
|
dcb->state = DCB_STATE_DISCONNECTED;
|
||||||
ss_dassert(succp);
|
|
||||||
dcb_next = dcb->memdata.next;
|
dcb_next = dcb->memdata.next;
|
||||||
dcb_final_free(dcb);
|
dcb_final_free(dcb);
|
||||||
dcb = dcb_next;
|
dcb = dcb_next;
|
||||||
@ -644,7 +597,7 @@ int rc;
|
|||||||
if ((funcs = (GWPROTOCOL *)load_module(protocol,
|
if ((funcs = (GWPROTOCOL *)load_module(protocol,
|
||||||
MODULE_PROTOCOL)) == NULL)
|
MODULE_PROTOCOL)) == NULL)
|
||||||
{
|
{
|
||||||
dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
|
dcb->state = DCB_STATE_DISCONNECTED;
|
||||||
dcb_final_free(dcb);
|
dcb_final_free(dcb);
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
@ -682,7 +635,7 @@ int rc;
|
|||||||
dcb,
|
dcb,
|
||||||
session->client,
|
session->client,
|
||||||
session->client->fd)));
|
session->client->fd)));
|
||||||
dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
|
dcb->state = DCB_STATE_DISCONNECTED;
|
||||||
dcb_final_free(dcb);
|
dcb_final_free(dcb);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -724,8 +677,8 @@ int rc;
|
|||||||
*/
|
*/
|
||||||
rc = poll_add_dcb(dcb);
|
rc = poll_add_dcb(dcb);
|
||||||
|
|
||||||
if (rc == DCBFD_CLOSED) {
|
if (rc) {
|
||||||
dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
|
dcb->state = DCB_STATE_DISCONNECTED;
|
||||||
dcb_final_free(dcb);
|
dcb_final_free(dcb);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1920,7 +1873,7 @@ dcb_drain_writeq_SSL(DCB *dcb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes dcb from poll set, and adds it to zombies list. As a consequense,
|
* Removes dcb from poll set, and adds it to zombies list. As a consequence,
|
||||||
* dcb first moves to DCB_STATE_NOPOLLING, and then to DCB_STATE_ZOMBIE state.
|
* dcb first moves to DCB_STATE_NOPOLLING, and then to DCB_STATE_ZOMBIE state.
|
||||||
* At the end of the function state may not be DCB_STATE_ZOMBIE because once
|
* At the end of the function state may not be DCB_STATE_ZOMBIE because once
|
||||||
* dcb_initlock is released parallel threads may change the state.
|
* dcb_initlock is released parallel threads may change the state.
|
||||||
@ -1933,73 +1886,96 @@ dcb_drain_writeq_SSL(DCB *dcb)
|
|||||||
void
|
void
|
||||||
dcb_close(DCB *dcb)
|
dcb_close(DCB *dcb)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
CHK_DCB(dcb);
|
||||||
|
|
||||||
CHK_DCB(dcb);
|
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
|
||||||
|
"%lu [dcb_close] DCB %p in state %s",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
dcb ? STRDCBSTATE(dcb->state) : "Invalid DCB")));
|
||||||
|
|
||||||
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
|
if (DCB_STATE_ZOMBIE == dcb->state)
|
||||||
"%lu [dcb_close]",
|
{
|
||||||
pthread_self())));
|
return;
|
||||||
|
}
|
||||||
/**
|
|
||||||
* dcb_close may be called for freshly created dcb, in which case
|
if (DCB_STATE_UNDEFINED == dcb->state
|
||||||
* it only needs to be freed.
|
|| DCB_STATE_DISCONNECTED == dcb->state)
|
||||||
*/
|
{
|
||||||
if (dcb->state == DCB_STATE_ALLOC)
|
LOGIF(LE, (skygw_log_write(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [dcb_close] Error : Removing DCB %p but was in state %s "
|
||||||
|
"which is not legal for a call to dcb_close. ",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
STRDCBSTATE(dcb->state))));
|
||||||
|
raise(SIGABRT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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->fd != DCBFD_CLOSED)
|
||||||
|
{
|
||||||
|
dcb_final_free(dcb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*<
|
||||||
|
* Stop dcb's listening and modify state accordingly.
|
||||||
|
*/
|
||||||
|
if (dcb->state == DCB_STATE_POLLING || dcb->state == DCB_STATE_LISTENING)
|
||||||
|
{
|
||||||
|
if (dcb->state == DCB_STATE_LISTENING)
|
||||||
{
|
{
|
||||||
dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
|
LOGIF(LE, (skygw_log_write(
|
||||||
dcb_final_free(dcb);
|
LOGFILE_ERROR,
|
||||||
return;
|
"%lu [dcb_close] Error : Removing DCB %p but was in state %s "
|
||||||
|
"which is not expected for a call to dcb_close, although it"
|
||||||
|
"should be processed correctly. ",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
STRDCBSTATE(dcb->state))));
|
||||||
}
|
}
|
||||||
|
poll_remove_dcb(dcb);
|
||||||
ss_dassert(dcb->state == DCB_STATE_POLLING ||
|
/*
|
||||||
dcb->state == DCB_STATE_NOPOLLING ||
|
* Return will always be 0 or function will have crashed, so we
|
||||||
dcb->state == DCB_STATE_ZOMBIE);
|
* threw away return value.
|
||||||
|
*/
|
||||||
|
LOGIF(LD, (skygw_log_write(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [dcb_close] Removed dcb %p in state %s from "
|
||||||
|
"poll set.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
STRDCBSTATE(dcb->state))));
|
||||||
|
/**
|
||||||
|
* close protocol and router session
|
||||||
|
*/
|
||||||
|
if (dcb->func.close != NULL)
|
||||||
|
{
|
||||||
|
dcb->func.close(dcb);
|
||||||
|
}
|
||||||
|
/** Call possible callback for this DCB in case of close */
|
||||||
|
dcb_call_callback(dcb, DCB_REASON_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinlock_acquire(&zombiespin);
|
||||||
|
if (dcb->state == DCB_STATE_NOPOLLING || dcb->state == DCB_STATE_ALLOC)
|
||||||
|
{
|
||||||
/*<
|
/*<
|
||||||
* Stop dcb's listening and modify state accordingly.
|
* Add closing dcb to the top of the list.
|
||||||
*/
|
*/
|
||||||
if (dcb->state == DCB_STATE_POLLING)
|
dcb->memdata.next = zombies;
|
||||||
{
|
zombies = dcb;
|
||||||
rc = poll_remove_dcb(dcb);
|
/*<
|
||||||
|
* Set state which indicates that it has been added to zombies
|
||||||
if (rc == 0) {
|
* list.
|
||||||
LOGIF(LD, (skygw_log_write(
|
*/
|
||||||
LOGFILE_DEBUG,
|
dcb->state = DCB_STATE_ZOMBIE;
|
||||||
"%lu [dcb_close] Removed dcb %p in state %s from "
|
}
|
||||||
"poll set.",
|
spinlock_release(&zombiespin);
|
||||||
pthread_self(),
|
|
||||||
dcb,
|
|
||||||
STRDCBSTATE(dcb->state))));
|
|
||||||
} else {
|
|
||||||
LOGIF(LE, (skygw_log_write(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Removing DCB fd == %d in state %s from "
|
|
||||||
"poll set failed.",
|
|
||||||
dcb->fd,
|
|
||||||
STRDCBSTATE(dcb->state))));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == 0)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* close protocol and router session
|
|
||||||
*/
|
|
||||||
if (dcb->func.close != NULL)
|
|
||||||
{
|
|
||||||
dcb->func.close(dcb);
|
|
||||||
}
|
|
||||||
/** Call possible callback for this DCB in case of close */
|
|
||||||
dcb_call_callback(dcb, DCB_REASON_CLOSE);
|
|
||||||
|
|
||||||
if (dcb->state == DCB_STATE_NOPOLLING)
|
|
||||||
{
|
|
||||||
dcb_add_to_zombieslist(dcb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ss_dassert(dcb->state == DCB_STATE_NOPOLLING ||
|
|
||||||
dcb->state == DCB_STATE_ZOMBIE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2341,171 +2317,6 @@ void dcb_hashtable_stats(
|
|||||||
dcb_printf(dcb, "\tLongest chain length: %d\n", longest);
|
dcb_printf(dcb, "\tLongest chain length: %d\n", longest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool dcb_set_state(
|
|
||||||
DCB* dcb,
|
|
||||||
const dcb_state_t new_state,
|
|
||||||
dcb_state_t* old_state)
|
|
||||||
{
|
|
||||||
bool succp;
|
|
||||||
dcb_state_t state ;
|
|
||||||
|
|
||||||
CHK_DCB(dcb);
|
|
||||||
spinlock_acquire(&dcb->dcb_initlock);
|
|
||||||
succp = dcb_set_state_nomutex(dcb, new_state, &state);
|
|
||||||
|
|
||||||
spinlock_release(&dcb->dcb_initlock);
|
|
||||||
|
|
||||||
if (old_state != NULL) {
|
|
||||||
*old_state = state;
|
|
||||||
}
|
|
||||||
return succp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool dcb_set_state_nomutex(
|
|
||||||
DCB* dcb,
|
|
||||||
const dcb_state_t new_state,
|
|
||||||
dcb_state_t* old_state)
|
|
||||||
{
|
|
||||||
bool succp = false;
|
|
||||||
dcb_state_t state = DCB_STATE_UNDEFINED;
|
|
||||||
|
|
||||||
CHK_DCB(dcb);
|
|
||||||
|
|
||||||
state = dcb->state;
|
|
||||||
|
|
||||||
if (old_state != NULL) {
|
|
||||||
*old_state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case DCB_STATE_UNDEFINED:
|
|
||||||
dcb->state = new_state;
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_ALLOC:
|
|
||||||
switch (new_state) {
|
|
||||||
/** fall through, for client requests */
|
|
||||||
case DCB_STATE_POLLING:
|
|
||||||
/** fall through, for connect listeners */
|
|
||||||
case DCB_STATE_LISTENING:
|
|
||||||
/** for failed connections */
|
|
||||||
case DCB_STATE_DISCONNECTED:
|
|
||||||
dcb->state = new_state;
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_POLLING:
|
|
||||||
switch(new_state) {
|
|
||||||
case DCB_STATE_NOPOLLING:
|
|
||||||
dcb->state = new_state;
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_LISTENING:
|
|
||||||
switch(new_state) {
|
|
||||||
case DCB_STATE_NOPOLLING:
|
|
||||||
dcb->state = new_state;
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_NOPOLLING:
|
|
||||||
switch (new_state) {
|
|
||||||
/** Stopped services which are restarting will go from
|
|
||||||
* DCB_STATE_NOPOLLING to DCB_STATE_LISTENING.*/
|
|
||||||
case DCB_STATE_LISTENING:
|
|
||||||
case DCB_STATE_ZOMBIE: /*< fall through */
|
|
||||||
dcb->state = new_state;
|
|
||||||
case DCB_STATE_POLLING: /*< ok to try but state can't change */
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_ZOMBIE:
|
|
||||||
switch (new_state) {
|
|
||||||
case DCB_STATE_DISCONNECTED: /*< fall through */
|
|
||||||
dcb->state = new_state;
|
|
||||||
case DCB_STATE_POLLING: /*< ok to try but state can't change */
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_DISCONNECTED:
|
|
||||||
switch (new_state) {
|
|
||||||
case DCB_STATE_FREED:
|
|
||||||
dcb->state = new_state;
|
|
||||||
succp = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DCB_STATE_FREED:
|
|
||||||
ss_dassert(old_state != NULL);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Unknown dcb state %s for "
|
|
||||||
"dcb %p",
|
|
||||||
STRDCBSTATE(dcb->state),
|
|
||||||
dcb)));
|
|
||||||
ss_dassert(false);
|
|
||||||
break;
|
|
||||||
} /*< switch (dcb->state) */
|
|
||||||
|
|
||||||
if (succp) {
|
|
||||||
LOGIF(LD, (skygw_log_write_flush(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [dcb_set_state_nomutex] dcb %p fd %d %s -> %s",
|
|
||||||
pthread_self(),
|
|
||||||
dcb,
|
|
||||||
dcb->fd,
|
|
||||||
STRDCBSTATE(state),
|
|
||||||
STRDCBSTATE(dcb->state))));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [dcb_set_state_nomutex] Failed "
|
|
||||||
"to change state of DCB %p. "
|
|
||||||
"Old state %s > new state %s.",
|
|
||||||
pthread_self(),
|
|
||||||
dcb,
|
|
||||||
(old_state == NULL ? "NULL" : STRDCBSTATE(*old_state)),
|
|
||||||
STRDCBSTATE(new_state))));
|
|
||||||
}
|
|
||||||
return succp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write data to a socket through an SSL structure. The SSL structure is linked to a DCB's socket
|
* Write data to a socket through an SSL structure. The SSL structure is linked to a DCB's socket
|
||||||
* and all communication is encrypted and done via the SSL structure.
|
* and all communication is encrypted and done via the SSL structure.
|
||||||
|
|||||||
@ -15,10 +15,12 @@
|
|||||||
*
|
*
|
||||||
* Copyright MariaDB Corporation Ab 2013-2014
|
* Copyright MariaDB Corporation Ab 2013-2014
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
@ -71,6 +73,7 @@ int max_poll_sleep;
|
|||||||
* in the loop after the epoll_wait. This allows for better
|
* in the loop after the epoll_wait. This allows for better
|
||||||
* thread utilisaiton and fairer scheduling of the event
|
* thread utilisaiton and fairer scheduling of the event
|
||||||
* processing.
|
* processing.
|
||||||
|
* 07/07/15 Martin Brampton Simplified add and remove DCB, improve error handling.
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -186,6 +189,11 @@ static struct {
|
|||||||
*/
|
*/
|
||||||
static void poll_loadav(void *);
|
static void poll_loadav(void *);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to analyse error return from epoll_ctl
|
||||||
|
*/
|
||||||
|
static int poll_resolve_error(DCB *, int, bool);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise the polling system we are using for the gateway.
|
* Initialise the polling system we are using for the gateway.
|
||||||
*
|
*
|
||||||
@ -247,7 +255,7 @@ int
|
|||||||
poll_add_dcb(DCB *dcb)
|
poll_add_dcb(DCB *dcb)
|
||||||
{
|
{
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
dcb_state_t old_state = DCB_STATE_UNDEFINED;
|
dcb_state_t old_state = dcb->state;
|
||||||
dcb_state_t new_state;
|
dcb_state_t new_state;
|
||||||
struct epoll_event ev;
|
struct epoll_event ev;
|
||||||
|
|
||||||
@ -263,58 +271,67 @@ poll_add_dcb(DCB *dcb)
|
|||||||
/*<
|
/*<
|
||||||
* Choose new state according to the role of dcb.
|
* Choose new state according to the role of dcb.
|
||||||
*/
|
*/
|
||||||
|
spinlock_acquire(&dcb->dcb_initlock);
|
||||||
if (dcb->dcb_role == DCB_ROLE_REQUEST_HANDLER) {
|
if (dcb->dcb_role == DCB_ROLE_REQUEST_HANDLER) {
|
||||||
new_state = DCB_STATE_POLLING;
|
new_state = DCB_STATE_POLLING;
|
||||||
} else {
|
} else {
|
||||||
ss_dassert(dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER);
|
ss_dassert(dcb->dcb_role == DCB_ROLE_SERVICE_LISTENER);
|
||||||
new_state = DCB_STATE_LISTENING;
|
new_state = DCB_STATE_LISTENING;
|
||||||
}
|
}
|
||||||
/*<
|
/*
|
||||||
* If dcb is in unexpected state, state change fails indicating that dcb
|
* Check DCB current state seems sensible
|
||||||
* is not polling anymore.
|
|
||||||
*/
|
*/
|
||||||
if (dcb_set_state(dcb, new_state, &old_state)) {
|
if (DCB_STATE_DISCONNECTED == dcb->state
|
||||||
rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, dcb->fd, &ev);
|
|| DCB_STATE_ZOMBIE == dcb->state
|
||||||
|
|| DCB_STATE_UNDEFINED == dcb->state)
|
||||||
if (rc != 0) {
|
{
|
||||||
int eno = errno;
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
errno = 0;
|
LOGFILE_ERROR,
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
"%lu [poll_add_dcb] Error : existing state of dcb %p "
|
||||||
LOGFILE_ERROR,
|
"is %s, but this should be impossible, crashing.",
|
||||||
"Error : Adding dcb %p in state %s "
|
pthread_self(),
|
||||||
"to poll set failed. epoll_ctl failed due "
|
dcb,
|
||||||
"%d, %s.",
|
STRDCBSTATE(dcb->state))));
|
||||||
dcb,
|
raise(SIGABRT);
|
||||||
STRDCBSTATE(dcb->state),
|
|
||||||
eno,
|
|
||||||
strerror(eno))));
|
|
||||||
} else {
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
|
||||||
LOGFILE_DEBUG,
|
|
||||||
"%lu [poll_add_dcb] Added dcb %p in state %s to "
|
|
||||||
"poll set.",
|
|
||||||
pthread_self(),
|
|
||||||
dcb,
|
|
||||||
STRDCBSTATE(dcb->state))));
|
|
||||||
}
|
|
||||||
ss_info_dassert(rc == 0, "Unable to add poll"); /*< trap in debug */
|
|
||||||
} else {
|
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
|
||||||
LOGFILE_ERROR,
|
|
||||||
"Error : Unable to set new state for dcb %p "
|
|
||||||
"in state %s. Adding to poll set failed.",
|
|
||||||
dcb,
|
|
||||||
STRDCBSTATE(dcb->state))));
|
|
||||||
}
|
}
|
||||||
|
if (DCB_STATE_POLLING == dcb->state
|
||||||
|
|| DCB_STATE_LISTENING == dcb->state)
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [poll_add_dcb] Error : existing state of dcb %p "
|
||||||
|
"is %s, but this is probably an error, not crashing.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
STRDCBSTATE(dcb->state))));
|
||||||
|
}
|
||||||
|
dcb->state = new_state;
|
||||||
|
spinlock_release(&dcb->dcb_initlock);
|
||||||
|
/*
|
||||||
|
* The only possible failure that will not cause a crash is
|
||||||
|
* running out of system resources.
|
||||||
|
*/
|
||||||
|
rc = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, dcb->fd, &ev);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
rc = poll_resolve_error(dcb, errno, true);
|
||||||
|
}
|
||||||
|
if (0 == rc)
|
||||||
|
{
|
||||||
|
LOGIF(LD, (skygw_log_write(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [poll_add_dcb] Added dcb %p in state %s to poll set.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
STRDCBSTATE(dcb->state))));
|
||||||
|
}
|
||||||
|
else dcb->state = old_state;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a descriptor from the set of descriptors within the
|
* Remove a descriptor from the set of descriptors within the
|
||||||
* polling environment.
|
* polling environment.
|
||||||
* The state change command may fail because concurrent threads may call
|
|
||||||
* dcb_set_state simultaneously and the conflict is prevented in dcb_set_state.
|
|
||||||
*
|
*
|
||||||
* @param dcb The descriptor to remove
|
* @param dcb The descriptor to remove
|
||||||
* @return -1 on error or 0 on success
|
* @return -1 on error or 0 on success
|
||||||
@ -322,62 +339,119 @@ poll_add_dcb(DCB *dcb)
|
|||||||
int
|
int
|
||||||
poll_remove_dcb(DCB *dcb)
|
poll_remove_dcb(DCB *dcb)
|
||||||
{
|
{
|
||||||
struct epoll_event ev;
|
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
dcb_state_t old_state = DCB_STATE_UNDEFINED;
|
struct epoll_event ev;
|
||||||
dcb_state_t new_state = DCB_STATE_NOPOLLING;
|
|
||||||
|
|
||||||
CHK_DCB(dcb);
|
CHK_DCB(dcb);
|
||||||
|
|
||||||
|
spinlock_acquire(&dcb->dcb_initlock);
|
||||||
/*< It is possible that dcb has already been removed from the set */
|
/*< It is possible that dcb has already been removed from the set */
|
||||||
if (dcb->state != DCB_STATE_POLLING &&
|
if (dcb->state == DCB_STATE_NOPOLLING ||
|
||||||
dcb->state != DCB_STATE_LISTENING)
|
dcb->state == DCB_STATE_ZOMBIE)
|
||||||
{
|
{
|
||||||
if (dcb->state == DCB_STATE_NOPOLLING ||
|
spinlock_release(&dcb->dcb_initlock);
|
||||||
dcb->state == DCB_STATE_ZOMBIE)
|
return 0;
|
||||||
{
|
}
|
||||||
rc = 0;
|
if (DCB_STATE_POLLING != dcb->state
|
||||||
}
|
&& DCB_STATE_LISTENING != dcb->state)
|
||||||
goto return_rc;
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [poll_remove_dcb] Error : existing state of dcb %p "
|
||||||
|
"is %s, but this is probably an error, not crashing.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb,
|
||||||
|
STRDCBSTATE(dcb->state))));
|
||||||
}
|
}
|
||||||
/*<
|
/*<
|
||||||
* Set state to NOPOLLING and remove dcb from poll set.
|
* Set state to NOPOLLING and remove dcb from poll set.
|
||||||
*/
|
*/
|
||||||
if (dcb_set_state(dcb, new_state, &old_state))
|
dcb->state = DCB_STATE_NOPOLLING;
|
||||||
{
|
/**
|
||||||
/**
|
* Only positive fds can be removed from epoll set.
|
||||||
* Only positive fds can be removed from epoll set.
|
* But this test was removed by Martin as it is hard to
|
||||||
*/
|
* see that there should ever be a situation where
|
||||||
if (dcb->fd > 0)
|
* fd isn't positive and the DCB is also in the poll list.
|
||||||
{
|
*/
|
||||||
rc = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, dcb->fd, &ev);
|
/* if (dcb->fd > 0) { */
|
||||||
|
spinlock_release(&dcb->dcb_initlock);
|
||||||
if (rc != 0) {
|
rc = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, dcb->fd, &ev);
|
||||||
int eno = errno;
|
/**
|
||||||
errno = 0;
|
* The poll_resolve_error function will always
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
* return 0 or crash. So if it returns non-zero result,
|
||||||
LOGFILE_ERROR,
|
* things have gone wrong and we crash.
|
||||||
"Error : epoll_ctl failed due %d, %s.",
|
|
||||||
eno,
|
|
||||||
strerror(eno))));
|
|
||||||
}
|
|
||||||
ss_dassert(rc == 0); /*< trap in debug */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*<
|
|
||||||
* This call was redundant, but the end result is correct.
|
|
||||||
*/
|
*/
|
||||||
else if (old_state == new_state)
|
if (rc) rc = poll_resolve_error(dcb, errno, false);
|
||||||
{
|
if (rc) raise(SIGABRT);
|
||||||
rc = 0;
|
|
||||||
goto return_rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*< Set bit for each maxscale thread */
|
/*< Set bit for each maxscale thread */
|
||||||
bitmask_copy(&dcb->memdata.bitmask, poll_bitmask());
|
bitmask_copy(&dcb->memdata.bitmask, poll_bitmask());
|
||||||
rc = 0;
|
|
||||||
return_rc:
|
|
||||||
return rc;
|
return rc;
|
||||||
|
/* } */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check error returns from epoll_ctl. Most result in a crash since they
|
||||||
|
* are "impossible". Adding when already present is assumed non-fatal.
|
||||||
|
* Likewise, removing when not present is assumed non-fatal.
|
||||||
|
* It is assumed that callers to poll routines can handle the failure
|
||||||
|
* that results from hitting system limit, although an error is written
|
||||||
|
* here to record the problem.
|
||||||
|
*
|
||||||
|
* @param errornum The errno set by epoll_ctl
|
||||||
|
* @param adding True for adding to poll list, false for removing
|
||||||
|
* @return -1 on error or 0 for possibly revised return code
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
poll_resolve_error(DCB *dcb, int errornum, bool adding)
|
||||||
|
{
|
||||||
|
if (adding)
|
||||||
|
{
|
||||||
|
if (EEXIST == errornum)
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [poll_resolve_error] Error : epoll_ctl could not add, "
|
||||||
|
"already exists for DCB %p.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb)));
|
||||||
|
// Assume another thread added and no serious harm done
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ENOSPC == errornum)
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [poll_resolve_error] The limit imposed by "
|
||||||
|
"/proc/sys/fs/epoll/max_user_watches was "
|
||||||
|
"encountered while trying to register (EPOLL_CTL_ADD) a new "
|
||||||
|
"file descriptor on an epoll instance for dcb %p.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb)));
|
||||||
|
/* Failure - assume handled by callers */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Must be removing */
|
||||||
|
if (ENOENT == errornum)
|
||||||
|
{
|
||||||
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
|
LOGFILE_ERROR,
|
||||||
|
"%lu [poll_resolve_error] Error : epoll_ctl could not remove, "
|
||||||
|
"not found, for dcb %p.",
|
||||||
|
pthread_self(),
|
||||||
|
dcb)));
|
||||||
|
// Assume another thread removed and no serious harm done
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Common checks for add or remove - crash MaxScale */
|
||||||
|
if (EBADF == errornum) assert (!(EBADF == errornum));
|
||||||
|
if (EINVAL == errornum) assert (!(EINVAL == errornum));
|
||||||
|
if (ENOMEM == errornum) assert (!(ENOMEM == errornum));
|
||||||
|
if (EPERM == errornum) assert (!(EPERM == errornum));
|
||||||
|
/* Undocumented error number */
|
||||||
|
raise(SIGABRT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BLOCKINGPOLL 0 /*< Set BLOCKING POLL to 1 if using a single thread and to make
|
#define BLOCKINGPOLL 0 /*< Set BLOCKING POLL to 1 if using a single thread and to make
|
||||||
@ -1605,7 +1679,7 @@ RESULT_ROW *row;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a resultset that has the current set of services in it
|
* Return a result set that has the current set of services in it
|
||||||
*
|
*
|
||||||
* @return A Result set
|
* @return A Result set
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -64,7 +64,7 @@ int buflen;
|
|||||||
ss_info_dassert(!dcb_isvalid(dcb), "Freed DCB must not be valid");
|
ss_info_dassert(!dcb_isvalid(dcb), "Freed DCB must not be valid");
|
||||||
ss_dfprintf(stderr, "\t..done\nMake clone DCB a zombie");
|
ss_dfprintf(stderr, "\t..done\nMake clone DCB a zombie");
|
||||||
clone->state = DCB_STATE_NOPOLLING;
|
clone->state = DCB_STATE_NOPOLLING;
|
||||||
dcb_add_to_zombieslist(clone);
|
dcb_close(clone);
|
||||||
ss_info_dassert(dcb_get_zombies() == clone, "Clone DCB must be start of zombie list now");
|
ss_info_dassert(dcb_get_zombies() == clone, "Clone DCB must be start of zombie list now");
|
||||||
ss_dfprintf(stderr, "\t..done\nProcess the zombies list");
|
ss_dfprintf(stderr, "\t..done\nProcess the zombies list");
|
||||||
dcb_process_zombies(0);
|
dcb_process_zombies(0);
|
||||||
|
|||||||
@ -330,7 +330,6 @@ const char *gw_dcb_state2string(int); /* DCB state to string */
|
|||||||
void dcb_printf(DCB *, const char *, ...); /* DCB version of printf */
|
void dcb_printf(DCB *, const char *, ...); /* DCB version of printf */
|
||||||
int dcb_isclient(DCB *); /* the DCB is the client of the session */
|
int dcb_isclient(DCB *); /* the DCB is the client of the session */
|
||||||
void dcb_hashtable_stats(DCB *, void *); /**< Print statisitics */
|
void dcb_hashtable_stats(DCB *, void *); /**< Print statisitics */
|
||||||
void dcb_add_to_zombieslist(DCB* dcb);
|
|
||||||
int dcb_add_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *),
|
int dcb_add_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *),
|
||||||
void *);
|
void *);
|
||||||
int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *),
|
int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, void *),
|
||||||
@ -338,7 +337,6 @@ int dcb_remove_callback(DCB *, DCB_REASON, int (*)(struct dcb *, DCB_REASON, vo
|
|||||||
int dcb_isvalid(DCB *); /* Check the DCB is in the linked list */
|
int dcb_isvalid(DCB *); /* Check the DCB is in the linked list */
|
||||||
int dcb_count_by_usage(DCB_USAGE); /* Return counts of DCBs */
|
int dcb_count_by_usage(DCB_USAGE); /* Return counts of DCBs */
|
||||||
|
|
||||||
bool dcb_set_state(DCB* dcb, dcb_state_t new_state, dcb_state_t* old_state);
|
|
||||||
void dcb_call_foreach (struct server* server, DCB_REASON reason);
|
void dcb_call_foreach (struct server* server, DCB_REASON reason);
|
||||||
size_t dcb_get_session_id(DCB* dcb);
|
size_t dcb_get_session_id(DCB* dcb);
|
||||||
bool dcb_get_ses_log_info(DCB* dcb, size_t* sesid, int* enabled_logs);
|
bool dcb_get_ses_log_info(DCB* dcb, size_t* sesid, int* enabled_logs);
|
||||||
|
|||||||
@ -58,6 +58,7 @@ extern __thread log_info_t tls_log_info;
|
|||||||
* Revision History
|
* Revision History
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 13/06/2014 Mark Riddoch Initial implementation
|
* 13/06/2014 Mark Riddoch Initial implementation
|
||||||
|
* 07/07/15 Martin Brampton Correct failure handling
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -270,9 +271,7 @@ int n_connect = 0;
|
|||||||
{
|
{
|
||||||
atomic_add(&dcb->stats.n_accepts, 1);
|
atomic_add(&dcb->stats.n_accepts, 1);
|
||||||
client_dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
|
client_dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
|
||||||
|
|
||||||
if (client_dcb == NULL)
|
if (client_dcb == NULL)
|
||||||
|
|
||||||
{
|
{
|
||||||
close(so);
|
close(so);
|
||||||
return n_connect;
|
return n_connect;
|
||||||
@ -283,7 +282,8 @@ int n_connect = 0;
|
|||||||
if ((maxscaled_pr = (MAXSCALED *)malloc(sizeof(MAXSCALED))) == NULL)
|
if ((maxscaled_pr = (MAXSCALED *)malloc(sizeof(MAXSCALED))) == NULL)
|
||||||
{
|
{
|
||||||
client_dcb->protocol = NULL;
|
client_dcb->protocol = NULL;
|
||||||
dcb_add_to_zombieslist(client_dcb);
|
close(so);
|
||||||
|
dcb_close(client_dcb);
|
||||||
return n_connect;
|
return n_connect;
|
||||||
}
|
}
|
||||||
maxscaled_pr->username = NULL;
|
maxscaled_pr->username = NULL;
|
||||||
@ -293,9 +293,9 @@ int n_connect = 0;
|
|||||||
client_dcb->session =
|
client_dcb->session =
|
||||||
session_alloc(dcb->session->service, client_dcb);
|
session_alloc(dcb->session->service, client_dcb);
|
||||||
|
|
||||||
if (poll_add_dcb(client_dcb) == -1)
|
if (poll_add_dcb(client_dcb))
|
||||||
{
|
{
|
||||||
dcb_add_to_zombieslist(dcb);
|
dcb_close(dcb);
|
||||||
return n_connect;
|
return n_connect;
|
||||||
}
|
}
|
||||||
n_connect++;
|
n_connect++;
|
||||||
|
|||||||
@ -1451,8 +1451,8 @@ int gw_MySQLListener(
|
|||||||
// add listening socket to poll structure
|
// add listening socket to poll structure
|
||||||
if (poll_add_dcb(listen_dcb) == -1) {
|
if (poll_add_dcb(listen_dcb) == -1) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\n* Failed to start polling the socket due error "
|
"\n* MaxScale encountered system limit while "
|
||||||
"%i, %s.\n\n",
|
"attempting to register on an epoll instance.\n\n",
|
||||||
errno,
|
errno,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
@ -1687,7 +1687,8 @@ int gw_MySQLAccept(DCB *listener)
|
|||||||
client_dcb,
|
client_dcb,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
"MaxScale internal error.");
|
"MaxScale encountered system limit while "
|
||||||
|
"attempting to register on an epoll instance.");
|
||||||
|
|
||||||
/** close client_dcb */
|
/** close client_dcb */
|
||||||
dcb_close(client_dcb);
|
dcb_close(client_dcb);
|
||||||
|
|||||||
@ -36,6 +36,7 @@
|
|||||||
* 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
|
* 10/11/2014 Massimiliano Pinto Charset at connect is passed to backend during authentication
|
||||||
|
* 07/07/15 Martin Brampton Fix problem recognising null password
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -46,6 +47,9 @@
|
|||||||
#include <log_manager.h>
|
#include <log_manager.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
|
/* The following can be compared using memcmp to detect a null password */
|
||||||
|
uint8_t null_client_sha1[MYSQL_SCRAMBLE_LEN]="";
|
||||||
|
|
||||||
/** Defined in log_manager.cc */
|
/** Defined in log_manager.cc */
|
||||||
extern int lm_enabled_logfiles_bitmask;
|
extern int lm_enabled_logfiles_bitmask;
|
||||||
extern size_t log_ses_count[];
|
extern size_t log_ses_count[];
|
||||||
@ -577,7 +581,7 @@ int gw_send_authentication_to_backend(
|
|||||||
if (strlen(dbname))
|
if (strlen(dbname))
|
||||||
curr_db = dbname;
|
curr_db = dbname;
|
||||||
|
|
||||||
if (strlen((char *)passwd))
|
if (memcmp(passwd, null_client_sha1, MYSQL_SCRAMBLE_LEN))
|
||||||
curr_passwd = passwd;
|
curr_passwd = passwd;
|
||||||
|
|
||||||
dcb = conn->owner_dcb;
|
dcb = conn->owner_dcb;
|
||||||
@ -1122,7 +1126,7 @@ GWBUF* gw_create_change_user_packet(
|
|||||||
curr_db = db;
|
curr_db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen((char *)pwd) > 0)
|
if (memcmp(pwd, null_client_sha1, MYSQL_SCRAMBLE_LEN))
|
||||||
{
|
{
|
||||||
curr_passwd = pwd;
|
curr_passwd = pwd;
|
||||||
}
|
}
|
||||||
@ -1358,12 +1362,7 @@ int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_le
|
|||||||
gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH);
|
gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH);
|
||||||
} else {
|
} else {
|
||||||
/* check if the password is not set in the user table */
|
/* check if the password is not set in the user table */
|
||||||
if (!strlen((char *)password)) {
|
return memcmp(password, null_client_sha1, MYSQL_SCRAMBLE_LEN) ? 1 : 0;
|
||||||
/* Username without password */
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*<
|
/*<
|
||||||
|
|||||||
@ -67,6 +67,7 @@ extern __thread log_info_t tls_log_info;
|
|||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 17/06/2013 Mark Riddoch Initial version
|
* 17/06/2013 Mark Riddoch Initial version
|
||||||
* 17/07/2013 Mark Riddoch Addition of login phase
|
* 17/07/2013 Mark Riddoch Addition of login phase
|
||||||
|
* 07/07/2015 Martin Brampton Call unified dcb_close on error
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -315,13 +316,13 @@ int n_connect = 0;
|
|||||||
|
|
||||||
if (telnetd_pr == NULL)
|
if (telnetd_pr == NULL)
|
||||||
{
|
{
|
||||||
dcb_add_to_zombieslist(client_dcb);
|
dcb_close(client_dcb);
|
||||||
return n_connect;
|
return n_connect;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll_add_dcb(client_dcb) == -1)
|
if (poll_add_dcb(client_dcb))
|
||||||
{
|
{
|
||||||
dcb_add_to_zombieslist(dcb);
|
dcb_close(dcb);
|
||||||
return n_connect;
|
return n_connect;
|
||||||
}
|
}
|
||||||
n_connect++;
|
n_connect++;
|
||||||
|
|||||||
Reference in New Issue
Block a user