From e4b66b962e7f4eaf85c1413eeae6c29df5ab8591 Mon Sep 17 00:00:00 2001 From: hvlad Date: Wed, 14 Feb 2007 08:58:07 +0000 Subject: [PATCH] Fixed CORE-1127 : Circular index references in corrupt database causes fbserver to loop infinitely. Thanks to Diane Downie --- src/jrd/jrd.h | 3 ++- src/jrd/validation.cpp | 15 ++++++++++++++- src/jrd/vio.cpp | 11 +++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/jrd/jrd.h b/src/jrd/jrd.h index b6f3bc7b0d..fd43866ae3 100644 --- a/src/jrd/jrd.h +++ b/src/jrd/jrd.h @@ -437,7 +437,8 @@ const int VAL_TIP_CONFUSED = 21; const int VAL_REL_CHAIN_ORPHANS = 22; const int VAL_INDEX_MISSING_ROWS = 23; const int VAL_INDEX_ORPHAN_CHILD = 24; -const int VAL_MAX_ERROR = 25; +const int VAL_INDEX_CYCLE = 25; +const int VAL_MAX_ERROR = 26; // diff --git a/src/jrd/validation.cpp b/src/jrd/validation.cpp index a91b66ad60..12fdd2693d 100644 --- a/src/jrd/validation.cpp +++ b/src/jrd/validation.cpp @@ -647,7 +647,8 @@ static const TEXT msg_table[][66] = { "Transaction inventory pages confused, sequence %ld", "Relation has %ld orphan backversions (%ld in use)", "Index %d is corrupt (missing entries)", - "Index %d has orphan child page at page %ld" + "Index %d has orphan child page at page %ld", + "Index %d has a circular reference at page %ld" }; @@ -1430,11 +1431,16 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation, SCHAR flags = 0; UCHAR* pointer; IndexNode node, lastNode; + PageBitmap visited_pages; // used to check circular page references, Diane Downie 2/9/07 while (next) { WIN window(-1); btree_page* page = 0; fetch_page(tdbb, control, next, pag_index, &window, &page); + + // remember each page for circular reference detection + visited_pages.set(next); + if ((next != page_number) && (page->btr_header.pag_flags & BTR_FLAG_COPY_MASK) != (flags & BTR_FLAG_COPY_MASK)) @@ -1686,6 +1692,13 @@ static RTN walk_index(thread_db* tdbb, vdr* control, jrd_rel* relation, nullKeyHandled = !(unique && null_key); } + // check for circular referenes + if (next && visited_pages.test(next)) + { + corrupt(tdbb, control, VAL_INDEX_CYCLE, relation, + id + 1, next); + next = 0; + } CCH_RELEASE(tdbb, &window); } diff --git a/src/jrd/vio.cpp b/src/jrd/vio.cpp index a816bf40a3..3daa33e963 100644 --- a/src/jrd/vio.cpp +++ b/src/jrd/vio.cpp @@ -768,6 +768,17 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb, RecordSource* CCH_RELEASE(tdbb, &rpb->rpb_window); return false; } + + // hvlad: if i'm garbage collector i don't need to read backversion of active + // record. Just do notify self about it (if background policy enabled) + if (attachment->att_flags & ATT_garbage_collector) + { + // VIO_chase_record_version + notify_garbage_collector(tdbb, rpb); + CCH_RELEASE(tdbb, &rpb->rpb_window); + return false; + } + if (!(rpb->rpb_flags & rpb_delta)) { rpb->rpb_prior = NULL; /* Fetch a back version. If a latch timeout occurs, refetch the