Renamed some methods; fixed bug that caused recovery to create potentially unbounded numbers of concurrent, active transactions.
(Note: this commit contains quite a few instances of auto-cleaned whitespace....)
This commit is contained in:
parent
dacc33642e
commit
4b07b538a6
15 changed files with 359 additions and 308 deletions
|
@ -42,6 +42,13 @@ int stasis_truncation_automatic = STASIS_TRUNCATION_AUTOMATIC;
|
||||||
int stasis_truncation_automatic = 1;
|
int stasis_truncation_automatic = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef STASIS_LOG_TYPE
|
||||||
|
int stasis_log_type = STASIS_LOG_TYPE;
|
||||||
|
#else
|
||||||
|
int stasis_log_type = LOG_TO_FILE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef STASIS_LOG_FILE_NAME
|
#ifdef STASIS_LOG_FILE_NAME
|
||||||
char * stasis_log_file_name = STASIS_LOG_FILE_NAME;
|
char * stasis_log_file_name = STASIS_LOG_FILE_NAME;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -2,160 +2,169 @@
|
||||||
#include <stasis/latches.h>
|
#include <stasis/latches.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
/**
|
|
||||||
@todo remove static fields from inMemoryLog
|
|
||||||
*/
|
|
||||||
static rwl * flushedLSN_lock;
|
|
||||||
static lsn_t nextAvailableLSN;
|
|
||||||
static lsn_t globalOffset;
|
|
||||||
static rwl * globalOffset_lock;
|
|
||||||
static LogEntry ** buffer;
|
|
||||||
static lsn_t bufferLen;
|
|
||||||
|
|
||||||
static lsn_t nextAvailableLSN_InMemoryLog(stasis_log_t * log) {
|
typedef struct {
|
||||||
writelock(flushedLSN_lock,0);
|
rwl * flushedLSN_lock;
|
||||||
writelock(globalOffset_lock,0);
|
lsn_t nextAvailableLSN;
|
||||||
lsn_t ret = nextAvailableLSN;
|
lsn_t globalOffset;
|
||||||
unlock(globalOffset_lock);
|
rwl * globalOffset_lock;
|
||||||
unlock(flushedLSN_lock);
|
LogEntry ** buffer;
|
||||||
|
lsn_t bufferLen;
|
||||||
|
} stasis_log_impl_in_memory;
|
||||||
|
|
||||||
|
static lsn_t stasis_log_impl_in_memory_next_available_lsn(stasis_log_t * log) {
|
||||||
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
|
writelock(impl->flushedLSN_lock,0);
|
||||||
|
writelock(impl->globalOffset_lock,0);
|
||||||
|
lsn_t ret = impl->nextAvailableLSN;
|
||||||
|
unlock(impl->globalOffset_lock);
|
||||||
|
unlock(impl->flushedLSN_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int writeLogEntry_InMemoryLog(stasis_log_t * log, LogEntry *e) {
|
static int stasis_log_impl_in_memory_write_entry(stasis_log_t * log, LogEntry *e) {
|
||||||
writelock(flushedLSN_lock, 0);
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
|
writelock(impl->flushedLSN_lock, 0);
|
||||||
lsn_t bufferOffset;
|
lsn_t bufferOffset;
|
||||||
|
|
||||||
int done = 0;
|
int done = 0;
|
||||||
do{
|
do{
|
||||||
writelock(globalOffset_lock,0);
|
writelock(impl->globalOffset_lock,0);
|
||||||
bufferOffset = nextAvailableLSN - globalOffset;
|
bufferOffset = impl->nextAvailableLSN - impl->globalOffset;
|
||||||
if(bufferOffset > bufferLen) {
|
if(bufferOffset > impl->bufferLen) {
|
||||||
bufferLen *= 2;
|
impl->bufferLen *= 2;
|
||||||
buffer = realloc(buffer, bufferLen);
|
impl->buffer = realloc(impl->buffer, impl->bufferLen);
|
||||||
} else {
|
} else {
|
||||||
done = 1;
|
done = 1;
|
||||||
}
|
}
|
||||||
} while (!done);
|
} while (!done);
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
e->LSN = impl->nextAvailableLSN;
|
||||||
e->LSN = nextAvailableLSN;
|
|
||||||
|
|
||||||
LogEntry * cpy = malloc(sizeofLogEntry(e));
|
LogEntry * cpy = malloc(sizeofLogEntry(e));
|
||||||
memcpy(cpy, e, sizeofLogEntry(e));
|
memcpy(cpy, e, sizeofLogEntry(e));
|
||||||
|
|
||||||
// printf ("lsn: %ld\n", e->LSN);
|
DEBUG("lsn: %ld\n", e->LSN);
|
||||||
buffer[bufferOffset] = cpy;
|
impl->buffer[bufferOffset] = cpy;
|
||||||
|
|
||||||
// printf("lsn: %ld type: %d\n", e->LSN, e->type);
|
DEBUG("lsn: %ld type: %d\n", e->LSN, e->type);
|
||||||
nextAvailableLSN++;
|
impl->nextAvailableLSN++;
|
||||||
|
|
||||||
unlock(globalOffset_lock);
|
unlock(impl->globalOffset_lock);
|
||||||
unlock(flushedLSN_lock);
|
unlock(impl->flushedLSN_lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lsn_t flushedLSN_InMemoryLog(stasis_log_t* log,
|
static lsn_t stasis_log_impl_in_memory_first_unstable_lsn(stasis_log_t* log,
|
||||||
stasis_log_force_mode_t mode) {
|
stasis_log_force_mode_t mode) {
|
||||||
return nextAvailableLSN;
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
|
return impl->nextAvailableLSN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void syncLog_InMemoryLog(stasis_log_t* log, stasis_log_force_mode_t m){
|
static void stasis_log_impl_in_memory_force_tail(stasis_log_t* log, stasis_log_force_mode_t m){
|
||||||
// no-op
|
// no-op
|
||||||
}
|
}
|
||||||
|
|
||||||
static lsn_t nextEntry_InMemoryLog(stasis_log_t * log, const LogEntry * e) {
|
static lsn_t stasis_log_impl_in_memory_next_entry(stasis_log_t * log, const LogEntry * e) {
|
||||||
return e->LSN + 1;
|
return e->LSN + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int truncateLog_InMemoryLog(stasis_log_t * log, lsn_t lsn) {
|
static int stasis_log_impl_in_memory_truncate(stasis_log_t * log, lsn_t lsn) {
|
||||||
writelock(flushedLSN_lock,1);
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
writelock(globalOffset_lock,1);
|
writelock(impl->flushedLSN_lock,1);
|
||||||
|
writelock(impl->globalOffset_lock,1);
|
||||||
assert(lsn <= nextAvailableLSN);
|
|
||||||
|
assert(lsn <= impl->nextAvailableLSN);
|
||||||
|
|
||||||
|
|
||||||
if(lsn > globalOffset) {
|
if(lsn > impl->globalOffset) {
|
||||||
for(int i = globalOffset; i < lsn; i++) {
|
for(int i = impl->globalOffset; i < lsn; i++) {
|
||||||
free(buffer[i - globalOffset]);
|
free(impl->buffer[i - impl->globalOffset]);
|
||||||
}
|
}
|
||||||
assert((lsn-globalOffset) + (nextAvailableLSN -lsn) < bufferLen);
|
assert((lsn-impl->globalOffset) + (impl->nextAvailableLSN -lsn) < impl->bufferLen);
|
||||||
memmove(&(buffer[0]), &(buffer[lsn - globalOffset]), sizeof(LogEntry*) * (nextAvailableLSN - lsn));
|
memmove(&(impl->buffer[0]), &(impl->buffer[lsn - impl->globalOffset]),
|
||||||
globalOffset = lsn;
|
sizeof(LogEntry*) * (impl->nextAvailableLSN - lsn));
|
||||||
|
impl->globalOffset = lsn;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeunlock(globalOffset_lock);
|
writeunlock(impl->globalOffset_lock);
|
||||||
writeunlock(flushedLSN_lock);
|
writeunlock(impl->flushedLSN_lock);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lsn_t firstLogEntry_InMemoryLog() {
|
static lsn_t stasis_log_impl_in_memory_truncation_point(stasis_log_t * log) {
|
||||||
return globalOffset;
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
|
return impl->globalOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int close_InMemoryLog(stasis_log_t * log) {
|
static int stasis_log_impl_in_memory_close(stasis_log_t * log) {
|
||||||
if(buffer) {
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
lsn_t firstEmptyOffset = nextAvailableLSN-globalOffset;
|
if(impl->buffer) {
|
||||||
for(lsn_t i = 0; i < firstEmptyOffset; i++) {
|
lsn_t firstEmptyOffset = impl->nextAvailableLSN-impl->globalOffset;
|
||||||
assert(buffer[i]->LSN == i+globalOffset);
|
for(lsn_t i = 0; i < firstEmptyOffset; i++) {
|
||||||
free(buffer[i]);
|
assert(impl->buffer[i]->LSN == i+impl->globalOffset);
|
||||||
|
free(impl->buffer[i]);
|
||||||
}
|
}
|
||||||
free(buffer);
|
free(impl->buffer);
|
||||||
nextAvailableLSN = 0;
|
impl->nextAvailableLSN = 0;
|
||||||
globalOffset = 0;
|
impl->globalOffset = 0;
|
||||||
bufferLen = 0;
|
impl->bufferLen = 0;
|
||||||
buffer = 0;
|
impl->buffer = 0;
|
||||||
|
free(impl);
|
||||||
}
|
}
|
||||||
free (log);
|
free (log);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const LogEntry * readLSNEntry_InMemoryLog(stasis_log_t* log,
|
static const LogEntry * stasis_log_impl_in_memory_read_entry(stasis_log_t* log,
|
||||||
lsn_t lsn) {
|
lsn_t lsn) {
|
||||||
// printf("lsn: %ld\n", lsn);
|
stasis_log_impl_in_memory * impl = log->impl;
|
||||||
if(lsn >= nextAvailableLSN) { return 0; }
|
DEBUG("lsn: %ld\n", lsn);
|
||||||
assert(lsn-globalOffset >= 0 && lsn-globalOffset< bufferLen);
|
if(lsn >= impl->nextAvailableLSN) { return 0; }
|
||||||
readlock(globalOffset_lock, 0);
|
assert(lsn-impl->globalOffset >= 0 && lsn-impl->globalOffset< impl->bufferLen);
|
||||||
LogEntry * ptr = buffer[lsn - globalOffset];
|
readlock(impl->globalOffset_lock, 0);
|
||||||
unlock(globalOffset_lock);
|
LogEntry * ptr = impl->buffer[lsn - impl->globalOffset];
|
||||||
|
unlock(impl->globalOffset_lock);
|
||||||
assert(ptr);
|
assert(ptr);
|
||||||
assert(ptr->LSN == lsn);
|
assert(ptr->LSN == lsn);
|
||||||
|
|
||||||
LogEntry * ret = malloc(sizeofLogEntry(ptr));
|
LogEntry * ret = malloc(sizeofLogEntry(ptr));
|
||||||
|
|
||||||
memcpy(ret, ptr, sizeofLogEntry(ptr));
|
memcpy(ret, ptr, sizeofLogEntry(ptr));
|
||||||
|
|
||||||
//printf("lsn: %ld prevlsn: %ld\n", ptr->LSN, ptr->prevLSN);
|
DEBUG("lsn: %ld prevlsn: %ld\n", ptr->LSN, ptr->prevLSN);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
static lsn_t sizeofInternalLogEntry_InMemoryLog(stasis_log_t* log,
|
static lsn_t stasis_log_impl_in_memory_sizeof_internal_entry(stasis_log_t* log,
|
||||||
const LogEntry * e) {
|
const LogEntry * e) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
static int isDurable_InMemoryLog(stasis_log_t*log) { return 0; }
|
static int stasis_log_impl_in_memory_is_durable(stasis_log_t*log) { return 0; }
|
||||||
|
|
||||||
stasis_log_t* open_InMemoryLog() {
|
stasis_log_t* stasis_log_impl_in_memory_open() {
|
||||||
flushedLSN_lock = initlock();
|
stasis_log_impl_in_memory * impl = malloc(sizeof(*impl));
|
||||||
globalOffset_lock = initlock();
|
impl->flushedLSN_lock = initlock();
|
||||||
globalOffset = 0;
|
impl->globalOffset_lock = initlock();
|
||||||
nextAvailableLSN = 0;
|
impl->globalOffset = 0;
|
||||||
buffer = malloc(4096 * 1024 * sizeof (LogEntry *));
|
impl->nextAvailableLSN = 0;
|
||||||
bufferLen =4096 * 1024;
|
impl->buffer = malloc(4096 * 1024 * sizeof (LogEntry *));
|
||||||
|
impl->bufferLen =4096 * 1024;
|
||||||
static stasis_log_t proto = {
|
static stasis_log_t proto = {
|
||||||
sizeofInternalLogEntry_InMemoryLog, // sizeof_internal_entry
|
stasis_log_impl_in_memory_sizeof_internal_entry,
|
||||||
writeLogEntry_InMemoryLog,// write_entry
|
stasis_log_impl_in_memory_write_entry,
|
||||||
readLSNEntry_InMemoryLog, // read_entry
|
stasis_log_impl_in_memory_read_entry,
|
||||||
nextEntry_InMemoryLog,// next_entry
|
stasis_log_impl_in_memory_next_entry,
|
||||||
flushedLSN_InMemoryLog, // first_unstable_lsn
|
stasis_log_impl_in_memory_first_unstable_lsn,
|
||||||
nextAvailableLSN_InMemoryLog, // next_available_lsn
|
stasis_log_impl_in_memory_next_available_lsn,
|
||||||
syncLog_InMemoryLog, // force_tail
|
stasis_log_impl_in_memory_force_tail,
|
||||||
truncateLog_InMemoryLog, // truncate
|
stasis_log_impl_in_memory_truncate,
|
||||||
firstLogEntry_InMemoryLog,// truncation_point
|
stasis_log_impl_in_memory_truncation_point,
|
||||||
close_InMemoryLog, // deinit
|
stasis_log_impl_in_memory_close,
|
||||||
isDurable_InMemoryLog// is_durable
|
stasis_log_impl_in_memory_is_durable
|
||||||
};
|
};
|
||||||
stasis_log_t* log = malloc(sizeof(*log));
|
stasis_log_t* log = malloc(sizeof(*log));
|
||||||
memcpy(log,&proto, sizeof(proto));
|
memcpy(log,&proto, sizeof(proto));
|
||||||
|
log->impl = impl;
|
||||||
return log;
|
return log;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,15 +61,6 @@ terms specified in this license.
|
||||||
#include <stasis/logger/inMemoryLog.h>
|
#include <stasis/logger/inMemoryLog.h>
|
||||||
#include <stasis/page.h>
|
#include <stasis/page.h>
|
||||||
|
|
||||||
/**
|
|
||||||
@todo loggerType should go away.
|
|
||||||
*/
|
|
||||||
#ifdef USE_LOGGER
|
|
||||||
int loggerType = USE_LOGGER;
|
|
||||||
#else
|
|
||||||
int loggerType = LOG_TO_FILE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@todo stasis_log_file should be in transactional2.c, and not global
|
@todo stasis_log_file should be in transactional2.c, and not global
|
||||||
*/
|
*/
|
||||||
|
@ -96,7 +87,7 @@ static lsn_t LogTransCommon(stasis_log_t* log, TransactionLog * l, int type) {
|
||||||
l->prevLSN = e->LSN;
|
l->prevLSN = e->LSN;
|
||||||
pthread_mutex_unlock(&l->mut);
|
pthread_mutex_unlock(&l->mut);
|
||||||
|
|
||||||
DEBUG("Log Common %d, LSN: %ld type: %ld (prevLSN %ld)\n", e->xid,
|
DEBUG("Log Common %d, LSN: %ld type: %ld (prevLSN %ld)\n", e->xid,
|
||||||
(long int)e->LSN, (long int)e->type, (long int)e->prevLSN);
|
(long int)e->LSN, (long int)e->type, (long int)e->prevLSN);
|
||||||
|
|
||||||
ret = e->LSN;
|
ret = e->LSN;
|
||||||
|
@ -138,7 +129,7 @@ LogEntry * LogUpdate(stasis_log_t* log, TransactionLog * l,
|
||||||
arg, arg_size);
|
arg, arg_size);
|
||||||
|
|
||||||
log->write_entry(log, e);
|
log->write_entry(log, e);
|
||||||
DEBUG("Log Update %d, LSN: %ld type: %ld (prevLSN %ld) (arg_size %ld)\n", e->xid,
|
DEBUG("Log Update %d, LSN: %ld type: %ld (prevLSN %ld) (arg_size %ld)\n", e->xid,
|
||||||
(long int)e->LSN, (long int)e->type, (long int)e->prevLSN, (long int) arg_size);
|
(long int)e->LSN, (long int)e->type, (long int)e->prevLSN, (long int) arg_size);
|
||||||
pthread_mutex_lock(&l->mut);
|
pthread_mutex_lock(&l->mut);
|
||||||
if(l->prevLSN == -1) { l->recLSN = e->LSN; }
|
if(l->prevLSN == -1) { l->recLSN = e->LSN; }
|
||||||
|
@ -147,11 +138,11 @@ LogEntry * LogUpdate(stasis_log_t* log, TransactionLog * l,
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
lsn_t LogCLR(stasis_log_t* log, const LogEntry * old_e) {
|
lsn_t LogCLR(stasis_log_t* log, const LogEntry * old_e) {
|
||||||
LogEntry * e = allocCLRLogEntry(old_e);
|
LogEntry * e = allocCLRLogEntry(old_e);
|
||||||
log->write_entry(log, e);
|
log->write_entry(log, e);
|
||||||
|
|
||||||
DEBUG("Log CLR %d, LSN: %ld (undoing: %ld, next to undo: %ld)\n", xid,
|
DEBUG("Log CLR %d, LSN: %ld (undoing: %ld, next to undo: %ld)\n", xid,
|
||||||
e->LSN, LSN, prevLSN);
|
e->LSN, LSN, prevLSN);
|
||||||
lsn_t ret = e->LSN;
|
lsn_t ret = e->LSN;
|
||||||
freeLogEntry(e);
|
freeLogEntry(e);
|
||||||
|
@ -178,6 +169,9 @@ lsn_t LogTransCommit(stasis_log_t* log, TransactionLog * l) {
|
||||||
lsn_t LogTransAbort(stasis_log_t* log, TransactionLog * l) {
|
lsn_t LogTransAbort(stasis_log_t* log, TransactionLog * l) {
|
||||||
return LogTransCommon(log, l, XABORT);
|
return LogTransCommon(log, l, XABORT);
|
||||||
}
|
}
|
||||||
|
lsn_t LogTransEnd(stasis_log_t* log, TransactionLog * l) {
|
||||||
|
return LogTransCommon(log, l, XEND);
|
||||||
|
}
|
||||||
lsn_t LogTransPrepare(stasis_log_t* log, TransactionLog * l) {
|
lsn_t LogTransPrepare(stasis_log_t* log, TransactionLog * l) {
|
||||||
lsn_t lsn = LogTransCommonPrepare(log, l);
|
lsn_t lsn = LogTransCommonPrepare(log, l);
|
||||||
LogForce(log, lsn, LOG_FORCE_COMMIT);
|
LogForce(log, lsn, LOG_FORCE_COMMIT);
|
||||||
|
@ -226,8 +220,8 @@ static void groupCommit(stasis_log_t* log, lsn_t lsn) {
|
||||||
if((xactcount > 1 && pendingCommits < xactcount) ||
|
if((xactcount > 1 && pendingCommits < xactcount) ||
|
||||||
(xactcount > 20 && pendingCommits < (int)((double)xactcount * 0.95))) {
|
(xactcount > 20 && pendingCommits < (int)((double)xactcount * 0.95))) {
|
||||||
int retcode;
|
int retcode;
|
||||||
while(ETIMEDOUT != (retcode = pthread_cond_timedwait(&tooFewXacts, &check_commit, &timeout))) {
|
while(ETIMEDOUT != (retcode = pthread_cond_timedwait(&tooFewXacts, &check_commit, &timeout))) {
|
||||||
if(retcode != 0) {
|
if(retcode != 0) {
|
||||||
printf("Warning: %s:%d: pthread_cond_timedwait was interrupted by "
|
printf("Warning: %s:%d: pthread_cond_timedwait was interrupted by "
|
||||||
"a signal in groupCommit(). Acting as though it timed out.\n",
|
"a signal in groupCommit(). Acting as though it timed out.\n",
|
||||||
__FILE__, __LINE__);
|
__FILE__, __LINE__);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/**
|
||||||
|
|
||||||
@file
|
@file
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
#include <stasis/logger/logHandle.h>
|
#include <stasis/logger/logHandle.h>
|
||||||
/** @todo Get rid of linkedlist */
|
/** @todo Get rid of linkedlist */
|
||||||
#include <stasis/linkedlist.h>
|
#include <stasis/linkedlist.h>
|
||||||
#include <stasis/page.h> // Needed for pageReadLSN.
|
#include <stasis/page.h> // Needed for pageReadLSN.
|
||||||
|
|
||||||
static pblHashTable_t * transactionLSN;
|
static pblHashTable_t * transactionLSN;
|
||||||
static LinkedList * rollbackLSNs = NULL;
|
static LinkedList * rollbackLSNs = NULL;
|
||||||
|
@ -41,15 +41,15 @@ static pthread_mutex_t rollback_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
- Calculated a list of all dirty pages.
|
- Calculated a list of all dirty pages.
|
||||||
|
|
||||||
It no longer does either of these things:
|
It no longer does either of these things:
|
||||||
- A checkpointing algorithm could figure out where the redo pass
|
- A checkpointing algorithm could figure out where the redo pass
|
||||||
should begin. (It would then truncate the log at that point.) This
|
should begin. (It would then truncate the log at that point.) This
|
||||||
function could be called before analysis if efficiency is a concern.
|
function could be called before analysis if efficiency is a concern.
|
||||||
- We were using the list of dirty pages as an optimization to prevent
|
- We were using the list of dirty pages as an optimization to prevent
|
||||||
the pages from being read later during recovery. Since this function
|
the pages from being read later during recovery. Since this function
|
||||||
no longer reads the pages in, there's no longer any reason to build
|
no longer reads the pages in, there's no longer any reason to build
|
||||||
the list of dirty pages.
|
the list of dirty pages.
|
||||||
*/
|
*/
|
||||||
static void Analysis(stasis_log_t* log) {
|
static void stasis_recovery_analysis(stasis_log_t* log) {
|
||||||
|
|
||||||
DEBUG("Recovery: Analysis\n");
|
DEBUG("Recovery: Analysis\n");
|
||||||
|
|
||||||
|
@ -74,16 +74,16 @@ static void Analysis(stasis_log_t* log) {
|
||||||
- map: xid -> max LSN
|
- map: xid -> max LSN
|
||||||
- sorted list of maxLSN's
|
- sorted list of maxLSN's
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if(xactLSN == NULL) {
|
if(xactLSN == NULL) {
|
||||||
xactLSN = malloc(sizeof(lsn_t));
|
xactLSN = malloc(sizeof(lsn_t));
|
||||||
pblHtInsert(transactionLSN, &(e->xid), sizeof(int), xactLSN);
|
pblHtInsert(transactionLSN, &(e->xid), sizeof(int), xactLSN);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* We've seen this xact before, and must have put a value in
|
/* We've seen this xact before, and must have put a value in
|
||||||
rollbackLSNs for it. That value is now stale, so remove
|
rollbackLSNs for it. That value is now stale, so remove
|
||||||
it. */
|
it. */
|
||||||
|
|
||||||
DEBUG("Removing %lld\n", *xactLSN);
|
DEBUG("Removing %lld\n", *xactLSN);
|
||||||
removeVal(&rollbackLSNs, *xactLSN);
|
removeVal(&rollbackLSNs, *xactLSN);
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ static void Analysis(stasis_log_t* log) {
|
||||||
be rolled back, so we're done. */
|
be rolled back, so we're done. */
|
||||||
break;
|
break;
|
||||||
case XEND: {
|
case XEND: {
|
||||||
/*
|
/*
|
||||||
XEND means this transaction reached stable storage.
|
XEND means this transaction reached stable storage.
|
||||||
Therefore, we can skip redoing any of its operations. (The
|
Therefore, we can skip redoing any of its operations. (The
|
||||||
timestamps on each page guarantee that the redo phase will
|
timestamps on each page guarantee that the redo phase will
|
||||||
|
@ -115,14 +115,15 @@ static void Analysis(stasis_log_t* log) {
|
||||||
lsn_t* free_lsn = pblHtLookup(transactionLSN, &(e->xid), sizeof(int));
|
lsn_t* free_lsn = pblHtLookup(transactionLSN, &(e->xid), sizeof(int));
|
||||||
pblHtRemove(transactionLSN, &(e->xid), sizeof(int));
|
pblHtRemove(transactionLSN, &(e->xid), sizeof(int));
|
||||||
free(free_lsn);
|
free(free_lsn);
|
||||||
|
stasis_transaction_table_forget(e->xid);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UPDATELOG:
|
case UPDATELOG:
|
||||||
case CLRLOG:
|
case CLRLOG:
|
||||||
/*
|
/*
|
||||||
If the last record we see for a transaction is an update or clr,
|
If the last record we see for a transaction is an update or clr,
|
||||||
then the transaction must not have committed, so it must need
|
then the transaction must not have committed, so it must need
|
||||||
to be rolled back.
|
to be rolled back.
|
||||||
|
|
||||||
Add it to the list
|
Add it to the list
|
||||||
|
|
||||||
|
@ -131,9 +132,9 @@ static void Analysis(stasis_log_t* log) {
|
||||||
|
|
||||||
addSortedVal(&rollbackLSNs, e->LSN);
|
addSortedVal(&rollbackLSNs, e->LSN);
|
||||||
break;
|
break;
|
||||||
case XABORT:
|
case XABORT:
|
||||||
// If the last record we see for a transaction is an abort, then
|
// If the last record we see for a transaction is an abort, then
|
||||||
// the transaction didn't commit, and must be rolled back.
|
// the transaction didn't commit, and must be rolled back.
|
||||||
DEBUG("Adding %lld\n", e->LSN);
|
DEBUG("Adding %lld\n", e->LSN);
|
||||||
addSortedVal(&rollbackLSNs, e->LSN);
|
addSortedVal(&rollbackLSNs, e->LSN);
|
||||||
break;
|
break;
|
||||||
|
@ -143,8 +144,8 @@ static void Analysis(stasis_log_t* log) {
|
||||||
case INTERNALLOG:
|
case INTERNALLOG:
|
||||||
// Created by the logger, just ignore it
|
// Created by the logger, just ignore it
|
||||||
// Make sure the log entry doesn't interfere with real xacts.
|
// Make sure the log entry doesn't interfere with real xacts.
|
||||||
assert(e->xid == INVALID_XID);
|
assert(e->xid == INVALID_XID);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -171,7 +172,7 @@ static void Analysis(stasis_log_t* log) {
|
||||||
Y (NTA replaces physical undo)
|
Y (NTA replaces physical undo)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void Redo(stasis_log_t* log) {
|
static void stasis_recovery_redo(stasis_log_t* log) {
|
||||||
LogHandle* lh = getLogHandle(log);
|
LogHandle* lh = getLogHandle(log);
|
||||||
const LogEntry * e;
|
const LogEntry * e;
|
||||||
|
|
||||||
|
@ -250,7 +251,7 @@ static void Redo(stasis_log_t* log) {
|
||||||
freeLogHandle(lh);
|
freeLogHandle(lh);
|
||||||
|
|
||||||
}
|
}
|
||||||
static void Undo(stasis_log_t* log, int recovery) {
|
static void stasis_recovery_undo(stasis_log_t* log, int recovery) {
|
||||||
LogHandle* lh;
|
LogHandle* lh;
|
||||||
|
|
||||||
DEBUG("Recovery: Undo\n");
|
DEBUG("Recovery: Undo\n");
|
||||||
|
@ -274,7 +275,7 @@ static void Undo(stasis_log_t* log, int recovery) {
|
||||||
switch(e->type) {
|
switch(e->type) {
|
||||||
case UPDATELOG:
|
case UPDATELOG:
|
||||||
{
|
{
|
||||||
if(e->update.page == INVALID_PAGE) {
|
if(e->update.page == INVALID_PAGE) {
|
||||||
DEBUG("logical update\n");
|
DEBUG("logical update\n");
|
||||||
|
|
||||||
// logical undo: no-op; then the NTA didn't complete, and
|
// logical undo: no-op; then the NTA didn't complete, and
|
||||||
|
@ -337,7 +338,8 @@ static void Undo(stasis_log_t* log, int recovery) {
|
||||||
// records may be passed in by undoTrans.
|
// records may be passed in by undoTrans.
|
||||||
break;
|
break;
|
||||||
case XCOMMIT:
|
case XCOMMIT:
|
||||||
// Should never abort a transaction that contains a commit record
|
case XEND:
|
||||||
|
// Should never abort a transaction that contains a commit or end record
|
||||||
abort();
|
abort();
|
||||||
case XPREPARE: {
|
case XPREPARE: {
|
||||||
DEBUG("found prepared xact %d\n", e->xid);
|
DEBUG("found prepared xact %d\n", e->xid);
|
||||||
|
@ -355,15 +357,14 @@ static void Undo(stasis_log_t* log, int recovery) {
|
||||||
default:
|
default:
|
||||||
DEBUG
|
DEBUG
|
||||||
("Unknown log type to undo (TYPE=%d,XID= %d,LSN=%lld), skipping...\n",
|
("Unknown log type to undo (TYPE=%d,XID= %d,LSN=%lld), skipping...\n",
|
||||||
e->type, e->xid, e->LSN);
|
e->type, e->xid, e->LSN);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
freeLogEntry(e);
|
freeLogEntry(e);
|
||||||
}
|
}
|
||||||
if(!prepared) {
|
if(!prepared) {
|
||||||
if(recovery) {
|
// Log an XEND, remove transaction from XactionTable.
|
||||||
stasis_transaction_table_forget(thisXid);
|
Tforget(thisXid);
|
||||||
}
|
|
||||||
if(globalLockManager.abort) {
|
if(globalLockManager.abort) {
|
||||||
globalLockManager.abort(thisXid);
|
globalLockManager.abort(thisXid);
|
||||||
}
|
}
|
||||||
|
@ -375,12 +376,12 @@ void stasis_recovery_initiate(stasis_log_t* log) {
|
||||||
|
|
||||||
transactionLSN = pblHtCreate();
|
transactionLSN = pblHtCreate();
|
||||||
DEBUG("Analysis started\n");
|
DEBUG("Analysis started\n");
|
||||||
Analysis(log);
|
stasis_recovery_analysis(log);
|
||||||
DEBUG("Redo started\n");
|
DEBUG("Redo started\n");
|
||||||
Redo(log);
|
stasis_recovery_redo(log);
|
||||||
DEBUG("Undo started\n");
|
DEBUG("Undo started\n");
|
||||||
TallocPostInit();
|
TallocPostInit();
|
||||||
Undo(log,1);
|
stasis_recovery_undo(log,1);
|
||||||
DEBUG("Recovery complete.\n");
|
DEBUG("Recovery complete.\n");
|
||||||
|
|
||||||
for(void * it = pblHtFirst(transactionLSN); it; it = pblHtNext(transactionLSN)) {
|
for(void * it = pblHtFirst(transactionLSN); it; it = pblHtNext(transactionLSN)) {
|
||||||
|
@ -393,7 +394,7 @@ void stasis_recovery_initiate(stasis_log_t* log) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void undoTrans(stasis_log_t* log, TransactionLog transaction) {
|
void undoTrans(stasis_log_t* log, TransactionLog transaction) {
|
||||||
|
|
||||||
pthread_mutex_lock(&rollback_mutex);
|
pthread_mutex_lock(&rollback_mutex);
|
||||||
assert(!rollbackLSNs);
|
assert(!rollbackLSNs);
|
||||||
|
@ -405,7 +406,7 @@ void undoTrans(stasis_log_t* log, TransactionLog transaction) {
|
||||||
/* Nothing to undo. (Happens for read-only xacts.) */
|
/* Nothing to undo. (Happens for read-only xacts.) */
|
||||||
}
|
}
|
||||||
|
|
||||||
Undo(log, 0);
|
stasis_recovery_undo(log, 0);
|
||||||
if(rollbackLSNs) {
|
if(rollbackLSNs) {
|
||||||
destroyList(&rollbackLSNs);
|
destroyList(&rollbackLSNs);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ struct ringBufferLog_s {
|
||||||
#define offset_to_lsn(x, lsn) ((lsn) + (x)->offset)
|
#define offset_to_lsn(x, lsn) ((lsn) + (x)->offset)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int truncateLog(ringBufferLog_t * log, lsn_t lsn);
|
static int stasis_ringbuffer_truncate(ringBufferLog_t * log, lsn_t lsn);
|
||||||
|
|
||||||
ringBufferLog_t * openLogRingBuffer(size_t size, lsn_t initialOffset) {
|
ringBufferLog_t * openLogRingBuffer(size_t size, lsn_t initialOffset) {
|
||||||
ringBufferLog_t * ret = malloc(sizeof(ringBufferLog_t));
|
ringBufferLog_t * ret = malloc(sizeof(ringBufferLog_t));
|
||||||
|
@ -132,12 +132,12 @@ int ringBufferTruncateRead(byte * buf, ringBufferLog_t * log, size_t size) {
|
||||||
}
|
}
|
||||||
memcpyFromRingBuffer(buf, log, lsn_to_offset(log, log->start), size);
|
memcpyFromRingBuffer(buf, log, lsn_to_offset(log, log->start), size);
|
||||||
|
|
||||||
return truncateLog(log, log->start + size);
|
return stasis_ringbuffer_truncate(log, log->start + size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** static because it does no error checking. */
|
/** static because it does no error checking. */
|
||||||
static int truncateLog(ringBufferLog_t * log, lsn_t lsn) {
|
static int stasis_ringbuffer_truncate(ringBufferLog_t * log, lsn_t lsn) {
|
||||||
|
|
||||||
#ifdef TRACK_OFFSETS
|
#ifdef TRACK_OFFSETS
|
||||||
lsn_t newStart = lsn_to_offset(log, lsn);
|
lsn_t newStart = lsn_to_offset(log, lsn);
|
||||||
|
|
|
@ -37,9 +37,9 @@ static int initted = 0;
|
||||||
const recordid ROOT_RECORD = {1, 0, -1};
|
const recordid ROOT_RECORD = {1, 0, -1};
|
||||||
const recordid NULLRID = {0,0,-1};
|
const recordid NULLRID = {0,0,-1};
|
||||||
const short SLOT_TYPE_LENGTHS[] = { -1, -1, sizeof(blob_record_t), -1};
|
const short SLOT_TYPE_LENGTHS[] = { -1, -1, sizeof(blob_record_t), -1};
|
||||||
/**
|
/**
|
||||||
Locking for transactional2.c works as follows:
|
Locking for transactional2.c works as follows:
|
||||||
|
|
||||||
numActiveXactions, xidCount are protected, XactionTable is not.
|
numActiveXactions, xidCount are protected, XactionTable is not.
|
||||||
This implies that we do not support multi-threaded transactions,
|
This implies that we do not support multi-threaded transactions,
|
||||||
at least for now.
|
at least for now.
|
||||||
|
@ -58,7 +58,7 @@ void stasis_transaction_table_init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo this factory stuff doesn't really belong here...
|
// @todo this factory stuff doesn't really belong here...
|
||||||
static stasis_handle_t * fast_factory(lsn_t off, lsn_t len, void * ignored) {
|
static stasis_handle_t * fast_factory(lsn_t off, lsn_t len, void * ignored) {
|
||||||
stasis_handle_t * h = stasis_handle(open_memory)(off);
|
stasis_handle_t * h = stasis_handle(open_memory)(off);
|
||||||
//h = stasis_handle(open_debug)(h);
|
//h = stasis_handle(open_debug)(h);
|
||||||
stasis_write_buffer_t * w = h->append_buffer(h, len);
|
stasis_write_buffer_t * w = h->append_buffer(h, len);
|
||||||
|
@ -70,7 +70,7 @@ typedef struct sf_args {
|
||||||
int openMode;
|
int openMode;
|
||||||
int filePerm;
|
int filePerm;
|
||||||
} sf_args;
|
} sf_args;
|
||||||
static stasis_handle_t * slow_file_factory(void * argsP) {
|
static stasis_handle_t * slow_file_factory(void * argsP) {
|
||||||
sf_args * args = (sf_args*) argsP;
|
sf_args * args = (sf_args*) argsP;
|
||||||
stasis_handle_t * h = stasis_handle(open_file)(0, args->filename, args->openMode, args->filePerm);
|
stasis_handle_t * h = stasis_handle(open_file)(0, args->filename, args->openMode, args->filePerm);
|
||||||
//h = stasis_handle(open_debug)(h);
|
//h = stasis_handle(open_debug)(h);
|
||||||
|
@ -94,12 +94,12 @@ int Tinit() {
|
||||||
stasis_transaction_table_init();
|
stasis_transaction_table_init();
|
||||||
stasis_operation_table_init();
|
stasis_operation_table_init();
|
||||||
dirtyPagesInit();
|
dirtyPagesInit();
|
||||||
if(LOG_TO_FILE == loggerType) {
|
if(LOG_TO_FILE == stasis_log_type) {
|
||||||
stasis_log_file = stasis_log_safe_writes_open(stasis_log_file_name,
|
stasis_log_file = stasis_log_safe_writes_open(stasis_log_file_name,
|
||||||
stasis_log_file_mode,
|
stasis_log_file_mode,
|
||||||
stasis_log_file_permissions);
|
stasis_log_file_permissions);
|
||||||
} else if(LOG_TO_MEMORY == loggerType) {
|
} else if(LOG_TO_MEMORY == stasis_log_type) {
|
||||||
stasis_log_file = open_InMemoryLog();
|
stasis_log_file = stasis_log_impl_in_memory_open();
|
||||||
} else {
|
} else {
|
||||||
assert(stasis_log_file != NULL);
|
assert(stasis_log_file != NULL);
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ int Tinit() {
|
||||||
openMode, FILE_PERM);
|
openMode, FILE_PERM);
|
||||||
pageHandleOpen(pageFile);
|
pageHandleOpen(pageFile);
|
||||||
} break;
|
} break;
|
||||||
case BUFFER_MANAGER_FILE_HANDLE_DEPRECATED: {
|
case BUFFER_MANAGER_FILE_HANDLE_DEPRECATED: {
|
||||||
printf("\nWarning: Using old I/O routines (with known bugs).\n");
|
printf("\nWarning: Using old I/O routines (with known bugs).\n");
|
||||||
openPageFile();
|
openPageFile();
|
||||||
} break;
|
} break;
|
||||||
|
@ -245,7 +245,7 @@ static compensated_function void TactionHelper(int xid,
|
||||||
Page * p) {
|
Page * p) {
|
||||||
LogEntry * e;
|
LogEntry * e;
|
||||||
assert(xid >= 0 && XactionTable[xid % MAX_TRANSACTIONS].xid == xid);
|
assert(xid >= 0 && XactionTable[xid % MAX_TRANSACTIONS].xid == xid);
|
||||||
try {
|
try {
|
||||||
if(globalLockManager.writeLockPage) {
|
if(globalLockManager.writeLockPage) {
|
||||||
globalLockManager.writeLockPage(xid, p->id);
|
globalLockManager.writeLockPage(xid, p->id);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ void TreorderableUpdate(int xid, void * hp, pageid_t page,
|
||||||
assert(xid >= 0 && XactionTable[xid % MAX_TRANSACTIONS].xid == xid);
|
assert(xid >= 0 && XactionTable[xid % MAX_TRANSACTIONS].xid == xid);
|
||||||
Page * p = loadPage(xid, page);
|
Page * p = loadPage(xid, page);
|
||||||
assert(p);
|
assert(p);
|
||||||
try {
|
try {
|
||||||
if(globalLockManager.writeLockPage) {
|
if(globalLockManager.writeLockPage) {
|
||||||
globalLockManager.writeLockPage(xid, p->id);
|
globalLockManager.writeLockPage(xid, p->id);
|
||||||
}
|
}
|
||||||
|
@ -322,8 +322,8 @@ compensated_function void TupdateStr(int xid, pageid_t page,
|
||||||
Tupdate(xid, page, dat, datlen, op);
|
Tupdate(xid, page, dat, datlen, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
compensated_function void Tupdate(int xid, pageid_t page,
|
compensated_function void Tupdate(int xid, pageid_t page,
|
||||||
const void *dat, size_t datlen, int op) {
|
const void *dat, size_t datlen, int op) {
|
||||||
Page * p = loadPage(xid, page);
|
Page * p = loadPage(xid, page);
|
||||||
assert(initted);
|
assert(initted);
|
||||||
TactionHelper(xid, dat, datlen, op, p);
|
TactionHelper(xid, dat, datlen, op, p);
|
||||||
|
@ -336,14 +336,14 @@ compensated_function void TreadStr(int xid, recordid rid, char * dat) {
|
||||||
|
|
||||||
compensated_function void Tread(int xid, recordid rid, void * dat) {
|
compensated_function void Tread(int xid, recordid rid, void * dat) {
|
||||||
Page * p;
|
Page * p;
|
||||||
try {
|
try {
|
||||||
p = loadPage(xid, rid.page);
|
p = loadPage(xid, rid.page);
|
||||||
} end;
|
} end;
|
||||||
|
|
||||||
readlock(p->rwlatch,0);
|
readlock(p->rwlatch,0);
|
||||||
|
|
||||||
rid = stasis_record_dereference(xid, p, rid);
|
rid = stasis_record_dereference(xid, p, rid);
|
||||||
if(rid.page != p->id) {
|
if(rid.page != p->id) {
|
||||||
unlock(p->rwlatch);
|
unlock(p->rwlatch);
|
||||||
releasePage(p);
|
releasePage(p);
|
||||||
p = loadPage(xid, rid.page);
|
p = loadPage(xid, rid.page);
|
||||||
|
@ -363,7 +363,7 @@ compensated_function void Tread(int xid, recordid rid, void * dat) {
|
||||||
|
|
||||||
compensated_function void TreadRaw(int xid, recordid rid, void * dat) {
|
compensated_function void TreadRaw(int xid, recordid rid, void * dat) {
|
||||||
Page * p;
|
Page * p;
|
||||||
try {
|
try {
|
||||||
p = loadPage(xid, rid.page);
|
p = loadPage(xid, rid.page);
|
||||||
} end;
|
} end;
|
||||||
readlock(p->rwlatch,0);
|
readlock(p->rwlatch,0);
|
||||||
|
@ -375,7 +375,7 @@ compensated_function void TreadRaw(int xid, recordid rid, void * dat) {
|
||||||
int Tcommit(int xid) {
|
int Tcommit(int xid) {
|
||||||
lsn_t lsn;
|
lsn_t lsn;
|
||||||
assert(xid >= 0);
|
assert(xid >= 0);
|
||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
pthread_mutex_lock(&transactional_2_mutex);
|
pthread_mutex_lock(&transactional_2_mutex);
|
||||||
assert(numActiveXactions <= MAX_TRANSACTIONS);
|
assert(numActiveXactions <= MAX_TRANSACTIONS);
|
||||||
pthread_mutex_unlock(&transactional_2_mutex);
|
pthread_mutex_unlock(&transactional_2_mutex);
|
||||||
|
@ -420,15 +420,15 @@ int Tabort(int xid) {
|
||||||
|
|
||||||
allocTransactionAbort(xid);
|
allocTransactionAbort(xid);
|
||||||
|
|
||||||
pthread_mutex_lock(&transactional_2_mutex);
|
|
||||||
|
|
||||||
XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID;
|
|
||||||
numActiveXactions--;
|
|
||||||
assert( numActiveXactions >= 0 );
|
|
||||||
pthread_mutex_unlock(&transactional_2_mutex);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int Tforget(int xid) {
|
||||||
|
TransactionLog * t = &XactionTable[xid%MAX_TRANSACTIONS];
|
||||||
|
assert(t->xid == xid);
|
||||||
|
LogTransEnd(stasis_log_file, t);
|
||||||
|
stasis_transaction_table_forget(t->xid);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int Tdeinit() {
|
int Tdeinit() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -454,7 +454,7 @@ int Tdeinit() {
|
||||||
slow_close = 0;
|
slow_close = 0;
|
||||||
}
|
}
|
||||||
stasis_page_deinit();
|
stasis_page_deinit();
|
||||||
stasis_log_file->deinit(stasis_log_file);
|
stasis_log_file->close(stasis_log_file);
|
||||||
dirtyPagesDeinit();
|
dirtyPagesDeinit();
|
||||||
|
|
||||||
initted = 0;
|
initted = 0;
|
||||||
|
@ -475,7 +475,7 @@ int TuncleanShutdown() {
|
||||||
slow_close = 0;
|
slow_close = 0;
|
||||||
}
|
}
|
||||||
stasis_page_deinit();
|
stasis_page_deinit();
|
||||||
stasis_log_file->deinit(stasis_log_file);
|
stasis_log_file->close(stasis_log_file);
|
||||||
numActiveXactions = 0;
|
numActiveXactions = 0;
|
||||||
dirtyPagesDeinit();
|
dirtyPagesDeinit();
|
||||||
|
|
||||||
|
@ -496,13 +496,13 @@ void stasis_transaction_table_active_transaction_count_set(int xid) {
|
||||||
pthread_mutex_unlock(&transactional_2_mutex);
|
pthread_mutex_unlock(&transactional_2_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
lsn_t transactions_minRecLSN() {
|
lsn_t transactions_minRecLSN() {
|
||||||
lsn_t minRecLSN = LSN_T_MAX;
|
lsn_t minRecLSN = LSN_T_MAX;
|
||||||
pthread_mutex_lock(&transactional_2_mutex);
|
pthread_mutex_lock(&transactional_2_mutex);
|
||||||
for(int i = 0; i < MAX_TRANSACTIONS; i++) {
|
for(int i = 0; i < MAX_TRANSACTIONS; i++) {
|
||||||
if(XactionTable[i].xid != INVALID_XTABLE_XID) {
|
if(XactionTable[i].xid != INVALID_XTABLE_XID) {
|
||||||
lsn_t recLSN = XactionTable[i].recLSN;
|
lsn_t recLSN = XactionTable[i].recLSN;
|
||||||
if(recLSN != -1 && recLSN < minRecLSN) {
|
if(recLSN != -1 && recLSN < minRecLSN) {
|
||||||
minRecLSN = recLSN;
|
minRecLSN = recLSN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -531,7 +531,7 @@ int* TlistActiveTransactions() {
|
||||||
pthread_mutex_unlock(&transactional_2_mutex);
|
pthread_mutex_unlock(&transactional_2_mutex);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
int TisActiveTransaction(int xid) {
|
int TisActiveTransaction(int xid) {
|
||||||
if(xid < 0) { return 0; }
|
if(xid < 0) { return 0; }
|
||||||
pthread_mutex_lock(&transactional_2_mutex);
|
pthread_mutex_lock(&transactional_2_mutex);
|
||||||
int ret = xid != INVALID_XTABLE_XID && XactionTable[xid%MAX_TRANSACTIONS].xid == xid;
|
int ret = xid != INVALID_XTABLE_XID && XactionTable[xid%MAX_TRANSACTIONS].xid == xid;
|
||||||
|
@ -579,11 +579,11 @@ int stasis_transaction_table_forget(int xid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int TdurabilityLevel() {
|
int TdurabilityLevel() {
|
||||||
if(bufferManagerType == BUFFER_MANAGER_MEM_ARRAY) {
|
if(bufferManagerType == BUFFER_MANAGER_MEM_ARRAY) {
|
||||||
return VOLATILE;
|
return VOLATILE;
|
||||||
} else if(loggerType == LOG_TO_MEMORY) {
|
} else if(stasis_log_type == LOG_TO_MEMORY) {
|
||||||
return PERSISTENT;
|
return PERSISTENT;
|
||||||
} else {
|
} else {
|
||||||
return DURABLE;
|
return DURABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -642,7 +642,7 @@ lsn_t TendNestedTopAction(int xid, void * handle) {
|
||||||
// Ensure that the next action in this transaction points to the CLR.
|
// Ensure that the next action in this transaction points to the CLR.
|
||||||
XactionTable[xid % MAX_TRANSACTIONS].prevLSN = clrLSN;
|
XactionTable[xid % MAX_TRANSACTIONS].prevLSN = clrLSN;
|
||||||
|
|
||||||
DEBUG("NestedTopAction CLR %d, LSN: %ld type: %ld (undoing: %ld, next to undo: %ld)\n", e->xid,
|
DEBUG("NestedTopAction CLR %d, LSN: %ld type: %ld (undoing: %ld, next to undo: %ld)\n", e->xid,
|
||||||
clrLSN, undoneLSN, *prevLSN);
|
clrLSN, undoneLSN, *prevLSN);
|
||||||
|
|
||||||
free(h);
|
free(h);
|
||||||
|
|
|
@ -57,6 +57,23 @@ extern int stasis_suppress_unclean_shutdown_warnings;
|
||||||
*/
|
*/
|
||||||
extern int stasis_truncation_automatic;
|
extern int stasis_truncation_automatic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This is the log implementation that is being used.
|
||||||
|
|
||||||
|
Before Stasis is initialized it will be set to a default value.
|
||||||
|
It may be changed before Tinit() is called by assigning to it.
|
||||||
|
The default can be overridden at compile time by defining
|
||||||
|
USE_LOGGER.
|
||||||
|
|
||||||
|
(eg: gcc ... -DSTASIS_LOG_TYPE=LOG_TO_FOO)
|
||||||
|
|
||||||
|
@see constants.h for a list of recognized log implementations.
|
||||||
|
(The constants are named LOG_TO_*)
|
||||||
|
@todo rename LOG_TO_* constants to STASIS_LOG_TYPE_*
|
||||||
|
|
||||||
|
*/
|
||||||
|
extern int stasis_log_type;
|
||||||
|
|
||||||
extern char * stasis_log_file_name;
|
extern char * stasis_log_file_name;
|
||||||
extern int stasis_log_file_mode;
|
extern int stasis_log_file_mode;
|
||||||
extern int stasis_log_file_permissions;
|
extern int stasis_log_file_permissions;
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
|
|
||||||
#include <stasis/logger/logger2.h>
|
#include <stasis/logger/logger2.h>
|
||||||
|
|
||||||
stasis_log_t* open_InMemoryLog();
|
stasis_log_t* stasis_log_impl_in_memory_open();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -90,21 +90,6 @@ typedef enum {
|
||||||
extern TransactionLog XactionTable[MAX_TRANSACTIONS];
|
extern TransactionLog XactionTable[MAX_TRANSACTIONS];
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
This is the log implementation that is being used.
|
|
||||||
|
|
||||||
Before Stasis is intialized it will be set to a default value.
|
|
||||||
It may be changed before Tinit() is called by assigning to it.
|
|
||||||
The default can be overridden at compile time by defining
|
|
||||||
USE_LOGGER.
|
|
||||||
|
|
||||||
(eg: gcc ... -DUSE_LOGGER=LOG_TO_FOO)
|
|
||||||
|
|
||||||
@see constants.h for a list of recognized log implementations.
|
|
||||||
(The constants are named LOG_TO_*)
|
|
||||||
|
|
||||||
*/
|
|
||||||
extern int loggerType;
|
|
||||||
|
|
||||||
struct stasis_log_t {
|
struct stasis_log_t {
|
||||||
/**
|
/**
|
||||||
|
@ -169,7 +154,7 @@ struct stasis_log_t {
|
||||||
/**
|
/**
|
||||||
@return 0 on success
|
@return 0 on success
|
||||||
*/
|
*/
|
||||||
int (*deinit)(struct stasis_log_t* log);
|
int (*close)(struct stasis_log_t* log);
|
||||||
|
|
||||||
int (*is_durable)(struct stasis_log_t* log);
|
int (*is_durable)(struct stasis_log_t* log);
|
||||||
|
|
||||||
|
@ -228,11 +213,10 @@ lsn_t LogTransCommit(stasis_log_t* log, TransactionLog * l);
|
||||||
lsn_t LogTransAbort(stasis_log_t* log, TransactionLog * l);
|
lsn_t LogTransAbort(stasis_log_t* log, TransactionLog * l);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Write a end transaction record @see XEND
|
Write a end transaction record. This entry tells recovery's undo
|
||||||
|
phase that it may safely ignore the transaction.
|
||||||
@todo Implement LogEnd
|
|
||||||
*/
|
*/
|
||||||
void LogEnd (stasis_log_t* log, TransactionLog * l);
|
lsn_t LogTransEnd (stasis_log_t* log, TransactionLog * l);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
LogUpdate writes an UPDATELOG log record to the log tail. It
|
LogUpdate writes an UPDATELOG log record to the log tail. It
|
||||||
|
|
|
@ -55,7 +55,7 @@ terms specified in this license.
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
@mainpage Introduction to Stasis
|
@mainpage Introduction to Stasis
|
||||||
|
|
||||||
Stasis is a <i>flexible</i> transactional storage library. Unlike
|
Stasis is a <i>flexible</i> transactional storage library. Unlike
|
||||||
existing systems, it provides application and server developers
|
existing systems, it provides application and server developers
|
||||||
with much freedom, but little guidance regarding page file layouts,
|
with much freedom, but little guidance regarding page file layouts,
|
||||||
|
@ -116,18 +116,18 @@ terms specified in this license.
|
||||||
@section compiling Compiling and installation
|
@section compiling Compiling and installation
|
||||||
|
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
|
|
||||||
- automake 1.8+: needed to build from CVS
|
- automake 1.8+: needed to build from CVS
|
||||||
- <a href="http://check.sourceforge.net">check</a>: A unit testing
|
- <a href="http://check.sourceforge.net">check</a>: A unit testing
|
||||||
framework (needed to run the self-tests)
|
framework (needed to run the self-tests)
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
|
|
||||||
- libconfuse: Used by older networking code to parse configuration options.
|
- libconfuse: Used by older networking code to parse configuration options.
|
||||||
- BerkeleyDB: Used by the benchmarking code for purposes of comparison.
|
- BerkeleyDB: Used by the benchmarking code for purposes of comparison.
|
||||||
|
|
||||||
Development is currently performed under Debian's Testing branch.
|
Development is currently performed under Debian's Testing branch.
|
||||||
|
|
||||||
To compile Stasis, first check out a copy with SVN. If you have commit access:
|
To compile Stasis, first check out a copy with SVN. If you have commit access:
|
||||||
|
|
||||||
@verbatim
|
@verbatim
|
||||||
|
@ -141,17 +141,17 @@ terms specified in this license.
|
||||||
@endverbatim
|
@endverbatim
|
||||||
|
|
||||||
then:
|
then:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
|
||||||
$ ./reconf
|
$ ./reconf
|
||||||
$ ./configure --quiet
|
$ ./configure --quiet
|
||||||
$ make -j4 > /dev/null
|
$ make -j4 > /dev/null
|
||||||
$ cd test/stasis
|
$ cd test/stasis
|
||||||
$ make check
|
$ make check
|
||||||
|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
This will fail if your system defaults to an old (pre-1.7) version
|
This will fail if your system defaults to an old (pre-1.7) version
|
||||||
of autotools. Fortunately, multiple versions of autotools may
|
of autotools. Fortunately, multiple versions of autotools may
|
||||||
exist on the same system. Execute the following commands to
|
exist on the same system. Execute the following commands to
|
||||||
|
@ -183,22 +183,22 @@ terms specified in this license.
|
||||||
|
|
||||||
@include examples/ex1.c
|
@include examples/ex1.c
|
||||||
|
|
||||||
Hopefully, Tbegin(), Talloc(), Tset(), Tcommit(), Tabort() and Tdealloc() are
|
Hopefully, Tbegin(), Talloc(), Tset(), Tcommit(), Tabort() and Tdealloc() are
|
||||||
self explanatory. If not, they are covered in detail elsewhere. Tinit() and
|
self explanatory. If not, they are covered in detail elsewhere. Tinit() and
|
||||||
Tdeinit() initialize the library, and clean up when the program is finished.
|
Tdeinit() initialize the library, and clean up when the program is finished.
|
||||||
|
|
||||||
Other particularly useful functions are ThashCreate(), ThashDelete(),
|
Other particularly useful functions are ThashCreate(), ThashDelete(),
|
||||||
ThashInsert(), ThashRemove(), and ThashLookup() which provide a
|
ThashInsert(), ThashRemove(), and ThashLookup() which provide a
|
||||||
re-entrant linear hash implementation. ThashIterator() and
|
re-entrant linear hash implementation. ThashIterator() and
|
||||||
ThashNext() provide an iterator over the hashtable's values.
|
ThashNext() provide an iterator over the hashtable's values.
|
||||||
|
|
||||||
@subsection bootstrap Reopening a closed data store
|
@subsection bootstrap Reopening a closed data store
|
||||||
|
|
||||||
Stasis imposes as little structure upon the application's data structures as
|
Stasis imposes as little structure upon the application's data structures as
|
||||||
possible. Therefore, it does not maintain any information about the contents
|
possible. Therefore, it does not maintain any information about the contents
|
||||||
or naming of objects within the page file. This means that the application
|
or naming of objects within the page file. This means that the application
|
||||||
must maintain such information manually.
|
must maintain such information manually.
|
||||||
|
|
||||||
In order to facilitate this, Stasis provides the function
|
In order to facilitate this, Stasis provides the function
|
||||||
TrecordType() and guarantees that the first recordid returned by
|
TrecordType() and guarantees that the first recordid returned by
|
||||||
any allocation will point to the same page and slot as the constant
|
any allocation will point to the same page and slot as the constant
|
||||||
|
@ -206,10 +206,10 @@ terms specified in this license.
|
||||||
record passed to it does not exist. A second function,
|
record passed to it does not exist. A second function,
|
||||||
TrecordSize() returns the size of a record in bytes, or -1 if the
|
TrecordSize() returns the size of a record in bytes, or -1 if the
|
||||||
record does not exist.
|
record does not exist.
|
||||||
|
|
||||||
Therefore, the following code (found in examples/ex2.c) will safely
|
Therefore, the following code (found in examples/ex2.c) will safely
|
||||||
initialize or reopen a data store:
|
initialize or reopen a data store:
|
||||||
|
|
||||||
@include examples/ex2.c
|
@include examples/ex2.c
|
||||||
|
|
||||||
@todo Explain how to determine the correct value of rootEntry.size in the case
|
@todo Explain how to determine the correct value of rootEntry.size in the case
|
||||||
|
@ -476,7 +476,7 @@ terms specified in this license.
|
||||||
* @defgroup LOGGING_DISCIPLINES Logging Disciplines
|
* @defgroup LOGGING_DISCIPLINES Logging Disciplines
|
||||||
*
|
*
|
||||||
* Stasis' log API provides a number of methods that directly
|
* Stasis' log API provides a number of methods that directly
|
||||||
* manipulate the log.
|
* manipulate the log.
|
||||||
*
|
*
|
||||||
* @section SNF STEAL/NO-FORCE recovery
|
* @section SNF STEAL/NO-FORCE recovery
|
||||||
* Stasis includes a function, Tupdate(), that
|
* Stasis includes a function, Tupdate(), that
|
||||||
|
@ -521,13 +521,13 @@ terms specified in this license.
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
*
|
*
|
||||||
* Defines Stasis' primary interface.
|
* Defines Stasis' primary interface.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @todo error handling
|
* @todo error handling
|
||||||
*
|
*
|
||||||
* @ingroup LLADD_CORE
|
* @ingroup LLADD_CORE
|
||||||
* $Id$
|
* $Id$
|
||||||
|
@ -607,12 +607,12 @@ int Tbegin();
|
||||||
*
|
*
|
||||||
* @see operations.h For an overview of the operations API
|
* @see operations.h For an overview of the operations API
|
||||||
*/
|
*/
|
||||||
compensated_function void Tupdate(int xid, pageid_t page,
|
compensated_function void Tupdate(int xid, pageid_t page,
|
||||||
const void *dat, size_t datlen, int op);
|
const void *dat, size_t datlen, int op);
|
||||||
/**
|
/**
|
||||||
@deprecated Only exists to work around swig/python limitations.
|
@deprecated Only exists to work around swig/python limitations.
|
||||||
*/
|
*/
|
||||||
compensated_function void TupdateStr(int xid, pageid_t page,
|
compensated_function void TupdateStr(int xid, pageid_t page,
|
||||||
const char *dat, size_t datlen, int op);
|
const char *dat, size_t datlen, int op);
|
||||||
|
|
||||||
void TreorderableUpdate(int xid, void * h, pageid_t page,
|
void TreorderableUpdate(int xid, void * h, pageid_t page,
|
||||||
|
@ -632,7 +632,7 @@ void TreorderableWritebackUpdate(int xid, void* h,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read the value of a record.
|
* Read the value of a record.
|
||||||
*
|
*
|
||||||
* @param xid transaction ID
|
* @param xid transaction ID
|
||||||
* @param rid reference to page/slot
|
* @param rid reference to page/slot
|
||||||
* @param dat buffer into which data goes
|
* @param dat buffer into which data goes
|
||||||
|
@ -650,9 +650,9 @@ compensated_function void TreadRaw(int xid, recordid rid, void *dat);
|
||||||
compensated_function void TreadStr(int xid, recordid rid, char *dat);
|
compensated_function void TreadStr(int xid, recordid rid, char *dat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit an active transaction. Each transaction should be completed
|
* Commit an active transaction. Each transaction should be completed
|
||||||
* with exactly one call to Tcommit() or Tabort().
|
* with exactly one call to Tcommit() or Tabort().
|
||||||
*
|
*
|
||||||
* @param xid transaction ID
|
* @param xid transaction ID
|
||||||
* @return 0 on success
|
* @return 0 on success
|
||||||
*/
|
*/
|
||||||
|
@ -661,8 +661,8 @@ int Tcommit(int xid);
|
||||||
/**
|
/**
|
||||||
* Abort (rollback) an active transaction. Each transaction should be
|
* Abort (rollback) an active transaction. Each transaction should be
|
||||||
* completed with exactly one call to Tcommit() or Tabort().
|
* completed with exactly one call to Tcommit() or Tabort().
|
||||||
*
|
*
|
||||||
* @param xid transaction ID
|
* @param xid transaction ID
|
||||||
* @return 0 on success, -1 on error.
|
* @return 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int Tabort(int xid);
|
int Tabort(int xid);
|
||||||
|
@ -689,7 +689,7 @@ int TuncleanShutdown();
|
||||||
* Used by the recovery process.
|
* Used by the recovery process.
|
||||||
* Revives Tprepare'ed transactions.
|
* Revives Tprepare'ed transactions.
|
||||||
*
|
*
|
||||||
* @param xid The xid that is to be revived.
|
* @param xid The xid that is to be revived.
|
||||||
* @param prevlsn The lsn of that xid's most recent PREPARE entry in the log.
|
* @param prevlsn The lsn of that xid's most recent PREPARE entry in the log.
|
||||||
* @param reclsn The lsn of the transaction's BEGIN record.
|
* @param reclsn The lsn of the transaction's BEGIN record.
|
||||||
*/
|
*/
|
||||||
|
@ -753,7 +753,7 @@ void stasis_transaction_table_max_transaction_id_set(int xid);
|
||||||
/**
|
/**
|
||||||
* Used by test cases to mess with internal transaction table state.
|
* Used by test cases to mess with internal transaction table state.
|
||||||
*
|
*
|
||||||
* @param xid The new active transaction count.
|
* @param xid The new active transaction count.
|
||||||
*/
|
*/
|
||||||
void stasis_transaction_table_active_transaction_count_set(int xid);
|
void stasis_transaction_table_active_transaction_count_set(int xid);
|
||||||
|
|
||||||
|
@ -783,6 +783,8 @@ int stasis_transaction_table_roll_forward_with_reclsn(int xid, lsn_t lsn,
|
||||||
lsn_t prevLSN,
|
lsn_t prevLSN,
|
||||||
lsn_t recLSN);
|
lsn_t recLSN);
|
||||||
int stasis_transaction_table_forget(int xid);
|
int stasis_transaction_table_forget(int xid);
|
||||||
|
|
||||||
|
int Tforget(int xid);
|
||||||
/**
|
/**
|
||||||
This is used by log truncation.
|
This is used by log truncation.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -414,7 +414,7 @@ Suite * check_suite(void) {
|
||||||
TCase *tc = tcase_create("recovery");
|
TCase *tc = tcase_create("recovery");
|
||||||
|
|
||||||
tcase_set_timeout(tc, 0); // disable timeouts
|
tcase_set_timeout(tc, 0); // disable timeouts
|
||||||
if(LOG_TO_MEMORY != loggerType) {
|
if(LOG_TO_MEMORY != stasis_log_type) {
|
||||||
/* 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_add_test(tc, recoverBlob__idempotent);
|
tcase_add_test(tc, recoverBlob__idempotent);
|
||||||
|
|
|
@ -40,10 +40,10 @@ permission to use and distribute the software in accordance with the
|
||||||
terms specified in this license.
|
terms specified in this license.
|
||||||
---*/
|
---*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@file check_logWriter
|
@file check_logWriter
|
||||||
|
|
||||||
Tests logWriter.
|
Tests logWriter.
|
||||||
|
|
||||||
@todo Get rid of include for logWriter.h (stop calling deleteLogWriter, syncLog_logWriter...)
|
@todo Get rid of include for logWriter.h (stop calling deleteLogWriter, syncLog_logWriter...)
|
||||||
*/
|
*/
|
||||||
|
@ -92,7 +92,7 @@ static void setup_log() {
|
||||||
|
|
||||||
assert(test <= e->LSN);
|
assert(test <= e->LSN);
|
||||||
|
|
||||||
if(first) {
|
if(first) {
|
||||||
first = 0;
|
first = 0;
|
||||||
firstLSN = prevLSN;
|
firstLSN = prevLSN;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ static void setup_log() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@test
|
@test
|
||||||
|
|
||||||
Quick test of log writer and log handler. Not very extensive.
|
Quick test of log writer and log handler. Not very extensive.
|
||||||
Just writes out 3000 log entries, checks that 1000 of them make
|
Just writes out 3000 log entries, checks that 1000 of them make
|
||||||
|
@ -139,8 +139,9 @@ static void setup_log() {
|
||||||
@todo Test logHandle more thoroughly. (Still need to test the guard mechanism.)
|
@todo Test logHandle more thoroughly. (Still need to test the guard mechanism.)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
START_TEST(loggerTest)
|
static void loggerTest(int logType) {
|
||||||
{
|
|
||||||
|
stasis_log_type = logType;
|
||||||
const LogEntry * e;
|
const LogEntry * e;
|
||||||
LogHandle* h;
|
LogHandle* h;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -161,16 +162,21 @@ START_TEST(loggerTest)
|
||||||
stasis_log_safe_writes_delete(stasis_log_file_name);
|
stasis_log_safe_writes_delete(stasis_log_file_name);
|
||||||
Tdeinit();
|
Tdeinit();
|
||||||
}
|
}
|
||||||
END_TEST
|
START_TEST(loggerFileTest) {
|
||||||
|
loggerTest(LOG_TO_FILE);
|
||||||
/**
|
} END_TEST
|
||||||
|
START_TEST(loggerMemTest) {
|
||||||
|
loggerTest(LOG_TO_MEMORY);
|
||||||
|
} END_TEST
|
||||||
|
/**
|
||||||
@test
|
@test
|
||||||
Checks for a bug ecountered during devlopment. What happens when
|
Checks for a bug ecountered during devlopment. What happens when
|
||||||
previousInTransaction is called immediately after the handle is
|
previousInTransaction is called immediately after the handle is
|
||||||
allocated? */
|
allocated? */
|
||||||
|
|
||||||
START_TEST(logHandleColdReverseIterator) {
|
static void logHandleColdReverseIterator(int logType) {
|
||||||
const LogEntry * e;
|
const LogEntry * e;
|
||||||
|
stasis_log_type = logType;
|
||||||
setup_log();
|
setup_log();
|
||||||
LogHandle* lh = getLogHandle(stasis_log_file);
|
LogHandle* lh = getLogHandle(stasis_log_file);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -180,7 +186,7 @@ START_TEST(logHandleColdReverseIterator) {
|
||||||
freeLogEntry(e);
|
freeLogEntry(e);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
lh = getLSNHandle(stasis_log_file, e->LSN);
|
lh = getLSNHandle(stasis_log_file, e->LSN);
|
||||||
while((e = previousInTransaction(lh))) {
|
while((e = previousInTransaction(lh))) {
|
||||||
|
@ -191,14 +197,20 @@ START_TEST(logHandleColdReverseIterator) {
|
||||||
assert(i <= 4); /* We should almost immediately hit a clr that goes to the beginning of the log... */
|
assert(i <= 4); /* We should almost immediately hit a clr that goes to the beginning of the log... */
|
||||||
Tdeinit();
|
Tdeinit();
|
||||||
}
|
}
|
||||||
END_TEST
|
START_TEST(logHandleFileColdReverseIterator) {
|
||||||
|
logHandleColdReverseIterator(LOG_TO_FILE);
|
||||||
|
} END_TEST
|
||||||
|
START_TEST(logHandleMemColdReverseIterator) {
|
||||||
|
logHandleColdReverseIterator(LOG_TO_MEMORY);
|
||||||
|
} END_TEST
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@test
|
@test
|
||||||
|
|
||||||
Build a simple log, truncate it, and then test the logWriter routines against it.
|
Build a simple log, truncate it, and then test the logWriter routines against it.
|
||||||
*/
|
*/
|
||||||
START_TEST(loggerTruncate) {
|
static void loggerTruncate(int logType) {
|
||||||
|
stasis_log_type = logType;
|
||||||
const LogEntry * le;
|
const LogEntry * le;
|
||||||
const LogEntry * le2;
|
const LogEntry * le2;
|
||||||
const LogEntry * le3 = NULL;
|
const LogEntry * le3 = NULL;
|
||||||
|
@ -212,21 +224,21 @@ START_TEST(loggerTruncate) {
|
||||||
i++;
|
i++;
|
||||||
le = nextInLog(lh);
|
le = nextInLog(lh);
|
||||||
}
|
}
|
||||||
|
|
||||||
le2 = nextInLog(lh);
|
le2 = nextInLog(lh);
|
||||||
i = 0;
|
i = 0;
|
||||||
while(i < 23) {
|
while(i < 23) {
|
||||||
i++;
|
i++;
|
||||||
le3 = nextInLog(lh);
|
le3 = nextInLog(lh);
|
||||||
}
|
}
|
||||||
|
|
||||||
stasis_log_file->truncate(stasis_log_file, le->LSN);
|
stasis_log_file->truncate(stasis_log_file, le->LSN);
|
||||||
|
|
||||||
tmp = stasis_log_file->read_entry(stasis_log_file, le->LSN);
|
tmp = stasis_log_file->read_entry(stasis_log_file, le->LSN);
|
||||||
|
|
||||||
fail_unless(NULL != tmp, NULL);
|
fail_unless(NULL != tmp, NULL);
|
||||||
fail_unless(tmp->LSN == le->LSN, NULL);
|
fail_unless(tmp->LSN == le->LSN, NULL);
|
||||||
|
|
||||||
freeLogEntry(tmp);
|
freeLogEntry(tmp);
|
||||||
tmp = stasis_log_file->read_entry(stasis_log_file, le2->LSN);
|
tmp = stasis_log_file->read_entry(stasis_log_file, le2->LSN);
|
||||||
|
|
||||||
|
@ -238,19 +250,19 @@ START_TEST(loggerTruncate) {
|
||||||
|
|
||||||
fail_unless(NULL != tmp, NULL);
|
fail_unless(NULL != tmp, NULL);
|
||||||
fail_unless(tmp->LSN == le3->LSN, NULL);
|
fail_unless(tmp->LSN == le3->LSN, NULL);
|
||||||
|
|
||||||
freeLogEntry(tmp);
|
freeLogEntry(tmp);
|
||||||
freeLogHandle(lh);
|
freeLogHandle(lh);
|
||||||
lh = getLogHandle(stasis_log_file);
|
lh = getLogHandle(stasis_log_file);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
freeLogEntry(le);
|
freeLogEntry(le);
|
||||||
freeLogEntry(le2);
|
freeLogEntry(le2);
|
||||||
freeLogEntry(le3);
|
freeLogEntry(le3);
|
||||||
|
|
||||||
while((le = nextInLog(lh))) {
|
while((le = nextInLog(lh))) {
|
||||||
if(le->type != INTERNALLOG) {
|
if(le->type != INTERNALLOG) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
freeLogEntry(le);
|
freeLogEntry(le);
|
||||||
|
@ -258,7 +270,12 @@ START_TEST(loggerTruncate) {
|
||||||
assert(i == (3000 - 234 + 1));
|
assert(i == (3000 - 234 + 1));
|
||||||
freeLogHandle(lh);
|
freeLogHandle(lh);
|
||||||
Tdeinit();
|
Tdeinit();
|
||||||
|
}
|
||||||
|
START_TEST(loggerFileTruncate) {
|
||||||
|
loggerTruncate(LOG_TO_FILE);
|
||||||
|
} END_TEST
|
||||||
|
START_TEST(loggerMemTruncate) {
|
||||||
|
loggerTruncate(LOG_TO_MEMORY);
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
|
||||||
#define ENTRIES_PER_THREAD 200
|
#define ENTRIES_PER_THREAD 200
|
||||||
|
@ -277,7 +294,7 @@ static void* worker_thread(void * arg) {
|
||||||
|
|
||||||
lsn_t lsns[ENTRIES_PER_THREAD];
|
lsn_t lsns[ENTRIES_PER_THREAD];
|
||||||
|
|
||||||
for(i = 0; i < ENTRIES_PER_THREAD; i++) {
|
for(i = 0; i < ENTRIES_PER_THREAD; i++) {
|
||||||
lsns[i] = 0;
|
lsns[i] = 0;
|
||||||
}
|
}
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -293,7 +310,7 @@ static void* worker_thread(void * arg) {
|
||||||
threshold = (int) (2000.0*random()/(RAND_MAX+1.0));
|
threshold = (int) (2000.0*random()/(RAND_MAX+1.0));
|
||||||
entry = (long) (ENTRIES_PER_THREAD*random()/(RAND_MAX+1.0));
|
entry = (long) (ENTRIES_PER_THREAD*random()/(RAND_MAX+1.0));
|
||||||
|
|
||||||
if(threshold < 3) {
|
if(threshold < 3) {
|
||||||
if(i > 10) {
|
if(i > 10) {
|
||||||
needToTruncate = 1;
|
needToTruncate = 1;
|
||||||
if(lsns[i - 10] > truncated_to) {
|
if(lsns[i - 10] > truncated_to) {
|
||||||
|
@ -305,32 +322,32 @@ static void* worker_thread(void * arg) {
|
||||||
|
|
||||||
pthread_mutex_unlock(&random_mutex);
|
pthread_mutex_unlock(&random_mutex);
|
||||||
|
|
||||||
if(needToTruncate) {
|
if(needToTruncate) {
|
||||||
#ifdef NO_CONCURRENCY
|
#ifdef NO_CONCURRENCY
|
||||||
pthread_mutex_lock(&big);
|
pthread_mutex_lock(&big);
|
||||||
#endif
|
#endif
|
||||||
stasis_log_file->truncate(stasis_log_file, myTruncVal);
|
stasis_log_file->truncate(stasis_log_file, myTruncVal);
|
||||||
#ifdef NO_CONCURRENCY
|
#ifdef NO_CONCURRENCY
|
||||||
pthread_mutex_unlock(&big);
|
pthread_mutex_unlock(&big);
|
||||||
#endif
|
#endif
|
||||||
assert(stasis_log_file->truncation_point(stasis_log_file) >= myTruncVal);
|
assert(stasis_log_file->truncation_point(stasis_log_file) >= myTruncVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(threshold < 3) {
|
if(threshold < 3) {
|
||||||
} else {
|
} else {
|
||||||
le->xid = i+key;
|
le->xid = i+key;
|
||||||
#ifdef NO_CONCURRENCY
|
#ifdef NO_CONCURRENCY
|
||||||
pthread_mutex_lock(&big);
|
pthread_mutex_lock(&big);
|
||||||
#endif
|
#endif
|
||||||
stasis_log_file->write_entry(stasis_log_file,le);
|
stasis_log_file->write_entry(stasis_log_file,le);
|
||||||
#ifdef NO_CONCURRENCY
|
#ifdef NO_CONCURRENCY
|
||||||
pthread_mutex_unlock(&big);
|
pthread_mutex_unlock(&big);
|
||||||
#endif
|
#endif
|
||||||
lsns[i] = le->LSN;
|
lsns[i] = le->LSN;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
pthread_mutex_lock(&random_mutex);
|
pthread_mutex_lock(&random_mutex);
|
||||||
#ifdef NO_CONCURRENCY
|
#ifdef NO_CONCURRENCY
|
||||||
pthread_mutex_lock(&big);
|
pthread_mutex_lock(&big);
|
||||||
#endif
|
#endif
|
||||||
if(lsns[entry] > truncated_to && entry < i) {
|
if(lsns[entry] > truncated_to && entry < i) {
|
||||||
|
@ -341,13 +358,13 @@ static void* worker_thread(void * arg) {
|
||||||
|
|
||||||
assert(e->xid == entry+key);
|
assert(e->xid == entry+key);
|
||||||
freeLogEntry(e);
|
freeLogEntry(e);
|
||||||
} else {
|
} else {
|
||||||
pthread_mutex_unlock(&random_mutex);
|
pthread_mutex_unlock(&random_mutex);
|
||||||
}
|
}
|
||||||
#ifdef NO_CONCURRENCY
|
#ifdef NO_CONCURRENCY
|
||||||
pthread_mutex_unlock(&big);
|
pthread_mutex_unlock(&big);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Try to interleave requests as much as possible */
|
/* Try to interleave requests as much as possible */
|
||||||
sched_yield();
|
sched_yield();
|
||||||
freeLogEntry(le);
|
freeLogEntry(le);
|
||||||
|
@ -357,8 +374,8 @@ static void* worker_thread(void * arg) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static void loggerCheckWorker(int logType) {
|
||||||
START_TEST(loggerCheckWorker) {
|
stasis_log_type = logType;
|
||||||
int four = 4;
|
int four = 4;
|
||||||
|
|
||||||
pthread_mutex_init(&random_mutex, NULL);
|
pthread_mutex_init(&random_mutex, NULL);
|
||||||
|
@ -367,9 +384,16 @@ START_TEST(loggerCheckWorker) {
|
||||||
worker_thread(&four);
|
worker_thread(&four);
|
||||||
Tdeinit();
|
Tdeinit();
|
||||||
|
|
||||||
|
}
|
||||||
|
START_TEST(loggerFileCheckWorker) {
|
||||||
|
loggerCheckWorker(LOG_TO_FILE);
|
||||||
|
} END_TEST
|
||||||
|
START_TEST(loggerMemCheckWorker) {
|
||||||
|
loggerCheckWorker(LOG_TO_MEMORY);
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
|
||||||
START_TEST(loggerCheckThreaded) {
|
static void loggerCheckThreaded(int logType) {
|
||||||
|
stasis_log_type = logType;
|
||||||
|
|
||||||
#define THREAD_COUNT 100
|
#define THREAD_COUNT 100
|
||||||
pthread_t workers[THREAD_COUNT];
|
pthread_t workers[THREAD_COUNT];
|
||||||
|
@ -386,9 +410,16 @@ START_TEST(loggerCheckThreaded) {
|
||||||
}
|
}
|
||||||
Tdeinit();
|
Tdeinit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(loggerFileCheckThreaded) {
|
||||||
|
loggerCheckThreaded(LOG_TO_FILE);
|
||||||
|
} END_TEST
|
||||||
|
START_TEST(loggerMemCheckThreaded) {
|
||||||
|
loggerCheckThreaded(LOG_TO_MEMORY);
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
|
||||||
void reopenLogWorkload(int truncating) {
|
void reopenLogWorkload(int truncating) {
|
||||||
stasis_operation_table_init();
|
stasis_operation_table_init();
|
||||||
stasis_truncation_automatic = 0;
|
stasis_truncation_automatic = 0;
|
||||||
|
|
||||||
|
@ -397,12 +428,12 @@ void reopenLogWorkload(int truncating) {
|
||||||
|
|
||||||
stasis_transaction_table_active_transaction_count_set(0);
|
stasis_transaction_table_active_transaction_count_set(0);
|
||||||
|
|
||||||
if(LOG_TO_FILE == loggerType) {
|
if(LOG_TO_FILE == stasis_log_type) {
|
||||||
stasis_log_file = stasis_log_safe_writes_open(stasis_log_file_name,
|
stasis_log_file = stasis_log_safe_writes_open(stasis_log_file_name,
|
||||||
stasis_log_file_mode,
|
stasis_log_file_mode,
|
||||||
stasis_log_file_permissions);
|
stasis_log_file_permissions);
|
||||||
} else if(LOG_TO_MEMORY == loggerType) {
|
} else if(LOG_TO_MEMORY == stasis_log_type) {
|
||||||
stasis_log_file = open_InMemoryLog();
|
stasis_log_file = stasis_log_impl_in_memory_open();
|
||||||
} else {
|
} else {
|
||||||
assert(stasis_log_file != NULL);
|
assert(stasis_log_file != NULL);
|
||||||
}
|
}
|
||||||
|
@ -418,24 +449,24 @@ void reopenLogWorkload(int truncating) {
|
||||||
for(int i = 0; i < ENTRY_COUNT; i++) {
|
for(int i = 0; i < ENTRY_COUNT; i++) {
|
||||||
|
|
||||||
entries[i] = LogUpdate(stasis_log_file,
|
entries[i] = LogUpdate(stasis_log_file,
|
||||||
&l, NULL, OPERATION_NOOP, NULL, 0);
|
&l, NULL, OPERATION_NOOP, NULL, 0);
|
||||||
|
|
||||||
if(i == SYNC_POINT) {
|
if(i == SYNC_POINT) {
|
||||||
if(truncating) {
|
if(truncating) {
|
||||||
stasis_log_file->truncate(stasis_log_file,entries[i]->LSN);
|
stasis_log_file->truncate(stasis_log_file,entries[i]->LSN);
|
||||||
startLSN = entries[i]->LSN;
|
startLSN = entries[i]->LSN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stasis_log_file->deinit(stasis_log_file);
|
stasis_log_file->close(stasis_log_file);
|
||||||
|
|
||||||
if(LOG_TO_FILE == loggerType) {
|
if(LOG_TO_FILE == stasis_log_type) {
|
||||||
stasis_log_file = stasis_log_safe_writes_open(stasis_log_file_name,
|
stasis_log_file = stasis_log_safe_writes_open(stasis_log_file_name,
|
||||||
stasis_log_file_mode,
|
stasis_log_file_mode,
|
||||||
stasis_log_file_permissions);
|
stasis_log_file_permissions);
|
||||||
} else if(LOG_TO_MEMORY == loggerType) {
|
} else if(LOG_TO_MEMORY == stasis_log_type) {
|
||||||
stasis_log_file = open_InMemoryLog();
|
stasis_log_file = stasis_log_impl_in_memory_open();
|
||||||
} else {
|
} else {
|
||||||
assert(stasis_log_file != NULL);
|
assert(stasis_log_file != NULL);
|
||||||
}
|
}
|
||||||
|
@ -443,51 +474,51 @@ void reopenLogWorkload(int truncating) {
|
||||||
LogHandle * h;
|
LogHandle * h;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(truncating) {
|
if(truncating) {
|
||||||
h = getLogHandle(stasis_log_file);
|
h = getLogHandle(stasis_log_file);
|
||||||
i = SYNC_POINT;
|
i = SYNC_POINT;
|
||||||
} else {
|
} else {
|
||||||
h = getLogHandle(stasis_log_file);
|
h = getLogHandle(stasis_log_file);
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LogEntry * e;
|
const LogEntry * e;
|
||||||
while((e = nextInLog(h))) {
|
while((e = nextInLog(h))) {
|
||||||
if(e->type != INTERNALLOG) {
|
if(e->type != INTERNALLOG) {
|
||||||
assert(sizeofLogEntry(e) == sizeofLogEntry(entries[i]));
|
assert(sizeofLogEntry(e) == sizeofLogEntry(entries[i]));
|
||||||
assert(!memcmp(e, entries[i], sizeofLogEntry(entries[i])));
|
assert(!memcmp(e, entries[i], sizeofLogEntry(entries[i])));
|
||||||
assert(i < ENTRY_COUNT);
|
assert(i < ENTRY_COUNT);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(i == (ENTRY_COUNT));
|
assert(i == (ENTRY_COUNT));
|
||||||
|
|
||||||
LogEntry * entries2[ENTRY_COUNT];
|
LogEntry * entries2[ENTRY_COUNT];
|
||||||
for(int i = 0; i < ENTRY_COUNT; i++) {
|
for(int i = 0; i < ENTRY_COUNT; i++) {
|
||||||
entries2[i] = LogUpdate(stasis_log_file, &l, NULL, OPERATION_NOOP,
|
entries2[i] = LogUpdate(stasis_log_file, &l, NULL, OPERATION_NOOP,
|
||||||
NULL, 0);
|
NULL, 0);
|
||||||
if(i == SYNC_POINT) {
|
if(i == SYNC_POINT) {
|
||||||
stasis_log_file->force_tail(stasis_log_file, LOG_FORCE_COMMIT);
|
stasis_log_file->force_tail(stasis_log_file, LOG_FORCE_COMMIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
freeLogHandle(h);
|
freeLogHandle(h);
|
||||||
|
|
||||||
if(truncating) {
|
if(truncating) {
|
||||||
h = getLSNHandle(stasis_log_file, startLSN);
|
h = getLSNHandle(stasis_log_file, startLSN);
|
||||||
i = SYNC_POINT;
|
i = SYNC_POINT;
|
||||||
} else {
|
} else {
|
||||||
h = getLogHandle(stasis_log_file);
|
h = getLogHandle(stasis_log_file);
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while((e = nextInLog(h))) {
|
while((e = nextInLog(h))) {
|
||||||
if(e->type != INTERNALLOG) {
|
if(e->type != INTERNALLOG) {
|
||||||
if( i < ENTRY_COUNT) {
|
if( i < ENTRY_COUNT) {
|
||||||
assert(sizeofLogEntry(e) == sizeofLogEntry(entries[i]));
|
assert(sizeofLogEntry(e) == sizeofLogEntry(entries[i]));
|
||||||
assert(!memcmp(e, entries[i], sizeofLogEntry(entries[i])));
|
assert(!memcmp(e, entries[i], sizeofLogEntry(entries[i])));
|
||||||
} else {
|
} else {
|
||||||
assert(i < ENTRY_COUNT * 2);
|
assert(i < ENTRY_COUNT * 2);
|
||||||
assert(sizeofLogEntry(e) == sizeofLogEntry(entries2[i-ENTRY_COUNT]));
|
assert(sizeofLogEntry(e) == sizeofLogEntry(entries2[i-ENTRY_COUNT]));
|
||||||
assert(!memcmp(e, entries2[i-ENTRY_COUNT], sizeofLogEntry(entries2[i-ENTRY_COUNT])));
|
assert(!memcmp(e, entries2[i-ENTRY_COUNT], sizeofLogEntry(entries2[i-ENTRY_COUNT])));
|
||||||
|
@ -497,19 +528,21 @@ void reopenLogWorkload(int truncating) {
|
||||||
}
|
}
|
||||||
|
|
||||||
freeLogHandle(h);
|
freeLogHandle(h);
|
||||||
assert(i == (ENTRY_COUNT * 2));
|
assert(i == (ENTRY_COUNT * 2));
|
||||||
|
|
||||||
stasis_truncation_automatic = 1;
|
stasis_truncation_automatic = 1;
|
||||||
stasis_log_file->deinit(stasis_log_file);
|
stasis_log_file->close(stasis_log_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(loggerReopenTest) {
|
START_TEST(loggerReopenTest) {
|
||||||
stasis_log_safe_writes_delete(stasis_log_file_name);
|
stasis_log_type = LOG_TO_FILE;
|
||||||
|
stasis_log_safe_writes_delete(stasis_log_file_name);
|
||||||
reopenLogWorkload(0);
|
reopenLogWorkload(0);
|
||||||
|
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
|
||||||
START_TEST(loggerTruncateReopenTest) {
|
START_TEST(loggerTruncateReopenTest) {
|
||||||
|
stasis_log_type = LOG_TO_FILE;
|
||||||
stasis_log_safe_writes_delete(stasis_log_file_name);
|
stasis_log_safe_writes_delete(stasis_log_file_name);
|
||||||
reopenLogWorkload(1);
|
reopenLogWorkload(1);
|
||||||
} END_TEST
|
} END_TEST
|
||||||
|
@ -520,19 +553,23 @@ Suite * check_suite(void) {
|
||||||
TCase *tc = tcase_create("writeNew");
|
TCase *tc = tcase_create("writeNew");
|
||||||
tcase_set_timeout(tc, 0);
|
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, loggerFileTest);
|
||||||
tcase_add_test(tc, loggerTest);
|
tcase_add_test(tc, loggerMemTest);
|
||||||
tcase_add_test(tc, logHandleColdReverseIterator);
|
tcase_add_test(tc, logHandleFileColdReverseIterator);
|
||||||
tcase_add_test(tc, loggerTruncate);
|
tcase_add_test(tc, logHandleMemColdReverseIterator);
|
||||||
tcase_add_test(tc, loggerCheckWorker);
|
tcase_add_test(tc, loggerFileTruncate);
|
||||||
tcase_add_test(tc, loggerCheckThreaded);
|
tcase_add_test(tc, loggerMemTruncate);
|
||||||
if(loggerType != LOG_TO_MEMORY) {
|
tcase_add_test(tc, loggerFileCheckWorker);
|
||||||
|
tcase_add_test(tc, loggerMemCheckWorker);
|
||||||
|
tcase_add_test(tc, loggerFileCheckThreaded);
|
||||||
|
tcase_add_test(tc, loggerMemCheckThreaded);
|
||||||
|
if(stasis_log_type != LOG_TO_MEMORY) {
|
||||||
tcase_add_test(tc, loggerReopenTest);
|
tcase_add_test(tc, loggerReopenTest);
|
||||||
tcase_add_test(tc, loggerTruncateReopenTest);
|
tcase_add_test(tc, loggerTruncateReopenTest);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------- */
|
/* --------------------------------------------- */
|
||||||
|
|
||||||
tcase_add_checked_fixture(tc, setup, teardown);
|
tcase_add_checked_fixture(tc, setup, teardown);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -697,7 +697,7 @@ Suite * check_suite(void) {
|
||||||
tcase_add_test(tc, operation_physical_do_undo);
|
tcase_add_test(tc, operation_physical_do_undo);
|
||||||
tcase_add_test(tc, operation_nestedTopAction);
|
tcase_add_test(tc, operation_nestedTopAction);
|
||||||
tcase_add_test(tc, operation_set_range);
|
tcase_add_test(tc, operation_set_range);
|
||||||
if(loggerType != LOG_TO_MEMORY) {
|
if(stasis_log_type != LOG_TO_MEMORY) {
|
||||||
tcase_add_test(tc, operation_prepare);
|
tcase_add_test(tc, operation_prepare);
|
||||||
}
|
}
|
||||||
tcase_add_test(tc, operation_alloc_test);
|
tcase_add_test(tc, operation_alloc_test);
|
||||||
|
|
|
@ -212,7 +212,7 @@ Suite * check_suite(void) {
|
||||||
/* Sub tests are added, one per line, here */
|
/* Sub tests are added, one per line, here */
|
||||||
|
|
||||||
tcase_add_test(tc, pageOpCheckAllocDealloc);
|
tcase_add_test(tc, pageOpCheckAllocDealloc);
|
||||||
if(LOG_TO_MEMORY != loggerType) {
|
if(LOG_TO_MEMORY != stasis_log_type) {
|
||||||
tcase_add_test(tc, pageOpCheckRecovery);
|
tcase_add_test(tc, pageOpCheckRecovery);
|
||||||
}
|
}
|
||||||
/* --------------------------------------------- */
|
/* --------------------------------------------- */
|
||||||
|
|
|
@ -484,7 +484,7 @@ Suite * check_suite(void) {
|
||||||
|
|
||||||
tcase_set_timeout(tc, 0); // disable timeouts
|
tcase_set_timeout(tc, 0); // disable timeouts
|
||||||
|
|
||||||
if(LOG_TO_MEMORY != loggerType) {
|
if(LOG_TO_MEMORY != stasis_log_type) {
|
||||||
|
|
||||||
/* Sub tests are added, one per line, here */
|
/* Sub tests are added, one per line, here */
|
||||||
tcase_add_test(tc, recovery_idempotent);
|
tcase_add_test(tc, recovery_idempotent);
|
||||||
|
|
Loading…
Reference in a new issue