Allocation bugfixes

This commit is contained in:
Sears Russell 2008-02-29 18:03:32 +00:00
parent c7ccb2c2db
commit 673f6b55d3
5 changed files with 83 additions and 23 deletions

View file

@ -29,6 +29,7 @@
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <stasis/allocationPolicy.h>
#include <stasis/lhtable.h>
#include <stasis/redblack.h>
@ -81,7 +82,7 @@ static int cmpFreespace(const void * ap, const void * bp, const void * param) {
}
inline static availablePage* getAvailablePage(allocationPolicy * ap, int pageid) {
return (availablePage*) LH_ENTRY(find)(ap->allPages, &pageid, sizeof(int));
return (availablePage*) LH_ENTRY(find)(ap->allPages, &pageid, sizeof(pageid));
}
inline static void insert_xidAlloced(allocationPolicy * ap, int xid, availablePage * p) {
@ -96,6 +97,7 @@ inline static void insert_xidAlloced(allocationPolicy * ap, int xid, availablePa
}
inline static void remove_xidAlloced(allocationPolicy * ap, int xid, availablePage * p) {
assert(p->lockCount);
struct RB_ENTRY(tree) * pages = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(xid));
assert(pages);
const availablePage * check = RB_ENTRY(delete)(p, pages);
@ -150,14 +152,16 @@ inline static void lockAlloced(allocationPolicy * ap, int xid, availablePage
inline static void unlockAlloced(allocationPolicy * ap, int xid, availablePage * p) {
remove_xidAlloced(ap, xid, p);
assert(p->lockCount == 1);
p->lockCount = 0;
const availablePage * check = RB_ENTRY(search)(p, ap->availablePages);
assert(check == p);
p->lockCount--;
// assert(p->lockCount == 1);
// p->lockCount = 0;
if(!p->lockCount) {
const availablePage * check = RB_ENTRY(search)(p, ap->availablePages);
assert(check == p);
}
int * xidp = LH_ENTRY(remove)(ap->pageOwners, &(p->pageid), sizeof(p->pageid));
assert(*xidp == xid);
free(xidp);
//assert(*xidp == xid);
if(xidp) { free(xidp); }
}
@ -202,12 +206,14 @@ inline static void lockDealloced(allocationPolicy * ap, int xid, availablePage *
}
inline static void unlockDealloced(allocationPolicy * ap, int xid, availablePage * p) {
assert(p->lockCount);
assert(p->lockCount > 0);
p->lockCount--;
assert(p->lockCount >= 0);
remove_xidDealloced(ap, xid, p);
if(!p->lockCount) {
// put it back into available pages.
LH_ENTRY(remove)(ap->pageOwners, &(p->pageid), sizeof(p->pageid)); // XXX new feb-29
const availablePage * check = RB_ENTRY(search)(p, ap->availablePages);
assert(check == p);
}
@ -286,10 +292,10 @@ availablePage * allocationPolicyFindPage(allocationPolicy * ap, int xid, int fre
// No; get a page from the availablePages.
ret = RB_ENTRY(lookup)(RB_LUGREAT, &tmp, ap->availablePages);
if(ret) {
/*if(ret) {
assert(ret->lockCount == 0);
lockAlloced(ap, xid, (availablePage*) ret);
}
} */
}
// Done. (If ret is null, then it's the caller's problem.)
@ -300,11 +306,20 @@ void allocationPolicyAllocedFromPage(allocationPolicy *ap, int xid, int pageid)
availablePage * p = getAvailablePage(ap, pageid);
const availablePage * check1 = RB_ENTRY(find)(p, ap->availablePages);
int * xidp = LH_ENTRY(find)(ap->pageOwners, &(pageid), sizeof(pageid));
assert(xidp || check1);
if(!(xidp || check1)) {
// the page is not available, and is not owned.
// this can happen if more than one transaction deallocs from the same page
assert(p->lockCount);
printf("Two transactions concurrently dealloced from page; now a "
"transaction has alloced from it. This leads to unrecoverable "
"schedules. Refusing to continue.");
fflush(stdout);
abort();
}
if(check1) {
assert(p->lockCount == 0);
lockAlloced(ap, xid, (availablePage*)p);
}
}
}
void allocationPolicyLockPage(allocationPolicy *ap, int xid, int pageid) {
@ -350,6 +365,7 @@ void allocationPolicyTransactionCompleted(allocationPolicy * ap, int xid) {
void allocationPolicyUpdateFreespaceUnlockedPage(allocationPolicy * ap, availablePage * key, int newFree) {
availablePage * p = (availablePage*) RB_ENTRY(delete)(key, ap->availablePages);
assert(key == p);
p->freespace = newFree;
const availablePage * ret = RB_ENTRY(search)(p, ap->availablePages);
assert(ret == p);
@ -357,6 +373,7 @@ void allocationPolicyUpdateFreespaceUnlockedPage(allocationPolicy * ap, availabl
void allocationPolicyUpdateFreespaceLockedPage(allocationPolicy * ap, int xid, availablePage * key, int newFree) {
struct RB_ENTRY(tree) * locks = LH_ENTRY(find)(ap->xidAlloced, &xid, sizeof(int));
assert(key);
availablePage * p = (availablePage*) RB_ENTRY(delete)(key, locks);
assert(p);
p->freespace = newFree;

View file

@ -1,4 +1,5 @@
#include <config.h>
#include <stasis/constants.h>
#include <stasis/common.h>
#include <stasis/operations.h>
@ -154,26 +155,62 @@ Operation getRealloc() {
static uint64_t lastFreepage;
static allocationPolicy * allocPolicy;
static void registerOldRegions();
void TallocInit() {
lastFreepage = UINT64_MAX;
allocPolicy = allocationPolicyInit();
// pthread_mutex_init(&talloc_mutex, NULL);
}
void TallocPostInit() {
registerOldRegions();
}
void TallocDeinit() {
allocationPolicyDeinit(allocPolicy);
}
static void registerOldRegions() {
pageid_t boundary = REGION_FIRST_TAG;
boundary_tag t;
DEBUG("registering old regions\n");
int succ = TregionReadBoundaryTag(-1, boundary, &t);
if(succ) {
do {
DEBUG("boundary tag %lld type %d\n", boundary, t.allocation_manager);
if(t.allocation_manager == STORAGE_MANAGER_TALLOC) {
availablePage ** newPages = malloc(sizeof(availablePage*)*(t.size+1));
for(pageid_t i = 0; i < t.size; i++) {
Page * p = loadPage(-1, boundary + i);
readlock(p->rwlatch,0);
if(*stasis_page_type_ptr(p) == SLOTTED_PAGE) {
availablePage * next = malloc(sizeof(availablePage));
next->pageid = boundary+i;
next->freespace = stasis_record_freespace(-1, p);
next->lockCount = 0;
newPages[i] = next;
DEBUG("registered page %lld\n", boundary+i);
} else {
abort();
}
unlock(p->rwlatch);
releasePage(p);
}
newPages[t.size]=0;
allocationPolicyAddPages(allocPolicy, newPages);
free(newPages);
}
} while(TregionNextBoundaryTag(-1, &boundary, &t, 0)); //STORAGE_MANAGER_TALLOC)) {
}
}
static void reserveNewRegion(int xid) {
void* nta = TbeginNestedTopAction(xid, OPERATION_NOOP, 0,0);
int firstPage = TregionAlloc(xid, TALLOC_REGION_SIZE, STORAGE_MANAGER_TALLOC);
int initialFreespace = -1;
void* nta = TbeginNestedTopAction(xid, OPERATION_NOOP, 0,0);
availablePage ** newPages = malloc(sizeof(availablePage**)*(TALLOC_REGION_SIZE+1));
availablePage ** newPages = malloc(sizeof(availablePage*)*(TALLOC_REGION_SIZE+1));
for(int i = 0; i < TALLOC_REGION_SIZE; i++) {
availablePage * next = malloc(sizeof(availablePage) * TALLOC_REGION_SIZE);
availablePage * next = malloc(sizeof(availablePage)); // * TALLOC_REGION_SIZE);
TinitializeSlottedPage(xid, firstPage + i);
if(initialFreespace == -1) {
@ -229,8 +266,11 @@ compensated_function recordid Talloc(int xid, unsigned long size) {
}
unlock(p->rwlatch);
if(!ap->lockCount) {
allocationPolicyUpdateFreespaceUnlockedPage(allocPolicy, ap, newFreespace);
} else {
allocationPolicyUpdateFreespaceLockedPage(allocPolicy, xid, ap, newFreespace);
}
releasePage(p);
ap = allocationPolicyFindPage(allocPolicy, xid, stasis_record_type_to_size(type));
@ -252,6 +292,7 @@ compensated_function recordid Talloc(int xid, unsigned long size) {
stasis_record_alloc_done(xid, p, rid);
int newFreespace = stasis_record_freespace(xid, p);
allocationPolicyAllocedFromPage(allocPolicy, xid, ap->pageid);
allocationPolicyUpdateFreespaceLockedPage(allocPolicy, xid, ap, newFreespace);
unlock(p->rwlatch);

View file

@ -284,6 +284,7 @@ void InitiateRecovery() {
DEBUG("Redo started\n");
Redo();
DEBUG("Undo started\n");
TallocPostInit();
Undo(1);
DEBUG("Recovery complete.\n");

View file

@ -21,6 +21,7 @@ void allocTransactionAbort(int xid);
void allocTransactionCommit(int xid);
void TallocInit();
void TallocPostInit();
void TallocDeinit();
/**
Allocate a record.

View file

@ -210,7 +210,7 @@ static void takeRandomAction(allocationPolicy * ap, int * xids,
if(p && p->lockCount == 0) {
int thenewfreespace = p->freespace+thespacediff;
allocationPolicyUpdateFreespaceUnlockedPage(ap, p, thenewfreespace);
printf("updated freespace unlocked");
// printf("updated freespace unlocked");
}
} break;
case 3 : { // update freespace locked
@ -295,7 +295,7 @@ Suite * check_suite(void) {
/* Sub tests are added, one per line, here */
tcase_add_test(tc, allocationPolicy_smokeTest);
// tcase_add_test(tc, allocationPolicy_smokeTest);
tcase_add_test(tc, allocationPolicy_randomTest);
/* --------------------------------------------- */