develop branch merged
develop branch merged
This commit is contained in:
@ -47,7 +47,7 @@ CC=cc
|
||||
CFLAGS=-c -I/usr/include -I../include -I../modules/include -I../inih \
|
||||
$(MYSQL_HEADERS) \
|
||||
-I$(LOGPATH) -I$(UTILSPATH) \
|
||||
-Wall -g
|
||||
-Wall -pedantic -g
|
||||
|
||||
LDFLAGS=-rdynamic -L$(LOGPATH) \
|
||||
-Wl,-rpath,$(DEST)/lib \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
|
||||
* 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.
|
||||
@ -13,11 +13,11 @@
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright MariaDB Corporation Ab 2013-2014
|
||||
* Copyright SkySQL Ab 2013
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file buffer.h - The MaxScale buffer management functions
|
||||
* @file buffer.h - The Gateway buffer management functions
|
||||
*
|
||||
* The buffer management is based on the principle of a linked list
|
||||
* of variable size buffer, the intention beign to allow longer
|
||||
@ -42,6 +42,8 @@
|
||||
#include <buffer.h>
|
||||
#include <atomic.h>
|
||||
#include <skygw_debug.h>
|
||||
#include <spinlock.h>
|
||||
#include <hint.h>
|
||||
|
||||
static buffer_object_t* gwbuf_remove_buffer_object(
|
||||
GWBUF* buf,
|
||||
@ -65,20 +67,20 @@ gwbuf_alloc(unsigned int size)
|
||||
GWBUF *rval;
|
||||
SHARED_BUF *sbuf;
|
||||
|
||||
// Allocate the buffer header
|
||||
/* Allocate the buffer header */
|
||||
if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate the shared data buffer
|
||||
/* Allocate the shared data buffer */
|
||||
if ((sbuf = (SHARED_BUF *)malloc(sizeof(SHARED_BUF))) == NULL)
|
||||
{
|
||||
free(rval);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate the space for the actual data
|
||||
/* Allocate the space for the actual data */
|
||||
if ((sbuf->data = (unsigned char *)malloc(size)) == NULL)
|
||||
{
|
||||
free(rval);
|
||||
@ -87,7 +89,7 @@ SHARED_BUF *sbuf;
|
||||
}
|
||||
spinlock_init(&rval->gwbuf_lock);
|
||||
rval->start = sbuf->data;
|
||||
rval->end = (void*)((uint8_t*)rval->start + size);
|
||||
rval->end = (void *)((char *)rval->start+size);
|
||||
sbuf->refcount = 1;
|
||||
rval->sbuf = sbuf;
|
||||
rval->next = NULL;
|
||||
@ -197,8 +199,8 @@ GWBUF *gwbuf_clone_portion(
|
||||
atomic_add(&buf->sbuf->refcount, 1);
|
||||
clonebuf->sbuf = buf->sbuf;
|
||||
clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone info bits too */
|
||||
clonebuf->start = (void *)((char*)buf->start)+start_offset;
|
||||
clonebuf->end = (void *)((char *)clonebuf->start)+length;
|
||||
clonebuf->start = (void *)((char*)buf->start+start_offset);
|
||||
clonebuf->end = (void *)((char *)clonebuf->start+length);
|
||||
clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */
|
||||
clonebuf->properties = NULL;
|
||||
clonebuf->hint = NULL;
|
||||
@ -277,8 +279,6 @@ return_clonebuf:
|
||||
GWBUF *
|
||||
gwbuf_append(GWBUF *head, GWBUF *tail)
|
||||
{
|
||||
GWBUF *ptr = head;
|
||||
|
||||
if (!head)
|
||||
return tail;
|
||||
CHK_GWBUF(head);
|
||||
@ -311,7 +311,7 @@ GWBUF *rval = head;
|
||||
|
||||
CHK_GWBUF(head);
|
||||
GWBUF_CONSUME(head, length);
|
||||
CHK_GWBUF(head);
|
||||
CHK_GWBUF(head);
|
||||
|
||||
if (GWBUF_EMPTY(head))
|
||||
{
|
||||
@ -370,11 +370,36 @@ gwbuf_trim(GWBUF *buf, unsigned int n_bytes)
|
||||
gwbuf_consume(buf, GWBUF_LENGTH(buf));
|
||||
return NULL;
|
||||
}
|
||||
buf->end -= n_bytes;
|
||||
buf->end = (void *)((char *)buf->end - n_bytes);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim bytes from the end of a GWBUF structure that may be the first
|
||||
* in a list. If the buffer has n_bytes or less then it will be freed and
|
||||
* the next buffer in the list will be returned, or if none, NULL.
|
||||
*
|
||||
* @param head The buffer to trim
|
||||
* @param n_bytes The number of bytes to trim off
|
||||
* @return The buffer chain or NULL if buffer chain now empty
|
||||
*/
|
||||
GWBUF *
|
||||
gwbuf_rtrim(GWBUF *head, unsigned int n_bytes)
|
||||
{
|
||||
GWBUF *rval = head;
|
||||
CHK_GWBUF(head);
|
||||
GWBUF_RTRIM(head, n_bytes);
|
||||
CHK_GWBUF(head);
|
||||
|
||||
if (GWBUF_EMPTY(head))
|
||||
{
|
||||
rval = head->next;
|
||||
gwbuf_free(head);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set given type to all buffers on the list.
|
||||
* *
|
||||
|
@ -41,6 +41,7 @@
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
#include <my_config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
@ -131,7 +132,7 @@ CONFIG_PARAMETER *param, *p1;
|
||||
ptr->element = NULL;
|
||||
cntxt->next = ptr;
|
||||
}
|
||||
/* Check to see if the paramter already exists for the section */
|
||||
/* Check to see if the parameter already exists for the section */
|
||||
p1 = ptr->parameters;
|
||||
while (p1)
|
||||
{
|
||||
|
@ -32,7 +32,7 @@
|
||||
* 12/06/13 Mark Riddoch Initial implementation
|
||||
* 21/06/13 Massimiliano Pinto free_dcb is used
|
||||
* 25/06/13 Massimiliano Pinto Added checks to session and router_session
|
||||
* 28/06/13 Mark Riddoch Changed the free mechanism ti
|
||||
* 28/06/13 Mark Riddoch Changed the free mechanism to
|
||||
* introduce a zombie state for the
|
||||
* dcb
|
||||
* 02/07/2013 Massimiliano Pinto Addition of delayqlock, delayq and
|
||||
@ -73,7 +73,7 @@
|
||||
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
|
||||
static DCB *allDCBs = NULL; /* Diagnotics need a list of DCBs */
|
||||
static DCB *allDCBs = NULL; /* Diagnostics need a list of DCBs */
|
||||
static DCB *zombies = NULL;
|
||||
static SPINLOCK dcbspin = SPINLOCK_INIT;
|
||||
static SPINLOCK zombiespin = SPINLOCK_INIT;
|
||||
@ -88,6 +88,7 @@ static DCB* dcb_get_next (DCB* dcb);
|
||||
static int dcb_null_write(DCB *dcb, GWBUF *buf);
|
||||
static int dcb_null_close(DCB *dcb);
|
||||
static int dcb_null_auth(DCB *dcb, SERVER *server, SESSION *session, GWBUF *buf);
|
||||
static int dcb_isvalid_nolock(DCB *dcb);
|
||||
|
||||
/**
|
||||
* Return the pointer to the lsit of zombie DCB's
|
||||
@ -1893,20 +1894,40 @@ dcb_isvalid(DCB *dcb)
|
||||
DCB *ptr;
|
||||
int rval = 0;
|
||||
|
||||
if (dcb)
|
||||
{
|
||||
spinlock_acquire(&dcbspin);
|
||||
rval = dcb_isvalid_nolock(dcb);
|
||||
spinlock_release(&dcbspin);
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check the passed DCB to ensure it is in the list of allDCBS.
|
||||
* Requires that the DCB list is already locked before call.
|
||||
*
|
||||
* @param dcb The DCB to check
|
||||
* @return 1 if the DCB is in the list, otherwise 0
|
||||
*/
|
||||
static int
|
||||
dcb_isvalid_nolock(DCB *dcb)
|
||||
{
|
||||
DCB *ptr;
|
||||
int rval = 0;
|
||||
|
||||
if (dcb)
|
||||
{
|
||||
ptr = allDCBs;
|
||||
while (ptr)
|
||||
while (ptr && ptr != dcb)
|
||||
{
|
||||
if (ptr == dcb)
|
||||
{
|
||||
rval = 1;
|
||||
break;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
spinlock_release(&dcbspin);
|
||||
|
||||
return rval;
|
||||
rval = (ptr == dcb);
|
||||
}
|
||||
return rval;
|
||||
}
|
||||
|
||||
|
||||
@ -1919,33 +1940,11 @@ int rval = 0;
|
||||
static DCB *
|
||||
dcb_get_next (DCB* dcb)
|
||||
{
|
||||
DCB* p;
|
||||
|
||||
spinlock_acquire(&dcbspin);
|
||||
|
||||
p = allDCBs;
|
||||
|
||||
if (dcb == NULL || p == NULL)
|
||||
{
|
||||
dcb = p;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
while (p != NULL && dcb != p)
|
||||
{
|
||||
p = p->next;
|
||||
}
|
||||
|
||||
if (p != NULL)
|
||||
{
|
||||
dcb = p->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
dcb = NULL;
|
||||
}
|
||||
if (dcb) {
|
||||
dcb = dcb_isvalid_nolock(dcb) ? dcb->next : NULL;
|
||||
}
|
||||
else dcb = allDCBs;
|
||||
spinlock_release(&dcbspin);
|
||||
|
||||
return dcb;
|
||||
|
@ -40,10 +40,13 @@
|
||||
* @endverbatim
|
||||
*/
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <my_config.h>
|
||||
#include <ftw.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <gw.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <getopt.h>
|
||||
#include <service.h>
|
||||
#include <server.h>
|
||||
@ -226,7 +229,6 @@ sigfatal_handler (int i)
|
||||
|
||||
{
|
||||
void *addrs[128];
|
||||
char **strings= NULL;
|
||||
int n, count = backtrace(addrs, 128);
|
||||
char** symbols = backtrace_symbols( addrs, count );
|
||||
|
||||
@ -1088,9 +1090,9 @@ int main(int argc, char **argv)
|
||||
goto return_main;
|
||||
|
||||
case 'l':
|
||||
if (strncasecmp(optarg, "file") == 0)
|
||||
if (strncasecmp(optarg, "file", PATH_MAX) == 0)
|
||||
logtofile = 1;
|
||||
else if (strncasecmp(optarg, "shm") == 0)
|
||||
else if (strncasecmp(optarg, "shm", PATH_MAX) == 0)
|
||||
logtofile = 0;
|
||||
else
|
||||
{
|
||||
@ -1669,6 +1671,8 @@ static void log_flush_cb(
|
||||
void* arg)
|
||||
{
|
||||
ssize_t timeout_ms = *(ssize_t *)arg;
|
||||
const struct timespec ts1 = {0, 1000000*timeout_ms};
|
||||
struct timespec ts2;
|
||||
|
||||
LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE,
|
||||
"Started MaxScale log flusher.")));
|
||||
@ -1677,7 +1681,7 @@ static void log_flush_cb(
|
||||
skygw_log_flush(LOGFILE_MESSAGE);
|
||||
skygw_log_flush(LOGFILE_TRACE);
|
||||
skygw_log_flush(LOGFILE_DEBUG);
|
||||
usleep(timeout_ms*1000);
|
||||
nanosleep(&ts1, &ts2);
|
||||
}
|
||||
LOGIF(LM, (skygw_log_write(LOGFILE_MESSAGE,
|
||||
"Finished MaxScale log flusher.")));
|
||||
|
@ -34,6 +34,7 @@
|
||||
* 25-09-2013 Massimiliano Pinto setipaddress uses getaddrinfo
|
||||
* 06-02-2014 Mark Riddoch Added parse_bindconfig
|
||||
* 10-02-2014 Massimiliano Pinto Added return code to setipaddress
|
||||
* 02-09-2014 Martin Brampton Replace C++ comment with C comment
|
||||
*
|
||||
*@endverbatim
|
||||
*/
|
||||
@ -148,7 +149,7 @@ void gw_daemonize(void) {
|
||||
}
|
||||
|
||||
if (pid != 0) {
|
||||
// exit from main
|
||||
/* exit from main */
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*
|
||||
* Copyright MariaDB Corporation Ab 2013-2014
|
||||
*/
|
||||
#include <my_config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -257,7 +258,7 @@ poll_add_dcb(DCB *dcb)
|
||||
dcb,
|
||||
STRDCBSTATE(dcb->state))));
|
||||
}
|
||||
ss_dassert(rc == 0); /*< trap in debug */
|
||||
ss_info_dassert(rc == 0, "Unable to add poll"); /*< trap in debug */
|
||||
} else {
|
||||
LOGIF(LE, (skygw_log_write_flush(
|
||||
LOGFILE_ERROR,
|
||||
|
@ -136,7 +136,7 @@ SERVER *ptr;
|
||||
/**
|
||||
* Set a unique name for the server
|
||||
*
|
||||
* @param server The server to ste the name on
|
||||
* @param server The server to set the name on
|
||||
* @param name The unique name for the server
|
||||
*/
|
||||
void
|
||||
|
@ -91,10 +91,10 @@ static void service_add_qualified_param(
|
||||
* @param servname The service name
|
||||
* @param router Name of the router module this service uses
|
||||
*
|
||||
* @return The newly created service or NULL if an error occured
|
||||
* @return The newly created service or NULL if an error occurred
|
||||
*/
|
||||
SERVICE *
|
||||
service_alloc(char *servname, char *router)
|
||||
service_alloc(const char *servname, const char *router)
|
||||
{
|
||||
SERVICE *service;
|
||||
|
||||
@ -152,7 +152,7 @@ SERVICE *service;
|
||||
/**
|
||||
* Check to see if a service pointer is valid
|
||||
*
|
||||
* @param service The poitner to check
|
||||
* @param service The pointer to check
|
||||
* @return 1 if the service is in the list of all services
|
||||
*/
|
||||
int
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include <spinlock.h>
|
||||
#include <atomic.h>
|
||||
#include <time.h>
|
||||
|
||||
/**
|
||||
* Initialise a spinlock.
|
||||
@ -39,13 +40,13 @@
|
||||
void
|
||||
spinlock_init(SPINLOCK *lock)
|
||||
{
|
||||
lock->lock = 0;
|
||||
lock->lock = 0;
|
||||
#if SPINLOCK_PROFILE
|
||||
lock->spins = 0;
|
||||
lock->acquired = 0;
|
||||
lock->waiting = 0;
|
||||
lock->max_waiting = 0;
|
||||
lock->contended = 0;
|
||||
lock->spins = 0;
|
||||
lock->acquired = 0;
|
||||
lock->waiting = 0;
|
||||
lock->max_waiting = 0;
|
||||
lock->contended = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -62,24 +63,30 @@ int spins = 0;
|
||||
|
||||
atomic_add(&(lock->waiting), 1);
|
||||
#endif
|
||||
while (atomic_add(&(lock->lock), 1) != 0)
|
||||
{
|
||||
atomic_add(&(lock->lock), -1);
|
||||
|
||||
#ifdef __GNUC__
|
||||
while (__sync_lock_test_and_set(&(lock->lock), 1))
|
||||
while (lock->lock) {
|
||||
#else
|
||||
while (atomic_add(&(lock->lock), 1) != 0)
|
||||
{
|
||||
atomic_add(&(lock->lock), -1);
|
||||
#endif
|
||||
#if SPINLOCK_PROFILE
|
||||
atomic_add(&(lock->spins), 1);
|
||||
spins++;
|
||||
#endif
|
||||
}
|
||||
#if SPINLOCK_PROFILE
|
||||
if (spins)
|
||||
{
|
||||
lock->contended++;
|
||||
if (lock->maxspins < spins)
|
||||
lock->maxspins = spins;
|
||||
}
|
||||
lock->acquired++;
|
||||
lock->owner = THREAD_SHELF();
|
||||
atomic_add(&(lock->waiting), -1);
|
||||
if (spins)
|
||||
{
|
||||
lock->contended++;
|
||||
if (lock->maxspins < spins)
|
||||
lock->maxspins = spins;
|
||||
}
|
||||
lock->acquired++;
|
||||
lock->owner = THREAD_SHELF();
|
||||
atomic_add(&(lock->waiting), -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -92,16 +99,20 @@ int spins = 0;
|
||||
int
|
||||
spinlock_acquire_nowait(SPINLOCK *lock)
|
||||
{
|
||||
if (atomic_add(&(lock->lock), 1) != 0)
|
||||
{
|
||||
atomic_add(&(lock->lock), -1);
|
||||
return FALSE;
|
||||
}
|
||||
#if SPINLOCK_PROFILE
|
||||
lock->acquired++;
|
||||
lock->owner = THREAD_SHELF();
|
||||
#ifdef __GNUC__
|
||||
if (__sync_lock_test_and_set(&(lock->lock), 1)) return FALSE;
|
||||
#else
|
||||
if (atomic_add(&(lock->lock), 1) != 0)
|
||||
{
|
||||
atomic_add(&(lock->lock), -1);
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
return TRUE;
|
||||
#if SPINLOCK_PROFILE
|
||||
lock->acquired++;
|
||||
lock->owner = THREAD_SHELF();
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -112,11 +123,16 @@ spinlock_acquire_nowait(SPINLOCK *lock)
|
||||
void
|
||||
spinlock_release(SPINLOCK *lock)
|
||||
{
|
||||
#if SPINLOCK_PROFILE
|
||||
if (lock->waiting > lock->max_waiting)
|
||||
lock->max_waiting = lock->waiting;
|
||||
#if SPINLOCK_PROFILE
|
||||
if (lock->waiting > lock->max_waiting)
|
||||
lock->max_waiting = lock->waiting;
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
__sync_synchronize(); /* Memory barrier. */
|
||||
lock->lock = 0;
|
||||
#else
|
||||
atomic_add(&(lock->lock), -1);
|
||||
#endif
|
||||
atomic_add(&(lock->lock), -1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,16 +1,40 @@
|
||||
add_executable(test_mysql_users test_mysql_users.c)
|
||||
add_executable(test_hash testhash.c)
|
||||
add_executable(test_hint testhint.c)
|
||||
add_executable(test_spinlock testspinlock.c)
|
||||
add_executable(test_filter testfilter.c)
|
||||
add_executable(test_buffer testbuffer.c)
|
||||
add_executable(test_dcb testdcb.c)
|
||||
add_executable(test_modutil testmodutil.c)
|
||||
add_executable(test_poll testpoll.c)
|
||||
add_executable(test_service testservice.c)
|
||||
add_executable(test_server testserver.c)
|
||||
add_executable(test_users testusers.c)
|
||||
add_executable(test_adminusers testadminusers.c)
|
||||
target_link_libraries(test_mysql_users fullcore MySQLClient)
|
||||
target_link_libraries(test_hash fullcore)
|
||||
target_link_libraries(test_hint fullcore)
|
||||
target_link_libraries(test_spinlock fullcore)
|
||||
target_link_libraries(test_filter fullcore)
|
||||
target_link_libraries(test_buffer fullcore)
|
||||
target_link_libraries(test_dcb fullcore)
|
||||
target_link_libraries(test_modutil fullcore)
|
||||
target_link_libraries(test_poll fullcore)
|
||||
target_link_libraries(test_service fullcore)
|
||||
target_link_libraries(test_server fullcore)
|
||||
target_link_libraries(test_users fullcore)
|
||||
target_link_libraries(test_adminusers fullcore)
|
||||
add_test(testMySQLUsers test_mysql_users)
|
||||
add_test(TestHash test_hash)
|
||||
add_test(TestHint test_hint)
|
||||
add_test(TestSpinlock test_spinlock)
|
||||
add_test(TestFilter test_filter)
|
||||
add_test(TestBuffer test_buffer)
|
||||
add_test(TestDCB test_dcb)
|
||||
add_test(TestModutil test_modutil)
|
||||
add_test(TestPoll test_poll)
|
||||
add_test(TestService test_service)
|
||||
add_test(TestServer test_server)
|
||||
add_test(TestUsers test_users)
|
||||
add_test(TestAdminUsers test_adminusers)
|
||||
|
||||
|
@ -18,10 +18,11 @@ LDFLAGS=-rdynamic -L$(LOGPATH) -L$(EMBEDDED_LIB) \
|
||||
-Wl,-rpath,$(LOGPATH) -Wl,-rpath,$(UTILSPATH) \
|
||||
-Wl,-rpath,$(EMBEDDED_LIB)
|
||||
|
||||
LIBS= -lz -lm -lcrypt -lcrypto -ldl -laio -lrt -pthread -llog_manager \
|
||||
-L../../inih/extra -linih -lssl -lstdc++ -lmysqld
|
||||
LIBS= -L$(EMBEDDED_LIB) -lmysqld \
|
||||
-lz -lm -lcrypt -lcrypto -ldl -laio -lrt -pthread -llog_manager \
|
||||
-L../../inih/extra -linih -lssl -lstdc++
|
||||
|
||||
TESTS=testhash testspinlock testfilter testadminusers
|
||||
TESTS=testhash testspinlock testbuffer testmodutil testpoll testservice testdcb testfilter testadminusers
|
||||
|
||||
cleantests:
|
||||
- $(DEL) *.o
|
||||
@ -47,6 +48,39 @@ testspinlock: testspinlock.c
|
||||
-I$(ROOT_PATH)/utils \
|
||||
testspinlock.c ../spinlock.o ../atomic.o ../thread.o -o testspinlock
|
||||
|
||||
testmodutil: testmodutil.c
|
||||
$(CC) $(CFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
-I$(ROOT_PATH)/utils \
|
||||
testmodutil.c ../modutil.o ../buffer.o ../atomic.o -o testmodutil
|
||||
|
||||
testbuffer: testbuffer.c
|
||||
$(CC) $(CFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
-I$(ROOT_PATH)/utils \
|
||||
testbuffer.c ../buffer.o ../atomic.o -o testbuffer
|
||||
|
||||
testpoll: testpoll.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
-I$(ROOT_PATH)/utils \
|
||||
-I$(ROOT_PATH)/log_manager \
|
||||
testpoll.c libcore.a $(UTILSPATH)/skygw_utils.o $(LIBS) -o testpoll
|
||||
|
||||
testservice: testservice.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
-I$(ROOT_PATH)/utils \
|
||||
-I$(ROOT_PATH)/log_manager \
|
||||
testservice.c libcore.a $(UTILSPATH)/skygw_utils.o $(LIBS) -o testservice
|
||||
|
||||
testdcb: testdcb.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
-I$(ROOT_PATH)/utils \
|
||||
-I$(ROOT_PATH)/log_manager \
|
||||
testdcb.c libcore.a $(UTILSPATH)/skygw_utils.o $(LIBS) -o testdcb
|
||||
|
||||
testfilter: testfilter.c libcore.a
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) \
|
||||
-I$(ROOT_PATH)/server/include \
|
||||
|
158
server/core/test/testbuffer.c
Normal file
158
server/core/test/testbuffer.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 29-08-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <buffer.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate a buffer and do lots of things
|
||||
*
|
||||
*/
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
GWBUF *buffer, *extra, *clone, *partclone, *transform;
|
||||
int size = 100;
|
||||
int bite1 = 35;
|
||||
int bite2 = 60;
|
||||
int bite3 = 10;
|
||||
int buflen;
|
||||
|
||||
/* Single buffer tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testbuffer : creating buffer with data size %d bytes",
|
||||
size);
|
||||
buffer = gwbuf_alloc(size);
|
||||
ss_dfprintf(stderr, "\t..done\nAllocated buffer of size %d.", size);
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "\nBuffer length is now %d", buflen);
|
||||
ss_info_dassert(size == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(0 == GWBUF_EMPTY(buffer), "Buffer should not be empty");
|
||||
ss_info_dassert(GWBUF_IS_TYPE_UNDEFINED(buffer), "Buffer type should be undefined");
|
||||
ss_dfprintf(stderr, "\t..done\nSet a property for the buffer");
|
||||
gwbuf_add_property(buffer, "name", "value");
|
||||
ss_info_dassert(0 == strcmp("value", gwbuf_get_property(buffer, "name")), "Should now have correct property");
|
||||
strcpy(GWBUF_DATA(buffer), "The quick brown fox jumps over the lazy dog");
|
||||
ss_dfprintf(stderr, "\t..done\nLoad some data into the buffer");
|
||||
ss_info_dassert('q' == GWBUF_DATA_CHAR(buffer, 4), "Fourth character of buffer must be 'q'");
|
||||
ss_info_dassert(-1 == GWBUF_DATA_CHAR(buffer, 105), "Hundred and fifth character of buffer must return -1");
|
||||
ss_info_dassert(0 == GWBUF_IS_SQL(buffer), "Must say buffer is not SQL, as it does not have marker");
|
||||
strcpy(GWBUF_DATA(buffer), "1234\x03SELECT * FROM sometable");
|
||||
ss_dfprintf(stderr, "\t..done\nLoad SQL data into the buffer");
|
||||
ss_info_dassert(1 == GWBUF_IS_SQL(buffer), "Must say buffer is SQL, as it does have marker");
|
||||
transform = gwbuf_clone_transform(buffer, GWBUF_TYPE_PLAINSQL);
|
||||
ss_dfprintf(stderr, "\t..done\nAttempt to transform buffer to plain SQL - should fail");
|
||||
ss_info_dassert(NULL == transform, "Buffer cannot be transformed to plain SQL");
|
||||
gwbuf_set_type(buffer, GWBUF_TYPE_MYSQL);
|
||||
ss_dfprintf(stderr, "\t..done\nChanged buffer type to MySQL");
|
||||
ss_info_dassert(GWBUF_IS_TYPE_MYSQL(buffer), "Buffer type changed to MySQL");
|
||||
transform = gwbuf_clone_transform(buffer, GWBUF_TYPE_PLAINSQL);
|
||||
ss_dfprintf(stderr, "\t..done\nAttempt to transform buffer to plain SQL - should succeed");
|
||||
ss_info_dassert((NULL != transform) && (GWBUF_IS_TYPE_PLAINSQL(transform)), "Transformed buffer is plain SQL");
|
||||
clone = gwbuf_clone(buffer);
|
||||
ss_dfprintf(stderr, "\t..done\nCloned buffer");
|
||||
buflen = GWBUF_LENGTH(clone);
|
||||
ss_dfprintf(stderr, "\nCloned buffer length is now %d", buflen);
|
||||
ss_info_dassert(size == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(0 == GWBUF_EMPTY(clone), "Cloned buffer should not be empty");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
gwbuf_free(clone);
|
||||
ss_dfprintf(stderr, "Freed cloned buffer");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
partclone = gwbuf_clone_portion(buffer, 25, 50);
|
||||
buflen = GWBUF_LENGTH(partclone);
|
||||
ss_dfprintf(stderr, "Part cloned buffer length is now %d", buflen);
|
||||
ss_info_dassert(50 == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(0 == GWBUF_EMPTY(partclone), "Part cloned buffer should not be empty");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
gwbuf_free(partclone);
|
||||
ss_dfprintf(stderr, "Freed part cloned buffer");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
buffer = gwbuf_consume(buffer, bite1);
|
||||
ss_info_dassert(NULL != buffer, "Buffer should not be null");
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "Consumed %d bytes, now have %d, should have %d", bite1, buflen, size-bite1);
|
||||
ss_info_dassert((size - bite1) == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(0 == GWBUF_EMPTY(buffer), "Buffer should not be empty");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
buffer = gwbuf_consume(buffer, bite2);
|
||||
ss_info_dassert(NULL != buffer, "Buffer should not be null");
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "Consumed %d bytes, now have %d, should have %d", bite2, buflen, size-bite1-bite2);
|
||||
ss_info_dassert((size-bite1-bite2) == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(0 == GWBUF_EMPTY(buffer), "Buffer should not be empty");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
buffer = gwbuf_consume(buffer, bite3);
|
||||
ss_dfprintf(stderr, "Consumed %d bytes, should have null buffer", bite3);
|
||||
ss_info_dassert(NULL == buffer, "Buffer should be null");
|
||||
|
||||
/* Buffer list tests */
|
||||
size = 100000;
|
||||
buffer = gwbuf_alloc(size);
|
||||
ss_dfprintf(stderr, "\t..done\nAllocated buffer of size %d.", size);
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "\nBuffer length is now %d", buflen);
|
||||
ss_info_dassert(size == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(0 == GWBUF_EMPTY(buffer), "Buffer should not be empty");
|
||||
ss_info_dassert(GWBUF_IS_TYPE_UNDEFINED(buffer), "Buffer type should be undefined");
|
||||
extra = gwbuf_alloc(size);
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "\t..done\nAllocated extra buffer of size %d.", size);
|
||||
ss_info_dassert(size == buflen, "Incorrect buffer size");
|
||||
buffer = gwbuf_append(buffer, extra);
|
||||
buflen = gwbuf_length(buffer);
|
||||
ss_dfprintf(stderr, "\t..done\nAppended extra buffer to original buffer to create list of size %d", buflen);
|
||||
ss_info_dassert((size*2) == gwbuf_length(buffer), "Incorrect size for set of buffers");
|
||||
buffer = gwbuf_rtrim(buffer, 60000);
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "\t..done\nTrimmed 60 bytes from buffer, now size is %d.", buflen);
|
||||
ss_info_dassert((size-60000) == buflen, "Incorrect buffer size");
|
||||
buffer = gwbuf_rtrim(buffer, 60000);
|
||||
buflen = GWBUF_LENGTH(buffer);
|
||||
ss_dfprintf(stderr, "\t..done\nTrimmed another 60 bytes from buffer, now size is %d.", buflen);
|
||||
ss_info_dassert(100000 == buflen, "Incorrect buffer size");
|
||||
ss_info_dassert(buffer == extra, "The buffer pointer should now point to the extra buffer");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
||||
|
87
server/core/test/testdcb.c
Normal file
87
server/core/test/testdcb.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 05-09-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <dcb.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate a dcb and do lots of other things
|
||||
*
|
||||
*/
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
DCB *dcb, *extra, *clone;
|
||||
int size = 100;
|
||||
int bite1 = 35;
|
||||
int bite2 = 60;
|
||||
int bite3 = 10;
|
||||
int buflen;
|
||||
|
||||
/* Single buffer tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testdcb : creating buffer with type DCB_ROLE_SERVICE_LISTENER");
|
||||
dcb = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);
|
||||
ss_info_dassert(dcb_isvalid(dcb), "New DCB must be valid");
|
||||
ss_dfprintf(stderr, "\t..done\nAllocated dcb.");
|
||||
clone = dcb_clone(dcb);
|
||||
ss_dfprintf(stderr, "\t..done\nCloned dcb");
|
||||
printAllDCBs();
|
||||
ss_info_dassert(true, "Something is true");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
dcb_free(dcb);
|
||||
ss_dfprintf(stderr, "Freed original dcb");
|
||||
ss_info_dassert(!dcb_isvalid(dcb), "Freed DCB must not be valid");
|
||||
ss_dfprintf(stderr, "\t..done\nMake clone DCB a zombie");
|
||||
clone->state = DCB_STATE_NOPOLLING;
|
||||
dcb_add_to_zombieslist(clone);
|
||||
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");
|
||||
dcb_process_zombies(0);
|
||||
ss_dfprintf(stderr, "\t..done\nCheck clone no longer valid");
|
||||
ss_info_dassert(!dcb_isvalid(clone), "After zombie processing, clone DCB must not be valid");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
||||
|
||||
|
69
server/core/test/testhint.c
Normal file
69
server/core/test/testhint.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 08-10-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <hint.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate table of users and mess around with it
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
HINT *hint;
|
||||
|
||||
/* Hint tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testhint : Add a parameter hint to a null list");
|
||||
hint = hint_create_parameter(NULL, strdup("name"), "value");
|
||||
ss_info_dassert(NULL != hint, "New hint list should not be null");
|
||||
ss_info_dassert(0 == strcmp("value", hint->value), "Hint value should be correct");
|
||||
ss_info_dassert(0 != hint_exists(hint, HINT_PARAMETER), "Hint of parameter type should exist");
|
||||
ss_dfprintf(stderr, "\t..done\nFree hints.");
|
||||
if (NULL != hint) hint_free(hint);
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
78
server/core/test/testmodutil.c
Normal file
78
server/core/test/testmodutil.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 17-09-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <modutil.h>
|
||||
#include <buffer.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate a service and do lots of other things
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
GWBUF *buffer;
|
||||
char *(sql[100]);
|
||||
int result, length, residual;
|
||||
|
||||
/* Poll tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testmodutil : Rudimentary tests.");
|
||||
buffer = gwbuf_alloc(100);
|
||||
ss_info_dassert(0 == modutil_is_SQL(buffer), "Default buffer should be diagnosed as not SQL");
|
||||
/* There would ideally be some straightforward way to create a SQL buffer? */
|
||||
ss_dfprintf(stderr, "\t..done\nExtract SQL from buffer");
|
||||
ss_info_dassert(0 == modutil_extract_SQL(buffer, sql, &length), "Default buffer should fail");
|
||||
ss_dfprintf(stderr, "\t..done\nExtract SQL from buffer different way?");
|
||||
ss_info_dassert(0 == modutil_MySQL_Query(buffer, sql, &length, &residual), "Default buffer should fail");
|
||||
ss_dfprintf(stderr, "\t..done\nReplace SQL in buffer");
|
||||
ss_info_dassert(0 == modutil_replace_SQL(buffer, "select * from some_table;"), "Default buffer should fail");
|
||||
ss_dfprintf(stderr, "\t..done\nTidy up.");
|
||||
gwbuf_free(buffer);
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
||||
|
77
server/core/test/testpoll.c
Normal file
77
server/core/test/testpoll.c
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 11-09-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <dcb.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate a service and do lots of other things
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
DCB *dcb;
|
||||
int result;
|
||||
|
||||
/* Poll tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testpoll : Initialise the polling system.");
|
||||
poll_init();
|
||||
ss_dfprintf(stderr, "\t..done\nAdd a DCB");
|
||||
dcb = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);
|
||||
dcb->fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
poll_add_dcb(dcb);
|
||||
poll_remove_dcb(dcb);
|
||||
poll_add_dcb(dcb);
|
||||
ss_dfprintf(stderr, "\t..done\nStart wait for events.");
|
||||
sleep(10);
|
||||
poll_shutdown();
|
||||
ss_dfprintf(stderr, "\t..done\nTidy up.");
|
||||
dcb_free(dcb);
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
92
server/core/test/testserver.c
Normal file
92
server/core/test/testserver.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 08-10-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <server.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate a server and do lots of other things
|
||||
*
|
||||
*/
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
SERVER *server;
|
||||
int result;
|
||||
char *status;
|
||||
|
||||
/* Server tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testserver : creating server called MyServer");
|
||||
server = server_alloc("MyServer", "HTTPD", 9876);
|
||||
|
||||
|
||||
//ss_info_dassert(NULL != service, "New server with valid protocol and port must not be null");
|
||||
//ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
|
||||
|
||||
ss_dfprintf(stderr, "\t..done\nTest Parameter for Server.");
|
||||
ss_info_dassert(NULL == serverGetParameter(server, "name"), "Parameter should be null when not set");
|
||||
serverAddParameter(server, "name", "value");
|
||||
ss_info_dassert(0 == strcmp("value", serverGetParameter(server, "name")), "Parameter should be returned correctly");
|
||||
ss_dfprintf(stderr, "\t..done\nTesting Unique Name for Server.");
|
||||
ss_info_dassert(NULL == server_find_by_unique_name("uniquename"), "Should not find non-existent unique name.");
|
||||
server_set_unique_name(server, "uniquename");
|
||||
ss_info_dassert(server == server_find_by_unique_name("uniquename"), "Should find by unique name.");
|
||||
ss_dfprintf(stderr, "\t..done\nTesting Status Setting for Server.");
|
||||
status = server_status(server);
|
||||
ss_info_dassert(0 == strcmp("Down", status), "Status of Server should be Down prior to being set.");
|
||||
if (NULL != status) free(status);
|
||||
server_set_status(server, SERVER_MASTER);
|
||||
status = server_status(server);
|
||||
ss_info_dassert(0 == strcmp("Master, Down", status), "Should find correct status.");
|
||||
server_clear_status(server, SERVER_MASTER);
|
||||
ss_info_dassert(0 == strcmp("Down", status), "Status of Server should be Down after status cleared.");
|
||||
if (NULL != status) free(status);
|
||||
ss_dfprintf(stderr, "\t..done\nRun Prints for Server and all Servers.");
|
||||
printServer(server);
|
||||
printAllServers();
|
||||
ss_dfprintf(stderr, "\t..done\nFreeing Server.");
|
||||
ss_info_dassert(0 != server_free(server), "Free should succeed");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
86
server/core/test/testservice.c
Normal file
86
server/core/test/testservice.c
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 08-09-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <service.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate a service and do lots of other things
|
||||
*
|
||||
*/
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
SERVICE *service;
|
||||
int result;
|
||||
|
||||
/* Service tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testservice : creating service called MyService with router nonexistent");
|
||||
service = service_alloc("MyService", "non-existent");
|
||||
ss_info_dassert(NULL == service, "New service with invalid router should be null");
|
||||
ss_info_dassert(0 == service_isvalid(service), "Service must not be valid after incorrect creation");
|
||||
ss_dfprintf(stderr, "\t..done\nValid service creation, router testroute.");
|
||||
service = service_alloc("MyService", "testroute");
|
||||
ss_info_dassert(NULL != service, "New service with valid router must not be null");
|
||||
ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
|
||||
ss_info_dassert(0 == strcmp("MyService", service_get_name(service)), "Service must have given name");
|
||||
ss_dfprintf(stderr, "\t..done\nAdding protocol HTTPD.");
|
||||
ss_info_dassert(0 != serviceAddProtocol(service, "HTTPD", "localhost", 9876), "Add Protocol should succeed");
|
||||
ss_info_dassert(0 != serviceHasProtocol(service, "HTTPD", 9876), "Service should have new protocol as requested");
|
||||
serviceStartProtocol(service, "HTTPD", 9876);
|
||||
ss_dfprintf(stderr, "\t..done\nStarting Service.");
|
||||
result = serviceStart(service);
|
||||
ss_info_dassert(0 != result, "Start should succeed");
|
||||
result = serviceStop(service);
|
||||
ss_info_dassert(0 != result, "Stop should succeed");
|
||||
result = serviceStartAll();
|
||||
ss_info_dassert(0 != result, "Start all should succeed");
|
||||
|
||||
ss_dfprintf(stderr, "\t..done\nStopping Service.");
|
||||
ss_info_dassert(0 != serviceStop(service), "Stop should succeed");
|
||||
ss_dfprintf(stderr, "\t..done\nFreeing Service.");
|
||||
ss_info_dassert(0 != service_free(service), "Free should succeed");
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
@ -105,12 +105,16 @@ test2()
|
||||
{
|
||||
SPINLOCK lck;
|
||||
void *handle;
|
||||
struct timespec sleeptime;
|
||||
|
||||
sleeptime.tv_sec = 10;
|
||||
sleeptime.tv_nsec = 0;
|
||||
|
||||
acquire_time = 0;
|
||||
spinlock_init(&lck);
|
||||
spinlock_acquire(&lck);
|
||||
handle = thread_start(test2_helper, (void *)&lck);
|
||||
sleep(10);
|
||||
nanosleep(&sleeptime, NULL);
|
||||
spinlock_release(&lck);
|
||||
thread_wait(handle);
|
||||
|
||||
@ -122,12 +126,118 @@ void *handle;
|
||||
return 0;
|
||||
}
|
||||
|
||||
main(int argc, char **argv)
|
||||
/**
|
||||
* test3 spinlock_acquire tests process bound threads
|
||||
*
|
||||
* Check that spinlock correctly blocks all other threads whilst the spinlock
|
||||
* is held.
|
||||
*
|
||||
* Start multiple threads that obtain spinlock and run process bound
|
||||
*/
|
||||
#define THREADS 5
|
||||
#define ITERATIONS 50000
|
||||
#define PROCESS_LOOP 10000
|
||||
#define SECONDS 15
|
||||
#define NANOTIME 100000
|
||||
|
||||
static int times_run, failures;
|
||||
static volatile int active;
|
||||
static int threadrun[THREADS];
|
||||
static int nowait[THREADS];
|
||||
static SPINLOCK lck;
|
||||
static void
|
||||
test3_helper(void *data)
|
||||
{
|
||||
// SPINLOCK *lck = (SPINLOCK *)data;
|
||||
int i;
|
||||
int n = *(int *)data;
|
||||
struct timespec sleeptime;
|
||||
time_t rawtime;
|
||||
|
||||
sleeptime.tv_sec = 0;
|
||||
sleeptime.tv_nsec = 1;
|
||||
|
||||
while (1) {
|
||||
if (spinlock_acquire_nowait(&lck)) {
|
||||
nowait[n]++;
|
||||
}
|
||||
else {
|
||||
spinlock_acquire(&lck);
|
||||
}
|
||||
if (times_run++ > ITERATIONS) {
|
||||
break;
|
||||
}
|
||||
threadrun[n]++;
|
||||
/*
|
||||
if (99 == (times_run % 100)) {
|
||||
time ( &rawtime );
|
||||
fprintf(stderr, "%s Done %d iterations of test, in thread %d.\n", asctime (localtime ( &rawtime )), times_run, n);
|
||||
}
|
||||
*/
|
||||
if (0 != active) {
|
||||
fprintf(stderr, "spinlock: test 3 failed with active non-zero after lock obtained.\n");
|
||||
failures++;
|
||||
}
|
||||
else {
|
||||
active = 1;
|
||||
for (i=0; i<PROCESS_LOOP; i++);
|
||||
}
|
||||
active = 0;
|
||||
spinlock_release(&lck);
|
||||
for (i=0; i<(4*PROCESS_LOOP); i++);
|
||||
// nanosleep(&sleeptime, NULL);
|
||||
}
|
||||
spinlock_release(&lck);
|
||||
}
|
||||
|
||||
static int
|
||||
test3()
|
||||
{
|
||||
// SPINLOCK lck;
|
||||
void *handle[THREADS];
|
||||
int i;
|
||||
int tnum[THREADS];
|
||||
time_t rawtime;
|
||||
|
||||
struct timespec sleeptime;
|
||||
|
||||
sleeptime.tv_sec = 20;
|
||||
sleeptime.tv_nsec = NANOTIME;
|
||||
|
||||
times_run = 0;
|
||||
active = 0;
|
||||
failures = 0;
|
||||
spinlock_init(&lck);
|
||||
time ( &rawtime );
|
||||
fprintf(stderr, "%s Starting %d threads.\n", asctime (localtime ( &rawtime )), THREADS);
|
||||
for (i = 0; i<THREADS; i++) {
|
||||
threadrun[i] = 0;
|
||||
tnum[i] = i;
|
||||
handle[i] = thread_start(test3_helper, &tnum[i]);
|
||||
}
|
||||
for (i = 0; i<THREADS; i++) {
|
||||
fprintf(stderr, "spinlock_test 3 thread %d ran %d times, no wait %d times before waits.\n", i, threadrun[i], nowait[i]);
|
||||
}
|
||||
for (i = 0; i<THREADS; i++) {
|
||||
time ( &rawtime );
|
||||
fprintf(stderr, "%s spinlock_test 3 finished sleeps, about to wait for thread %d.\n", asctime (localtime ( &rawtime )), i);
|
||||
thread_wait(handle[i]);
|
||||
}
|
||||
for (i = 0; i<THREADS; i++) {
|
||||
fprintf(stderr, "spinlock_test 3 thread %d ran %d times, no wait %d times.\n", i, threadrun[i], nowait[i]);
|
||||
}
|
||||
time ( &rawtime );
|
||||
fprintf(stderr, "%s spinlock_test 3 completed, %d failures.\n", asctime (localtime ( &rawtime )), failures);
|
||||
return 0 == failures ? 0: 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
result += test2();
|
||||
result += test3();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
81
server/core/test/testusers.c
Normal file
81
server/core/test/testusers.c
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is distributed as part of MaxScale. 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 2014
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @verbatim
|
||||
* Revision History
|
||||
*
|
||||
* Date Who Description
|
||||
* 08-10-2014 Martin Brampton Initial implementation
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <users.h>
|
||||
|
||||
/**
|
||||
* test1 Allocate table of users and mess around with it
|
||||
*
|
||||
*/
|
||||
|
||||
static int
|
||||
test1()
|
||||
{
|
||||
USERS *users;
|
||||
int result, count;
|
||||
|
||||
/* Poll tests */
|
||||
ss_dfprintf(stderr,
|
||||
"testusers : Initialise the user table.");
|
||||
users = users_alloc();
|
||||
ss_info_dassert(NULL != users, "Allocating user table should not return NULL.")
|
||||
ss_dfprintf(stderr, "\t..done\nAdd a user");
|
||||
count = users_add(users, "username", "authorisation");
|
||||
ss_info_dassert(1 == count, "Should add one user");
|
||||
ss_info_dassert(strcmp("authorisation", users_fetch(users, "username")), "User authorisation should be correct");
|
||||
ss_dfprintf(stderr, "\t..done\nPrint users");
|
||||
usersPrint(users);
|
||||
ss_dfprintf(stderr, "\t..done\nUpdate a user");
|
||||
count = users_update(users, "username", "newauth");
|
||||
ss_info_dassert(1 == count, "Should update just one user");
|
||||
ss_info_dassert(strcmp("newauth", users_fetch(users, "username")), "User authorisation should be correctly updated");
|
||||
ss_dfprintf(stderr, "\t..done\nDelete a user.");
|
||||
count = users_delete(users, "username");
|
||||
ss_info_dassert(1 == count, "Should delete just one user");
|
||||
ss_dfprintf(stderr, "\t..done\nFree user table.");
|
||||
users_free(users);
|
||||
ss_dfprintf(stderr, "\t..done\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
result += test1();
|
||||
|
||||
exit(result);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
* the gwbuff strategy
|
||||
* 13-06-2013 Massimiliano Pinto MaxScale local authentication
|
||||
* basics
|
||||
* 02-09-2014 Martin Brampton Replaced C++ comments by C comments
|
||||
*
|
||||
* @endverbatim
|
||||
*/
|
||||
@ -44,19 +45,19 @@
|
||||
|
||||
extern int lm_enabled_logfiles_bitmask;
|
||||
|
||||
// used in the hex2bin function
|
||||
/* used in the hex2bin function */
|
||||
#define char_val(X) (X >= '0' && X <= '9' ? X-'0' :\
|
||||
X >= 'A' && X <= 'Z' ? X-'A'+10 :\
|
||||
X >= 'a' && X <= 'z' ? X-'a'+10 :\
|
||||
'\177')
|
||||
|
||||
// used in the bin2hex function
|
||||
/* used in the bin2hex function */
|
||||
char hex_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
char hex_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
//////////////////////////////////////////
|
||||
//backend read event triggered by EPOLLIN
|
||||
//////////////////////////////////////////
|
||||
/*****************************************
|
||||
* backend read event triggered by EPOLLIN
|
||||
*****************************************/
|
||||
|
||||
|
||||
int setnonblocking(int fd) {
|
||||
@ -91,17 +92,17 @@ char *gw_strend(register const char *s) {
|
||||
return (char*) (s-1);
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// generate a random char
|
||||
//////////////////////////////
|
||||
/*****************************************
|
||||
* generate a random char
|
||||
*****************************************/
|
||||
static char gw_randomchar() {
|
||||
return (char)((rand() % 78) + 30);
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// generate a random string
|
||||
// output must be pre allocated
|
||||
/////////////////////////////////
|
||||
/*****************************************
|
||||
* generate a random string
|
||||
* output must be pre allocated
|
||||
*****************************************/
|
||||
int gw_generate_random_str(char *output, int len) {
|
||||
|
||||
int i;
|
||||
@ -116,10 +117,10 @@ int gw_generate_random_str(char *output, int len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// hex string to binary data
|
||||
// output must be pre allocated
|
||||
/////////////////////////////////
|
||||
/*****************************************
|
||||
* hex string to binary data
|
||||
* output must be pre allocated
|
||||
*****************************************/
|
||||
int gw_hex2bin(uint8_t *out, const char *in, unsigned int len) {
|
||||
const char *in_end= in + len;
|
||||
|
||||
@ -140,10 +141,10 @@ int gw_hex2bin(uint8_t *out, const char *in, unsigned int len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// binary data to hex string
|
||||
// output must be pre allocated
|
||||
/////////////////////////////////
|
||||
/*****************************************
|
||||
* binary data to hex string
|
||||
* output must be pre allocated
|
||||
*****************************************/
|
||||
char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) {
|
||||
const uint8_t *in_end= in + len;
|
||||
if (len == 0 || in == NULL) {
|
||||
@ -159,12 +160,12 @@ char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) {
|
||||
return out;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// fill a preallocated buffer with XOR(str1, str2)
|
||||
// XOR between 2 equal len strings
|
||||
// note that XOR(str1, XOR(str1 CONCAT str2)) == str2
|
||||
// and that XOR(str1, str2) == XOR(str2, str1)
|
||||
///////////////////////////////////////////////////////
|
||||
/****************************************************
|
||||
* fill a preallocated buffer with XOR(str1, str2)
|
||||
* XOR between 2 equal len strings
|
||||
* note that XOR(str1, XOR(str1 CONCAT str2)) == str2
|
||||
* and that XOR(str1, str2) == XOR(str2, str1)
|
||||
*****************************************************/
|
||||
void gw_str_xor(uint8_t *output, const uint8_t *input1, const uint8_t *input2, unsigned int len) {
|
||||
const uint8_t *input1_end = NULL;
|
||||
input1_end = input1 + len;
|
||||
@ -175,10 +176,10 @@ void gw_str_xor(uint8_t *output, const uint8_t *input1, const uint8_t *input2, u
|
||||
*output = '\0';
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// fill a 20 bytes preallocated with SHA1 digest (160 bits)
|
||||
// for one input on in_len bytes
|
||||
/////////////////////////////////////////////////////////////
|
||||
/**********************************************************
|
||||
* fill a 20 bytes preallocated with SHA1 digest (160 bits)
|
||||
* for one input on in_len bytes
|
||||
**********************************************************/
|
||||
void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out) {
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
|
||||
@ -186,10 +187,10 @@ void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out) {
|
||||
memcpy(out, hash, SHA_DIGEST_LENGTH);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// fill 20 bytes preallocated with SHA1 digest (160 bits)
|
||||
// for two inputs, in_len and in2_len bytes
|
||||
/////////////////////////////////////////////////////////////
|
||||
/********************************************************
|
||||
* fill 20 bytes preallocated with SHA1 digest (160 bits)
|
||||
* for two inputs, in_len and in2_len bytes
|
||||
********************************************************/
|
||||
void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out) {
|
||||
SHA_CTX context;
|
||||
unsigned char hash[SHA_DIGEST_LENGTH];
|
||||
|
Reference in New Issue
Block a user