From 1575d97a6b12d9c2fdd5160559eae5a73a3fd44d Mon Sep 17 00:00:00 2001 From: Sears Russell Date: Thu, 5 Oct 2006 22:08:42 +0000 Subject: [PATCH] Fixed recovery bug. TregionDealloc was being called during redo(), causing an assert to fail. Without the assert, would have gone into infinite recursion. --- src/lladd/operations/regions.c | 50 +++++++++++++++++++++++++++------- test/lladd/check_regions.c | 39 ++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/src/lladd/operations/regions.c b/src/lladd/operations/regions.c index f841a6a..69b020d 100644 --- a/src/lladd/operations/regions.c +++ b/src/lladd/operations/regions.c @@ -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(); diff --git a/test/lladd/check_regions.c b/test/lladd/check_regions.c index eeb955e..51154ec 100644 --- a/test/lladd/check_regions.c +++ b/test/lladd/check_regions.c @@ -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);