2004-07-06 01:22:18 +00:00
|
|
|
#include <config.h>
|
2007-03-13 08:39:29 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
2007-06-11 21:36:57 +00:00
|
|
|
#include <stasis/common.h>
|
2004-07-20 03:40:57 +00:00
|
|
|
#include "latches.h"
|
2007-06-11 21:36:57 +00:00
|
|
|
#include <stasis/transactional.h>
|
|
|
|
#include <stasis/recovery.h>
|
|
|
|
#include <stasis/bufferManager.h>
|
|
|
|
#include <stasis/consumer.h>
|
|
|
|
#include <stasis/lockManager.h>
|
|
|
|
#include <stasis/compensations.h>
|
2007-03-13 08:39:29 +00:00
|
|
|
#include "pageFile.h"
|
2007-06-11 21:36:57 +00:00
|
|
|
#include <stasis/pageHandle.h>
|
2004-07-30 01:28:39 +00:00
|
|
|
#include "page.h"
|
2007-06-11 21:36:57 +00:00
|
|
|
#include <stasis/logger/logger2.h>
|
|
|
|
#include <stasis/truncation.h>
|
|
|
|
#include <stasis/io/handle.h>
|
2004-07-06 01:22:18 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <assert.h>
|
2006-06-12 21:50:21 +00:00
|
|
|
#include <limits.h>
|
2004-06-24 21:10:31 +00:00
|
|
|
|
|
|
|
TransactionLog XactionTable[MAX_TRANSACTIONS];
|
|
|
|
int numActiveXactions = 0;
|
|
|
|
int xidCount = 0;
|
2004-07-20 03:40:57 +00:00
|
|
|
|
2005-02-16 04:11:14 +00:00
|
|
|
const recordid ROOT_RECORD = {1, 0, -1};
|
|
|
|
const recordid NULLRID = {0,0,-1};
|
2006-06-17 00:25:09 +00:00
|
|
|
const short SLOT_TYPE_LENGTHS[] = { 0, 0, sizeof(blob_record_t), -1};
|
2004-07-20 03:40:57 +00:00
|
|
|
/**
|
|
|
|
Locking for transactional2.c works as follows:
|
|
|
|
|
|
|
|
numActiveXactions, xidCount are protected, XactionTable is not.
|
|
|
|
This implies that we do not support multi-threaded transactions,
|
|
|
|
at least for now.
|
|
|
|
*/
|
|
|
|
pthread_mutex_t transactional_2_mutex;
|
|
|
|
|
2006-07-27 00:13:20 +00:00
|
|
|
#define INVALID_XTABLE_XID INVALID_XID
|
|
|
|
#define PENDING_XTABLE_XID (-2)
|
2004-06-30 01:09:57 +00:00
|
|
|
/** Needed for debugging -- sometimes we don't want to run all of Tinit() */
|
2004-06-24 21:10:31 +00:00
|
|
|
|
2004-06-30 01:09:57 +00:00
|
|
|
void setupOperationsTable() {
|
2004-06-24 21:10:31 +00:00
|
|
|
memset(XactionTable, INVALID_XTABLE_XID, sizeof(TransactionLog)*MAX_TRANSACTIONS);
|
2007-03-28 09:21:07 +00:00
|
|
|
// @todo clean out unused constants...
|
2004-06-24 21:10:31 +00:00
|
|
|
operationsTable[OPERATION_SET] = getSet();
|
|
|
|
operationsTable[OPERATION_INCREMENT] = getIncrement();
|
|
|
|
operationsTable[OPERATION_DECREMENT] = getDecrement();
|
2004-08-03 02:04:56 +00:00
|
|
|
operationsTable[OPERATION_ALLOC] = getAlloc();
|
2004-06-24 21:10:31 +00:00
|
|
|
operationsTable[OPERATION_PREPARE] = getPrepare();
|
2004-07-06 01:22:18 +00:00
|
|
|
/* operationsTable[OPERATION_LHINSERT] = getLHInsert();
|
|
|
|
operationsTable[OPERATION_LHREMOVE] = getLHRemove(); */
|
2004-06-24 21:10:31 +00:00
|
|
|
operationsTable[OPERATION_DEALLOC] = getDealloc();
|
2004-10-02 07:29:34 +00:00
|
|
|
operationsTable[OPERATION_REALLOC] = getRealloc();
|
2004-08-21 00:03:30 +00:00
|
|
|
/* operationsTable[OPERATION_PAGE_ALLOC] = getPageAlloc();
|
|
|
|
operationsTable[OPERATION_PAGE_DEALLOC] = getPageDealloc(); */
|
2004-08-03 02:04:56 +00:00
|
|
|
operationsTable[OPERATION_PAGE_SET] = getPageSet();
|
|
|
|
|
2006-07-20 01:29:39 +00:00
|
|
|
/* operationsTable[OPERATION_UPDATE_FREESPACE] = getUpdateFreespace();
|
2004-08-21 00:03:30 +00:00
|
|
|
operationsTable[OPERATION_UPDATE_FREESPACE_INVERSE] = getUpdateFreespaceInverse();
|
|
|
|
operationsTable[OPERATION_UPDATE_FREELIST] = getUpdateFreelist();
|
|
|
|
operationsTable[OPERATION_UPDATE_FREELIST_INVERSE] = getUpdateFreelistInverse();
|
|
|
|
|
|
|
|
operationsTable[OPERATION_FREE_PAGE] = getFreePageOperation();
|
|
|
|
operationsTable[OPERATION_ALLOC_FREED] = getAllocFreedPage();
|
2006-07-20 01:29:39 +00:00
|
|
|
operationsTable[OPERATION_UNALLOC_FREED] = getUnallocFreedPage(); */
|
2004-10-02 07:29:34 +00:00
|
|
|
operationsTable[OPERATION_NOOP] = getNoop();
|
|
|
|
operationsTable[OPERATION_INSTANT_SET] = getInstantSet();
|
2004-10-06 06:08:09 +00:00
|
|
|
operationsTable[OPERATION_ARRAY_LIST_ALLOC] = getArrayListAlloc();
|
2006-07-29 00:56:54 +00:00
|
|
|
// operationsTable[OPERATION_INITIALIZE_FIXED_PAGE] = getInitFixed();
|
|
|
|
operationsTable[OPERATION_INITIALIZE_PAGE] = getInitializePage();
|
|
|
|
// operationsTable[OPERATION_UNINITIALIZE_PAGE] = getUnInitPage();
|
2004-06-30 01:09:57 +00:00
|
|
|
|
2004-10-18 18:24:54 +00:00
|
|
|
operationsTable[OPERATION_LINEAR_INSERT] = getLinearInsert();
|
|
|
|
operationsTable[OPERATION_UNDO_LINEAR_INSERT] = getUndoLinearInsert();
|
|
|
|
operationsTable[OPERATION_LINEAR_DELETE] = getLinearDelete();
|
|
|
|
operationsTable[OPERATION_UNDO_LINEAR_DELETE] = getUndoLinearDelete();
|
2004-12-03 00:27:47 +00:00
|
|
|
|
|
|
|
operationsTable[OPERATION_SET_RANGE] = getSetRange();
|
|
|
|
operationsTable[OPERATION_SET_RANGE_INVERSE] = getSetRangeInverse();
|
2005-01-14 10:08:10 +00:00
|
|
|
|
|
|
|
operationsTable[OPERATION_LINKED_LIST_INSERT] = getLinkedListInsert();
|
|
|
|
operationsTable[OPERATION_LINKED_LIST_REMOVE] = getLinkedListRemove();
|
2004-10-18 18:24:54 +00:00
|
|
|
|
2005-01-15 01:45:27 +00:00
|
|
|
operationsTable[OPERATION_LINEAR_HASH_INSERT] = getLinearHashInsert();
|
|
|
|
operationsTable[OPERATION_LINEAR_HASH_REMOVE] = getLinearHashRemove();
|
2005-03-01 07:32:02 +00:00
|
|
|
|
2007-03-28 09:21:07 +00:00
|
|
|
//operationsTable[OPERATION_SET_RAW] = getSetRaw();
|
|
|
|
//operationsTable[OPERATION_INSTANT_SET_RAW] = getInstantSetRaw();
|
2006-05-25 20:08:12 +00:00
|
|
|
|
2006-07-18 23:59:00 +00:00
|
|
|
operationsTable[OPERATION_ALLOC_BOUNDARY_TAG] = getAllocBoundaryTag();
|
|
|
|
|
2006-07-20 00:49:28 +00:00
|
|
|
operationsTable[OPERATION_FIXED_PAGE_ALLOC] = getFixedPageAlloc();
|
|
|
|
|
2006-07-25 00:56:50 +00:00
|
|
|
operationsTable[OPERATION_ALLOC_REGION] = getAllocRegion();
|
|
|
|
operationsTable[OPERATION_DEALLOC_REGION] = getDeallocRegion();
|
|
|
|
|
2004-06-30 01:09:57 +00:00
|
|
|
}
|
|
|
|
|
2007-03-13 08:39:29 +00:00
|
|
|
// @todo this factory stuff doesn't really belong here...
|
|
|
|
static stasis_handle_t * fast_factory(lsn_t off, lsn_t len, void * ignored) {
|
|
|
|
stasis_handle_t * h = stasis_handle(open_memory)(off);
|
|
|
|
//h = stasis_handle(open_debug)(h);
|
|
|
|
stasis_write_buffer_t * w = h->append_buffer(h, len);
|
|
|
|
w->h->release_write_buffer(w);
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
typedef struct sf_args {
|
|
|
|
char * filename;
|
|
|
|
int openMode;
|
|
|
|
int filePerm;
|
|
|
|
} sf_args;
|
2007-08-20 16:23:57 +00:00
|
|
|
static stasis_handle_t * slow_file_factory(void * argsP) {
|
2007-03-13 08:39:29 +00:00
|
|
|
sf_args * args = (sf_args*) argsP;
|
|
|
|
stasis_handle_t * h = stasis_handle(open_file)(0, args->filename, args->openMode, args->filePerm);
|
|
|
|
//h = stasis_handle(open_debug)(h);
|
|
|
|
return h;
|
|
|
|
}
|
2007-08-20 16:23:57 +00:00
|
|
|
static stasis_handle_t * slow_pfile_factory(void * argsP) {
|
|
|
|
stasis_handle_t * h = argsP;
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
static int (*slow_close)(stasis_handle_t * h) = 0;
|
|
|
|
static stasis_handle_t * slow_pfile = 0;
|
|
|
|
static int nop_close(stasis_handle_t*h) { return 0; }
|
|
|
|
|
2004-06-30 01:09:57 +00:00
|
|
|
int Tinit() {
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_init(&transactional_2_mutex, NULL);
|
2006-04-08 00:05:09 +00:00
|
|
|
numActiveXactions = 0;
|
2006-04-14 03:45:26 +00:00
|
|
|
|
2006-07-27 23:59:21 +00:00
|
|
|
compensations_init();
|
|
|
|
|
|
|
|
setupOperationsTable();
|
2006-04-14 03:45:26 +00:00
|
|
|
dirtyPagesInit();
|
2007-03-03 22:51:07 +00:00
|
|
|
LogInit(loggerType);
|
2007-10-02 00:18:33 +00:00
|
|
|
stasis_page_init();
|
2007-08-20 16:23:57 +00:00
|
|
|
|
|
|
|
#ifndef HAVE_O_DIRECT
|
2007-10-22 20:50:00 +00:00
|
|
|
if(bufferManagerO_DIRECT) {
|
|
|
|
printf("O_DIRECT not supported by this build; switching to conventional buffered I/O.\n");
|
|
|
|
bufferManagerO_DIRECT = 0;
|
|
|
|
}
|
2007-06-01 21:06:18 +00:00
|
|
|
#endif
|
2007-10-22 20:50:00 +00:00
|
|
|
int openMode;
|
|
|
|
if(bufferManagerO_DIRECT) {
|
2007-08-20 16:23:57 +00:00
|
|
|
#ifdef HAVE_O_DIRECT
|
2007-10-22 20:50:00 +00:00
|
|
|
openMode = O_CREAT | O_RDWR | O_DIRECT;
|
2007-06-01 21:06:18 +00:00
|
|
|
#else
|
2007-08-20 16:23:57 +00:00
|
|
|
printf("Can't happen\n");
|
|
|
|
abort();
|
|
|
|
#endif
|
2007-10-22 20:50:00 +00:00
|
|
|
} else {
|
|
|
|
openMode = O_CREAT | O_RDWR;
|
|
|
|
}
|
|
|
|
switch(bufferManagerFileHandleType) {
|
|
|
|
case BUFFER_MANAGER_FILE_HANDLE_NON_BLOCKING: {
|
|
|
|
struct sf_args * slow_arg = malloc(sizeof(sf_args));
|
|
|
|
slow_arg->filename = STORE_FILE;
|
|
|
|
|
|
|
|
slow_arg->openMode = openMode;
|
2007-08-20 16:23:57 +00:00
|
|
|
|
|
|
|
slow_arg->filePerm = FILE_PERM;
|
|
|
|
// Allow 4MB of outstanding writes.
|
|
|
|
// @todo Where / how should we open storefile?
|
|
|
|
stasis_handle_t * pageFile;
|
|
|
|
int worker_thread_count = 4;
|
|
|
|
if(bufferManagerNonBlockingSlowHandleType == IO_HANDLE_PFILE) {
|
|
|
|
// printf("\nusing pread()/pwrite()\n");
|
|
|
|
slow_pfile = stasis_handle_open_pfile(0, slow_arg->filename, slow_arg->openMode, slow_arg->filePerm);
|
|
|
|
slow_close = slow_pfile->close;
|
|
|
|
slow_pfile->close = nop_close;
|
|
|
|
pageFile =
|
2007-10-23 01:51:03 +00:00
|
|
|
stasis_handle(open_non_blocking)(slow_pfile_factory, slow_pfile, 1, fast_factory,
|
|
|
|
NULL, worker_thread_count, PAGE_SIZE * 1024 , 1024);
|
2007-08-20 16:23:57 +00:00
|
|
|
|
|
|
|
} else if(bufferManagerNonBlockingSlowHandleType == IO_HANDLE_FILE) {
|
|
|
|
pageFile =
|
2007-10-23 01:51:03 +00:00
|
|
|
stasis_handle(open_non_blocking)(slow_file_factory, slow_arg, 0, fast_factory,
|
|
|
|
NULL, worker_thread_count, PAGE_SIZE * 1024, 1024);
|
2007-08-20 16:23:57 +00:00
|
|
|
} else {
|
|
|
|
printf("Unknown value for config option bufferManagerNonBlockingSlowHandleType\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
//pageFile = stasis_handle(open_debug)(pageFile);
|
|
|
|
pageHandleOpen(pageFile);
|
|
|
|
} break;
|
2007-10-22 20:50:00 +00:00
|
|
|
case BUFFER_MANAGER_FILE_HANDLE_FILE: {
|
|
|
|
stasis_handle_t * pageFile =
|
|
|
|
stasis_handle_open_file(0, STORE_FILE, openMode, FILE_PERM);
|
|
|
|
pageHandleOpen(pageFile);
|
|
|
|
} break;
|
|
|
|
case BUFFER_MANAGER_FILE_HANDLE_PFILE: {
|
|
|
|
stasis_handle_t * pageFile =
|
|
|
|
stasis_handle_open_pfile(0, STORE_FILE, openMode, FILE_PERM);
|
|
|
|
pageHandleOpen(pageFile);
|
|
|
|
} break;
|
|
|
|
case BUFFER_MANAGER_FILE_HANDLE_DEPRECATED: {
|
2007-08-20 16:23:57 +00:00
|
|
|
printf("\nWarning: Using old I/O routines (with known bugs).\n");
|
|
|
|
openPageFile();
|
|
|
|
} break;
|
|
|
|
default: {
|
|
|
|
printf("\nUnknown buffer manager filehandle type: %d\n",
|
|
|
|
bufferManagerFileHandleType);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
2007-03-06 00:00:26 +00:00
|
|
|
bufInit(bufferManagerType);
|
2007-06-01 21:06:18 +00:00
|
|
|
DEBUG("Buffer manager type = %d\n", bufferManagerType);
|
2007-03-03 22:51:07 +00:00
|
|
|
pageOperationsInit();
|
2004-11-29 21:28:13 +00:00
|
|
|
initNestedTopActions();
|
2006-06-15 05:31:20 +00:00
|
|
|
TallocInit();
|
2004-10-17 02:17:00 +00:00
|
|
|
ThashInit();
|
2005-03-02 05:47:38 +00:00
|
|
|
LinearHashNTAInit();
|
|
|
|
LinkedListNTAInit();
|
2005-03-10 03:19:04 +00:00
|
|
|
iterator_init();
|
2005-03-23 08:07:53 +00:00
|
|
|
consumer_init();
|
2005-02-14 02:49:59 +00:00
|
|
|
setupLockManagerCallbacksNil();
|
|
|
|
//setupLockManagerCallbacksPage();
|
2005-02-24 21:12:36 +00:00
|
|
|
|
2005-02-10 03:51:09 +00:00
|
|
|
InitiateRecovery();
|
2005-02-24 21:12:36 +00:00
|
|
|
|
2006-07-20 01:30:58 +00:00
|
|
|
truncationInit();
|
2007-10-23 23:16:58 +00:00
|
|
|
if(stasis_truncation_automatic) {
|
2006-04-14 03:45:26 +00:00
|
|
|
autoTruncate(); // should this be before InitiateRecovery?
|
2006-07-20 01:30:58 +00:00
|
|
|
}
|
2004-06-24 21:10:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Tbegin() {
|
|
|
|
|
|
|
|
int i, index = 0;
|
2004-07-20 03:40:57 +00:00
|
|
|
int xidCount_tmp;
|
|
|
|
|
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2004-06-24 21:10:31 +00:00
|
|
|
|
2004-07-27 21:30:54 +00:00
|
|
|
if( numActiveXactions == MAX_TRANSACTIONS ) {
|
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
|
|
|
return EXCEED_MAX_TRANSACTIONS;
|
|
|
|
}
|
2004-06-24 21:10:31 +00:00
|
|
|
else
|
|
|
|
numActiveXactions++;
|
|
|
|
|
|
|
|
for( i = 0; i < MAX_TRANSACTIONS; i++ ) {
|
|
|
|
xidCount++;
|
|
|
|
if( XactionTable[xidCount%MAX_TRANSACTIONS].xid == INVALID_XTABLE_XID ) {
|
|
|
|
index = xidCount%MAX_TRANSACTIONS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-07-20 03:40:57 +00:00
|
|
|
xidCount_tmp = xidCount;
|
2004-06-24 21:10:31 +00:00
|
|
|
|
2004-07-27 21:30:54 +00:00
|
|
|
XactionTable[index].xid = PENDING_XTABLE_XID;
|
2004-06-24 21:10:31 +00:00
|
|
|
|
2004-07-27 21:30:54 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
|
|
|
|
|
|
|
XactionTable[index] = LogTransBegin(xidCount_tmp);
|
2004-07-23 20:21:44 +00:00
|
|
|
|
2005-02-10 03:51:09 +00:00
|
|
|
if(globalLockManager.begin) { globalLockManager.begin(XactionTable[index].xid); }
|
|
|
|
|
2004-06-24 21:10:31 +00:00
|
|
|
return XactionTable[index].xid;
|
|
|
|
}
|
|
|
|
|
2007-03-30 09:16:21 +00:00
|
|
|
static compensated_function void TactionHelper(int xid, recordid rid,
|
|
|
|
const void * dat, int op,
|
|
|
|
Page * p, int deferred) {
|
2004-06-24 21:10:31 +00:00
|
|
|
LogEntry * e;
|
2007-03-03 01:48:58 +00:00
|
|
|
assert(xid >= 0);
|
2005-02-24 21:12:36 +00:00
|
|
|
try {
|
|
|
|
if(globalLockManager.writeLockPage) {
|
|
|
|
globalLockManager.writeLockPage(xid, rid.page);
|
|
|
|
}
|
|
|
|
} end;
|
2007-03-30 09:16:21 +00:00
|
|
|
if(! deferred) {
|
|
|
|
e = LogUpdate(&XactionTable[xid % MAX_TRANSACTIONS], p, rid, op, dat);
|
|
|
|
assert(XactionTable[xid % MAX_TRANSACTIONS].prevLSN == e->LSN);
|
|
|
|
DEBUG("Tupdate() e->LSN: %ld\n", e->LSN);
|
|
|
|
doUpdate(e, p);
|
|
|
|
FreeLogEntry(e);
|
|
|
|
} else {
|
|
|
|
e = LogDeferred(&XactionTable[xid % MAX_TRANSACTIONS], p, rid, op, dat);
|
|
|
|
assert(XactionTable[xid % MAX_TRANSACTIONS].prevLSN == e->LSN);
|
|
|
|
DEBUG("Deferring e->LSN: %ld\n", e->LSN);
|
|
|
|
// XXX update XactionTable...
|
|
|
|
//XXX deferred_push(e);
|
|
|
|
}
|
2005-02-24 21:12:36 +00:00
|
|
|
|
|
|
|
|
2007-03-30 09:16:21 +00:00
|
|
|
}
|
|
|
|
|
2007-03-28 09:21:07 +00:00
|
|
|
compensated_function void TupdateRaw(int xid, recordid rid,
|
|
|
|
const void * dat, int op) {
|
2007-03-03 01:48:58 +00:00
|
|
|
assert(xid >= 0);
|
2007-03-28 09:21:07 +00:00
|
|
|
Page * p = loadPage(xid, rid.page);
|
2007-03-30 09:16:21 +00:00
|
|
|
TactionHelper(xid, rid, dat, op, p, 0); // 0 -> not deferred
|
2007-03-28 09:21:07 +00:00
|
|
|
releasePage(p);
|
|
|
|
}
|
|
|
|
|
2007-05-30 23:48:36 +00:00
|
|
|
compensated_function void TupdateStr(int xid, recordid rid,
|
|
|
|
const char *dat, int op) {
|
|
|
|
Tupdate(xid, rid, dat, op);
|
|
|
|
}
|
|
|
|
|
2007-03-28 09:21:07 +00:00
|
|
|
compensated_function void Tupdate(int xid, recordid rid,
|
2007-03-30 09:16:21 +00:00
|
|
|
const void *dat, int op) {
|
2007-03-28 09:21:07 +00:00
|
|
|
Page * p = loadPage(xid, rid.page);
|
2007-10-02 00:18:33 +00:00
|
|
|
rid = stasis_record_dereference(xid, p, rid);
|
2007-03-30 09:16:21 +00:00
|
|
|
|
2007-03-28 09:21:07 +00:00
|
|
|
if(p->id != rid.page) {
|
|
|
|
releasePage(p);
|
2005-02-24 21:12:36 +00:00
|
|
|
p = loadPage(xid, rid.page);
|
2006-05-25 20:08:12 +00:00
|
|
|
}
|
2007-03-30 09:16:21 +00:00
|
|
|
|
|
|
|
TactionHelper(xid, rid, dat, op, p, 0); // 0 -> not deferred
|
|
|
|
releasePage(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
compensated_function void Tdefer(int xid, recordid rid,
|
|
|
|
const void * dat, int op) {
|
|
|
|
|
|
|
|
Page * p = loadPage(xid, rid.page);
|
2007-10-02 00:18:33 +00:00
|
|
|
recordid newrid = stasis_record_dereference(xid, p, rid);
|
2007-03-30 09:16:21 +00:00
|
|
|
// Caller cannot rely on late or early binding of rid.
|
|
|
|
assert(rid.page == newrid.page &&
|
|
|
|
rid.slot == newrid.slot &&
|
|
|
|
rid.size == newrid.size);
|
|
|
|
TactionHelper(xid, rid, dat, op, p, 1); // 1 -> deferred.
|
2007-03-28 09:21:07 +00:00
|
|
|
releasePage(p);
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
|
|
|
|
2007-05-30 23:48:36 +00:00
|
|
|
compensated_function void TreadStr(int xid, recordid rid, char * dat) {
|
|
|
|
Tread(xid, rid, dat);
|
|
|
|
}
|
|
|
|
|
2005-02-22 03:10:54 +00:00
|
|
|
compensated_function void Tread(int xid, recordid rid, void * dat) {
|
|
|
|
Page * p;
|
|
|
|
try {
|
|
|
|
p = loadPage(xid, rid.page);
|
|
|
|
} end;
|
2004-10-06 06:08:09 +00:00
|
|
|
|
2007-10-02 00:18:33 +00:00
|
|
|
rid = stasis_record_dereference(xid, p, rid);
|
2006-08-11 02:24:01 +00:00
|
|
|
if(rid.page != p->id) {
|
2004-08-03 02:04:56 +00:00
|
|
|
releasePage(p);
|
2006-08-11 02:24:01 +00:00
|
|
|
p = loadPage(xid, rid.page);
|
2004-08-03 02:04:56 +00:00
|
|
|
}
|
2007-10-02 00:18:33 +00:00
|
|
|
stasis_record_read(xid, p, rid, dat);
|
2004-07-23 20:21:44 +00:00
|
|
|
releasePage(p);
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Tcommit(int xid) {
|
2004-06-28 21:10:10 +00:00
|
|
|
lsn_t lsn;
|
2007-03-03 01:48:58 +00:00
|
|
|
assert(xid >= 0);
|
2004-07-20 03:40:57 +00:00
|
|
|
#ifdef DEBUGGING
|
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2004-06-24 21:10:31 +00:00
|
|
|
assert(numActiveXactions <= MAX_TRANSACTIONS);
|
2004-07-27 01:04:35 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
2004-07-20 03:40:57 +00:00
|
|
|
#endif
|
|
|
|
|
2004-06-28 21:10:10 +00:00
|
|
|
lsn = LogTransCommit(&XactionTable[xid % MAX_TRANSACTIONS]);
|
2006-07-26 17:48:36 +00:00
|
|
|
if(globalLockManager.commit) { globalLockManager.commit(xid); }
|
2004-07-23 20:21:44 +00:00
|
|
|
|
2006-07-29 00:56:54 +00:00
|
|
|
allocTransactionCommit(xid);
|
|
|
|
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2006-07-29 00:56:54 +00:00
|
|
|
|
2004-07-23 20:21:44 +00:00
|
|
|
XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID;
|
2004-06-24 21:10:31 +00:00
|
|
|
numActiveXactions--;
|
|
|
|
assert( numActiveXactions >= 0 );
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
|
|
|
|
2004-06-24 21:10:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Tabort(int xid) {
|
2004-06-28 21:10:10 +00:00
|
|
|
lsn_t lsn;
|
2007-03-03 01:48:58 +00:00
|
|
|
assert(xid >= 0);
|
|
|
|
|
2004-07-23 20:21:44 +00:00
|
|
|
TransactionLog * t =&XactionTable[xid%MAX_TRANSACTIONS];
|
2004-06-28 21:10:10 +00:00
|
|
|
|
2007-03-28 09:21:07 +00:00
|
|
|
lsn = LogTransAbort(t);
|
2004-06-28 22:48:02 +00:00
|
|
|
|
2004-07-23 20:21:44 +00:00
|
|
|
/** @todo is the order of the next two calls important? */
|
2007-03-28 09:21:07 +00:00
|
|
|
undoTrans(*t);
|
2006-07-26 17:48:36 +00:00
|
|
|
if(globalLockManager.abort) { globalLockManager.abort(xid); }
|
2004-06-28 22:48:02 +00:00
|
|
|
|
2006-07-29 00:56:54 +00:00
|
|
|
allocTransactionAbort(xid);
|
|
|
|
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2004-07-23 20:21:44 +00:00
|
|
|
|
|
|
|
XactionTable[xid%MAX_TRANSACTIONS].xid = INVALID_XTABLE_XID;
|
2004-07-20 03:40:57 +00:00
|
|
|
numActiveXactions--;
|
2004-06-24 21:10:31 +00:00
|
|
|
assert( numActiveXactions >= 0 );
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
2004-06-24 21:10:31 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Tdeinit() {
|
2007-10-23 23:16:58 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for( i = 0; i < MAX_TRANSACTIONS; i++ ) {
|
|
|
|
if( XactionTable[i].xid != INVALID_XTABLE_XID ) {
|
|
|
|
if(!stasis_suppress_unclean_shutdown_warnings) {
|
|
|
|
fprintf(stderr, "WARNING: Tdeinit() is aborting transaction %d\n",
|
|
|
|
XactionTable[i].xid);
|
|
|
|
}
|
|
|
|
Tabort(XactionTable[i].xid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert( numActiveXactions == 0 );
|
|
|
|
truncationDeinit();
|
|
|
|
ThashDeinit();
|
|
|
|
TallocDeinit();
|
|
|
|
deinitNestedTopActions();
|
|
|
|
bufDeinit();
|
|
|
|
DEBUG("Closing page file tdeinit\n");
|
|
|
|
closePageFile();
|
|
|
|
if(slow_pfile) {
|
|
|
|
slow_close(slow_pfile);
|
|
|
|
slow_pfile = 0;
|
|
|
|
slow_close = 0;
|
|
|
|
}
|
|
|
|
stasis_page_deinit();
|
|
|
|
LogDeinit();
|
|
|
|
dirtyPagesDeinit();
|
|
|
|
return 0;
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
|
|
|
|
2007-07-19 23:47:06 +00:00
|
|
|
int TuncleanShutdown() {
|
2007-10-23 23:16:58 +00:00
|
|
|
// We're simulating a crash; don't complain when writes get lost,
|
|
|
|
// and active transactions get rolled back.
|
|
|
|
stasis_suppress_unclean_shutdown_warnings = 1;
|
2007-07-19 23:47:06 +00:00
|
|
|
truncationDeinit();
|
|
|
|
ThashDeinit();
|
|
|
|
simulateBufferManagerCrash();
|
2007-08-20 16:23:57 +00:00
|
|
|
if(slow_pfile) {
|
|
|
|
slow_close(slow_pfile);
|
|
|
|
slow_pfile = 0;
|
|
|
|
slow_close = 0;
|
|
|
|
}
|
2007-10-02 00:18:33 +00:00
|
|
|
stasis_page_deinit();
|
2007-07-19 23:47:06 +00:00
|
|
|
LogDeinit();
|
|
|
|
numActiveXactions = 0;
|
|
|
|
dirtyPagesDeinit();
|
2007-10-23 23:16:58 +00:00
|
|
|
|
|
|
|
// Reset it here so the warnings will appear if a new stasis
|
|
|
|
// instance encounters problems during a clean shutdown.
|
|
|
|
stasis_suppress_unclean_shutdown_warnings = 0;
|
2007-07-19 23:47:06 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-06-24 21:10:31 +00:00
|
|
|
void Trevive(int xid, long lsn) {
|
2007-03-03 01:48:58 +00:00
|
|
|
assert(xid >= 0);
|
2004-06-24 21:10:31 +00:00
|
|
|
int index = xid % MAX_TRANSACTIONS;
|
2004-07-23 20:21:44 +00:00
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2004-10-02 07:29:34 +00:00
|
|
|
|
|
|
|
DEBUG("Reviving xid %d at lsn %ld\n", xid, lsn);
|
|
|
|
|
2004-06-24 21:10:31 +00:00
|
|
|
if(XactionTable[index].xid != INVALID_XTABLE_XID) {
|
|
|
|
if(xid != XactionTable[index].xid) {
|
2006-06-13 22:43:20 +00:00
|
|
|
fprintf(stderr, "Clashing Tprepare()'ed XID's encountered on recovery!!\n");
|
|
|
|
abort();
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
|
|
|
assert(XactionTable[index].xid == xid);
|
|
|
|
assert(XactionTable[index].prevLSN == lsn);
|
|
|
|
} else {
|
|
|
|
XactionTable[index].xid = xid;
|
|
|
|
XactionTable[index].prevLSN = lsn;
|
2004-07-23 20:21:44 +00:00
|
|
|
|
2004-06-24 21:10:31 +00:00
|
|
|
numActiveXactions++;
|
2004-07-23 20:21:44 +00:00
|
|
|
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
2004-07-23 20:21:44 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void TsetXIDCount(int xid) {
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2004-06-24 21:10:31 +00:00
|
|
|
xidCount = xid;
|
2004-07-20 03:40:57 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
2004-06-24 21:10:31 +00:00
|
|
|
}
|
2006-04-14 03:45:26 +00:00
|
|
|
|
|
|
|
lsn_t transactions_minRecLSN() {
|
2007-03-28 09:21:07 +00:00
|
|
|
lsn_t minRecLSN = LSN_T_MAX;
|
2006-04-14 03:45:26 +00:00
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
|
|
|
for(int i = 0; i < MAX_TRANSACTIONS; i++) {
|
|
|
|
if(XactionTable[i].xid != INVALID_XTABLE_XID) {
|
|
|
|
lsn_t recLSN = XactionTable[i].recLSN;
|
|
|
|
if(recLSN != -1 && recLSN < minRecLSN) {
|
|
|
|
minRecLSN = recLSN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
|
|
|
return minRecLSN;
|
|
|
|
}
|
|
|
|
|
2006-07-26 17:48:36 +00:00
|
|
|
int TisActiveTransaction(int xid) {
|
2007-03-03 22:51:07 +00:00
|
|
|
if(xid < 0) { return 0; }
|
2006-07-26 17:48:36 +00:00
|
|
|
pthread_mutex_lock(&transactional_2_mutex);
|
2006-07-27 00:13:20 +00:00
|
|
|
int ret = xid != INVALID_XTABLE_XID && XactionTable[xid%MAX_TRANSACTIONS].xid == xid;
|
2006-07-26 17:48:36 +00:00
|
|
|
pthread_mutex_unlock(&transactional_2_mutex);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2007-03-07 06:45:28 +00:00
|
|
|
int TdurabilityLevel() {
|
|
|
|
if(bufferManagerType == BUFFER_MANAGER_MEM_ARRAY) {
|
|
|
|
return VOLATILE;
|
|
|
|
} else if(loggerType == LOG_TO_MEMORY) {
|
|
|
|
return PERSISTENT;
|
|
|
|
} else {
|
|
|
|
return DURABLE;
|
|
|
|
}
|
|
|
|
}
|