8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 22:43:04 +01:00

Backported fix for CORE-1657: AV with long inactive read-only read-commited transaction

This commit is contained in:
alexpeshkoff 2007-12-19 13:22:39 +00:00
parent c73581bddc
commit b531d60e80

View File

@ -391,16 +391,16 @@ static ULONG cache_transactions(thread_db* tdbb, TxPageCache** tip_cache_ptr,
#ifdef SUPERSERVER_V2 #ifdef SUPERSERVER_V2
const ULONG top = dbb->dbb_next_transaction; const ULONG top = dbb->dbb_next_transaction;
oldest = MAX(oldest, dbb->dbb_oldest_transaction); const ULONG hdr_oldest = dbb->dbb_oldest_transaction;
#else #else
WIN window(HEADER_PAGE); WIN window(HEADER_PAGE);
const Ods::header_page* header = const Ods::header_page* header =
(Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header); (Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_read, pag_header);
const ULONG top = header->hdr_next_transaction; const ULONG top = header->hdr_next_transaction;
const ULONG hdr_oldest = (ULONG) header->hdr_oldest_transaction; const ULONG hdr_oldest = (ULONG) header->hdr_oldest_transaction;
oldest = MAX(oldest, hdr_oldest);
CCH_RELEASE(tdbb, &window); CCH_RELEASE(tdbb, &window);
#endif #endif
oldest = MAX(oldest, hdr_oldest);
/* allocate TxPageCache blocks to hold all transaction states -- /* allocate TxPageCache blocks to hold all transaction states --
assign one TxPageCache block per page to simplify cache maintenance */ assign one TxPageCache block per page to simplify cache maintenance */
@ -421,11 +421,23 @@ static ULONG cache_transactions(thread_db* tdbb, TxPageCache** tip_cache_ptr,
TRA_get_inventory(tdbb, NULL, oldest, top); TRA_get_inventory(tdbb, NULL, oldest, top);
#ifdef SUPERSERVER_V2 // hvlad: cache_transactions returns number of oldest transaction
return dbb->dbb_oldest_transaction; // just refreshed from header page. No need to cache TIP pages below it
#else // Moreover out tip cache can now contain an gap between last
// cached tip page and new pages if our process was idle for long time
for (TxPageCache* tip_cache = dbb->dbb_tip_cache;
tip_cache && (tip_cache->tpc_base + trans_per_tip < hdr_oldest);
tip_cache = dbb->dbb_tip_cache)
{
dbb->dbb_tip_cache = tip_cache->tpc_next;
// hvlad: commented out in 2.0 release branch, enabled and required
// additional testing in 2.1
// delete tip_cache;
}
return hdr_oldest; return hdr_oldest;
#endif
} }
@ -461,23 +473,6 @@ static int extend_cache(thread_db* tdbb, SLONG number)
const ULONG oldest = cache_transactions(tdbb, tip_cache_ptr, const ULONG oldest = cache_transactions(tdbb, tip_cache_ptr,
tip_cache->tpc_base + trans_per_tip); tip_cache->tpc_base + trans_per_tip);
// hvlad: cache_transactions returns number of oldest transaction
// just refreshed from header page. No need to cache TIP pages below it
// Moreover out tip cache can now contain an gap between last
// cached tip page and new pages if our process was idle for long time
for (tip_cache = dbb->dbb_tip_cache;
tip_cache && (tip_cache->tpc_base + trans_per_tip < oldest);
tip_cache = dbb->dbb_tip_cache)
{
dbb->dbb_tip_cache = tip_cache->tpc_next;
// hvlad: commented out in 2.0 release branch, enabled and required
// additional testing in 2.1
// delete tip_cache;
}
if (number < oldest) if (number < oldest)
return tra_committed; return tra_committed;