Fixed unit tests, added iterator interface, and generic (almost) iterator test harness.

This commit is contained in:
Sears Russell 2005-03-10 03:19:04 +00:00
parent 935de3aeb5
commit f28df29736
32 changed files with 823 additions and 29 deletions

8
lladd/arrayCollection.h Normal file
View file

@ -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);

View file

@ -113,22 +113,26 @@ void compensation_set_error(int code);
#define end while(0); if(compensation_error()) return; }while(0) #define end while(0); if(compensation_error()) return; }while(0)
#define end_ret(x) while(0); if(compensation_error()) return (x); }while(0) #define end_ret(x) while(0); if(compensation_error()) return (x); }while(0)
extern int ___compensation_count___;
#define begin_action(func, var) \ #define begin_action(func, var) \
if(compensation_error()) return; \ if(compensation_error()) return; \
do{ \ do{ \
void (*_func_)(void*); \ void (*_func_)(void*); \
assert(func); \
pthread_cleanup_push(_func_=(void(*)(void*))(func), (void*)(var));\ pthread_cleanup_push(_func_=(void(*)(void*))(func), (void*)(var));\
assert(_func_); \
do do
/** @todo compensation variables don't need _func_ anymore. */ /** @todo compensation variables don't need _func_ anymore. */
#define end_action \ #define end_action \
while(0); \ while(0); \
pthread_cleanup_pop(_func_ && compensation_error()); \ pthread_cleanup_pop(/*_func_ &&*/compensation_error()); \
if(compensation_error()) return; \ if(compensation_error()) return; \
} while(0) } while(0)
#define compensate \ #define compensate \
while(0); \ while(0); \
pthread_cleanup_pop((int)_func_); \ pthread_cleanup_pop(1/*(int)_func_*/); \
if(compensation_error()) return; \ if(compensation_error()) return; \
} while(0) } while(0)
@ -141,13 +145,13 @@ void compensation_set_error(int code);
#define end_action_ret(ret) \ #define end_action_ret(ret) \
while(0); \ while(0); \
pthread_cleanup_pop(_func_ && compensation_error()); \ pthread_cleanup_pop(/*_func_ &&*/compensation_error()); \
if(compensation_error()) return (ret); \ if(compensation_error()) return (ret); \
} while(0) } while(0)
#define compensate_ret(ret) \ #define compensate_ret(ret) \
while(0); \ while(0); \
pthread_cleanup_pop((int)_func_); \ pthread_cleanup_pop(1/*(int)_func*/); \
if(compensation_error()) return (ret); \ if(compensation_error()) return (ret); \
} while(0) } while(0)

74
lladd/iterator.h Normal file
View file

@ -0,0 +1,74 @@
#include <lladd/transactional.h>
#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

View file

@ -57,7 +57,8 @@ terms specified in this license.
#include <lladd/transactional.h> #include <lladd/transactional.h>
#include <lladd/logger/logEntry.h> #include <lladd/logger/logEntry.h>
#include <lladd/bufferManager.h> #include <lladd/bufferManager.h>
#include <lladd/iterator.h>
#include <lladd/arrayCollection.h>
BEGIN_C_DECLS BEGIN_C_DECLS

View file

@ -20,6 +20,8 @@
*/ */
#include <lladd/iterator.h>
#ifndef __LINEAR_HASH_NTA_H #ifndef __LINEAR_HASH_NTA_H
#define __LINEAR_HASH_NTA_H #define __LINEAR_HASH_NTA_H
/** Currently, only used in the type field of the iterators. */ /** 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 hash the recordid returned by ThashAlloc
@param keySize the same as the value passed into ThashAlloc. @param keySize the same as the value passed into ThashAlloc.
@param valueSize 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); 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. semantics.
@param value analagous to value. @param value analagous to value.
@param valueSize analagous to keySize @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); 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); void ThashDone(int xid, lladd_hash_iterator * it);
Operation getLinearHashInsert(); Operation getLinearHashInsert();
@ -93,6 +101,17 @@ Operation getLinearHashRemove();
void LinearHashNTAInit(); 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. //Support 16 entries by default.
#define HASH_INIT_BITS 4 #define HASH_INIT_BITS 4

View file

@ -5,7 +5,7 @@ lib_LIBRARIES=liblladd.a
# removed: recovery.c transactional.c logger.c logger/logparser.c logger/logstreamer.c # 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 \ 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 \ 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/logEntry.c logger/logWriter.c logger/logHandle.c logger/logger2.c \
logger/logMemory.c \ logger/logMemory.c \
page/slotted.c page/header.c page/fixed.c compensations.c \ page/slotted.c page/header.c page/fixed.c compensations.c \

View file

@ -0,0 +1,68 @@
#include <lladd/transactional.h>
#include <stdlib.h>
#include <stdio.h>
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) {
}*/

View file

@ -1,5 +1,7 @@
#include <lladd/compensations.h> #include <lladd/compensations.h>
int ___compensation_count___ = 0;
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>

33
src/lladd/iterator.c Normal file
View file

@ -0,0 +1,33 @@
#include <lladd/iterator.h>
#include <assert.h>
#include <stdlib.h>
#include <lladd/operations.h>
#include <lladd/arrayCollection.h>
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); }

View file

@ -0,0 +1,135 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#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;
}

View file

@ -0,0 +1,8 @@
#include <lladd/transactional.h>
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);

View file

@ -405,10 +405,14 @@ lladd_hash_iterator * ThashIterator(int xid, recordid hashHeader, int keySize, i
it->bucket = lhh.buckets; it->bucket = lhh.buckets;
it->numBuckets = lhh.nextSplit +twoToThe(lhh.bits-1); it->numBuckets = lhh.nextSplit +twoToThe(lhh.bits-1);
it->bucket.slot = 0; it->bucket.slot = 0;
it->keySize = keySize; /* it->keySize = keySize;
it->valueSize = valueSize; it->valueSize = valueSize;
assert(keySize == lhh.keySize); 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) { if(keySize == VARIABLE_LENGTH || valueSize == VARIABLE_LENGTH) {
it->it = NULL; it->it = NULL;
recordid bucketList; recordid bucketList;
@ -464,3 +468,69 @@ void ThashDone(int xid, lladd_hash_iterator * it) {
} }
free(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;
}

View file

@ -5,6 +5,7 @@
#include <lladd/transactional.h> #include <lladd/transactional.h>
#include <lladd/hash.h> #include <lladd/hash.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>

View file

@ -1,6 +1,7 @@
#include <lladd/transactional.h> #include <lladd/transactional.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>

View file

@ -19,6 +19,7 @@ compensated_function recordid dereferenceRID(int xid, recordid rid) {
try_ret(NULLRID) { try_ret(NULLRID) {
this = loadPage(xid, rid.page); this = loadPage(xid, rid.page);
} end_ret(NULLRID); } end_ret(NULLRID);
// printf("a"); fflush(stdout);
int offset = 0; int offset = 0;
int max_slot; int max_slot;
while(*page_type_ptr(this) == INDIRECT_PAGE) { while(*page_type_ptr(this) == INDIRECT_PAGE) {
@ -39,11 +40,13 @@ compensated_function recordid dereferenceRID(int xid, recordid rid) {
this = loadPage(xid, nextPage); this = loadPage(xid, nextPage);
} end_ret(NULLRID); } end_ret(NULLRID);
} }
// printf("b"); fflush(stdout);
rid.page = this->id; rid.page = this->id;
rid.slot -= offset; rid.slot -= offset;
releasePage(this); releasePage(this);
// printf("c"); fflush(stdout);
return rid; return rid;
} }

View file

@ -109,7 +109,7 @@ int Tinit() {
LinearHashNTAInit(); LinearHashNTAInit();
LinkedListNTAInit(); LinkedListNTAInit();
compensations_init(); compensations_init();
iterator_init();
setupLockManagerCallbacksNil(); setupLockManagerCallbacksNil();
//setupLockManagerCallbacksPage(); //setupLockManagerCallbacksPage();

View file

@ -42,7 +42,7 @@ terms specified in this license.
#include <config.h> #include <config.h>
#include <check.h> #include <check.h>
#include <assert.h> #include <assert.h>
#include <unistd.h>
#ifndef NULL #ifndef NULL
#define NULL 0 #define NULL 0
@ -75,6 +75,10 @@ START_TEST(core_last)
} }
END_TEST END_TEST
START_TEST(slep) {
sleep(1);
}END_TEST
/** /**
Add suite declarations here Add suite declarations here
*/ */
@ -92,6 +96,7 @@ Suite * check_suite(void) {
tc = tcase_create("second"); tc = tcase_create("second");
tcase_add_test(tc, core_last); tcase_add_test(tc, core_last);
tcase_add_test(tc, slep);
suite_add_tcase(s, tc); suite_add_tcase(s, tc);
return s; return s;

View file

@ -203,7 +203,7 @@ Suite * check_suite(void) {
TCase *tc = tcase_create("pingpong"); TCase *tc = tcase_create("pingpong");
/* void * foobar; */ /* used to supress warnings. */ /* void * foobar; */ /* used to supress warnings. */
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
tcase_set_timeout(tc, 0); // disable timeouts
tcase_add_test(tc, pingpong_check); tcase_add_test(tc, pingpong_check);
/* --------------------------------------------- */ /* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown); tcase_add_checked_fixture(tc, setup, teardown);

View file

@ -1,12 +1,12 @@
INCLUDES = @CHECK_CFLAGS@ INCLUDES = @CHECK_CFLAGS@
if HAVE_CHECK if HAVE_CHECK
## Had to disable check_lht because lht needs to be rewritten. ## 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 #check_lladdhash
else else
TESTS = TESTS =
endif endif
noinst_PROGRAMS = $(TESTS) 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 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 AM_CFLAGS= -g -Wall -pedantic -std=gnu99

View file

@ -60,15 +60,15 @@ void decrement(void * j) {
void nested(int * i); void nested(int * i);
void happy_nest(int * i); void happy_nest(int * i);
void nested2(int * i) { void nested2(int * i) {
begin_action(NULL, NULL) { try {
nested(i); nested(i);
} compensate; } end; //compensate;
assert(0); assert(0);
} }
void nested3(int * i) { void nested3(int * i) {
begin_action(NULL, NULL) { try {
happy_nest(i); happy_nest(i);
} compensate; } end; //compensate;
} }
void nested(int * i) { void nested(int * i) {
@ -136,7 +136,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("compensations"); Suite *s = suite_create("compensations");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("simple_compensations"); TCase *tc = tcase_create("simple_compensations");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
tcase_add_test(tc, compensationTest); tcase_add_test(tc, compensationTest);

View file

@ -234,13 +234,21 @@ START_TEST(indirectAccessIndirect) {
xid = Tbegin(); xid = Tbegin();
releasePage(p); releasePage(p);
// printf("A"); fflush(stdout);
for(int i = 0; i < 500000; i++) { for(int i = 0; i < 500000; i++) {
rid.slot = 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); Tcommit(xid);
xid = Tbegin(); xid = Tbegin();
// printf("B"); fflush(stdout);
for(int i = 0; i < 500000; i++) { for(int i = 0; i < 500000; i++) {
rid.slot = i; rid.slot = i;
@ -249,10 +257,14 @@ START_TEST(indirectAccessIndirect) {
assert(j == i); assert(j == i);
} }
// printf("C"); fflush(stdout);
Tcommit(xid); Tcommit(xid);
Tdeinit(); Tdeinit();
// printf("D"); fflush(stdout);
} END_TEST } END_TEST
/** @test check that the indirectPageRecordCount() function works /** @test check that the indirectPageRecordCount() function works
@ -282,6 +294,8 @@ Suite * check_suite(void) {
Suite *s = suite_create("indirect"); Suite *s = suite_create("indirect");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("indirect"); TCase *tc = tcase_create("indirect");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */

179
test/lladd/check_iterator.c Normal file
View file

@ -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 <lladd/transactional.h>
#include <pbl/pbl.h>
#include <stdlib.h>
#include <string.h>
#include <config.h>
#include <check.h>
#include <assert.h>
#include "../check_includes.h"
#include <sys/time.h>
#include <time.h>
#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"

View file

@ -285,7 +285,7 @@ Suite * check_suite(void) {
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("simple"); TCase *tc = tcase_create("simple");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
/* tcase_add_test(tc, checkHashFcn); */ /* tcase_add_test(tc, checkHashFcn); */

View file

@ -363,7 +363,7 @@ Suite * check_suite(void) {
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("simple"); TCase *tc = tcase_create("simple");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
tcase_add_test(tc, emptyHashIterator); tcase_add_test(tc, emptyHashIterator);
tcase_add_test(tc, emptyHashIterator2); tcase_add_test(tc, emptyHashIterator2);

View file

@ -185,7 +185,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("linkedListNTA"); Suite *s = suite_create("linkedListNTA");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("simple"); TCase *tc = tcase_create("simple");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */

View file

@ -162,7 +162,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("lockManager"); Suite *s = suite_create("lockManager");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("multithreaded"); TCase *tc = tcase_create("multithreaded");
tcase_set_timeout(tc, 0); // disable timeouts
// kinda hacky, but here it is: // kinda hacky, but here it is:
compensations_init(); compensations_init();

View file

@ -289,6 +289,7 @@ static void* worker_thread(void * arg) {
} }
/* fail_unless(1, NULL); */ /* fail_unless(1, NULL); */
if(entry > truncated_to && entry < i) { 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); assert(readLSNEntry(lsns[entry])->xid == entry+key);
/* fail_unless(readLSNEntry(lsns[entry])->xid == entry+key, NULL); */ /* fail_unless(readLSNEntry(lsns[entry])->xid == entry+key, NULL); */
} }
@ -327,9 +328,12 @@ START_TEST(logWriterCheckThreaded) {
for(i = 0; i < THREAD_COUNT; i++) { for(i = 0; i < THREAD_COUNT; i++) {
pthread_create(&workers[i], NULL, worker_thread, &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++) { for(i = 0; i < THREAD_COUNT; i++) {
pthread_join(workers[i], NULL); pthread_join(workers[i], NULL);
// printf("%d", i); fflush(stdout);
} }
Tdeinit(); Tdeinit();
@ -340,7 +344,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("logWriter"); Suite *s = suite_create("logWriter");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("writeNew"); TCase *tc = tcase_create("writeNew");
tcase_set_timeout(tc, 0);
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
tcase_add_test(tc, logWriterTest); tcase_add_test(tc, logWriterTest);

View file

@ -45,6 +45,7 @@ terms specified in this license.
#include "../check_includes.h" #include "../check_includes.h"
#include <lladd/transactional.h> #include <lladd/transactional.h>
#include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <lladd/hash.h> #include <lladd/hash.h>
@ -65,6 +66,7 @@ terms specified in this license.
@test Runs some simple tests on the hash() function. Not comprehensive enough. @test Runs some simple tests on the hash() function. Not comprehensive enough.
@todo the checkHashFcn test is broken. @todo the checkHashFcn test is broken.
*/ */
START_TEST(checkHashFcn) { START_TEST(checkHashFcn) {
int i; int i;
srandom(12312313); srandom(12312313);

View file

@ -466,7 +466,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("page"); Suite *s = suite_create("page");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("pagethreads"); TCase *tc = tcase_create("pagethreads");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
tcase_add_test(tc, pageCheckMacros); tcase_add_test(tc, pageCheckMacros);

View file

@ -196,6 +196,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("pageOrientedList"); Suite *s = suite_create("pageOrientedList");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("pageOrientedList"); TCase *tc = tcase_create("pageOrientedList");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */

View file

@ -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 <config.h>
#include <check.h>
#include "../../src/lladd/logger/logMemory.h"
#include <assert.h>
#include "../check_includes.h"
#include <sys/time.h>
#include <time.h>
#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"

View file

@ -442,6 +442,7 @@ Suite * check_suite(void) {
Suite *s = suite_create("transactional"); Suite *s = suite_create("transactional");
/* Begin a new test */ /* Begin a new test */
TCase *tc = tcase_create("transactional_smokeTest"); TCase *tc = tcase_create("transactional_smokeTest");
tcase_set_timeout(tc, 0); // disable timeouts
/* Sub tests are added, one per line, here */ /* Sub tests are added, one per line, here */
tcase_add_test(tc, transactional_smokeTest); tcase_add_test(tc, transactional_smokeTest);