Skip to content

Commit

Permalink
Fixed bug CORE-3515 : Index corruption. Validation put "missing entri…
Browse files Browse the repository at this point in the history
…es" message into firebird.log
  • Loading branch information
hvlad committed Jun 5, 2011
1 parent e97bd14 commit 5ac9733
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 35 deletions.
20 changes: 20 additions & 0 deletions src/jrd/dpm.epp
Expand Up @@ -193,6 +193,26 @@ void DPM_backout( thread_db* tdbb, record_param* rpb)
}


void DPM_backout_mark(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
{
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
CHECK_DBB(dbb);

WIN *window = &rpb->getWindow(tdbb);
CCH_MARK(tdbb, window);

data_page* page = (data_page*) window->win_buffer;
data_page::dpg_repeat* index = page->dpg_rpt + rpb->rpb_line;
rhd* header = (rhd*) ((SCHAR *) page + index->dpg_offset);

header->rhd_flags |= rhd_gc_active;
header->rhd_transaction = transaction->tra_number;

CCH_RELEASE(tdbb, window);
}


double DPM_cardinality(thread_db* tdbb, jrd_rel* relation, const Format* format)
{
/**************************************
Expand Down
1 change: 1 addition & 0 deletions src/jrd/dpm_proto.h
Expand Up @@ -43,6 +43,7 @@ namespace Ods {

Ods::pag* DPM_allocate(Jrd::thread_db*, Jrd::win*);
void DPM_backout(Jrd::thread_db*, Jrd::record_param*);
void DPM_backout_mark(Jrd::thread_db*, Jrd::record_param*, const Jrd::jrd_tra*);
double DPM_cardinality(Jrd::thread_db*, Jrd::jrd_rel*, const Jrd::Format*);
bool DPM_chain(Jrd::thread_db*, Jrd::record_param*, Jrd::record_param*);
int DPM_compress(Jrd::thread_db*, Ods::data_page*);
Expand Down
9 changes: 3 additions & 6 deletions src/jrd/idx.cpp
Expand Up @@ -753,12 +753,9 @@ void IDX_garbage_collect(thread_db* tdbb,
for (++stack2; stack2.hasData(); ++stack2)
{
Record* rec2 = stack2.object();
if (rec2->rec_number == rec1->rec_number)
{
BTR_key(tdbb, rpb->rpb_relation, rec2, &idx, &key2, 0, false);
if (key_equal(&key1, &key2))
break;
}
BTR_key(tdbb, rpb->rpb_relation, rec2, &idx, &key2, 0, false);
if (key_equal(&key1, &key2))
break;
}
if (stack2.hasData())
continue;
Expand Down
92 changes: 63 additions & 29 deletions src/jrd/vio.cpp
Expand Up @@ -299,6 +299,9 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
Record* old_data = NULL;
Record* gc_rec2 = NULL;

bool samePage;
bool deleted;

if ((temp.rpb_flags & rpb_deleted) && (!(temp.rpb_flags & rpb_delta)))
CCH_RELEASE(tdbb, &temp.getWindow(tdbb));
else
Expand Down Expand Up @@ -389,25 +392,53 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)

if (!rpb->rpb_b_page)
{
delete_record(tdbb, rpb, (SLONG) 0, 0);
if (!(rpb->rpb_flags & rpb_deleted))
{
DPM_backout_mark(tdbb, rpb, transaction);

RecordStack empty_staying;
BLB_garbage_collect(tdbb, going, empty_staying, rpb->rpb_page, relation);
IDX_garbage_collect(tdbb, rpb, going, empty_staying);
going.pop();

if (!DPM_get(tdbb, rpb, LCK_write))
BUGCHECK(186); // msg 186 record disappeared
}

delete_record(tdbb, rpb, (SLONG) 0, 0);
goto gc_cleanup;
}

// If both record versions are on the same page, things are a little simpler

if (rpb->rpb_page == temp.rpb_page && !rpb->rpb_prior)
samePage = (rpb->rpb_page == temp.rpb_page && !rpb->rpb_prior);
deleted = (temp2.rpb_flags & rpb_deleted);
if (!deleted)
{
DPM_backout_mark(tdbb, rpb, transaction);

rpb->rpb_prior = NULL;
list_staying(tdbb, rpb, staying);
BLB_garbage_collect(tdbb, going, staying, rpb->rpb_page, relation);
IDX_garbage_collect(tdbb, rpb, going, staying);

if (going.hasData())
{
going.pop();
}

clearRecordStack(staying);

if (!DPM_get(tdbb, rpb, LCK_write))
BUGCHECK(186); // msg 186 record disappeared
}

if (samePage)
{
DPM_backout(tdbb, rpb);
if (temp2.rpb_flags & rpb_deleted)
goto gc_cleanup;
delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0);
if (!deleted) {
delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0);
}
}
else
{
Expand All @@ -424,20 +455,18 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
rpb->rpb_transaction_nr = temp.rpb_transaction_nr;
rpb->rpb_format_number = temp.rpb_format_number;

if (temp2.rpb_flags & rpb_deleted)
if (deleted)
{
replace_record(tdbb, rpb, 0, transaction);
if (!DPM_fetch(tdbb, &temp, LCK_write))
BUGCHECK(291); // msg 291 cannot find record back version
delete_record(tdbb, &temp, rpb->rpb_page, 0);
goto gc_cleanup;
}
else
{
// There is cleanup to be done. Bring the old version forward first

// There is cleanup to be done. Bring the old version forward first

rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active);
DPM_update(tdbb, rpb, 0, transaction);
delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0);
rpb->rpb_flags &= ~(rpb_fragment | rpb_incomplete | rpb_chained | rpb_gc_active);
DPM_update(tdbb, rpb, 0, transaction);
delete_tail(tdbb, &temp2, rpb->rpb_page, 0, 0);
}

// Next, delete the old copy of the now current version.

Expand All @@ -446,19 +475,6 @@ void VIO_backout(thread_db* tdbb, record_param* rpb, const jrd_tra* transaction)
delete_record(tdbb, &temp, rpb->rpb_page, 0);
}


rpb->rpb_prior = NULL;
list_staying(tdbb, rpb, staying);
BLB_garbage_collect(tdbb, going, staying, rpb->rpb_page, relation);
IDX_garbage_collect(tdbb, rpb, going, staying);

if (going.hasData())
{
going.pop();
}

clearRecordStack(staying);

// Return relation garbage collect record blocks to vector.

gc_cleanup:
Expand Down Expand Up @@ -4244,6 +4260,7 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
SET_TDBB(tdbb);

Record* data = rpb->rpb_prior;
Record* backout_rec = NULL;
ULONG next_page = rpb->rpb_page;
USHORT next_line = rpb->rpb_line;
int max_depth = 0;
Expand All @@ -4261,6 +4278,8 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
if (!DPM_fetch(tdbb, &temp, LCK_read))
{
clearRecordStack(staying);
delete backout_rec;
backout_rec = NULL;
return;
}

Expand All @@ -4271,6 +4290,8 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
temp.rpb_flags != rpb->rpb_flags)
{
clearRecordStack(staying);
delete backout_rec;
backout_rec = NULL;
next_page = temp.rpb_page;
next_line = temp.rpb_line;
max_depth = 0;
Expand All @@ -4293,6 +4314,8 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
fb_utils::init_status(tdbb->tdbb_status_vector);

clearRecordStack(staying);
delete backout_rec;
backout_rec = NULL;
next_page = rpb->rpb_page;
next_line = rpb->rpb_line;
max_depth = 0;
Expand Down Expand Up @@ -4321,8 +4344,18 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
}
else
{
// VIO_data below could change the flags
const bool backout = (temp.rpb_flags & rpb_gc_active);
VIO_data(tdbb, &temp, tdbb->getDefaultPool());
staying.push(temp.rpb_record);
if (!backout)
{
staying.push(temp.rpb_record);
}
else
{
fb_assert(!backout_rec);
backout_rec = temp.rpb_record;
}
data = temp.rpb_record;
}
max_depth = depth;
Expand All @@ -4346,6 +4379,7 @@ static void list_staying(thread_db* tdbb, record_param* rpb, RecordStack& stayin
delete staying.pop();
}
}
delete backout_rec;
}


Expand Down

0 comments on commit 5ac9733

Please sign in to comment.