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:
Sears Russell 2009-04-11 17:17:42 +00:00
parent dacc33642e
commit 4b07b538a6
15 changed files with 359 additions and 308 deletions

View file

@ -42,6 +42,13 @@ int stasis_truncation_automatic = STASIS_TRUNCATION_AUTOMATIC;
int stasis_truncation_automatic = 1;
#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
char * stasis_log_file_name = STASIS_LOG_FILE_NAME;
#else

View file

@ -2,123 +2,130 @@
#include <stasis/latches.h>
#include <string.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) {
writelock(flushedLSN_lock,0);
writelock(globalOffset_lock,0);
lsn_t ret = nextAvailableLSN;
unlock(globalOffset_lock);
unlock(flushedLSN_lock);
typedef struct {
rwl * flushedLSN_lock;
lsn_t nextAvailableLSN;
lsn_t globalOffset;
rwl * globalOffset_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;
}
static int writeLogEntry_InMemoryLog(stasis_log_t * log, LogEntry *e) {
writelock(flushedLSN_lock, 0);
static int stasis_log_impl_in_memory_write_entry(stasis_log_t * log, LogEntry *e) {
stasis_log_impl_in_memory * impl = log->impl;
writelock(impl->flushedLSN_lock, 0);
lsn_t bufferOffset;
int done = 0;
do{
writelock(globalOffset_lock,0);
bufferOffset = nextAvailableLSN - globalOffset;
if(bufferOffset > bufferLen) {
bufferLen *= 2;
buffer = realloc(buffer, bufferLen);
writelock(impl->globalOffset_lock,0);
bufferOffset = impl->nextAvailableLSN - impl->globalOffset;
if(bufferOffset > impl->bufferLen) {
impl->bufferLen *= 2;
impl->buffer = realloc(impl->buffer, impl->bufferLen);
} else {
done = 1;
}
} while (!done);
return 0;
e->LSN = nextAvailableLSN;
e->LSN = impl->nextAvailableLSN;
LogEntry * cpy = malloc(sizeofLogEntry(e));
memcpy(cpy, e, sizeofLogEntry(e));
// printf ("lsn: %ld\n", e->LSN);
buffer[bufferOffset] = cpy;
DEBUG("lsn: %ld\n", e->LSN);
impl->buffer[bufferOffset] = cpy;
// printf("lsn: %ld type: %d\n", e->LSN, e->type);
nextAvailableLSN++;
DEBUG("lsn: %ld type: %d\n", e->LSN, e->type);
impl->nextAvailableLSN++;
unlock(globalOffset_lock);
unlock(flushedLSN_lock);
unlock(impl->globalOffset_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) {
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
}
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;
}
static int truncateLog_InMemoryLog(stasis_log_t * log, lsn_t lsn) {
writelock(flushedLSN_lock,1);
writelock(globalOffset_lock,1);
static int stasis_log_impl_in_memory_truncate(stasis_log_t * log, lsn_t lsn) {
stasis_log_impl_in_memory * impl = log->impl;
writelock(impl->flushedLSN_lock,1);
writelock(impl->globalOffset_lock,1);
assert(lsn <= nextAvailableLSN);
assert(lsn <= impl->nextAvailableLSN);
if(lsn > globalOffset) {
for(int i = globalOffset; i < lsn; i++) {
free(buffer[i - globalOffset]);
if(lsn > impl->globalOffset) {
for(int i = impl->globalOffset; i < lsn; i++) {
free(impl->buffer[i - impl->globalOffset]);
}
assert((lsn-globalOffset) + (nextAvailableLSN -lsn) < bufferLen);
memmove(&(buffer[0]), &(buffer[lsn - globalOffset]), sizeof(LogEntry*) * (nextAvailableLSN - lsn));
globalOffset = lsn;
assert((lsn-impl->globalOffset) + (impl->nextAvailableLSN -lsn) < impl->bufferLen);
memmove(&(impl->buffer[0]), &(impl->buffer[lsn - impl->globalOffset]),
sizeof(LogEntry*) * (impl->nextAvailableLSN - lsn));
impl->globalOffset = lsn;
}
writeunlock(globalOffset_lock);
writeunlock(flushedLSN_lock);
writeunlock(impl->globalOffset_lock);
writeunlock(impl->flushedLSN_lock);
return 0;
}
static lsn_t firstLogEntry_InMemoryLog() {
return globalOffset;
static lsn_t stasis_log_impl_in_memory_truncation_point(stasis_log_t * log) {
stasis_log_impl_in_memory * impl = log->impl;
return impl->globalOffset;
}
static int close_InMemoryLog(stasis_log_t * log) {
if(buffer) {
lsn_t firstEmptyOffset = nextAvailableLSN-globalOffset;
static int stasis_log_impl_in_memory_close(stasis_log_t * log) {
stasis_log_impl_in_memory * impl = log->impl;
if(impl->buffer) {
lsn_t firstEmptyOffset = impl->nextAvailableLSN-impl->globalOffset;
for(lsn_t i = 0; i < firstEmptyOffset; i++) {
assert(buffer[i]->LSN == i+globalOffset);
free(buffer[i]);
assert(impl->buffer[i]->LSN == i+impl->globalOffset);
free(impl->buffer[i]);
}
free(buffer);
nextAvailableLSN = 0;
globalOffset = 0;
bufferLen = 0;
buffer = 0;
free(impl->buffer);
impl->nextAvailableLSN = 0;
impl->globalOffset = 0;
impl->bufferLen = 0;
impl->buffer = 0;
free(impl);
}
free (log);
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) {
// printf("lsn: %ld\n", lsn);
if(lsn >= nextAvailableLSN) { return 0; }
assert(lsn-globalOffset >= 0 && lsn-globalOffset< bufferLen);
readlock(globalOffset_lock, 0);
LogEntry * ptr = buffer[lsn - globalOffset];
unlock(globalOffset_lock);
stasis_log_impl_in_memory * impl = log->impl;
DEBUG("lsn: %ld\n", lsn);
if(lsn >= impl->nextAvailableLSN) { return 0; }
assert(lsn-impl->globalOffset >= 0 && lsn-impl->globalOffset< impl->bufferLen);
readlock(impl->globalOffset_lock, 0);
LogEntry * ptr = impl->buffer[lsn - impl->globalOffset];
unlock(impl->globalOffset_lock);
assert(ptr);
assert(ptr->LSN == lsn);
@ -126,36 +133,38 @@ static const LogEntry * readLSNEntry_InMemoryLog(stasis_log_t* log,
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;
}
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) {
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() {
flushedLSN_lock = initlock();
globalOffset_lock = initlock();
globalOffset = 0;
nextAvailableLSN = 0;
buffer = malloc(4096 * 1024 * sizeof (LogEntry *));
bufferLen =4096 * 1024;
stasis_log_t* stasis_log_impl_in_memory_open() {
stasis_log_impl_in_memory * impl = malloc(sizeof(*impl));
impl->flushedLSN_lock = initlock();
impl->globalOffset_lock = initlock();
impl->globalOffset = 0;
impl->nextAvailableLSN = 0;
impl->buffer = malloc(4096 * 1024 * sizeof (LogEntry *));
impl->bufferLen =4096 * 1024;
static stasis_log_t proto = {
sizeofInternalLogEntry_InMemoryLog, // sizeof_internal_entry
writeLogEntry_InMemoryLog,// write_entry
readLSNEntry_InMemoryLog, // read_entry
nextEntry_InMemoryLog,// next_entry
flushedLSN_InMemoryLog, // first_unstable_lsn
nextAvailableLSN_InMemoryLog, // next_available_lsn
syncLog_InMemoryLog, // force_tail
truncateLog_InMemoryLog, // truncate
firstLogEntry_InMemoryLog,// truncation_point
close_InMemoryLog, // deinit
isDurable_InMemoryLog// is_durable
stasis_log_impl_in_memory_sizeof_internal_entry,
stasis_log_impl_in_memory_write_entry,
stasis_log_impl_in_memory_read_entry,
stasis_log_impl_in_memory_next_entry,
stasis_log_impl_in_memory_first_unstable_lsn,
stasis_log_impl_in_memory_next_available_lsn,
stasis_log_impl_in_memory_force_tail,
stasis_log_impl_in_memory_truncate,
stasis_log_impl_in_memory_truncation_point,
stasis_log_impl_in_memory_close,
stasis_log_impl_in_memory_is_durable
};
stasis_log_t* log = malloc(sizeof(*log));
memcpy(log,&proto, sizeof(proto));
log->impl = impl;
return log;
}

View file

@ -61,15 +61,6 @@ terms specified in this license.
#include <stasis/logger/inMemoryLog.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
*/
@ -178,6 +169,9 @@ lsn_t LogTransCommit(stasis_log_t* log, TransactionLog * l) {
lsn_t LogTransAbort(stasis_log_t* log, TransactionLog * l) {
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 lsn = LogTransCommonPrepare(log, l);
LogForce(log, lsn, LOG_FORCE_COMMIT);

View file

@ -49,7 +49,7 @@ static pthread_mutex_t rollback_mutex = PTHREAD_MUTEX_INITIALIZER;
no longer reads the pages in, there's no longer any reason to build
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");
@ -115,6 +115,7 @@ static void Analysis(stasis_log_t* log) {
lsn_t* free_lsn = pblHtLookup(transactionLSN, &(e->xid), sizeof(int));
pblHtRemove(transactionLSN, &(e->xid), sizeof(int));
free(free_lsn);
stasis_transaction_table_forget(e->xid);
}
break;
case UPDATELOG:
@ -171,7 +172,7 @@ static void Analysis(stasis_log_t* log) {
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);
const LogEntry * e;
@ -250,7 +251,7 @@ static void Redo(stasis_log_t* log) {
freeLogHandle(lh);
}
static void Undo(stasis_log_t* log, int recovery) {
static void stasis_recovery_undo(stasis_log_t* log, int recovery) {
LogHandle* lh;
DEBUG("Recovery: Undo\n");
@ -337,7 +338,8 @@ static void Undo(stasis_log_t* log, int recovery) {
// records may be passed in by undoTrans.
break;
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();
case XPREPARE: {
DEBUG("found prepared xact %d\n", e->xid);
@ -361,9 +363,8 @@ static void Undo(stasis_log_t* log, int recovery) {
freeLogEntry(e);
}
if(!prepared) {
if(recovery) {
stasis_transaction_table_forget(thisXid);
}
// Log an XEND, remove transaction from XactionTable.
Tforget(thisXid);
if(globalLockManager.abort) {
globalLockManager.abort(thisXid);
}
@ -375,12 +376,12 @@ void stasis_recovery_initiate(stasis_log_t* log) {
transactionLSN = pblHtCreate();
DEBUG("Analysis started\n");
Analysis(log);
stasis_recovery_analysis(log);
DEBUG("Redo started\n");
Redo(log);
stasis_recovery_redo(log);
DEBUG("Undo started\n");
TallocPostInit();
Undo(log,1);
stasis_recovery_undo(log,1);
DEBUG("Recovery complete.\n");
for(void * it = pblHtFirst(transactionLSN); it; it = pblHtNext(transactionLSN)) {
@ -405,7 +406,7 @@ void undoTrans(stasis_log_t* log, TransactionLog transaction) {
/* Nothing to undo. (Happens for read-only xacts.) */
}
Undo(log, 0);
stasis_recovery_undo(log, 0);
if(rollbackLSNs) {
destroyList(&rollbackLSNs);
}

View file

@ -42,7 +42,7 @@ struct ringBufferLog_s {
#define offset_to_lsn(x, lsn) ((lsn) + (x)->offset)
#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 * 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);
return truncateLog(log, log->start + size);
return stasis_ringbuffer_truncate(log, log->start + size);
}
/** 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
lsn_t newStart = lsn_to_offset(log, lsn);

View file

@ -94,12 +94,12 @@ int Tinit() {
stasis_transaction_table_init();
stasis_operation_table_init();
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_mode,
stasis_log_file_permissions);
} else if(LOG_TO_MEMORY == loggerType) {
stasis_log_file = open_InMemoryLog();
} else if(LOG_TO_MEMORY == stasis_log_type) {
stasis_log_file = stasis_log_impl_in_memory_open();
} else {
assert(stasis_log_file != NULL);
}
@ -420,15 +420,15 @@ int Tabort(int 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;
}
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 i;
@ -454,7 +454,7 @@ int Tdeinit() {
slow_close = 0;
}
stasis_page_deinit();
stasis_log_file->deinit(stasis_log_file);
stasis_log_file->close(stasis_log_file);
dirtyPagesDeinit();
initted = 0;
@ -475,7 +475,7 @@ int TuncleanShutdown() {
slow_close = 0;
}
stasis_page_deinit();
stasis_log_file->deinit(stasis_log_file);
stasis_log_file->close(stasis_log_file);
numActiveXactions = 0;
dirtyPagesDeinit();
@ -581,7 +581,7 @@ int stasis_transaction_table_forget(int xid) {
int TdurabilityLevel() {
if(bufferManagerType == BUFFER_MANAGER_MEM_ARRAY) {
return VOLATILE;
} else if(loggerType == LOG_TO_MEMORY) {
} else if(stasis_log_type == LOG_TO_MEMORY) {
return PERSISTENT;
} else {
return DURABLE;

View file

@ -57,6 +57,23 @@ extern int stasis_suppress_unclean_shutdown_warnings;
*/
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 int stasis_log_file_mode;
extern int stasis_log_file_permissions;

View file

@ -3,6 +3,6 @@
#include <stasis/logger/logger2.h>
stasis_log_t* open_InMemoryLog();
stasis_log_t* stasis_log_impl_in_memory_open();
#endif

View file

@ -90,21 +90,6 @@ typedef enum {
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 {
/**
@ -169,7 +154,7 @@ struct stasis_log_t {
/**
@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);
@ -228,11 +213,10 @@ lsn_t LogTransCommit(stasis_log_t* log, TransactionLog * l);
lsn_t LogTransAbort(stasis_log_t* log, TransactionLog * l);
/**
Write a end transaction record @see XEND
@todo Implement LogEnd
Write a end transaction record. This entry tells recovery's undo
phase that it may safely ignore the transaction.
*/
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

View file

@ -783,6 +783,8 @@ int stasis_transaction_table_roll_forward_with_reclsn(int xid, lsn_t lsn,
lsn_t prevLSN,
lsn_t recLSN);
int stasis_transaction_table_forget(int xid);
int Tforget(int xid);
/**
This is used by log truncation.
*/

View file

@ -414,7 +414,7 @@ Suite * check_suite(void) {
TCase *tc = tcase_create("recovery");
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. */
/* Sub tests are added, one per line, here */
tcase_add_test(tc, recoverBlob__idempotent);

View file

@ -139,8 +139,9 @@ static void setup_log() {
@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;
LogHandle* h;
int i = 0;
@ -161,16 +162,21 @@ START_TEST(loggerTest)
stasis_log_safe_writes_delete(stasis_log_file_name);
Tdeinit();
}
END_TEST
START_TEST(loggerFileTest) {
loggerTest(LOG_TO_FILE);
} END_TEST
START_TEST(loggerMemTest) {
loggerTest(LOG_TO_MEMORY);
} END_TEST
/**
@test
Checks for a bug ecountered during devlopment. What happens when
previousInTransaction is called immediately after the handle is
allocated? */
START_TEST(logHandleColdReverseIterator) {
static void logHandleColdReverseIterator(int logType) {
const LogEntry * e;
stasis_log_type = logType;
setup_log();
LogHandle* lh = getLogHandle(stasis_log_file);
int i = 0;
@ -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... */
Tdeinit();
}
END_TEST
START_TEST(logHandleFileColdReverseIterator) {
logHandleColdReverseIterator(LOG_TO_FILE);
} END_TEST
START_TEST(logHandleMemColdReverseIterator) {
logHandleColdReverseIterator(LOG_TO_MEMORY);
} END_TEST
/**
@test
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 * le2;
const LogEntry * le3 = NULL;
@ -258,7 +270,12 @@ START_TEST(loggerTruncate) {
assert(i == (3000 - 234 + 1));
freeLogHandle(lh);
Tdeinit();
}
START_TEST(loggerFileTruncate) {
loggerTruncate(LOG_TO_FILE);
} END_TEST
START_TEST(loggerMemTruncate) {
loggerTruncate(LOG_TO_MEMORY);
} END_TEST
#define ENTRIES_PER_THREAD 200
@ -357,8 +374,8 @@ static void* worker_thread(void * arg) {
return 0;
}
START_TEST(loggerCheckWorker) {
static void loggerCheckWorker(int logType) {
stasis_log_type = logType;
int four = 4;
pthread_mutex_init(&random_mutex, NULL);
@ -367,9 +384,16 @@ START_TEST(loggerCheckWorker) {
worker_thread(&four);
Tdeinit();
}
START_TEST(loggerFileCheckWorker) {
loggerCheckWorker(LOG_TO_FILE);
} END_TEST
START_TEST(loggerMemCheckWorker) {
loggerCheckWorker(LOG_TO_MEMORY);
} END_TEST
START_TEST(loggerCheckThreaded) {
static void loggerCheckThreaded(int logType) {
stasis_log_type = logType;
#define THREAD_COUNT 100
pthread_t workers[THREAD_COUNT];
@ -386,6 +410,13 @@ START_TEST(loggerCheckThreaded) {
}
Tdeinit();
}
START_TEST(loggerFileCheckThreaded) {
loggerCheckThreaded(LOG_TO_FILE);
} END_TEST
START_TEST(loggerMemCheckThreaded) {
loggerCheckThreaded(LOG_TO_MEMORY);
} END_TEST
void reopenLogWorkload(int truncating) {
@ -397,12 +428,12 @@ void reopenLogWorkload(int truncating) {
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_mode,
stasis_log_file_permissions);
} else if(LOG_TO_MEMORY == loggerType) {
stasis_log_file = open_InMemoryLog();
} else if(LOG_TO_MEMORY == stasis_log_type) {
stasis_log_file = stasis_log_impl_in_memory_open();
} else {
assert(stasis_log_file != NULL);
}
@ -428,14 +459,14 @@ void reopenLogWorkload(int truncating) {
}
}
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_mode,
stasis_log_file_permissions);
} else if(LOG_TO_MEMORY == loggerType) {
stasis_log_file = open_InMemoryLog();
} else if(LOG_TO_MEMORY == stasis_log_type) {
stasis_log_file = stasis_log_impl_in_memory_open();
} else {
assert(stasis_log_file != NULL);
}
@ -500,16 +531,18 @@ void reopenLogWorkload(int truncating) {
assert(i == (ENTRY_COUNT * 2));
stasis_truncation_automatic = 1;
stasis_log_file->deinit(stasis_log_file);
stasis_log_file->close(stasis_log_file);
}
START_TEST(loggerReopenTest) {
stasis_log_type = LOG_TO_FILE;
stasis_log_safe_writes_delete(stasis_log_file_name);
reopenLogWorkload(0);
} END_TEST
START_TEST(loggerTruncateReopenTest) {
stasis_log_type = LOG_TO_FILE;
stasis_log_safe_writes_delete(stasis_log_file_name);
reopenLogWorkload(1);
} END_TEST
@ -520,13 +553,17 @@ Suite * check_suite(void) {
TCase *tc = tcase_create("writeNew");
tcase_set_timeout(tc, 0);
/* Sub tests are added, one per line, here */
tcase_add_test(tc, loggerTest);
tcase_add_test(tc, logHandleColdReverseIterator);
tcase_add_test(tc, loggerTruncate);
tcase_add_test(tc, loggerCheckWorker);
tcase_add_test(tc, loggerCheckThreaded);
if(loggerType != LOG_TO_MEMORY) {
tcase_add_test(tc, loggerFileTest);
tcase_add_test(tc, loggerMemTest);
tcase_add_test(tc, logHandleFileColdReverseIterator);
tcase_add_test(tc, logHandleMemColdReverseIterator);
tcase_add_test(tc, loggerFileTruncate);
tcase_add_test(tc, loggerMemTruncate);
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, loggerTruncateReopenTest);
}

View file

@ -697,7 +697,7 @@ Suite * check_suite(void) {
tcase_add_test(tc, operation_physical_do_undo);
tcase_add_test(tc, operation_nestedTopAction);
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_alloc_test);

View file

@ -212,7 +212,7 @@ Suite * check_suite(void) {
/* Sub tests are added, one per line, here */
tcase_add_test(tc, pageOpCheckAllocDealloc);
if(LOG_TO_MEMORY != loggerType) {
if(LOG_TO_MEMORY != stasis_log_type) {
tcase_add_test(tc, pageOpCheckRecovery);
}
/* --------------------------------------------- */

View file

@ -484,7 +484,7 @@ Suite * check_suite(void) {
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 */
tcase_add_test(tc, recovery_idempotent);