Fixed recovery bug. TregionDealloc was being called during redo(), causing an assert to fail. Without the

assert, would have gone into infinite recursion.
This commit is contained in:
Sears Russell 2006-10-05 22:08:42 +00:00
parent 71f51d11bc
commit 1575d97a6b
2 changed files with 79 additions and 10 deletions

View file

@ -12,6 +12,10 @@ typedef struct regionAllocLogArg{
static pthread_mutex_t region_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_t holding_mutex;
static void TregionAllocHelper(int xid, unsigned int pageid, unsigned int pageCount, int allocationManager);
static void TallocBoundaryTag(int xid, unsigned int page, boundary_tag* tag);
static void TreadBoundaryTag(int xid, unsigned int page, boundary_tag* tag);
static void TsetBoundaryTag(int xid, unsigned int page, boundary_tag* tag);
static void TdeallocBoundaryTag(int xid, unsigned int page);
/** This doesn't need a latch since it is only initiated within nested
top actions (and is local to this file. During abort(), the nested
@ -40,12 +44,39 @@ static int operate_alloc_region(int xid, Page * p, lsn_t lsn, recordid rid, cons
return 0;
}
static int operate_dealloc_region(int xid, Page * p, lsn_t lsn, recordid rid, const void * datP) {
static int operate_dealloc_region_unlocked(int xid, Page * p, lsn_t lsn, recordid rid, const void * datP) {
regionAllocArg *dat = (regionAllocArg*)datP;
TregionDealloc(xid, dat->startPage+1);
unsigned int firstPage = dat->startPage + 1;
boundary_tag t;
TreadBoundaryTag(xid, firstPage - 1, &t);
t.status = REGION_VACANT;
t.region_xid = xid;
TsetBoundaryTag(xid, firstPage -1, &t);
// TregionDealloc(xid, dat->startPage+1);
return 0;
}
static int operate_dealloc_region(int xid, Page * p, lsn_t lsn, recordid rid, const void * datP) {
int ret;
pthread_mutex_lock(&region_mutex);
assert(0 == holding_mutex);
holding_mutex = pthread_self();
operate_dealloc_region_unlocked(xid, p, lsn, rid, datP);
holding_mutex = 0;
pthread_mutex_unlock(&region_mutex);
return ret;
}
static void TallocBoundaryTag(int xid, unsigned int page, boundary_tag* tag) {
//printf("Alloc boundary tag at %d = { %d, %d, %d }\n", page, tag->size, tag->prev_size, tag->status);
assert(holding_mutex == pthread_self());
@ -84,7 +115,6 @@ static void TdeallocBoundaryTag(int xid, unsigned int page) {
TreadBoundaryTag(xid, page, &t);
t.status = REGION_CONDEMNED;
t.region_xid = xid;
//printf("(dealloc) ");
TsetBoundaryTag(xid, page, &t);
}
@ -331,28 +361,28 @@ void TregionDealloc(int xid, unsigned int firstPage) {
regionAllocArg arg = { firstPage-1, t.size, t.allocation_manager };
assert(t.status != REGION_VACANT);
void * handle = TbeginNestedTopAction(xid, OPERATION_DEALLOC_REGION, (const byte*)&arg, sizeof(regionAllocArg));
TreadBoundaryTag(xid, firstPage - 1, &t);
operate_dealloc_region_unlocked(xid, 0, 0, NULLRID, (const byte*)&arg);
assert(t.status != REGION_VACANT);
t.status = REGION_VACANT;
/*t.status = REGION_VACANT;
t.region_xid = xid;
TsetBoundaryTag(xid, firstPage -1, &t);
TsetBoundaryTag(xid, firstPage -1, &t); */
firstPage --;
// consolidateRegions(xid, &firstPage, &t);
TendNestedTopAction(xid, handle);
holding_mutex = 0;
pthread_mutex_unlock(&region_mutex);
}
unsigned int TregionAlloc(int xid, unsigned int pageCount, int allocationManager) {
// Initial implementation. Naive first fit.
pthread_mutex_lock(&region_mutex);
assert(0 == holding_mutex);
holding_mutex = pthread_self();

View file

@ -311,6 +311,44 @@ START_TEST(regions_lockRandomizedTest) {
Tdeinit();
} END_TEST
START_TEST(regions_recoveryTest) {
Tinit();
unsigned int pages[50];
int xid1 = Tbegin();
int xid2 = Tbegin();
for(int i = 0; i < 50; i+=2) {
pages[i] = TregionAlloc(xid1, myrandom(4)+1, 1);
pages[i+1] = TregionAlloc(xid2, myrandom(2)+1, 1);
}
fsckRegions(xid1);
Tcommit(xid1);
Tdeinit();
Tinit();
int xid = Tbegin();
fsckRegions(xid);
for(int i = 0; i < 50; i+=2) {
TregionDealloc(xid, pages[i]);
}
fsckRegions(xid);
Tabort(xid);
fsckRegions(Tbegin());
Tdeinit();
Tinit();
fsckRegions(Tbegin());
Tdeinit();
} END_TEST
/**
Add suite declarations here
*/
@ -325,6 +363,7 @@ Suite * check_suite(void) {
tcase_add_test(tc, regions_randomizedTest);
tcase_add_test(tc, regions_lockSmokeTest);
tcase_add_test(tc, regions_lockRandomizedTest);
tcase_add_test(tc, regions_recoveryTest);
/* --------------------------------------------- */
tcase_add_checked_fixture(tc, setup, teardown);
suite_add_tcase(s, tc);