Fixed unit tests, added iterator interface, and generic (almost) iterator test harness.
This commit is contained in:
parent
935de3aeb5
commit
f28df29736
32 changed files with 823 additions and 29 deletions
8
lladd/arrayCollection.h
Normal file
8
lladd/arrayCollection.h
Normal 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);
|
|
@ -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)
|
||||
|
||||
|
|
74
lladd/iterator.h
Normal file
74
lladd/iterator.h
Normal 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
|
||||
|
|
@ -57,7 +57,8 @@ terms specified in this license.
|
|||
#include <lladd/transactional.h>
|
||||
#include <lladd/logger/logEntry.h>
|
||||
#include <lladd/bufferManager.h>
|
||||
|
||||
#include <lladd/iterator.h>
|
||||
#include <lladd/arrayCollection.h>
|
||||
BEGIN_C_DECLS
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <lladd/iterator.h>
|
||||
|
||||
#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
|
||||
|
|
|
@ -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 \
|
||||
|
|
68
src/lladd/arrayCollection.c
Normal file
68
src/lladd/arrayCollection.c
Normal 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) {
|
||||
|
||||
}*/
|
|
@ -1,5 +1,7 @@
|
|||
#include <lladd/compensations.h>
|
||||
|
||||
int ___compensation_count___ = 0;
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
@ -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() {
|
||||
|
|
33
src/lladd/iterator.c
Normal file
33
src/lladd/iterator.c
Normal 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); }
|
135
src/lladd/logger/logMemory.c
Normal file
135
src/lladd/logger/logMemory.c
Normal 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;
|
||||
|
||||
}
|
8
src/lladd/logger/logMemory.h
Normal file
8
src/lladd/logger/logMemory.h
Normal 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);
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <lladd/transactional.h>
|
||||
#include <lladd/hash.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <lladd/transactional.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ int Tinit() {
|
|||
LinearHashNTAInit();
|
||||
LinkedListNTAInit();
|
||||
compensations_init();
|
||||
|
||||
iterator_init();
|
||||
setupLockManagerCallbacksNil();
|
||||
//setupLockManagerCallbacksPage();
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ terms specified in this license.
|
|||
#include <config.h>
|
||||
#include <check.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
179
test/lladd/check_iterator.c
Normal file
179
test/lladd/check_iterator.c
Normal 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"
|
|
@ -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); */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -45,6 +45,7 @@ terms specified in this license.
|
|||
#include "../check_includes.h"
|
||||
|
||||
#include <lladd/transactional.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <assert.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.
|
||||
@todo the checkHashFcn test is broken.
|
||||
*/
|
||||
|
||||
START_TEST(checkHashFcn) {
|
||||
int i;
|
||||
srandom(12312313);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
161
test/lladd/check_ringbuffer.c
Normal file
161
test/lladd/check_ringbuffer.c
Normal 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"
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue