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:
parent
71f51d11bc
commit
1575d97a6b
2 changed files with 79 additions and 10 deletions
|
@ -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(®ion_mutex);
|
||||
assert(0 == holding_mutex);
|
||||
holding_mutex = pthread_self();
|
||||
|
||||
operate_dealloc_region_unlocked(xid, p, lsn, rid, datP);
|
||||
|
||||
holding_mutex = 0;
|
||||
pthread_mutex_unlock(®ion_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(®ion_mutex);
|
||||
}
|
||||
|
||||
unsigned int TregionAlloc(int xid, unsigned int pageCount, int allocationManager) {
|
||||
// Initial implementation. Naive first fit.
|
||||
|
||||
|
||||
pthread_mutex_lock(®ion_mutex);
|
||||
assert(0 == holding_mutex);
|
||||
holding_mutex = pthread_self();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue