Numerous lock manager fixes; more realistic test case for lock manager, added support for optional page-level locking.(Still need to report deadlocks back up to the caller.)

This commit is contained in:
Sears Russell 2005-02-10 03:51:09 +00:00
parent 6f022cc577
commit b8a67cbfb2
23 changed files with 405 additions and 167 deletions

View file

@ -100,7 +100,7 @@ typedef struct Page_s Page;
* @param pageid ID of the page you want to load
* @return fully formed Page type
*/
Page * loadPage(int pageid);
Page * loadPage(int xid, int pageid);
/**
loadPage aquires a lock when it is called, effectively pinning it

View file

@ -1,9 +1,28 @@
#include <lladd/transactional.h>
typedef struct {
void (*init)();
int (*readLockPage) (int xid, int page);
int (*writeLockPage) (int xid, int page);
int (*unlockPage) (int xid, int page);
int (*readLockRecord) (int xid, recordid rid);
int (*writeLockRecord)(int xid, recordid rid);
int (*unlockRecord) (int xid, recordid rid);
int (*begin) (int xid);
int (*commit) (int xid);
int (*abort) (int xid);
} LockManagerSetup;
extern LockManagerSetup globalLockManager;
void lockManagerInit();
int lockManagerReadLockRecord(int xid, recordid rid);
int lockManagerWriteLockRecord(int xid, recordid rid);
int lockManagerUnlockRecord(int xid, recordid rid);
int lockManagerReleaseAll(int xid);
int lockManagerCommit(int xid);
void setupLockManagerCallbacksRecord();
void setupLockManagerCallbacksPage();
void setupLockManagerCallbacksNil();

View file

@ -51,7 +51,7 @@ terms specified in this license.
#include <assert.h>
#include <lladd/bufferManager.h>
#include <lladd/lockManager.h>
#include "page.h"
#include "blobManager.h"
#include <lladd/pageCache.h>
@ -133,9 +133,9 @@ void releasePage (Page * p) {
}
int bufTransCommit(int xid, lsn_t lsn) {
commitBlobs(xid);
pageCommit(xid);
if(globalLockManager.commit) { globalLockManager.commit(xid);}
return 0;
}
@ -144,6 +144,7 @@ int bufTransAbort(int xid, lsn_t lsn) {
abortBlobs(xid); /* abortBlobs doesn't write any log entries, so it doesn't need the lsn. */
pageAbort(xid);
if(globalLockManager.abort) { globalLockManager.abort(xid);}
return 0;
}
@ -151,6 +152,7 @@ int bufTransAbort(int xid, lsn_t lsn) {
Page * getPage(int pageid, int locktype) {
Page * ret;
int spin = 0;
pthread_mutex_lock(&loadPagePtr_mutex);
ret = pblHtLookup(activePages, &pageid, sizeof(int));
@ -265,7 +267,9 @@ Page * getPage(int pageid, int locktype) {
return ret;
}
Page *loadPage(int pageid) {
Page *loadPage(int xid, int pageid) {
if(globalLockManager.readLockPage) { globalLockManager.readLockPage(xid, pageid); }
Page * ret = getPage(pageid, RO);
return ret;
}

View file

@ -7,7 +7,7 @@
#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <lladd/hash.h>
@ -19,9 +19,9 @@
static pthread_mutex_t mutexes[MUTEX_COUNT];
static pthread_mutex_t xid_table_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t * getMutex(recordid rid) {
return &mutexes[hash(&rid, sizeof(recordid), MUTEX_BITS, MUTEX_EXT)];
static pthread_mutex_t rid_table_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t * getMutex(byte * dat, int datLen) {
return &mutexes[hash(dat, datLen, MUTEX_BITS, MUTEX_EXT)];
}
static pblHashTable_t * xidLockTable;
@ -36,7 +36,7 @@ typedef struct {
int active;
} lock;
void lockManagerInit() {
void lockManagerInitHashed() {
int i = 0;
for(i = 0; i < MUTEX_COUNT; i++) {
pthread_mutex_init(&mutexes[i], NULL);
@ -45,16 +45,19 @@ void lockManagerInit() {
ridLockTable = pblHtCreate();
}
/** @todo startTransaction needs a mutex!! */
void startTransaction(int xid) {
pthread_mutex_lock(&xid_table_mutex);
pblHashTable_t * lockManagerBeginTransactionUnlocked(int xid) {
pblHashTable_t * xidLocks = pblHtCreate();
pblHtInsert(xidLockTable, &xid, sizeof(int), xidLocks);
return xidLocks;
}
int lockManagerBeginTransaction(int xid) {
pthread_mutex_lock(&xid_table_mutex);
lockManagerBeginTransactionUnlocked(xid);
pthread_mutex_unlock(&xid_table_mutex);
return 0;
}
lock* createLock(recordid rid) {
lock* createLock(byte * dat, int datLen) {
lock * ret = malloc(sizeof(lock));
if(!ret) { return NULL; }
@ -62,43 +65,50 @@ lock* createLock(recordid rid) {
// pthread_mutex_init(&ret->mut, NULL);
pthread_cond_init(&ret->writeOK, NULL);
pthread_cond_init(&ret->readOK, NULL);
ret->active = 0;
ret->readers = 0;
ret->writers = 0;
ret->waiting = 0;
pblHtInsert(ridLockTable, &rid, sizeof(recordid), ret);
pblHtInsert(ridLockTable, dat, datLen, ret);
return ret;
}
void destroyLock(recordid rid, lock * l) {
void destroyLock(byte * dat, int datLen, lock * l) {
pthread_cond_destroy(&l->writeOK);
pthread_cond_destroy(&l->readOK);
free (l);
pblHtRemove(ridLockTable, &rid, sizeof(recordid));
pblHtRemove(ridLockTable, dat, datLen);
}
#define LM_READLOCK 1
#define LM_WRITELOCK 2
int lockManagerReadLockRecord(int xid, recordid rid) {
int lockManagerReadLockHashed(int xid, byte * dat, int datLen) {
if(xid == -1) { return 0; }
pthread_mutex_lock(&xid_table_mutex);
pblHashTable_t * xidLocks = pblHtLookup(xidLockTable, &xid, sizeof(int));
if((int)pblHtLookup(xidLocks, &rid, sizeof(recordid)) >= LM_READLOCK) {
if(!xidLocks) {
xidLocks = lockManagerBeginTransactionUnlocked(xid);
}
int currentLockLevel = (int)pblHtLookup(xidLocks, dat, datLen);
// printf("xid %d read lock (%d)\n", xid, currentLockLevel);
if(currentLockLevel >= LM_READLOCK) {
pthread_mutex_unlock(&xid_table_mutex);
return 0;
}
assert(!currentLockLevel);
pthread_mutex_unlock(&xid_table_mutex);
pthread_mutex_t * mut = getMutex(rid);
pthread_mutex_t * mut = getMutex(dat, datLen);
pthread_mutex_lock(mut);
lock * ridLock = pblHtLookup(ridLockTable, &rid, sizeof(recordid));
pthread_mutex_lock(&rid_table_mutex);
lock * ridLock = pblHtLookup(ridLockTable, dat, datLen);
if(!ridLock) {
ridLock = createLock(rid);
ridLock = createLock(dat, datLen);
}
pthread_mutex_unlock(&rid_table_mutex);
ridLock->active++;
if(ridLock->writers || ridLock->waiting) {
@ -117,22 +127,36 @@ int lockManagerReadLockRecord(int xid, recordid rid) {
if(wait_ret == ETIMEDOUT) {
ridLock->active--;
pthread_mutex_unlock(mut);
// printf("Deadlock!\n"); fflush(stdout);
// abort();
return LLADD_DEADLOCK;
}
} while(ridLock->writers);
}
ridLock->readers++;
if(currentLockLevel < LM_READLOCK) {
ridLock->readers++;
pblHtRemove(xidLocks, dat, datLen);
pblHtInsert(xidLocks, dat, datLen, (void*)LM_READLOCK);
}
ridLock->active--;
pthread_mutex_unlock(mut);
pblHtInsert(xidLocks, &rid, sizeof(recordid), (void*)LM_READLOCK);
return 0;
}
int lockManagerWriteLockRecord(int xid, recordid rid) {
int lockManagerWriteLockHashed(int xid, byte * dat, int datLen) {
if(xid == -1) { return 0; }
pthread_mutex_lock(&xid_table_mutex);
pblHashTable_t * xidLocks = pblHtLookup(xidLockTable, &xid, sizeof(int));
if(!xidLocks) {
xidLocks = lockManagerBeginTransactionUnlocked(xid);
}
int currentLockLevel = (int)pblHtLookup(xidLocks, dat, datLen);
// printf("xid %d write lock (%d)\n", xid, currentLockLevel);
int currentLockLevel = (int)pblHtLookup(xidLocks, &rid, sizeof(recordid));
int me = 0;
pthread_mutex_unlock(&xid_table_mutex);
@ -142,13 +166,15 @@ int lockManagerWriteLockRecord(int xid, recordid rid) {
me = 1;
}
pthread_mutex_t * mut = getMutex(rid);
pthread_mutex_t * mut = getMutex(dat, datLen);
pthread_mutex_lock(mut);
lock * ridLock = pblHtLookup(ridLockTable, &rid, sizeof(recordid));
pthread_mutex_lock(&rid_table_mutex);
lock * ridLock = pblHtLookup(ridLockTable, dat, datLen);
if(!ridLock) {
ridLock = createLock(rid);
ridLock = createLock(dat, datLen);
}
pthread_mutex_unlock(&rid_table_mutex);
ridLock->active++;
ridLock->waiting++;
@ -169,6 +195,8 @@ int lockManagerWriteLockRecord(int xid, recordid rid) {
ridLock->waiting--;
ridLock->active--;
pthread_mutex_unlock(mut);
// printf("Deadlock!\n"); fflush(stdout);
// abort();
return LLADD_DEADLOCK;
}
}
@ -176,33 +204,48 @@ int lockManagerWriteLockRecord(int xid, recordid rid) {
ridLock->waiting--;
if(currentLockLevel == 0) {
ridLock->readers++;
ridLock->writers++;
} else if (currentLockLevel == LM_READLOCK) {
ridLock->writers++;
pblHtRemove(xidLocks, dat, datLen);
}
ridLock->writers++;
if(currentLockLevel != LM_WRITELOCK) {
pblHtInsert(xidLocks, dat, datLen, (void*)LM_WRITELOCK);
}
ridLock->active--;
pthread_mutex_unlock(mut);
pblHtInsert(xidLocks, &rid, sizeof(recordid), (void*)LM_WRITELOCK);
return 0;
}
int lockManagerUnlockRecord(int xid, recordid rid) {
int lockManagerUnlockHashed(int xid, byte * dat, int datLen) {
if(xid == -1) { return 0; }
// printf("xid %d unlock\n", xid);
pthread_mutex_lock(&xid_table_mutex);
pblHashTable_t * xidLocks = pblHtLookup(xidLockTable, &xid, sizeof(int));
if(!xidLocks) {
xidLocks = lockManagerBeginTransactionUnlocked(xid);
}
int currentLevel = (int)pblHtLookup(xidLocks, &rid, sizeof(recordid));
int currentLevel = (int)pblHtLookup(xidLocks, dat, datLen);
if(currentLevel) {
pblHtRemove(xidLocks, &rid, sizeof(recordid));
pblHtRemove(xidLocks, dat, datLen);
}
pthread_mutex_unlock(&xid_table_mutex);
pthread_mutex_t * mut = getMutex(rid);
pthread_mutex_t * mut = getMutex(dat, datLen);
pthread_mutex_lock(mut);
lock * ridLock = pblHtLookup(ridLockTable, &rid, sizeof(recordid));
pthread_mutex_lock(&rid_table_mutex);
lock * ridLock = pblHtLookup(ridLockTable, dat, datLen);
assert(ridLock);
ridLock->active++;
pthread_mutex_unlock(&rid_table_mutex);
if(currentLevel == LM_WRITELOCK) {
ridLock->writers--;
ridLock->readers--;
@ -220,7 +263,10 @@ int lockManagerUnlockRecord(int xid, recordid rid) {
ridLock->active--;
if(!(ridLock->active || ridLock->waiting || ridLock->readers || ridLock->writers)) {
destroyLock(rid, ridLock);
// printf("destroyed lock");
destroyLock(dat, datLen, ridLock);
} else {
// printf("(%d %d %d %d)", ridLock->active, ridLock->waiting, ridLock->readers, ridLock->writers);
}
pthread_mutex_unlock(mut);
@ -228,24 +274,102 @@ int lockManagerUnlockRecord(int xid, recordid rid) {
return 0;
}
int lockManagerReleaseAll(int xid) {
int lockManagerCommitHashed(int xid, int datLen) {
if(xid == -1) { return 0; }
pthread_mutex_lock(&xid_table_mutex);
pblHashTable_t * xidLocks = pblHtLookup(xidLockTable, &xid, sizeof(int));
if(!xidLocks) {
xidLocks = lockManagerBeginTransactionUnlocked(xid);
}
pthread_mutex_unlock(&xid_table_mutex);
void * data;
int ret = 0;
byte * dat = malloc(datLen);
for(data = pblHtFirst(xidLocks); data; data = pblHtNext(xidLocks)) {
recordid rid = *(recordid*)pblHtCurrentKey(xidLocks);
int tmpret = lockManagerUnlockRecord(xid, rid);
memcpy(dat, pblHtCurrentKey(xidLocks), datLen);
int tmpret = lockManagerUnlockHashed(xid, dat, datLen);
// Pass any error(s) up to the user.
// (This logic relies on the fact that currently it only returns 0 and LLADD_INTERNAL_ERROR)
if(tmpret) {
ret = tmpret;
}
pblHtRemove(xidLocks, &rid, sizeof(recordid));
pblHtRemove(xidLocks, dat, datLen);
}
free(dat);
return ret;
}
int lockManagerReadLockRecord(int xid, recordid rid) {
return lockManagerReadLockHashed(xid, (byte*)&rid, sizeof(recordid));
}
int lockManagerWriteLockRecord(int xid, recordid rid) {
return lockManagerWriteLockHashed(xid, (byte*)&rid, sizeof(recordid));
}
int lockManagerUnlockRecord(int xid, recordid rid) {
return lockManagerUnlockHashed(xid, (byte*)&rid, sizeof(recordid));
}
int lockManagerCommitRecords(int xid) {
return lockManagerCommitHashed(xid, sizeof(recordid));
}
int lockManagerReadLockPage(int xid, int p) {
return lockManagerReadLockHashed(xid, (byte*)&p, sizeof(int));
}
int lockManagerWriteLockPage(int xid, int p) {
return lockManagerWriteLockHashed(xid, (byte*)&p, sizeof(int));
}
int lockManagerUnlockPage(int xid, int p) {
return lockManagerUnlockHashed(xid, (byte*)&p, sizeof(int));
}
int lockManagerCommitPages(int xid) {
return lockManagerCommitHashed(xid, sizeof(int));
}
LockManagerSetup globalLockManager;
void setupLockManagerCallbacksPage() {
globalLockManager.init = &lockManagerInitHashed;
globalLockManager.readLockPage = &lockManagerReadLockPage;
globalLockManager.writeLockPage = &lockManagerWriteLockPage;
globalLockManager.unlockPage = &lockManagerUnlockPage;
globalLockManager.readLockRecord = NULL;
globalLockManager.writeLockRecord = NULL;
globalLockManager.unlockRecord = NULL;
globalLockManager.commit = &lockManagerCommitPages;
globalLockManager.abort = &lockManagerCommitPages;
globalLockManager.begin = &lockManagerBeginTransaction;
globalLockManager.init();
}
void setupLockManagerCallbacksRecord () {
globalLockManager.init = &lockManagerInitHashed;
globalLockManager.readLockPage = NULL;
globalLockManager.writeLockPage = NULL;
globalLockManager.unlockPage = NULL;
globalLockManager.readLockRecord = &lockManagerReadLockRecord;
globalLockManager.writeLockRecord = &lockManagerWriteLockRecord;
globalLockManager.unlockRecord = &lockManagerUnlockRecord;
globalLockManager.commit = &lockManagerCommitRecords;
globalLockManager.abort = &lockManagerCommitRecords;
globalLockManager.begin = &lockManagerBeginTransaction;
globalLockManager.init();
}
void setupLockManagerCallbacksNil () {
globalLockManager.init = NULL;
globalLockManager.readLockPage = NULL;
globalLockManager.writeLockPage = NULL;
globalLockManager.unlockPage = NULL;
globalLockManager.readLockRecord = NULL;
globalLockManager.writeLockRecord = NULL;
globalLockManager.unlockRecord = NULL;
globalLockManager.commit = NULL;
globalLockManager.abort = NULL;
globalLockManager.begin = NULL;
}

View file

@ -65,7 +65,7 @@ void redoUpdate(const LogEntry * e) {
if(e->type == UPDATELOG) {
/* lsn_t pageLSN = readLSN(e->contents.update.rid.page); */
recordid rid = e->contents.update.rid;
Page * p = loadPage(rid.page);
Page * p = loadPage(e->xid, rid.page);
lsn_t pageLSN = pageReadLSN(p);
if(e->LSN > pageLSN) {
@ -79,7 +79,7 @@ void redoUpdate(const LogEntry * e) {
} else if(e->type == CLRLOG) {
LogEntry * f = readLSNEntry(e->contents.clr.thisUpdateLSN);
recordid rid = f->contents.update.rid;
Page * p = loadPage(rid.page);
Page * p = loadPage(e->xid, rid.page);
assert(rid.page == e->contents.update.rid.page); /* @todo Should this always hold? */
@ -127,7 +127,7 @@ void undoUpdate(const LogEntry * e, Page * p, lsn_t clr_lsn) {
assert(p);
DEBUG("OPERATION %d Whole page physical undo, %ld {%d}\n", undo, e->LSN, e->contents.update.rid.page);
memcpy(p->memAddr, getUpdatePreImage(e), PAGE_SIZE);
pageWriteLSN(p, clr_lsn);
pageWriteLSN(e->xid, p, clr_lsn);
} else {
/* @see doUpdate() */

View file

@ -44,7 +44,7 @@ static int operate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat)
if(rid.size >= BLOB_THRESHOLD_SIZE && rid.size != BLOB_SLOT) {
allocBlob(xid, p, lsn, rid);
} else {
slottedPostRalloc(p, lsn, rid);
slottedPostRalloc(xid, p, lsn, rid);
}
return 0;
@ -53,7 +53,7 @@ static int operate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat)
/** @todo Currently, we leak empty pages on dealloc. */
static int deoperate(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
assert(rid.page == p->id);
slottedDeRalloc(p, lsn, rid);
slottedDeRalloc(xid, p, lsn, rid);
return 0;
}
@ -64,7 +64,7 @@ static int reoperate(int xid, Page *p, lsn_t lsn, recordid rid, const void * dat
rid.size = sizeof(blob_record_t);
}
slottedPostRalloc(p, lsn, rid);
slottedPostRalloc(xid, p, lsn, rid);
/** @todo dat should be the pointer to the space in the blob store. */
writeRecord(xid, p, lsn, rid, dat);
@ -162,7 +162,7 @@ recordid TallocFromPage(int xid, long page, long size) {
void Tdealloc(int xid, recordid rid) {
void * preimage = malloc(rid.size);
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
readRecord(xid, p, rid, preimage);
/** @todo race in Tdealloc; do we care, or is this something that the log manager should cope with? */
Tupdate(xid, rid, preimage, OPERATION_DEALLOC);
@ -171,7 +171,7 @@ void Tdealloc(int xid, recordid rid) {
}
int TrecordType(int xid, recordid rid) {
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
int ret = getRecordType(xid, p, rid);
releasePage(p);
return ret;
@ -179,14 +179,14 @@ int TrecordType(int xid, recordid rid) {
int TrecordSize(int xid, recordid rid) {
int ret;
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
ret = getRecordSize(xid, p, rid);
releasePage(p);
return ret;
}
int TrecordsInPage(int xid, int pageid) {
Page * p = loadPage(pageid);
Page * p = loadPage(xid, pageid);
readlock(p->rwlatch, 187);
int ret = *numslots_ptr(p);
unlock(p->rwlatch);

View file

@ -96,7 +96,7 @@ static int operateAlloc(int xid, Page * p, lsn_t lsn, recordid rid, const void *
*page_type_ptr(p) = ARRAY_LIST_PAGE;
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
recordid ret;
ret.page = firstPage;
@ -118,7 +118,7 @@ Operation getArrayListAlloc() {
/*----------------------------------------------------------------------------*/
int TarrayListExtend(int xid, recordid rid, int slots) {
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
TarrayListParameters tlp = pageToTLP(p);
int lastCurrentBlock;
@ -181,7 +181,7 @@ int TarrayListExtend(int xid, recordid rid, int slots) {
}
/** @todo: TarrayListInstantExtend, is a hacked-up cut and paste version of TarrayListExtend */
int TarrayListInstantExtend(int xid, recordid rid, int slots) {
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
TarrayListParameters tlp = pageToTLP(p);
int lastCurrentBlock;
@ -249,13 +249,13 @@ static int operateInitFixed(int xid, Page * p, lsn_t lsn, recordid rid, const vo
fixedPageInitialize(p, rid.size, recordsPerPage(rid.size));
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}
static int operateUnInitPage(int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) {
*page_type_ptr(p) = UNINITIALIZED_PAGE;
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}

View file

@ -82,7 +82,7 @@ static int operateUndoDelete(int xid, Page * p, lsn_t lsn, recordid rid, const v
argBytes + keySize, valSize);
return 0;
}
static int noop (int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) { pageWriteLSN(p, lsn); return 0; }
static int noop (int xid, Page * p, lsn_t lsn, recordid rid, const void * dat) { pageWriteLSN(xid, p, lsn); return 0; }
Operation getLinearInsert() {
Operation o = {
@ -316,7 +316,8 @@ void instant_update_hash_header(int xid, recordid hash, int i, int next_split) {
static void recover_split(int xid, recordid hashRid, int i, int next_split, int keySize, int valSize) {
// This function would be simple, except for the ridiculous mount
// of state that it must maintain. See above for a description of what it does.
recordid * headerRidB;
recordid headerRidBstack;
recordid * headerRidB = &headerRidBstack;
hashRid.slot = 1;
Tread(xid, hashRid, headerRidB);
hashRid.slot = 0;

View file

@ -52,7 +52,7 @@ static int operate(int xid, Page *p, lsn_t lsn, recordid rid, const void *dat)
/* If p is null, then this is a logical no-op that spans pages, so do nothing.
Otherwise, write the LSN to the appropriate page (to keep recovery happy)
and return */
if(p) pageWriteLSN(p, lsn);
if(p) pageWriteLSN(xid, p, lsn);
return 0;
}

View file

@ -34,7 +34,7 @@ int __pageDealloc(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
*/
int __pageSet(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
memcpy(p->memAddr, d, PAGE_SIZE);
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}
@ -50,7 +50,7 @@ int __update_freepage(int xid, Page * p, lsn_t lsn, recordid r, const void * d)
fflush(NULL); */
* headerFreepage_ptr(p) = t->after;
freepage = t->after;
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}
@ -64,7 +64,7 @@ int __update_freespace_inverse(int xid, Page * p, lsn_t lsn, recordid r, const v
* headerFreepage_ptr(p) = t->before;
freepage = t->before;
#endif
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}
#ifdef REUSE_PAGES
@ -102,18 +102,18 @@ int __free_page(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
memset(p->memAddr, 0, PAGE_SIZE);
*page_type_ptr(p) = LLADD_FREE_PAGE;
*nextfreepage_ptr(p) = *successor;
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}
int __alloc_freed(int xid, Page * p, lsn_t lsn, recordid r, const void * d) {
memset(p->memAddr, 0, PAGE_SIZE);
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
return 0;
}
int TpageGet(int xid, int pageid, byte *memAddr) {
Page * q = loadPage(pageid);
Page * q = loadPage(xid, pageid);
memcpy(memAddr, q->memAddr, PAGE_SIZE);
releasePage(q);
return 0;
@ -139,7 +139,8 @@ void pageOperationsInit() {
assert(!posix_memalign((void **)&(p.memAddr), PAGE_SIZE, PAGE_SIZE));
p.id = 0;*/
Page * p = loadPage(0);
Page * p = loadPage(-1, 0);
/** Release lock on page zero. */
// pageRead(&p);

View file

@ -106,7 +106,7 @@ void TsetRange(int xid, recordid rid, int offset, int length, const void * dat)
// Copy new value into log structure
memcpy(range + 1, dat, length);
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
// No further locking is necessary here; readRecord protects the
// page layout, but attempts at concurrent modification have undefined
// results. (See page.c)

View file

@ -83,6 +83,7 @@ terms specified in this license.
#include <lladd/constants.h>
#include <assert.h>
#include "blobManager.h"
#include <lladd/lockManager.h>
#include "pageFile.h"
#include "page/slotted.h"
@ -102,9 +103,11 @@ static pthread_mutex_t pageMallocMutex;
/** We need one dummy page for locking purposes, so this array has one extra page in it. */
Page pool[MAX_BUFFER_SIZE+1];
void pageWriteLSN(Page * page, lsn_t lsn) {
void pageWriteLSN(int xid, Page * page, lsn_t lsn) {
/* unlocked since we're only called by a function that holds the writelock. */
/* *(long *)(page->memAddr + START_OF_LSN) = page->LSN; */
if(globalLockManager.writeLockPage) { globalLockManager.writeLockPage(xid, page->id); }
if(page->LSN < lsn) {
page->LSN = lsn;
*lsn_ptr(page) = page->LSN;
@ -263,7 +266,7 @@ void writeRecord(int xid, Page * p, lsn_t lsn, recordid rid, const void *dat) {
assert( (p->id == rid.page) && (p->memAddr != NULL) );
writelock(p->rwlatch, 225); /* Need a writelock so that we can update the lsn. */
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
unlock(p->rwlatch);
}
@ -378,7 +381,7 @@ void writeRecordUnlocked(int xid, Page * p, lsn_t lsn, recordid rid, const void
assert( (p->id == rid.page) && (p->memAddr != NULL) );
writelock(p->rwlatch, 225); /* Need a writelock so that we can update the lsn. */
pageWriteLSN(p, lsn);
pageWriteLSN(xid, p, lsn);
unlock(p->rwlatch);
}

View file

@ -221,7 +221,7 @@ void pageDeInit();
* @param page You must have a writelock on page before calling this function.
* @param lsn The new lsn of the page. If the new lsn is less than the page's current lsn, then the page's lsn will not be changed.
*/
void pageWriteLSN(Page * page, lsn_t lsn);
void pageWriteLSN(int xid, Page * page, lsn_t lsn);
/**
* assumes that the page is already loaded in memory. It takes

View file

@ -14,8 +14,8 @@ void indirectInitialize(Page * p, int height) {
memset(p->memAddr, INVALID_SLOT, ((int)level_ptr(p)) - ((int)p->memAddr));
}
/** @todo locking for dereferenceRID? */
recordid dereferenceRID(recordid rid) {
Page * this = loadPage(rid.page);
recordid dereferenceRID(int xid, recordid rid) {
Page * this = loadPage(xid, rid.page);
int offset = 0;
int max_slot;
while(*page_type_ptr(this) == INDIRECT_PAGE) {
@ -32,7 +32,7 @@ recordid dereferenceRID(recordid rid) {
int nextPage = *page_ptr(this, i);
releasePage(this);
this = loadPage(nextPage);
this = loadPage(xid, nextPage);
}
rid.page = this->id;
@ -168,8 +168,8 @@ recordid __rallocMany(int xid, int parentPage, int recordSize, int recordCount)
return rid;
}
unsigned int indirectPageRecordCount(recordid rid) {
Page * p = loadPage(rid.page);
unsigned int indirectPageRecordCount(int xid, recordid rid) {
Page * p = loadPage(xid, rid.page);
int i = 0;
unsigned int ret;
if(*page_type_ptr(p) == INDIRECT_PAGE) {

View file

@ -43,11 +43,11 @@ BEGIN_C_DECLS
Translates a recordid that points to an indirect block into the
physical location of the record.
*/
recordid dereferenceRID(recordid rid);
#define dereferenceRIDUnlocked(x) dereferenceRID((x))
recordid dereferenceRID(int xid, recordid rid);
#define dereferenceRIDUnlocked(y, x) dereferenceRID((y), (x))
void indirectInitialize(Page * p, int height);
recordid rallocMany(/*int parentPage, lsn_t lsn,*/int xid, int recordSize, int recordCount);
unsigned int indirectPageRecordCount(recordid rid);
unsigned int indirectPageRecordCount(int xid, recordid rid);
END_C_DECLS

View file

@ -175,18 +175,18 @@ recordid slottedPreRalloc(int xid, long size, Page ** pp) {
if(lastFreepage == -1) {
lastFreepage = TpageAlloc(xid);
*pp = loadPage(lastFreepage);
*pp = loadPage(xid, lastFreepage);
assert(*page_type_ptr(*pp) == UNINITIALIZED_PAGE);
slottedPageInitialize(*pp);
} else {
*pp = loadPage(lastFreepage);
*pp = loadPage(xid, lastFreepage);
}
if(slottedFreespace(*pp) < size ) {
releasePage(*pp);
lastFreepage = TpageAlloc(xid);
*pp = loadPage(lastFreepage);
*pp = loadPage(xid, lastFreepage);
slottedPageInitialize(*pp);
}
@ -209,7 +209,7 @@ recordid slottedPreRallocFromPage(int xid, long page, long size, Page **pp) {
size = sizeof(blob_record_t);
}
*pp = loadPage(page);
*pp = loadPage(xid, page);
if(slottedFreespace(*pp) < size) {
releasePage(*pp);
@ -302,7 +302,7 @@ static void __really_do_ralloc(Page * page, recordid rid) {
}
recordid slottedPostRalloc(Page * page, lsn_t lsn, recordid rid) {
recordid slottedPostRalloc(int xid, Page * page, lsn_t lsn, recordid rid) {
writelock(page->rwlatch, 376);
@ -348,14 +348,14 @@ recordid slottedPostRalloc(Page * page, lsn_t lsn, recordid rid) {
}
pageWriteLSN(page, lsn);
pageWriteLSN(xid, page, lsn);
writeunlock(page->rwlatch);
return rid;
}
void slottedDeRalloc(Page * page, lsn_t lsn, recordid rid) {
void slottedDeRalloc(int xid, Page * page, lsn_t lsn, recordid rid) {
readlock(page->rwlatch, 443);
@ -364,7 +364,7 @@ void slottedDeRalloc(Page * page, lsn_t lsn, recordid rid) {
*freelist_ptr(page) = rid.slot;
/* *slot_length_ptr(page, rid.slot) = 0; */
pageWriteLSN(page, lsn);
pageWriteLSN(xid, page, lsn);
unlock(page->rwlatch);
}

View file

@ -113,13 +113,13 @@ recordid slottedPreRallocFromPage(int xid, long page, long size, Page**p);
* page for this record (though it is possible that we need to compact
* the page)
*/
recordid slottedPostRalloc(Page * page, lsn_t lsn, recordid rid);
recordid slottedPostRalloc(int xid, Page * page, lsn_t lsn, recordid rid);
/**
* Mark the space used by a record for reclaimation.
*
* @param rid the recordid to be freed.
*/
void slottedDeRalloc(Page * page, lsn_t lsn, recordid rid);
void slottedDeRalloc(int xid, Page * page, lsn_t lsn, recordid rid);
void slottedPageInit();
void slottedPageDeinit();

View file

@ -6,6 +6,8 @@
#include <lladd/recovery.h>
#include "logger/logWriter.h"
#include <lladd/bufferManager.h>
#include <lladd/lockManager.h>
#include "page.h"
#include <lladd/logger/logger2.h>
@ -91,8 +93,10 @@ int Tinit() {
initNestedTopActions();
ThashInit();
InitiateRecovery();
setupLockManagerCallbacksNil();
// setupLockManagerCallbacksPage();
InitiateRecovery();
return 0;
}
@ -130,6 +134,8 @@ int Tbegin() {
XactionTable[index] = LogTransBegin(xidCount_tmp);
if(globalLockManager.begin) { globalLockManager.begin(XactionTable[index].xid); }
return XactionTable[index].xid;
}
@ -142,12 +148,12 @@ void Tupdate(int xid, recordid rid, const void *dat, int op) {
pthread_mutex_unlock(&transactional_2_mutex);
#endif
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
if(*page_type_ptr(p) == INDIRECT_PAGE) {
releasePage(p);
rid = dereferenceRID(rid);
p = loadPage(rid.page);
rid = dereferenceRID(xid, rid);
p = loadPage(xid, rid.page);
/** @todo Kludge! Shouldn't special case operations in transactional2. */
} else if(*page_type_ptr(p) == ARRAY_LIST_PAGE &&
op != OPERATION_LINEAR_INSERT &&
@ -156,7 +162,7 @@ void Tupdate(int xid, recordid rid, const void *dat, int op) {
op != OPERATION_UNDO_LINEAR_DELETE ) {
rid = dereferenceArrayListRid(p, rid.slot);
releasePage(p);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
}
e = LogUpdate(&XactionTable[xid % MAX_TRANSACTIONS], p, rid, op, dat);
@ -175,7 +181,7 @@ void Tupdate(int xid, recordid rid, const void *dat, int op) {
void alTupdate(int xid, recordid rid, const void *dat, int op) {
LogEntry * e;
Page * p;
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
/* if(*page_type_ptr(p) == INDIRECT_PAGE) {
releasePage(p);
@ -206,19 +212,19 @@ void alTupdate(int xid, recordid rid, const void *dat, int op) {
void TreadUnlocked(int xid, recordid rid, void * dat) {
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
int page_type = *page_type_ptr(p);
if(page_type == SLOTTED_PAGE || page_type == FIXED_PAGE || !page_type ) {
} else if(page_type == INDIRECT_PAGE) {
releasePage(p);
rid = dereferenceRIDUnlocked(rid);
p = loadPage(rid.page);
rid = dereferenceRIDUnlocked(xid, rid);
p = loadPage(xid, rid.page);
} else if(page_type == ARRAY_LIST_PAGE) {
rid = dereferenceArrayListRidUnlocked(p, rid.slot);
releasePage(p);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
} else {
abort();
@ -228,19 +234,19 @@ void TreadUnlocked(int xid, recordid rid, void * dat) {
}
void Tread(int xid, recordid rid, void * dat) {
Page * p = loadPage(rid.page);
Page * p = loadPage(xid, rid.page);
int page_type = *page_type_ptr(p);
if(page_type == SLOTTED_PAGE || page_type == FIXED_PAGE || !page_type ) {
} else if(page_type == INDIRECT_PAGE) {
releasePage(p);
rid = dereferenceRID(rid);
p = loadPage(rid.page);
rid = dereferenceRID(xid, rid);
p = loadPage(xid, rid.page);
} else if(page_type == ARRAY_LIST_PAGE) {
rid = dereferenceArrayListRid(p, rid.slot);
releasePage(p);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
} else {
abort();

View file

@ -35,10 +35,10 @@ void initializePages() {
rid.page = i;
rid.slot = 0;
rid.size = sizeof(int);
p = loadPage(rid.page);
p = loadPage(-1, rid.page);
assert(p->id != -1);
slottedPostRalloc(p, 0, rid);
slottedPostRalloc(-1, p, 0, rid);
writeRecord(1, p, 1, rid, &i);
@ -66,7 +66,7 @@ void * workerThread(void * p) {
rid.slot = 0;
rid.size = sizeof(int);
p = loadPage(rid.page);
p = loadPage(-1, rid.page);
readRecord(1, p, rid, &j);
@ -89,7 +89,7 @@ void * workerThreadWriting(void * q) {
Page * tmp;
pthread_mutex_lock(&ralloc_mutex);
rids[i] = slottedPreRalloc(1, sizeof(int), &tmp);
slottedPostRalloc(tmp, 1, rids[i]);
slottedPostRalloc(-1, tmp, 1, rids[i]);
releasePage(tmp);
pthread_mutex_unlock(&ralloc_mutex);
@ -106,7 +106,7 @@ void * workerThreadWriting(void * q) {
for(int i = 0; i < RECORDS_PER_THREAD; i++) {
int val = (i * 10000) + offset;
int k;
Page * p = loadPage(rids[i].page);
Page * p = loadPage(-1, rids[i].page);
assert(p->id == rids[i].page);
@ -135,7 +135,7 @@ void * workerThreadWriting(void * q) {
Page * p;
p = loadPage(rids[i].page);
p = loadPage(-1, rids[i].page);
readRecord(1, p, rids[i], &val);

View file

@ -101,7 +101,7 @@ START_TEST(indirectAlloc) {
fail_unless(rid.slot == RECORD_ARRAY, NULL);
fail_unless(rid.size == 1, NULL);
Page * p = loadPage(page);
Page * p = loadPage(xid, page);
int page_type = *page_type_ptr(p);
@ -122,7 +122,7 @@ START_TEST(indirectAlloc) {
fail_unless(rid.slot == RECORD_ARRAY, NULL);
fail_unless(rid.size == 2000, NULL);
p = loadPage(page);
p = loadPage(xid, page);
page_type = *page_type_ptr(p);
@ -146,7 +146,7 @@ START_TEST(indirectAlloc) {
fail_unless(rid.slot == RECORD_ARRAY, NULL);
fail_unless(rid.size == 2, NULL);
p = loadPage(page);
p = loadPage(xid, page);
page_type = *page_type_ptr(p);
@ -177,7 +177,7 @@ START_TEST(indirectAccessDirect) {
page = rid.page;
/* Make sure that it didn't create any indirect pages. */
Page * p = loadPage(page);
Page * p = loadPage(xid, page);
int page_type = *page_type_ptr(p);
@ -193,7 +193,7 @@ START_TEST(indirectAccessDirect) {
for(int i = 0; i < 500; i++) {
rid.slot = i;
Tset(xid, dereferenceRID(rid), &i);
Tset(xid, dereferenceRID(xid, rid), &i);
}
Tcommit(xid);
@ -202,7 +202,7 @@ START_TEST(indirectAccessDirect) {
for(int i = 0; i < 500; i++) {
rid.slot = i;
int j;
Tread(xid, dereferenceRID(rid), &j);
Tread(xid, dereferenceRID(xid, rid), &j);
assert(j == i);
}
@ -222,7 +222,7 @@ START_TEST(indirectAccessIndirect) {
page = rid.page;
/* Make sure that it didn't create any indirect pages. */
Page * p = loadPage(page);
Page * p = loadPage(xid, page);
int page_type = *page_type_ptr(p);
@ -236,7 +236,7 @@ START_TEST(indirectAccessIndirect) {
for(int i = 0; i < 500000; i++) {
rid.slot = i;
Tset(xid, dereferenceRID(rid), &i);
Tset(xid, dereferenceRID(xid, rid), &i);
}
Tcommit(xid);
@ -245,7 +245,7 @@ START_TEST(indirectAccessIndirect) {
for(int i = 0; i < 500000; i++) {
rid.slot = i;
int j;
Tread(xid, dereferenceRID(rid), &j);
Tread(xid, dereferenceRID(xid, rid), &j);
assert(j == i);
}
@ -264,12 +264,12 @@ START_TEST(indirectSizeTest) {
int xid = Tbegin();
recordid rid = rallocMany(xid, sizeof(int), 20);
int count = indirectPageRecordCount(rid);
int count = indirectPageRecordCount(xid, rid);
assert(count == 20);
recordid rid2 = rallocMany(xid, sizeof(int), 5000);
count = indirectPageRecordCount(rid2);
count = indirectPageRecordCount(xid, rid2);
assert(count == 5000);
Tcommit(xid);

View file

@ -11,14 +11,60 @@
#define LOG_NAME "check_lockManager.log"
/** Needs to be formatted as a floating point */
#define NUM_RECORDS 100000000.0
#define NUM_RECORDS 5000000.0
#define THREAD_COUNT 100
#define RIDS_PER_THREAD 10000
#define RIDS_PER_THREAD 1000
void * workerThread(void * j) {
void * pageWorkerThread(void * j) {
int xid = *(int*)j;
//startTransaction(xid);
globalLockManager.begin(xid);
recordid rid;
rid.page = 0;
rid.size = 0;
int k;
int deadlocks = 0;
for(k = 0; k < RIDS_PER_THREAD; k++) {
int m = (int) (NUM_RECORDS*random()/(RAND_MAX+1.0));
int rw = random() % 2;
if(rw) {
// readlock
if(LLADD_DEADLOCK == globalLockManager.readLockPage(xid, m)) {
// if(LLADD_DEADLOCK == lockManagerReadLockRecord(xid, rid)) {
k = 0;
globalLockManager.abort(xid);
deadlocks++;
printf("-");
}
} else {
// writelock
// if(LLADD_DEADLOCK == lockManagerWriteLockRecord(xid, rid)) {
if(LLADD_DEADLOCK == globalLockManager.writeLockPage(xid, m)) {
k = 0;
globalLockManager.abort(xid);
deadlocks++;
printf("-");
}
}
}
printf("%2d ", deadlocks); fflush(stdout);
// lockManagerCommit(xid);
globalLockManager.commit(xid);
return NULL;
}
void * ridWorkerThread(void * j) {
int xid = *(int*)j;
startTransaction(xid);
//startTransaction(xid);
globalLockManager.begin(xid);
recordid rid;
rid.page = 0;
rid.size = 0;
@ -30,16 +76,23 @@ void * workerThread(void * j) {
if(rw) {
// readlock
if(LLADD_DEADLOCK == lockManagerReadLockRecord(xid, rid)) {
if(LLADD_DEADLOCK == globalLockManager.readLockRecord(xid, rid)) {
// if(LLADD_DEADLOCK == lockManagerReadLockRecord(xid, rid)) {
k = 0;
globalLockManager.abort(xid);
deadlocks++;
printf("-");
}
} else {
// writelock
if(LLADD_DEADLOCK == lockManagerWriteLockRecord(xid, rid)) {
// if(LLADD_DEADLOCK == lockManagerWriteLockRecord(xid, rid)) {
if(LLADD_DEADLOCK == globalLockManager.writeLockRecord(xid, rid)) {
k = 0;
globalLockManager.abort(xid);
deadlocks++;
printf("-");
}
}
@ -47,21 +100,43 @@ void * workerThread(void * j) {
printf("%2d ", deadlocks); fflush(stdout);
lockManagerReleaseAll(xid);
// lockManagerCommit(xid);
globalLockManager.commit(xid);
return NULL;
}
START_TEST(lockManagerTest) {
START_TEST(recordidLockManagerTest) {
printf("\n");
setupLockManagerCallbacksRecord();
lockManagerInit();
pthread_t workers[THREAD_COUNT];
int i;
for(i = 0; i < THREAD_COUNT; i++) {
int *j = malloc(sizeof(int));
*j = i;
pthread_create(&workers[i], NULL, workerThread, j);
pthread_create(&workers[i], NULL, ridWorkerThread, j);
}
for(i = 0; i < THREAD_COUNT; i++) {
pthread_join(workers[i], NULL);
}
} END_TEST
START_TEST(pageLockManagerTest) {
printf("\n");
setupLockManagerCallbacksPage();
pthread_t workers[THREAD_COUNT];
int i;
for(i = 0; i < THREAD_COUNT; i++) {
int *j = malloc(sizeof(int));
*j = i;
pthread_create(&workers[i], NULL, pageWorkerThread, j);
}
for(i = 0; i < THREAD_COUNT; i++) {
pthread_join(workers[i], NULL);
@ -76,8 +151,9 @@ Suite * check_suite(void) {
/* Sub tests are added, one per line, here */
tcase_add_test(tc, lockManagerTest);
tcase_add_test(tc, recordidLockManagerTest);
tcase_add_test(tc, pageLockManagerTest);
/* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown);

View file

@ -74,7 +74,7 @@ START_TEST(operation_physical_do_undo) {
Page * p;
Tinit();
xid = -1;
rid = slottedPreRalloc(xid, sizeof(int), &p);
releasePage(p);
buf = 1;
@ -87,17 +87,17 @@ START_TEST(operation_physical_do_undo) {
DEBUG("B\n");
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
writeRecord(xid, p, lsn, rid, &buf);
releasePage(p);
setToTwo->LSN = 10;
DEBUG("C\n");
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
doUpdate(setToTwo, p); /* PAGE LSN= 10, value = 2. */
releasePage(p);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
readRecord(xid, p, rid, &buf);
releasePage(p);
@ -107,7 +107,7 @@ START_TEST(operation_physical_do_undo) {
DEBUG("D\n");
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
fail_unless(10 == pageReadLSN(p), "page lsn not set correctly.");
@ -116,7 +116,7 @@ START_TEST(operation_physical_do_undo) {
undoUpdate(setToTwo, p, 8); /* Should succeed, CLR LSN is too low, but undoUpdate only checks the log entry. */
releasePage(p);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
readRecord(xid, p, rid, &buf);
releasePage(p);
@ -126,7 +126,7 @@ START_TEST(operation_physical_do_undo) {
redoUpdate(setToTwo);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
readRecord(xid, p, rid, &buf);
releasePage(p);
@ -145,7 +145,7 @@ START_TEST(operation_physical_do_undo) {
lsn = 0;
buf = 1;
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
writeRecord(xid, p, lsn, rid, &buf);
releasePage(p);
/* Trace of test:
@ -169,7 +169,7 @@ START_TEST(operation_physical_do_undo) {
DEBUG("F\n");
redoUpdate(setToTwo);
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
readRecord(xid, p, rid, &buf);
assert(buf == 2);
fail_unless(buf == 2, NULL);
@ -185,7 +185,7 @@ START_TEST(operation_physical_do_undo) {
DEBUG("H don't redo set to 2\n");
redoUpdate(setToTwo); /* Fails */
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
readRecord(xid, p, rid, &buf);
@ -197,7 +197,7 @@ START_TEST(operation_physical_do_undo) {
releasePage(p);
redoUpdate(setToTwo); /* Succeeds */
p = loadPage(rid.page);
p = loadPage(xid, rid.page);
readRecord(xid, p, rid, &buf);
fail_unless(buf == 2, NULL);
@ -330,6 +330,7 @@ START_TEST(operation_prepare) {
and checks that the result is as expected.
@todo Write a more thorough (threaded!) nested top action test.
*/
START_TEST(operation_nestedTopAction) {
@ -512,7 +513,8 @@ START_TEST(operation_set_range) {
}
Tcommit(xid);
Tdeinit();
} END_TEST
START_TEST(operation_alloc_test) {

View file

@ -86,7 +86,7 @@ static void * multiple_simultaneous_pages ( void * arg_ptr) {
readRecord(1, p, rid[k], (byte*)&j);
assert((j + 1) == i + k);
slottedDeRalloc(p, lsn, rid[k]);
slottedDeRalloc(-1, p, lsn, rid[k]);
sched_yield();
}
}
@ -98,7 +98,7 @@ static void * multiple_simultaneous_pages ( void * arg_ptr) {
rid[k] = slottedRawRalloc(p, sizeof(short));
i +=k;
/* printf("Slot %d = %d\n", rid[k].slot, i); */
writeRecord(1, p, lsn, rid[k], (byte*)&i);
writeRecord(-1, p, lsn, rid[k], (byte*)&i);
i -=k;
sched_yield();
}
@ -159,14 +159,14 @@ static void* worker_thread(void * arg_ptr) {
if(! first ) {
readRecord(1, p, rid, (byte*)&j);
assert((j + 1) == i);
slottedDeRalloc(p, lsn, rid);
slottedDeRalloc(-1, p, lsn, rid);
sched_yield();
}
first = 0;
rid = slottedRawRalloc(p, sizeof(int));
writeRecord(1, p, lsn, rid, (byte*)&i);
writeRecord(-1, p, lsn, rid, (byte*)&i);
sched_yield();
assert(pageReadLSN(p) <= lsn);
@ -198,7 +198,8 @@ START_TEST(pageNoThreadTest)
Tinit();
p = loadPage(0);
p = loadPage(-1, 0);
slottedPageInitialize(p);
worker_thread(p);
@ -287,7 +288,7 @@ START_TEST(pageNoThreadMultPageTest)
Tinit();
p = loadPage(1);
p = loadPage(-1, 1);
slottedPageInitialize(p);
multiple_simultaneous_pages(p);
releasePage(p);
@ -315,7 +316,7 @@ START_TEST(pageThreadTest) {
Tinit();
fail_unless(1, NULL);
Page * p = loadPage(2);
Page * p = loadPage(-1, 2);
slottedPageInitialize(p);
fail_unless(1, NULL);
@ -345,7 +346,7 @@ START_TEST(fixedPageThreadTest) {
pthread_mutex_init(&random_mutex, NULL);
pthread_mutex_init(&lsn_mutex, NULL);
Tinit();
Page * p = loadPage(2);
Page * p = loadPage(-1, 2);
fixedPageInitialize(p, sizeof(int), 0);
for(i = 0; i < THREAD_COUNT; i++) {
@ -368,25 +369,26 @@ START_TEST(pageCheckSlotTypeTest) {
recordid fixedRoot = TarrayListAlloc(xid, 2, 10, 10);
recordid blob = Talloc(xid, PAGE_SIZE * 2);
Page * p = loadPage(slot.page);
Page * p = loadPage(-1, slot.page);
assert(getRecordType(xid, p, slot) == SLOTTED_RECORD);
releasePage(p);
/** @todo the use of the fixedRoot recordid to check getRecordType is
a bit questionable, but should work. */
p = loadPage(fixedRoot.page);
p = loadPage(-1, fixedRoot.page);
assert(getRecordType(xid, p, fixedRoot) == FIXED_RECORD);
releasePage(p);
fixedRoot.slot = 1;
recordid fixedEntry = dereferenceRID(fixedRoot);
recordid fixedEntry = dereferenceRID(xid, fixedRoot);
fixedRoot.slot = 0;
p = loadPage(fixedEntry.page);
p = loadPage(-1, fixedEntry.page);
assert(getRecordType(xid, p, fixedEntry) == FIXED_RECORD);
releasePage(p);
p = loadPage(blob.page);
p = loadPage(-1, blob.page);
int type = getRecordType(xid, p, blob);
assert(type == BLOB_RECORD);
releasePage(p);
@ -396,7 +398,7 @@ START_TEST(pageCheckSlotTypeTest) {
bad.slot = slot.slot + 10;
bad.size = 4;
p = loadPage(bad.page);
p = loadPage(xid, bad.page);
assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD);
bad.size = 100000;
assert(getRecordType(xid, p, bad) == UNINITIALIZED_RECORD);
@ -430,7 +432,7 @@ START_TEST(pageTrecordTypeTest) {
assert(TrecordType(xid, fixedRoot) == FIXED_RECORD);
fixedRoot.slot = 1;
recordid fixedEntry = dereferenceRID(fixedRoot);
recordid fixedEntry = dereferenceRID(xid, fixedRoot);
fixedRoot.slot = 0;
assert(TrecordType(xid, fixedEntry) == FIXED_RECORD);