MaxScale/core/dcb.c
Mark Riddoch a9bcc3841a Converted mysql_send_ok and MySQLSendHandshake to use the new buffer management
Also added the -p option to set listener port. This is a short term measure for testing only
until we have the proper configuration in place.
2013-06-12 17:13:04 +01:00

178 lines
3.8 KiB
C

/*
* This file is distributed as part of the SkySQL Gateway. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
*/
/*
* dcb.c - Descriptor Control Block generic functions
*
* Revision History
*
* Date Who Description
* 12/06/13 Mark Riddoch Initial implementation
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dcb.h>
#include <spinlock.h>
static DCB *allDCBs = NULL; /* Diagnotics need a list of DCBs */
static SPINLOCK *dcbspin = NULL;
/*
* Allocate a new DCB.
*
* This routine performs the generic initialisation on the DCB before returning
* the newly allocated DCB.
*
* @return A newly allocated DCB or NULL if non could be allocated.
*/
DCB *
alloc_dcb()
{
DCB *rval;
if (dcbspin == NULL)
{
if ((dcbspin = malloc(sizeof(SPINLOCK))) == NULL)
return NULL;
spinlock_init(dcbspin);
}
if ((rval = malloc(sizeof(DCB))) == NULL)
{
return NULL;
}
spinlock_init(&rval->writeqlock);
rval->writeq = NULL;
rval->state = DCB_STATE_ALLOC;
memset(&rval->stats, 0, sizeof(DCBSTATS)); // Zero the statistics
spinlock_acquire(dcbspin);
if (allDCBs == NULL)
allDCBs = rval;
else
{
DCB *ptr = allDCBs;
while (ptr->next)
ptr = ptr->next;
ptr->next = rval;
}
spinlock_release(dcbspin);
return rval;
}
/*
* Free a DCB and remove it from the chain of all DCBs
*
* @param dcb THe DCB to free
*/
void
free_dcb(DCB *dcb)
{
dcb->state = DCB_STATE_FREED;
/* First remove this DCB from the chain */
spinlock_acquire(dcbspin);
if (allDCBs == dcb)
allDCBs = dcb->next;
else
{
DCB *ptr = allDCBs;
while (ptr && ptr->next != dcb)
ptr = ptr->next;
if (ptr)
ptr->next = dcb->next;
}
spinlock_release(dcbspin);
free(dcb);
}
/*
* Diagnostic to print a DCB
*
* @param dcb The DCB to print
*
*/
void
printDCB(DCB *dcb)
{
(void)printf("DCB: 0x%x\n", (void *)dcb);
(void)printf("\tDCB state: %s\n", gw_dcb_state2string(dcb->state));
(void)printf("\tQueued write data: %d\n", gwbuf_length(dcb->writeq));
(void)printf("\tStatistics:\n");
(void)printf("\t\tNo. of Reads: %d\n", dcb->stats.n_reads);
(void)printf("\t\tNo. of Writes: %d\n", dcb->stats.n_writes);
(void)printf("\t\tNo. of Buffered Writes: %d\n", dcb->stats.n_buffered);
(void)printf("\t\tNo. of Accepts: %d\n", dcb->stats.n_accepts);
}
/*
* Diagnostic to print all DCB allocated in the system
*
*/
void printAllDCBs()
{
DCB *dcb;
if (dcbspin == NULL)
{
if ((dcbspin = malloc(sizeof(SPINLOCK))) == NULL)
return;
spinlock_init(dcbspin);
}
spinlock_acquire(dcbspin);
dcb = allDCBs;
while (dcb)
{
printDCB(dcb);
dcb = dcb->next;
}
spinlock_release(dcbspin);
}
/*
* Return a string representation of a DCB state.
*
* @param state The DCB state
* @return String representation of the state
*
*/
const char *
gw_dcb_state2string (int state) {
switch(state) {
case DCB_STATE_ALLOC:
return "DCB Allocated";
case DCB_STATE_IDLE:
return "DCB not yet in polling";
case DCB_STATE_POLLING:
return "DCB in the EPOLL";
case DCB_STATE_PROCESSING:
return "DCB processing event";
case DCB_STATE_LISTENING:
return "DCB for listening socket";
case DCB_STATE_DISCONNECTED:
return "DCB socket closed";
case DCB_STATE_FREED:
return "DCB memory could be freed";
default:
return "DCB (unknown)";
}
}