@@ -215,17 +215,6 @@ CommitNumber TipCache::cacheState(TraNumber number)
215215 if (!block)
216216 return CN_PREHISTORIC ;
217217
218- // Check if the block is not obsolete at the moment
219- oldest = header->oldest_transaction .load (std::memory_order_relaxed);
220-
221- if (number < oldest)
222- {
223- gds__log (" Re-created obsolete TPC block %u. For transaction %" UQUADFORMAT " , oldest %." UQUADFORMAT ,
224- blockNumber, number, oldest);
225-
226- return CN_PREHISTORIC ;
227- }
228-
229218 // Barrier is not needed here when we are reading state from cache
230219 // because all callers of this function are prepared to handle
231220 // slightly out-dated information and will take slow path if necessary
@@ -540,9 +529,32 @@ TipCache::TransactionStatusBlock* TipCache::getTransactionStatusBlock(GlobalTpcH
540529 else
541530 {
542531 // Check if block might be too old to be created.
543- TraNumber oldest = header->oldest_transaction .load (std::memory_order_relaxed);
532+ const TraNumber oldest = header->oldest_transaction .load (std::memory_order_relaxed);
544533 if (blockNumber >= oldest / m_transactionsPerBlock)
534+ {
545535 block = createTransactionStatusBlock (header->tpc_block_size , blockNumber);
536+
537+ // Check if the block is not obsolete at the moment
538+ const TraNumber oldest2 = header->oldest_transaction .load (std::memory_order_relaxed);
539+
540+ if (blockNumber < oldest2 / m_transactionsPerBlock)
541+ {
542+ gds__log (" TPC: Re-created obsolete block %u. Oldest before %" UQUADFORMAT " (%u), oldest after %" UQUADFORMAT " (%u)" ,
543+ blockNumber,
544+ oldest, oldest / m_transactionsPerBlock,
545+ oldest2, oldest2 / m_transactionsPerBlock);
546+
547+ if (m_blocks_memory.locate (blockNumber))
548+ {
549+ auto data = m_blocks_memory.current ();
550+ m_blocks_memory.fastRemove ();
551+ delete data;
552+ }
553+
554+ sync.unlock ();
555+ return nullptr ;
556+ }
557+ }
546558 else
547559 sync.unlock ();
548560 }
@@ -652,6 +664,13 @@ CommitNumber TipCache::setState(TraNumber number, int state)
652664 // We verified for all other cases, transaction must either be Active or in Limbo
653665 fb_assert (oldStateCn == CN_ACTIVE || oldStateCn == CN_LIMBO );
654666
667+ // Paranoid check against CN_ACTIVE state got from obsolete re-created TPC block.
668+ if ((oldStateCn == CN_ACTIVE ) && (number < header->oldest_transaction .load (std::memory_order_relaxed)))
669+ {
670+ gds__log (" TPC: Not generated new CN for old committed transaction %" UQUADFORMAT , number);
671+ return CN_PREHISTORIC ;
672+ }
673+
655674 // Generate new commit number
656675 CommitNumber newCommitNumber = header->latest_commit_number ++ + 1 ;
657676
0 commit comments