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 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
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/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
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 \
|
||||||
|
|
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>
|
#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
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->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;
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ int Tinit() {
|
||||||
LinearHashNTAInit();
|
LinearHashNTAInit();
|
||||||
LinkedListNTAInit();
|
LinkedListNTAInit();
|
||||||
compensations_init();
|
compensations_init();
|
||||||
|
iterator_init();
|
||||||
setupLockManagerCallbacksNil();
|
setupLockManagerCallbacksNil();
|
||||||
//setupLockManagerCallbacksPage();
|
//setupLockManagerCallbacksPage();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
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 */
|
/* 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); */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
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");
|
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);
|
||||||
|
|
Loading…
Reference in a new issue