diff --git a/lladd/arrayCollection.h b/lladd/arrayCollection.h new file mode 100644 index 0000000..13cf6bb --- /dev/null +++ b/lladd/arrayCollection.h @@ -0,0 +1,8 @@ + +lladdIterator_t * arrayIterator(byte * keyArray, unsigned int keySize, + byte * valueArray, unsigned int valueSize, + unsigned int elementCount); +void arrayIterator_close(int xid, void * impl); +int arrayIterator_next (int xid, void * impl); +int arrayIterator_key (int xid, void * impl, byte ** key); +int arrayIterator_value(int xid, void * impl, byte ** value); diff --git a/lladd/compensations.h b/lladd/compensations.h index 0503abc..08ebdc3 100644 --- a/lladd/compensations.h +++ b/lladd/compensations.h @@ -113,22 +113,26 @@ void compensation_set_error(int code); #define end while(0); if(compensation_error()) return; }while(0) #define end_ret(x) while(0); if(compensation_error()) return (x); }while(0) +extern int ___compensation_count___; + #define begin_action(func, var) \ if(compensation_error()) return; \ do{ \ void (*_func_)(void*); \ + assert(func); \ pthread_cleanup_push(_func_=(void(*)(void*))(func), (void*)(var));\ + assert(_func_); \ do /** @todo compensation variables don't need _func_ anymore. */ #define end_action \ while(0); \ - pthread_cleanup_pop(_func_ && compensation_error()); \ + pthread_cleanup_pop(/*_func_ &&*/compensation_error()); \ if(compensation_error()) return; \ } while(0) #define compensate \ while(0); \ - pthread_cleanup_pop((int)_func_); \ + pthread_cleanup_pop(1/*(int)_func_*/); \ if(compensation_error()) return; \ } while(0) @@ -141,13 +145,13 @@ void compensation_set_error(int code); #define end_action_ret(ret) \ while(0); \ - pthread_cleanup_pop(_func_ && compensation_error()); \ + pthread_cleanup_pop(/*_func_ &&*/compensation_error()); \ if(compensation_error()) return (ret); \ } while(0) #define compensate_ret(ret) \ while(0); \ - pthread_cleanup_pop((int)_func_); \ + pthread_cleanup_pop(1/*(int)_func*/); \ if(compensation_error()) return (ret); \ } while(0) diff --git a/lladd/iterator.h b/lladd/iterator.h new file mode 100644 index 0000000..46b0d73 --- /dev/null +++ b/lladd/iterator.h @@ -0,0 +1,74 @@ +#include + +#ifndef __ITERATOR_H +#define __ITERATOR_H + +#define MAX_ITERATOR_TYPES 10 +#define LINEAR_HASH_NTA_ITERATOR 0 +#define ARRAY_ITERATOR 1 + +typedef struct { + // void * new(void * arg); + void (*close)(int xid, void * it); + int (*next) (int xid, void * it); + int (*key) (int xid, void * it, byte ** key); + int (*value)(int xid, void * it, byte ** value); +} lladdIterator_def_t; + +typedef struct { + int type; + void * impl; +} lladdIterator_t; + +void iterator_init(); + +//void lladdIterator_register(int type, lladdIterator_def_t info); + +//lladdIterator_t Titerator(int type, void * arg); + +void Titerator_close(int xid, lladdIterator_t * it); + +/** + @param it the iterator + + @return 1 if the iterator position could advance, or 0 at end of iterator. + + @throw stanard lladd error values. + +*/ +int Titerator_next(int xid, lladdIterator_t * it); + +/** + This function allows the caller to access the current iterator + position. When an iterator is initialized, it is in the 'null' + position. Therefore, this call may not be made until + lladdIterator_next has been called. Calling this function after + lladdIterator_next has returned zero, or raised a compensation + error will have undefined results. + + Iterator support for concurrent modification is implementation + specfic and optional. + + @param it the iterator + + @param key a pointer to the current key of the iterator. This + memory is managed by the iterator implementation. + + @return the size of the value stored in key, or -1 if the + iterator's backing store does not have a concept of keys. + (-1 is used to distinguish 'empty key' from 'no key') + + @throw standard lladd error values + + @see lladdIterator_value +*/ +int Titerator_key(int xid, lladdIterator_t * it, byte ** key); +/** + Analagour to lladdIterator_key. + + @see lladdIterator_key. +*/ +int Titerator_value(int xid, lladdIterator_t * it, byte ** value); + +#endif + diff --git a/lladd/operations.h b/lladd/operations.h index 5ad282d..d384627 100644 --- a/lladd/operations.h +++ b/lladd/operations.h @@ -57,7 +57,8 @@ terms specified in this license. #include #include #include - +#include +#include BEGIN_C_DECLS diff --git a/lladd/operations/linearHashNTA.h b/lladd/operations/linearHashNTA.h index abc43dd..6b8205f 100644 --- a/lladd/operations/linearHashNTA.h +++ b/lladd/operations/linearHashNTA.h @@ -20,6 +20,8 @@ */ +#include + #ifndef __LINEAR_HASH_NTA_H #define __LINEAR_HASH_NTA_H /** Currently, only used in the type field of the iterators. */ @@ -60,6 +62,7 @@ compensated_function int ThashLookup(int xid, recordid hash, const byte* key, in @param hash the recordid returned by ThashAlloc @param keySize the same as the value passed into ThashAlloc. @param valueSize the same as the value passed into ThashAlloc + @deprecated @see interator.h. Use the linearHash implementation of that interface instead. */ lladd_hash_iterator * ThashIterator(int xid, recordid hash, int keySize, int valueSize); /** @@ -81,11 +84,16 @@ lladd_hash_iterator * ThashIterator(int xid, recordid hash, int keySize, int val semantics. @param value analagous to value. @param valueSize analagous to keySize + + @deprecated @see interator.h. Use the linearHash implementation of that interface instead. */ int ThashNext(int xid, lladd_hash_iterator * it, byte ** key, int * keySize, byte** value, int * valueSize); -/** Free the hash iterator and its associated resources. */ +/** Free the hash iterator and its associated resources. + @deprecated @see interator.h. Use the linearHash implementation of that interface instead. + +*/ void ThashDone(int xid, lladd_hash_iterator * it); Operation getLinearHashInsert(); @@ -93,6 +101,17 @@ Operation getLinearHashRemove(); void LinearHashNTAInit(); +/** Iterator that complies with the standard LLADD iterator interface. + @todo current generic linearHashIterator implemnetation is just slapped on top of old, slow interface. + @todo rename ThashGenericIterator to ThashIterator, and remove deprecated iterator interface... +*/ + +//void * linearHashNTAIterator_new (void * arg); +lladdIterator_t * ThashGenericIterator (int xid, recordid hash); +void linearHashNTAIterator_close(int xid, void * it); +int linearHashNTAIterator_next (int xid, void * it); +int linearHashNTAIterator_key (int xid, void * it, byte **key); +int linearHashNTAIterator_value(int xid, void * it, byte **value); //Support 16 entries by default. #define HASH_INIT_BITS 4 diff --git a/src/lladd/Makefile.am b/src/lladd/Makefile.am index 0366572..12ca5fa 100644 --- a/src/lladd/Makefile.am +++ b/src/lladd/Makefile.am @@ -5,7 +5,7 @@ lib_LIBRARIES=liblladd.a # removed: recovery.c transactional.c logger.c logger/logparser.c logger/logstreamer.c liblladd_a_SOURCES=crc32.c common.c stats.c io.c bufferManager.c linkedlist.c operations.c \ pageFile.c pageCache.c page.c blobManager.c recovery2.c transactional2.c \ - lockManager.c \ + lockManager.c iterator.c arrayCollection.c \ logger/logEntry.c logger/logWriter.c logger/logHandle.c logger/logger2.c \ logger/logMemory.c \ page/slotted.c page/header.c page/fixed.c compensations.c \ diff --git a/src/lladd/arrayCollection.c b/src/lladd/arrayCollection.c new file mode 100644 index 0000000..a01cadf --- /dev/null +++ b/src/lladd/arrayCollection.c @@ -0,0 +1,68 @@ +#include +#include +#include +typedef struct { + byte * keyArray; + byte * valueArray; + unsigned int element; + unsigned int keySize; + unsigned int valueSize; + unsigned int elementCount; +} array_iterator_t; + + +lladdIterator_t * arrayIterator(byte * keyArray, unsigned int keySize, + byte * valueArray, unsigned int valueSize, + unsigned int elementCount) { + lladdIterator_t * ret = malloc(sizeof(lladdIterator_t)); + ret->type = ARRAY_ITERATOR; + array_iterator_t * it = ret->impl = malloc(sizeof(array_iterator_t)); + + it->keyArray = keyArray; + it->valueArray = valueArray; + + it->element = -1; + + it->valueSize = valueSize; + it->keySize = keySize; + it->elementCount = elementCount; + + return ret; +} + +void arrayIterator_close(int xid, void * impl) { + free(impl); +} + +int arrayIterator_next (int xid, void * impl) { + array_iterator_t * it = (array_iterator_t *) impl; + it->element++; + return it->element < it->elementCount; +} +int arrayIterator_key (int xid, void * impl, byte ** key) { + array_iterator_t * it = (array_iterator_t *) impl; + // unsigned int offset = it->element * (it->valueSize + it->keySize); + *key = &(it->keyArray[it->element * it->keySize]); + // printf("elt = %d, s = %d, k = %x\n", it->element, it->keySize, *key); + return it->keySize; +} +int arrayIterator_value(int xid, void * impl, byte ** value) { + array_iterator_t * it = (array_iterator_t *) impl; + // unsigned int offset = it->element * (it->valueSize + it->keySize); + *value = &(it->valueArray[it->element * it->valueSize]); + // printf("elt = %d, s = %d, v = %x\n", it->element, it->valueSize, *value); + return it->valueSize; +} + + +typedef struct { + byte * array; + int element; + int elementSize; + int elementCount; +} pointer_array_iterator_t; + + +/*lladdIterator_t * ptrArray_iterator(byte * array, int elementCount) { + +}*/ diff --git a/src/lladd/compensations.c b/src/lladd/compensations.c index f7a1c2b..89d0b1f 100644 --- a/src/lladd/compensations.c +++ b/src/lladd/compensations.c @@ -1,5 +1,7 @@ #include +int ___compensation_count___ = 0; + #include #include #include @@ -9,7 +11,7 @@ static pthread_key_t error_key; void compensations_init () { int ret = pthread_key_create(&error_key, NULL); assert(!ret); - pthread_setspecific(error_key, NULL); + pthread_setspecific(error_key, NULL); } void compensations_deinit() { diff --git a/src/lladd/iterator.c b/src/lladd/iterator.c new file mode 100644 index 0000000..c3cd0dd --- /dev/null +++ b/src/lladd/iterator.c @@ -0,0 +1,33 @@ +#include +#include +#include + +#include +#include + + +static lladdIterator_def_t iterators[MAX_ITERATOR_TYPES]; + +static void lladdIterator_register(int type, lladdIterator_def_t info) { + assert(type < MAX_ITERATOR_TYPES); + iterators[type] = info; +} + + +void iterator_init() { + lladdIterator_def_t linearHashNTA_def = { + linearHashNTAIterator_close, linearHashNTAIterator_next, linearHashNTAIterator_key, linearHashNTAIterator_value + }; + lladdIterator_register(LINEAR_HASH_NTA_ITERATOR, linearHashNTA_def); + lladdIterator_def_t array_def = { + arrayIterator_close, arrayIterator_next, arrayIterator_key, arrayIterator_value + }; + lladdIterator_register(ARRAY_ITERATOR, array_def); +} + + +//lladdIterator_t Titerator(int type, void * arg); +void Titerator_close(int xid, lladdIterator_t * it) { iterators[it->type].close(xid, it->impl); free(it); } +int Titerator_next (int xid, lladdIterator_t * it) { return iterators[it->type].next (xid, it->impl); } +int Titerator_key (int xid, lladdIterator_t * it, byte ** key) { return iterators[it->type].key (xid, it->impl, key); } +int Titerator_value(int xid, lladdIterator_t * it, byte ** value){ return iterators[it->type].value(xid, it->impl, value); } diff --git a/src/lladd/logger/logMemory.c b/src/lladd/logger/logMemory.c new file mode 100644 index 0000000..4b2111f --- /dev/null +++ b/src/lladd/logger/logMemory.c @@ -0,0 +1,135 @@ +#include +#include +#include +#include +#include "logMemory.h" + +/* Could also use mod here, but 64-bit mod under intel is kinda slow, + and (in theory) gcc should only calculate ((lsn)-(x)->start) one + time...besides, I implemented it this way before I thought of using mod. ;) */ + +/*#define lsn_to_offset(x, lsn) \ + ((((lsn)-(x)->start) < (x)->size) ? \ + ((lsn)-(x)->start) : \ + ((lsn)-(x)->start) - (x)->size); */ + +#undef end +struct ringBufferLog_s { + /** An array of bytes that holds the contents of the ringbuffer. */ + byte * buf; + /** The number of bytes in the ringbuffer */ + int size; + /** The first byte in the ringbuffer that is valid. */ + lsn_t start; + /** The last byte in the ringbuffer that is valid. Note that due to + the nature of a ringbuffer, end may be less than start. This + simply means that the ring buffer wraps around the end of + buf. */ + lsn_t end; + /** The offset of the first byte in the ring buffer. Ignoring + wrap-around, lsn(buf[i]) = offset + (i-start). */ + lsn_t offset; +} ringBufferLog_s; + + +#define lsn_to_offset(x, lsn) ((lsn) % (x)->size) +#define offset_to_lsn(x, lsn) ((lsn) + (x)->offset) + +static int truncateLog(ringBufferLog_t * log, lsn_t lsn); + +ringBufferLog_t * openLogRingBuffer(size_t size, lsn_t initialOffset) { + ringBufferLog_t * ret = malloc(sizeof(ringBufferLog_t)); + ret->buf = malloc(size); + ret->size = size; + ret->start = initialOffset % size; + ret->end = initialOffset % size; + + ret->offset= initialOffset / size;; + + return ret; +} + +void closeLogRingBuffer(ringBufferLog_t * log) { + free(log->buf); + free(log); +} +/** + This function copies size bytes from the ringbuffer at offset + 'offset'. size must be less than log->size. + + It probably also should lie within the boundaries defined by start + and end, but this is optional. +*/ +static void memcpyFromRingBuffer(byte * dest, ringBufferLog_t * log, lsn_t lsn, size_t size) { + int offset = lsn_to_offset(log, lsn); + if(offset + size < log->size) { + memcpy(dest, &(log->buf[offset]), size); + } else { + int firstPieceLength = log->size - offset; + int secondPieceLength = size - firstPieceLength; + memcpy(dest, &(log->buf[offset]), firstPieceLength); + memcpy(dest + firstPieceLength, &(log->buf[0]), secondPieceLength); + } +} + +static void memcpyToRingBuffer(ringBufferLog_t * log, byte *src, lsn_t lsn, size_t size) { + int offset = lsn_to_offset(log, lsn); + if(offset + size < log->size) { + memcpy(&(log->buf[offset]), src, size); + } else { + int firstPieceLength = log->size - offset; + int secondPieceLength = size - firstPieceLength; + memcpy(&(log->buf[offset]), src, firstPieceLength); + memcpy(&(log->buf[0]), src + firstPieceLength, secondPieceLength); + } +} +/** @todo Return values for ringBufferAppend! */ + +int ringBufferAppend(ringBufferLog_t * log, byte * dat, size_t size) { + + assert(lsn_to_offset(log, log->end + size) == (lsn_to_offset(log, log->end + size))); + + if(size > log->size) { + // printf("!"); + return -1; // the value cannot possibly fit in the ring buffer. + } + + if(log->size < (log->end-log->start) + size) { + // printf("[WX]"); + return -2; // there is not enough room in the buffer right now. + } + + memcpyToRingBuffer(log, dat, log->end, size); + log->end += size; // lsn_to_offset(log, log->end + size); + + return 0; + +} + +int ringBufferTruncateRead(byte * buf, ringBufferLog_t * log, size_t size) { + if(size > log->size) { + return -1; // Request for chunk larger than entire ringbuffer + } + if(log->start + size > log->end) { + // printf("[RX]"); + return -2; + } + memcpyFromRingBuffer(buf, log, lsn_to_offset(log, log->start), size); + + return truncateLog(log, log->start + size); + +} + +/** static because it does no error checking. */ +static int truncateLog(ringBufferLog_t * log, lsn_t lsn) { + + int newStart = lsn_to_offset(log, lsn); + + if(newStart < lsn_to_offset(log, log->start)); // buffer wrapped. + + log->offset += log->size; + log->start = lsn; + + return 0; + +} diff --git a/src/lladd/logger/logMemory.h b/src/lladd/logger/logMemory.h new file mode 100644 index 0000000..a2f5b85 --- /dev/null +++ b/src/lladd/logger/logMemory.h @@ -0,0 +1,8 @@ +#include + +typedef struct ringBufferLog_s ringBufferLog_t; + +ringBufferLog_t * openLogRingBuffer(size_t size, lsn_t initialOffset); +void closeLogRingBuffer(ringBufferLog_t * log); +int ringBufferAppend(ringBufferLog_t * log, byte * dat, size_t size); +int ringBufferTruncateRead(byte * buf, ringBufferLog_t * log,size_t size); diff --git a/src/lladd/operations/linearHashNTA.c b/src/lladd/operations/linearHashNTA.c index 9ea77b4..140c1ed 100644 --- a/src/lladd/operations/linearHashNTA.c +++ b/src/lladd/operations/linearHashNTA.c @@ -405,10 +405,14 @@ lladd_hash_iterator * ThashIterator(int xid, recordid hashHeader, int keySize, i it->bucket = lhh.buckets; it->numBuckets = lhh.nextSplit +twoToThe(lhh.bits-1); it->bucket.slot = 0; - it->keySize = keySize; + /* it->keySize = keySize; it->valueSize = valueSize; assert(keySize == lhh.keySize); - assert(valueSize == lhh.valueSize); + assert(valueSize == lhh.valueSize); */ + keySize = lhh.keySize; + it->keySize = lhh.keySize; + valueSize = lhh.valueSize; + it->valueSize = lhh.valueSize; if(keySize == VARIABLE_LENGTH || valueSize == VARIABLE_LENGTH) { it->it = NULL; recordid bucketList; @@ -464,3 +468,69 @@ void ThashDone(int xid, lladd_hash_iterator * it) { } free(it); } + +typedef struct { + lladd_hash_iterator* hit; + byte * lastKey; + int lastKeySize; + byte * lastValue; + int lastValueSize; +} lladd_linearHashNTA_generic_it; + +lladdIterator_t * ThashGenericIterator(int xid, recordid hash) { + lladdIterator_t * ret = malloc(sizeof(lladdIterator_t)); + ret->type = LINEAR_HASH_NTA_ITERATOR; + ret->impl = malloc(sizeof(lladd_linearHashNTA_generic_it)); + + ((lladd_linearHashNTA_generic_it*)(ret->impl))->hit = ThashIterator(xid, hash, -1, -1); + ((lladd_linearHashNTA_generic_it*)(ret->impl))->lastKey = NULL; + ((lladd_linearHashNTA_generic_it*)(ret->impl))->lastValue = NULL; + + return ret; + +} + +void linearHashNTAIterator_close(int xid, void * impl) { + lladd_linearHashNTA_generic_it * it = impl; + + if(it->lastKey || it->lastValue) { + ThashDone(xid, it->hit); // otherwise, ThashNext returned zero, and freed it for us... + } + if(it->lastKey) { + free(it->lastKey); + } + if(it->lastValue) { + free(it->lastValue); + } + free(it); +} + +int linearHashNTAIterator_next (int xid, void * impl) { + lladd_linearHashNTA_generic_it * it = impl; + + if(it->lastKey) { + free(it->lastKey); + it->lastKey = NULL; + } + if(it->lastValue) { + free(it->lastValue); + it->lastValue = NULL; + } + return ThashNext(xid, it->hit, &(it->lastKey), &it->lastKeySize, &it->lastValue, &it->lastValueSize); +} + +int linearHashNTAIterator_key(int xid, void * impl, byte ** key) { + lladd_linearHashNTA_generic_it * it = impl; + + *key = it->lastKey; + + return (it->lastKey == NULL) ? 0 : it->lastKeySize; +} + +int linearHashNTAIterator_value(int xid, void * impl, byte ** value) { + lladd_linearHashNTA_generic_it * it = impl; + + *value = it->lastValue; + + return (it->lastValue == NULL) ? 0 : it->lastValueSize; +} diff --git a/src/lladd/operations/linkedListNTA.c b/src/lladd/operations/linkedListNTA.c index 59f0c8c..8347304 100644 --- a/src/lladd/operations/linkedListNTA.c +++ b/src/lladd/operations/linkedListNTA.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include diff --git a/src/lladd/operations/pageOrientedListNTA.c b/src/lladd/operations/pageOrientedListNTA.c index 0ba62a6..223993d 100644 --- a/src/lladd/operations/pageOrientedListNTA.c +++ b/src/lladd/operations/pageOrientedListNTA.c @@ -1,6 +1,7 @@ #include #include +#include #include #include diff --git a/src/lladd/page/indirect.c b/src/lladd/page/indirect.c index 2ff5c05..4af8add 100644 --- a/src/lladd/page/indirect.c +++ b/src/lladd/page/indirect.c @@ -19,6 +19,7 @@ compensated_function recordid dereferenceRID(int xid, recordid rid) { try_ret(NULLRID) { this = loadPage(xid, rid.page); } end_ret(NULLRID); + // printf("a"); fflush(stdout); int offset = 0; int max_slot; while(*page_type_ptr(this) == INDIRECT_PAGE) { @@ -39,12 +40,14 @@ compensated_function recordid dereferenceRID(int xid, recordid rid) { this = loadPage(xid, nextPage); } end_ret(NULLRID); } + // printf("b"); fflush(stdout); rid.page = this->id; rid.slot -= offset; releasePage(this); - + // printf("c"); fflush(stdout); + return rid; } diff --git a/src/lladd/transactional2.c b/src/lladd/transactional2.c index 1930db2..8d8784b 100644 --- a/src/lladd/transactional2.c +++ b/src/lladd/transactional2.c @@ -109,7 +109,7 @@ int Tinit() { LinearHashNTAInit(); LinkedListNTAInit(); compensations_init(); - + iterator_init(); setupLockManagerCallbacksNil(); //setupLockManagerCallbacksPage(); diff --git a/test/check_check.c b/test/check_check.c index f601d46..5343686 100644 --- a/test/check_check.c +++ b/test/check_check.c @@ -42,7 +42,7 @@ terms specified in this license. #include #include #include - +#include #ifndef NULL #define NULL 0 @@ -75,6 +75,10 @@ START_TEST(core_last) } END_TEST +START_TEST(slep) { + sleep(1); +}END_TEST + /** Add suite declarations here */ @@ -92,6 +96,7 @@ Suite * check_suite(void) { tc = tcase_create("second"); tcase_add_test(tc, core_last); + tcase_add_test(tc, slep); suite_add_tcase(s, tc); return s; diff --git a/test/dfa/ping_pong_dfa.c b/test/dfa/ping_pong_dfa.c index f923c6d..40e2de0 100644 --- a/test/dfa/ping_pong_dfa.c +++ b/test/dfa/ping_pong_dfa.c @@ -203,7 +203,7 @@ Suite * check_suite(void) { TCase *tc = tcase_create("pingpong"); /* void * foobar; */ /* used to supress warnings. */ /* Sub tests are added, one per line, here */ - + tcase_set_timeout(tc, 0); // disable timeouts tcase_add_test(tc, pingpong_check); /* --------------------------------------------- */ tcase_add_checked_fixture(tc, setup, teardown); diff --git a/test/lladd/Makefile.am b/test/lladd/Makefile.am index 77b1f76..f6538c5 100644 --- a/test/lladd/Makefile.am +++ b/test/lladd/Makefile.am @@ -1,12 +1,12 @@ INCLUDES = @CHECK_CFLAGS@ if HAVE_CHECK ## Had to disable check_lht because lht needs to be rewritten. -TESTS = check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_pageOperations check_linearHash check_logicalLinearHash check_header check_linkedListNTA check_linearHashNTA check_pageOrientedList check_lockManager check_compensations check_errorHandling check_ringbuffer +TESTS = check_logEntry check_logWriter check_page check_operations check_transactional2 check_recovery check_blobRecovery check_bufferManager check_indirect check_pageOperations check_linearHash check_logicalLinearHash check_header check_linkedListNTA check_linearHashNTA check_pageOrientedList check_lockManager check_compensations check_errorHandling check_ringbuffer check_iterator #check_lladdhash else TESTS = endif noinst_PROGRAMS = $(TESTS) LDADD = @CHECK_LIBS@ $(top_builddir)/src/lladd/liblladd.a $(top_builddir)/src/pbl/libpbl.a $(top_builddir)/src/libdfa/librw.a #-lefence -CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log check_linearhash.log check_linkedListNTA.log check_linearHashNTA.log check_pageOrientedListNTA.log check_lockManager.log check_compensations.log check_errorhandling.log +CLEANFILES = check_lht.log check_logEntry.log storefile.txt logfile.txt blob0_file.txt blob1_file.txt check_blobRecovery.log check_logWriter.log check_operations.log check_recovery.log check_transactional2.log check_page.log check_bufferManager.log check_indirect.log check_bufferMananger.log check_lladdhash.log check_pageOperations.log check_linearhash.log check_linkedListNTA.log check_linearHashNTA.log check_pageOrientedListNTA.log check_lockManager.log check_compensations.log check_errorhandling.log check_header.logg check_iterator.log check_linearHash.log check_ringbuffer.log AM_CFLAGS= -g -Wall -pedantic -std=gnu99 diff --git a/test/lladd/check_compensations.c b/test/lladd/check_compensations.c index 0280ee8..d98a112 100644 --- a/test/lladd/check_compensations.c +++ b/test/lladd/check_compensations.c @@ -60,15 +60,15 @@ void decrement(void * j) { void nested(int * i); void happy_nest(int * i); void nested2(int * i) { - begin_action(NULL, NULL) { + try { nested(i); - } compensate; + } end; //compensate; assert(0); } void nested3(int * i) { - begin_action(NULL, NULL) { + try { happy_nest(i); - } compensate; + } end; //compensate; } void nested(int * i) { @@ -136,7 +136,7 @@ Suite * check_suite(void) { Suite *s = suite_create("compensations"); /* Begin a new test */ TCase *tc = tcase_create("simple_compensations"); - + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ tcase_add_test(tc, compensationTest); diff --git a/test/lladd/check_indirect.c b/test/lladd/check_indirect.c index a492887..45af6c2 100644 --- a/test/lladd/check_indirect.c +++ b/test/lladd/check_indirect.c @@ -234,13 +234,21 @@ START_TEST(indirectAccessIndirect) { xid = Tbegin(); releasePage(p); + // printf("A"); fflush(stdout); + for(int i = 0; i < 500000; i++) { rid.slot = i; - Tset(xid, dereferenceRID(xid, rid), &i); + // printf("i=%d", i); fflush(stdout); + recordid rid2 = dereferenceRID(xid, rid); + // printf("."); fflush(stdout); + Tset(xid, rid2, &i); } + // printf("AA"); fflush(stdout); + Tcommit(xid); xid = Tbegin(); + // printf("B"); fflush(stdout); for(int i = 0; i < 500000; i++) { rid.slot = i; @@ -249,9 +257,13 @@ START_TEST(indirectAccessIndirect) { assert(j == i); } + // printf("C"); fflush(stdout); + Tcommit(xid); Tdeinit(); + + // printf("D"); fflush(stdout); } END_TEST @@ -282,6 +294,8 @@ Suite * check_suite(void) { Suite *s = suite_create("indirect"); /* Begin a new test */ TCase *tc = tcase_create("indirect"); + tcase_set_timeout(tc, 0); // disable timeouts + /* Sub tests are added, one per line, here */ diff --git a/test/lladd/check_iterator.c b/test/lladd/check_iterator.c new file mode 100644 index 0000000..9d00735 --- /dev/null +++ b/test/lladd/check_iterator.c @@ -0,0 +1,179 @@ +/*--- +This software is copyrighted by the Regents of the University of +California, and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" in +the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are +acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. +---*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "../check_includes.h" + + +#include +#include + +#define LOG_NAME "check_iterator.log" + +/** + @test + +*/ + + +/** Take two iterators, and make sure they represent the same set. */ +static void iterator_test(int xid, + lladdIterator_t * reference_impl, + lladdIterator_t * tested_impl) { + + pblHashTable_t * hash = pblHtCreate(); + + int numEntries = 0; + + while(Titerator_next(xid, reference_impl)) { + int keySize, valSize; + byte *key, *val, *valScratch; + + keySize = Titerator_key(xid, reference_impl, &key); + valSize = Titerator_value(xid, reference_impl, &valScratch); + val = malloc(valSize); + memcpy(val, valScratch, valSize); // pblHtInsert stores values a pointers to application managed memory. + + pblHtInsert(hash, key, keySize, val); + numEntries ++; + } + + while(Titerator_next(xid, tested_impl)) { + numEntries --; + + int keySize, valSize; + byte *key, *val, *valScratch; + + keySize = Titerator_key(xid, tested_impl, &key); + valSize = Titerator_value(xid, tested_impl, &valScratch); + + val = pblHtLookup(hash, key, keySize); + + assert(val); + + assert(!memcmp(val, valScratch, valSize)); + + free(val); + + pblHtRemove(hash, key, keySize); + + } + + assert(!numEntries); + +} + +#define NUM_ENTRIES 10000 + +START_TEST(iteratorTest) +{ + Tinit(); + int xid = Tbegin(); + unsigned int keyArray[NUM_ENTRIES]; + byte valueArray[NUM_ENTRIES]; + + unsigned int i; + + recordid hash = ThashCreate(xid, sizeof(unsigned int), sizeof(byte)); + + for(i = 0; i < NUM_ENTRIES; i++) { + keyArray[i] = i; + valueArray[i] = i % 256; + byte j = i % 256; + ThashInsert(xid, hash, (byte*)&i, sizeof(unsigned int), &j, sizeof(byte)); + } + + lladdIterator_t * arrayIt = arrayIterator((byte *)keyArray, sizeof(int), valueArray, sizeof(char), NUM_ENTRIES); + i = 0; + while(Titerator_next(-1, arrayIt)) { + unsigned int * key; + unsigned char * value; + int keySize = Titerator_key(-1, arrayIt, (byte**)&key); + int valueSize = Titerator_value(-1, arrayIt, (byte**)&value); + assert(keySize == sizeof(unsigned int)); + assert(valueSize == sizeof(unsigned char)); + assert(*key == i); + assert(*value == (i % 256)); + i++; + } + + Titerator_close(-1, arrayIt); + + arrayIt = arrayIterator((byte*)keyArray, sizeof(int), valueArray, sizeof(char), NUM_ENTRIES); + + lladdIterator_t * hashIt = ThashGenericIterator(xid, hash); + + iterator_test(xid, arrayIt, hashIt); + + Tcommit(xid); + Tdeinit(); +} END_TEST + + +Suite * check_suite(void) { + Suite *s = suite_create("iterator"); + /* Begin a new test */ + TCase *tc = tcase_create("iterator"); + + tcase_set_timeout(tc, 0); // disable timeouts + /* Sub tests are added, one per line, here */ + + tcase_add_test(tc, iteratorTest); + + /* --------------------------------------------- */ + + tcase_add_checked_fixture(tc, setup, teardown); + + + suite_add_tcase(s, tc); + return s; +} + +#include "../check_setup.h" diff --git a/test/lladd/check_linearHash.c b/test/lladd/check_linearHash.c index 8e481f5..fdbb27d 100644 --- a/test/lladd/check_linearHash.c +++ b/test/lladd/check_linearHash.c @@ -285,7 +285,7 @@ Suite * check_suite(void) { /* Begin a new test */ TCase *tc = tcase_create("simple"); - + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ /* tcase_add_test(tc, checkHashFcn); */ diff --git a/test/lladd/check_linearHashNTA.c b/test/lladd/check_linearHashNTA.c index 6b6bf38..1019a49 100644 --- a/test/lladd/check_linearHashNTA.c +++ b/test/lladd/check_linearHashNTA.c @@ -363,7 +363,7 @@ Suite * check_suite(void) { /* Begin a new test */ TCase *tc = tcase_create("simple"); - + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ tcase_add_test(tc, emptyHashIterator); tcase_add_test(tc, emptyHashIterator2); diff --git a/test/lladd/check_linkedListNTA.c b/test/lladd/check_linkedListNTA.c index 84046aa..b1c46a5 100644 --- a/test/lladd/check_linkedListNTA.c +++ b/test/lladd/check_linkedListNTA.c @@ -185,7 +185,7 @@ Suite * check_suite(void) { Suite *s = suite_create("linkedListNTA"); /* Begin a new test */ TCase *tc = tcase_create("simple"); - + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ diff --git a/test/lladd/check_lockManager.c b/test/lladd/check_lockManager.c index 6adc711..cd5ef10 100644 --- a/test/lladd/check_lockManager.c +++ b/test/lladd/check_lockManager.c @@ -162,7 +162,7 @@ Suite * check_suite(void) { Suite *s = suite_create("lockManager"); /* Begin a new test */ TCase *tc = tcase_create("multithreaded"); - + tcase_set_timeout(tc, 0); // disable timeouts // kinda hacky, but here it is: compensations_init(); diff --git a/test/lladd/check_logWriter.c b/test/lladd/check_logWriter.c index 826c4c9..37eb98a 100644 --- a/test/lladd/check_logWriter.c +++ b/test/lladd/check_logWriter.c @@ -289,6 +289,7 @@ static void* worker_thread(void * arg) { } /* fail_unless(1, NULL); */ if(entry > truncated_to && entry < i) { + /* printf("X %d\n", (readLSNEntry(lsns[entry])->xid == entry+key)); fflush(stdout); */ assert(readLSNEntry(lsns[entry])->xid == entry+key); /* fail_unless(readLSNEntry(lsns[entry])->xid == entry+key, NULL); */ } @@ -327,9 +328,12 @@ START_TEST(logWriterCheckThreaded) { for(i = 0; i < THREAD_COUNT; i++) { pthread_create(&workers[i], NULL, worker_thread, &i); + // printf("%d", i); fflush(stdout); } + // printf("\n\n\n\n\n"); for(i = 0; i < THREAD_COUNT; i++) { pthread_join(workers[i], NULL); + // printf("%d", i); fflush(stdout); } Tdeinit(); @@ -340,9 +344,9 @@ Suite * check_suite(void) { Suite *s = suite_create("logWriter"); /* Begin a new test */ TCase *tc = tcase_create("writeNew"); - + tcase_set_timeout(tc, 0); /* Sub tests are added, one per line, here */ - + tcase_add_test(tc, logWriterTest); tcase_add_test(tc, logHandleColdReverseIterator); tcase_add_test(tc, logWriterTruncate); diff --git a/test/lladd/check_logicalLinearHash.c b/test/lladd/check_logicalLinearHash.c index 8318134..210336c 100644 --- a/test/lladd/check_logicalLinearHash.c +++ b/test/lladd/check_logicalLinearHash.c @@ -45,6 +45,7 @@ terms specified in this license. #include "../check_includes.h" #include +#include #include #include @@ -65,6 +66,7 @@ terms specified in this license. @test Runs some simple tests on the hash() function. Not comprehensive enough. @todo the checkHashFcn test is broken. */ + START_TEST(checkHashFcn) { int i; srandom(12312313); diff --git a/test/lladd/check_page.c b/test/lladd/check_page.c index a7d3839..fd58f57 100644 --- a/test/lladd/check_page.c +++ b/test/lladd/check_page.c @@ -466,7 +466,7 @@ Suite * check_suite(void) { Suite *s = suite_create("page"); /* Begin a new test */ TCase *tc = tcase_create("pagethreads"); - + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ tcase_add_test(tc, pageCheckMacros); diff --git a/test/lladd/check_pageOrientedList.c b/test/lladd/check_pageOrientedList.c index 0b10277..40145b6 100644 --- a/test/lladd/check_pageOrientedList.c +++ b/test/lladd/check_pageOrientedList.c @@ -196,6 +196,7 @@ Suite * check_suite(void) { Suite *s = suite_create("pageOrientedList"); /* Begin a new test */ TCase *tc = tcase_create("pageOrientedList"); + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ diff --git a/test/lladd/check_ringbuffer.c b/test/lladd/check_ringbuffer.c new file mode 100644 index 0000000..24044d3 --- /dev/null +++ b/test/lladd/check_ringbuffer.c @@ -0,0 +1,161 @@ +/*--- +This software is copyrighted by the Regents of the University of +California, and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, +provided that existing copyright notices are retained in all copies +and that this notice is included verbatim in any distributions. No +written agreement, license, or royalty fee is required for any of the +authorized uses. Modifications to this software may be copyrighted by +their authors and need not follow the licensing terms described here, +provided that the new terms are clearly indicated on the first page of +each file where they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND +THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE +MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" in +the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you are +acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. +---*/ + +#include +#include + +#include "../../src/lladd/logger/logMemory.h" +#include + +#include "../check_includes.h" + + +#include +#include + +#define LOG_NAME "check_ringbuffer.log" + +/** + @test + +*/ + +#define NUM_ENTRIES 10000 + + +static int rb_test(double readBlock, double writeBlock) { + + int i; + byte ** array = malloc(sizeof(byte*) * NUM_ENTRIES); + int * length = malloc(sizeof(int) * NUM_ENTRIES); + for(i = 0; i < NUM_ENTRIES; i++) { + length[i] =1.0+ 1000.0 * (double)rand() / (double)RAND_MAX; + array[i] = malloc(length[i]); + int j; + for(j = 0; j < length[i]; j++) { + array[i][j] = i + j; + } + } + + ringBufferLog_t * log = openLogRingBuffer(NUM_ENTRIES, 5); + + int doneReading = 0; + int doneWriting = 0; + int readPos = 0; + int writePos = 0; + while(!doneReading) { + if(!doneWriting) { + int numToWrite = 1.0 + writeBlock * (rand() / RAND_MAX); + // printf("%d\n", numToWrite); + for(i = 0; i < numToWrite; i++) { + if(!ringBufferAppend(log, array[writePos], length[writePos])) { + // printf("W"); fflush(stdout); + writePos++; + if(writePos == NUM_ENTRIES) { break; } + } else { + break; + } + } + } + int numToRead = 1.0 + readBlock * ((double)rand() / (double)RAND_MAX); + // printf("%d\n", numToRead); + for(i = 0; i < numToRead; i++) { + byte * buf = malloc(length[readPos]); + if(!ringBufferTruncateRead(buf, log, length[readPos])) { + int j; + for(j = 0; j < length[readPos]; j++) { + assert(buf[j] == array[readPos][j]); + } + free(buf); + // printf("R"); fflush(stdout); + + readPos++; + if(readPos == NUM_ENTRIES) { break; } + } else { + break; + } + } + if(readPos == NUM_ENTRIES) { + doneReading = 1; + } + if(writePos == NUM_ENTRIES) { + doneWriting = 1; + } + } + return 0; +} + +START_TEST(ringBufferTest) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + + srand(tv.tv_sec + tv.tv_usec); + + printf("\nRunning balanced test.\n"); + rb_test(5.0,5.0); + printf("Running read-intensive test.\n"); + rb_test(10.0, 1.0); + printf("Running write-intensive test.\n"); + rb_test(1.0, 10); +} END_TEST + + +Suite * check_suite(void) { + Suite *s = suite_create("ringBuffer"); + /* Begin a new test */ + TCase *tc = tcase_create("ringBuffer"); + + /* Sub tests are added, one per line, here */ + + tcase_add_test(tc, ringBufferTest); + + /* --------------------------------------------- */ + + tcase_add_checked_fixture(tc, setup, teardown); + + + suite_add_tcase(s, tc); + return s; +} + +#include "../check_setup.h" diff --git a/test/lladd/check_transactional2.c b/test/lladd/check_transactional2.c index a9fcdbc..fdc2069 100644 --- a/test/lladd/check_transactional2.c +++ b/test/lladd/check_transactional2.c @@ -442,6 +442,7 @@ Suite * check_suite(void) { Suite *s = suite_create("transactional"); /* Begin a new test */ TCase *tc = tcase_create("transactional_smokeTest"); + tcase_set_timeout(tc, 0); // disable timeouts /* Sub tests are added, one per line, here */ tcase_add_test(tc, transactional_smokeTest);