This commit is contained in:
VilhoRaatikka
2014-10-06 11:51:47 +03:00
15 changed files with 332 additions and 137 deletions

View File

@ -108,6 +108,7 @@ if(NOT ( ${DEBBUILD} STREQUAL "DEBBUILD-NOTFOUND" ) )
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB") set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB")
execute_process(COMMAND dpgk --print-architecture OUTPUT_VARIABLE DEB_ARCHITECTURE) execute_process(COMMAND dpgk --print-architecture OUTPUT_VARIABLE DEB_ARCHITECTURE)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEB_ARCHITECTURE}) set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEB_ARCHITECTURE})
set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
message(STATUS "Generating DEB packages for ${DEB_ARCHITECTURE}") message(STATUS "Generating DEB packages for ${DEB_ARCHITECTURE}")
endif() endif()
@ -125,7 +126,6 @@ set(CPACK_RPM_SPEC_INSTALL_POST "/sbin/ldconfig")
set(CPACK_RPM_PACKAGE_NAME "maxscale") set(CPACK_RPM_PACKAGE_NAME "maxscale")
set(CPACK_RPM_PACKAGE_VENDOR "MariaDB Corporation Ab") set(CPACK_RPM_PACKAGE_VENDOR "MariaDB Corporation Ab")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2") set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_PACKAGE_AUTOREQPROV " no")
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/etc /etc/ld.so.conf.d /etc/init.d /etc/rc.d/init.d") set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/etc /etc/ld.so.conf.d /etc/init.d /etc/rc.d/init.d")
set(CPACK_RPM_SPEC_MORE_DEFINE "%define ignore \#") set(CPACK_RPM_SPEC_MORE_DEFINE "%define ignore \#")
set(CPACK_RPM_USER_FILELIST "%ignore /etc/init.d") set(CPACK_RPM_USER_FILELIST "%ignore /etc/init.d")
@ -136,6 +136,6 @@ add_custom_target(testall
COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR} COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR}
COMMAND make install COMMAND make install
COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null" COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null"
COMMAND make test COMMAND /bin/sh -c "make test || echo \"Test results written to: ${CMAKE_BINARY_DIR}/Testing/Temporary/\""
COMMAND /bin/sh -c "killall -KILL maxscale" COMMAND killall maxscale
COMMENT "Running full test suite") COMMENT "Running full test suite" VERBATIM)

View File

@ -47,7 +47,7 @@ CC=cc
CFLAGS=-c -I/usr/include -I../include -I../modules/include -I../inih \ CFLAGS=-c -I/usr/include -I../include -I../modules/include -I../inih \
$(MYSQL_HEADERS) \ $(MYSQL_HEADERS) \
-I$(LOGPATH) -I$(UTILSPATH) \ -I$(LOGPATH) -I$(UTILSPATH) \
-Wall -g -Wall -pedantic -g
LDFLAGS=-rdynamic -L$(LOGPATH) \ LDFLAGS=-rdynamic -L$(LOGPATH) \
-Wl,-rpath,$(DEST)/lib \ -Wl,-rpath,$(DEST)/lib \

View File

@ -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 * 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, * GNU General Public License as published by the Free Software Foundation,
* version 2. * version 2.
@ -13,11 +13,11 @@
* this program; if not, write to the Free Software Foundation, Inc., 51 * this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 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 * The buffer management is based on the principle of a linked list
* of variable size buffer, the intention beign to allow longer * of variable size buffer, the intention beign to allow longer
@ -65,20 +65,20 @@ gwbuf_alloc(unsigned int size)
GWBUF *rval; GWBUF *rval;
SHARED_BUF *sbuf; SHARED_BUF *sbuf;
// Allocate the buffer header /* Allocate the buffer header */
if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL) if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
{ {
return NULL; return NULL;
} }
// Allocate the shared data buffer /* Allocate the shared data buffer */
if ((sbuf = (SHARED_BUF *)malloc(sizeof(SHARED_BUF))) == NULL) if ((sbuf = (SHARED_BUF *)malloc(sizeof(SHARED_BUF))) == NULL)
{ {
free(rval); free(rval);
return NULL; return NULL;
} }
// Allocate the space for the actual data /* Allocate the space for the actual data */
if ((sbuf->data = (unsigned char *)malloc(size)) == NULL) if ((sbuf->data = (unsigned char *)malloc(size)) == NULL)
{ {
free(rval); free(rval);
@ -87,7 +87,7 @@ SHARED_BUF *sbuf;
} }
spinlock_init(&rval->gwbuf_lock); spinlock_init(&rval->gwbuf_lock);
rval->start = sbuf->data; rval->start = sbuf->data;
rval->end = (void*)((uint8_t*)rval->start + size); rval->end = (void *)((char *)rval->start+size);
sbuf->refcount = 1; sbuf->refcount = 1;
rval->sbuf = sbuf; rval->sbuf = sbuf;
rval->next = NULL; rval->next = NULL;
@ -197,8 +197,8 @@ GWBUF *gwbuf_clone_portion(
atomic_add(&buf->sbuf->refcount, 1); atomic_add(&buf->sbuf->refcount, 1);
clonebuf->sbuf = buf->sbuf; clonebuf->sbuf = buf->sbuf;
clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone info bits too */ clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone info bits too */
clonebuf->start = (void *)((char*)buf->start)+start_offset; clonebuf->start = (void *)((char*)buf->start+start_offset);
clonebuf->end = (void *)((char *)clonebuf->start)+length; clonebuf->end = (void *)((char *)clonebuf->start+length);
clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */ clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */
clonebuf->properties = NULL; clonebuf->properties = NULL;
clonebuf->hint = NULL; clonebuf->hint = NULL;
@ -277,8 +277,6 @@ return_clonebuf:
GWBUF * GWBUF *
gwbuf_append(GWBUF *head, GWBUF *tail) gwbuf_append(GWBUF *head, GWBUF *tail)
{ {
GWBUF *ptr = head;
if (!head) if (!head)
return tail; return tail;
CHK_GWBUF(head); CHK_GWBUF(head);
@ -311,7 +309,7 @@ GWBUF *rval = head;
CHK_GWBUF(head); CHK_GWBUF(head);
GWBUF_CONSUME(head, length); GWBUF_CONSUME(head, length);
CHK_GWBUF(head); CHK_GWBUF(head);
if (GWBUF_EMPTY(head)) if (GWBUF_EMPTY(head))
{ {
@ -370,11 +368,36 @@ gwbuf_trim(GWBUF *buf, unsigned int n_bytes)
gwbuf_consume(buf, GWBUF_LENGTH(buf)); gwbuf_consume(buf, GWBUF_LENGTH(buf));
return NULL; return NULL;
} }
buf->end -= n_bytes; buf->end = (void *)((char *)buf->end - n_bytes);
return buf; 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. * Set given type to all buffers on the list.
* * * *

View File

@ -131,7 +131,7 @@ CONFIG_PARAMETER *param, *p1;
ptr->element = NULL; ptr->element = NULL;
cntxt->next = ptr; 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; p1 = ptr->parameters;
while (p1) while (p1)
{ {

View File

@ -32,7 +32,7 @@
* 12/06/13 Mark Riddoch Initial implementation * 12/06/13 Mark Riddoch Initial implementation
* 21/06/13 Massimiliano Pinto free_dcb is used * 21/06/13 Massimiliano Pinto free_dcb is used
* 25/06/13 Massimiliano Pinto Added checks to session and router_session * 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 * introduce a zombie state for the
* dcb * dcb
* 02/07/2013 Massimiliano Pinto Addition of delayqlock, delayq and * 02/07/2013 Massimiliano Pinto Addition of delayqlock, delayq and
@ -73,7 +73,7 @@
extern int lm_enabled_logfiles_bitmask; 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 DCB *zombies = NULL;
static SPINLOCK dcbspin = SPINLOCK_INIT; static SPINLOCK dcbspin = SPINLOCK_INIT;
static SPINLOCK zombiespin = 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_write(DCB *dcb, GWBUF *buf);
static int dcb_null_close(DCB *dcb); static int dcb_null_close(DCB *dcb);
static int dcb_null_auth(DCB *dcb, SERVER *server, SESSION *session, GWBUF *buf); 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 * Return the pointer to the lsit of zombie DCB's
@ -1893,20 +1894,40 @@ dcb_isvalid(DCB *dcb)
DCB *ptr; DCB *ptr;
int rval = 0; int rval = 0;
if (dcb)
{
spinlock_acquire(&dcbspin); 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; ptr = allDCBs;
while (ptr) while (ptr && ptr != dcb)
{ {
if (ptr == dcb)
{
rval = 1;
break;
}
ptr = ptr->next; ptr = ptr->next;
} }
spinlock_release(&dcbspin); rval = (ptr == dcb);
}
return rval; return rval;
} }
@ -1919,33 +1940,11 @@ int rval = 0;
static DCB * static DCB *
dcb_get_next (DCB* dcb) dcb_get_next (DCB* dcb)
{ {
DCB* p;
spinlock_acquire(&dcbspin); spinlock_acquire(&dcbspin);
if (dcb) {
p = allDCBs; dcb = dcb_isvalid_nolock(dcb) ? dcb->next : NULL;
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;
}
} }
else dcb = allDCBs;
spinlock_release(&dcbspin); spinlock_release(&dcbspin);
return dcb; return dcb;

View File

@ -34,6 +34,7 @@
* 25-09-2013 Massimiliano Pinto setipaddress uses getaddrinfo * 25-09-2013 Massimiliano Pinto setipaddress uses getaddrinfo
* 06-02-2014 Mark Riddoch Added parse_bindconfig * 06-02-2014 Mark Riddoch Added parse_bindconfig
* 10-02-2014 Massimiliano Pinto Added return code to setipaddress * 10-02-2014 Massimiliano Pinto Added return code to setipaddress
* 02-09-2014 Martin Brampton Replace C++ comment with C comment
* *
*@endverbatim *@endverbatim
*/ */
@ -148,7 +149,7 @@ void gw_daemonize(void) {
} }
if (pid != 0) { if (pid != 0) {
// exit from main /* exit from main */
exit(0); exit(0);
} }

View File

@ -91,10 +91,10 @@ static void service_add_qualified_param(
* @param servname The service name * @param servname The service name
* @param router Name of the router module this service uses * @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 *
service_alloc(char *servname, char *router) service_alloc(const char *servname, const char *router)
{ {
SERVICE *service; SERVICE *service;
@ -152,7 +152,7 @@ SERVICE *service;
/** /**
* Check to see if a service pointer is valid * 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 * @return 1 if the service is in the list of all services
*/ */
int int

View File

@ -30,6 +30,7 @@
#include <spinlock.h> #include <spinlock.h>
#include <atomic.h> #include <atomic.h>
#include <time.h>
/** /**
* Initialise a spinlock. * Initialise a spinlock.
@ -39,13 +40,13 @@
void void
spinlock_init(SPINLOCK *lock) spinlock_init(SPINLOCK *lock)
{ {
lock->lock = 0; lock->lock = 0;
#if SPINLOCK_PROFILE #if SPINLOCK_PROFILE
lock->spins = 0; lock->spins = 0;
lock->acquired = 0; lock->acquired = 0;
lock->waiting = 0; lock->waiting = 0;
lock->max_waiting = 0; lock->max_waiting = 0;
lock->contended = 0; lock->contended = 0;
#endif #endif
} }
@ -62,24 +63,30 @@ int spins = 0;
atomic_add(&(lock->waiting), 1); atomic_add(&(lock->waiting), 1);
#endif #endif
while (atomic_add(&(lock->lock), 1) != 0)
{ #ifdef __GNUC__
atomic_add(&(lock->lock), -1); 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 #if SPINLOCK_PROFILE
atomic_add(&(lock->spins), 1); atomic_add(&(lock->spins), 1);
spins++; spins++;
#endif #endif
} }
#if SPINLOCK_PROFILE #if SPINLOCK_PROFILE
if (spins) if (spins)
{ {
lock->contended++; lock->contended++;
if (lock->maxspins < spins) if (lock->maxspins < spins)
lock->maxspins = spins; lock->maxspins = spins;
} }
lock->acquired++; lock->acquired++;
lock->owner = THREAD_SHELF(); lock->owner = THREAD_SHELF();
atomic_add(&(lock->waiting), -1); atomic_add(&(lock->waiting), -1);
#endif #endif
} }
@ -92,16 +99,20 @@ int spins = 0;
int int
spinlock_acquire_nowait(SPINLOCK *lock) spinlock_acquire_nowait(SPINLOCK *lock)
{ {
if (atomic_add(&(lock->lock), 1) != 0) #ifdef __GNUC__
{ if (__sync_lock_test_and_set(&(lock->lock), 1)) return FALSE;
atomic_add(&(lock->lock), -1); #else
return FALSE; if (atomic_add(&(lock->lock), 1) != 0)
} {
#if SPINLOCK_PROFILE atomic_add(&(lock->lock), -1);
lock->acquired++; return FALSE;
lock->owner = THREAD_SHELF(); }
#endif #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 void
spinlock_release(SPINLOCK *lock) spinlock_release(SPINLOCK *lock)
{ {
#if SPINLOCK_PROFILE #if SPINLOCK_PROFILE
if (lock->waiting > lock->max_waiting) if (lock->waiting > lock->max_waiting)
lock->max_waiting = lock->waiting; lock->max_waiting = lock->waiting;
#endif
#ifdef __GNUC__
__sync_synchronize(); /* Memory barrier. */
lock->lock = 0;
#else
atomic_add(&(lock->lock), -1);
#endif #endif
atomic_add(&(lock->lock), -1);
} }
/** /**

View File

@ -18,10 +18,11 @@ LDFLAGS=-rdynamic -L$(LOGPATH) -L$(EMBEDDED_LIB) \
-Wl,-rpath,$(LOGPATH) -Wl,-rpath,$(UTILSPATH) \ -Wl,-rpath,$(LOGPATH) -Wl,-rpath,$(UTILSPATH) \
-Wl,-rpath,$(EMBEDDED_LIB) -Wl,-rpath,$(EMBEDDED_LIB)
LIBS= -lz -lm -lcrypt -lcrypto -ldl -laio -lrt -pthread -llog_manager \ LIBS= -L$(EMBEDDED_LIB) -lmysqld \
-L../../inih/extra -linih -lssl -lstdc++ -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: cleantests:
- $(DEL) *.o - $(DEL) *.o
@ -47,6 +48,39 @@ testspinlock: testspinlock.c
-I$(ROOT_PATH)/utils \ -I$(ROOT_PATH)/utils \
testspinlock.c ../spinlock.o ../atomic.o ../thread.o -o testspinlock 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 testfilter: testfilter.c libcore.a
$(CC) $(CFLAGS) $(LDFLAGS) \ $(CC) $(CFLAGS) $(LDFLAGS) \
-I$(ROOT_PATH)/server/include \ -I$(ROOT_PATH)/server/include \

View File

@ -105,12 +105,16 @@ test2()
{ {
SPINLOCK lck; SPINLOCK lck;
void *handle; void *handle;
struct timespec sleeptime;
sleeptime.tv_sec = 10;
sleeptime.tv_nsec = 0;
acquire_time = 0; acquire_time = 0;
spinlock_init(&lck); spinlock_init(&lck);
spinlock_acquire(&lck); spinlock_acquire(&lck);
handle = thread_start(test2_helper, (void *)&lck); handle = thread_start(test2_helper, (void *)&lck);
sleep(10); nanosleep(&sleeptime, NULL);
spinlock_release(&lck); spinlock_release(&lck);
thread_wait(handle); thread_wait(handle);
@ -122,12 +126,118 @@ void *handle;
return 0; 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; int result = 0;
result += test1(); result += test1();
result += test2(); result += test2();
result += test3();
exit(result); exit(result);
} }

View File

@ -29,6 +29,7 @@
* the gwbuff strategy * the gwbuff strategy
* 13-06-2013 Massimiliano Pinto MaxScale local authentication * 13-06-2013 Massimiliano Pinto MaxScale local authentication
* basics * basics
* 02-09-2014 Martin Brampton Replaced C++ comments by C comments
* *
* @endverbatim * @endverbatim
*/ */
@ -44,19 +45,19 @@
extern int lm_enabled_logfiles_bitmask; 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' :\ #define char_val(X) (X >= '0' && X <= '9' ? X-'0' :\
X >= 'A' && X <= 'Z' ? X-'A'+10 :\ X >= 'A' && X <= 'Z' ? X-'A'+10 :\
X >= 'a' && X <= 'z' ? X-'a'+10 :\ X >= 'a' && X <= 'z' ? X-'a'+10 :\
'\177') '\177')
// used in the bin2hex function /* used in the bin2hex function */
char hex_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; char hex_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char hex_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz"; char hex_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
////////////////////////////////////////// /*****************************************
//backend read event triggered by EPOLLIN * backend read event triggered by EPOLLIN
////////////////////////////////////////// *****************************************/
int setnonblocking(int fd) { int setnonblocking(int fd) {
@ -91,17 +92,17 @@ char *gw_strend(register const char *s) {
return (char*) (s-1); return (char*) (s-1);
} }
/////////////////////////////// /*****************************************
// generate a random char * generate a random char
////////////////////////////// *****************************************/
static char gw_randomchar() { static char gw_randomchar() {
return (char)((rand() % 78) + 30); return (char)((rand() % 78) + 30);
} }
///////////////////////////////// /*****************************************
// generate a random string * generate a random string
// output must be pre allocated * output must be pre allocated
///////////////////////////////// *****************************************/
int gw_generate_random_str(char *output, int len) { int gw_generate_random_str(char *output, int len) {
int i; int i;
@ -116,10 +117,10 @@ int gw_generate_random_str(char *output, int len) {
return 0; return 0;
} }
///////////////////////////////// /*****************************************
// hex string to binary data * hex string to binary data
// output must be pre allocated * output must be pre allocated
///////////////////////////////// *****************************************/
int gw_hex2bin(uint8_t *out, const char *in, unsigned int len) { int gw_hex2bin(uint8_t *out, const char *in, unsigned int len) {
const char *in_end= in + 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; return 0;
} }
///////////////////////////////// /*****************************************
// binary data to hex string * binary data to hex string
// output must be pre allocated * output must be pre allocated
///////////////////////////////// *****************************************/
char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) { char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) {
const uint8_t *in_end= in + len; const uint8_t *in_end= in + len;
if (len == 0 || in == NULL) { if (len == 0 || in == NULL) {
@ -159,12 +160,12 @@ char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) {
return out; return out;
} }
/////////////////////////////////////////////////////// /****************************************************
// fill a preallocated buffer with XOR(str1, str2) * fill a preallocated buffer with XOR(str1, str2)
// XOR between 2 equal len strings * XOR between 2 equal len strings
// note that XOR(str1, XOR(str1 CONCAT str2)) == str2 * note that XOR(str1, XOR(str1 CONCAT str2)) == str2
// and that XOR(str1, str2) == XOR(str2, str1) * 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) { void gw_str_xor(uint8_t *output, const uint8_t *input1, const uint8_t *input2, unsigned int len) {
const uint8_t *input1_end = NULL; const uint8_t *input1_end = NULL;
input1_end = input1 + len; 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'; *output = '\0';
} }
///////////////////////////////////////////////////////////// /**********************************************************
// fill a 20 bytes preallocated with SHA1 digest (160 bits) * fill a 20 bytes preallocated with SHA1 digest (160 bits)
// for one input on in_len bytes * for one input on in_len bytes
///////////////////////////////////////////////////////////// **********************************************************/
void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out) { void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out) {
unsigned char hash[SHA_DIGEST_LENGTH]; 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); memcpy(out, hash, SHA_DIGEST_LENGTH);
} }
///////////////////////////////////////////////////////////// /********************************************************
// fill 20 bytes preallocated with SHA1 digest (160 bits) * fill 20 bytes preallocated with SHA1 digest (160 bits)
// for two inputs, in_len and in2_len bytes * 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) { 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; SHA_CTX context;
unsigned char hash[SHA_DIGEST_LENGTH]; unsigned char hash[SHA_DIGEST_LENGTH];

View File

@ -40,6 +40,9 @@
* 16/07/2013 Massimiliano Pinto Added command type for the queue * 16/07/2013 Massimiliano Pinto Added command type for the queue
* 10/07/2014 Mark Riddoch Addition of hints * 10/07/2014 Mark Riddoch Addition of hints
* 15/07/2014 Mark Riddoch Added buffer properties * 15/07/2014 Mark Riddoch Added buffer properties
* 03/10/2014 Martin Brampton Pointer arithmetic standard conformity
* Add more buffer handling macros
* Add gwbuf_rtrim (handle chains)
* *
* @endverbatim * @endverbatim
*/ */
@ -147,19 +150,25 @@ typedef struct gwbuf {
/*< /*<
* Macros to access the data in the buffers * Macros to access the data in the buffers
*/ */
/*< First valid, uncomsumed byte in the buffer */ /*< First valid, unconsumed byte in the buffer */
#define GWBUF_DATA(b) ((b)->start) #define GWBUF_DATA(b) ((b)->start)
/*< Number of bytes in the individual buffer */ /*< Number of bytes in the individual buffer */
#define GWBUF_LENGTH(b) ((unsigned int)(((uint8_t*)(b)->end) - ((uint8_t*)(b)->start))) #define GWBUF_LENGTH(b) ((char *)(b)->end - (char *)(b)->start)
/*< Return the byte at offset byte from the start of the unconsumed portion of the buffer */
#define GWBUF_DATA_CHAR(b, byte) (GWBUF_LENGTH(b) < ((byte)+1) ? -1 : *(((char *)(b)->start)+4))
/*< Check that the data in a buffer has the SQL marker*/
#define GWBUF_IS_SQL(b) (0x03 == GWBUF_DATA_CHAR(b,4))
/*< True if all bytes in the buffer have been consumed */ /*< True if all bytes in the buffer have been consumed */
#define GWBUF_EMPTY(b) ((b)->start == (b)->end) #define GWBUF_EMPTY(b) ((char *)(b)->start >= (char *)(b)->end)
/*< Consume a number of bytes in the buffer */ /*< Consume a number of bytes in the buffer */
#define GWBUF_CONSUME(b, bytes) (b)->start = (void*)((uint8_t*)(b)->start + (bytes)) #define GWBUF_CONSUME(b, bytes) ((b)->start = bytes > ((char *)(b)->end - (char *)(b)->start) ? (b)->end : (void *)((char *)(b)->start + (bytes)));
#define GWBUF_RTRIM(b, bytes) (b)->end = (void*)((uint8_t*)(b)->end - (bytes)) #define GWBUF_RTRIM(b, bytes) ((b)->end = bytes > ((char *)(b)->end - (char *)(b)->start) ? (b)->start : (void *)((char *)(b)->end - (bytes)));
#define GWBUF_TYPE(b) (b)->gwbuf_type #define GWBUF_TYPE(b) (b)->gwbuf_type
/*< /*<
@ -171,6 +180,7 @@ extern GWBUF *gwbuf_clone(GWBUF *buf);
extern GWBUF *gwbuf_append(GWBUF *head, GWBUF *tail); extern GWBUF *gwbuf_append(GWBUF *head, GWBUF *tail);
extern GWBUF *gwbuf_consume(GWBUF *head, unsigned int length); extern GWBUF *gwbuf_consume(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_trim(GWBUF *head, unsigned int length); extern GWBUF *gwbuf_trim(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_rtrim(GWBUF *head, unsigned int length);
extern unsigned int gwbuf_length(GWBUF *head); extern unsigned int gwbuf_length(GWBUF *head);
extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len); extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len);
extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type); extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type);

View File

@ -142,7 +142,7 @@ typedef enum count_spec_t {COUNT_NONE=0, COUNT_ATLEAST, COUNT_EXACT, COUNT_ATMOS
#define SERVICE_STATE_ALLOC 1 /**< The service has been allocated */ #define SERVICE_STATE_ALLOC 1 /**< The service has been allocated */
#define SERVICE_STATE_STARTED 2 /**< The service has been started */ #define SERVICE_STATE_STARTED 2 /**< The service has been started */
extern SERVICE *service_alloc(char *, char *); extern SERVICE *service_alloc(const char *, const char *);
extern int service_free(SERVICE *); extern int service_free(SERVICE *);
extern SERVICE *service_find(char *); extern SERVICE *service_find(char *);
extern int service_isvalid(SERVICE *); extern int service_isvalid(SERVICE *);

View File

@ -43,4 +43,5 @@ TMASTER_ID :=
# Global test log where all log is gathered # Global test log where all log is gathered
# TEST_MAXSCALE_LOG := $(ROOT_PATH)/test/test_maxscale.log # TEST_MAXSCALE_LOG := $(ROOT_PATH)/test/test_maxscale.log
# #
TEST_MAXSCALE_LOG := TEST_MAXSCALE_LOG := /home/mbrampton/Dropbox/skygit/MaxScale/test/testserver.log

View File

@ -474,7 +474,7 @@ typedef enum skygw_chk_t {
} }
#define CHK_GWBUF(b) { \ #define CHK_GWBUF(b) { \
ss_info_dassert(((b)->start <= (b)->end), \ ss_info_dassert(((char *)(b)->start <= (char *)(b)->end), \
"gwbuf start has passed the endpoint"); \ "gwbuf start has passed the endpoint"); \
} }