validation: MaybeRebalanceCaches when chain leaves IBD

Check to see if we need to rebalance caches across chainstates when
a chain leaves IBD.
This commit is contained in:
James O'Beirne 2023-05-01 17:39:28 -04:00
parent 434495a8c1
commit 9f2318c76c

View file

@ -3192,6 +3192,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
CBlockIndex *pindexMostWork = nullptr; CBlockIndex *pindexMostWork = nullptr;
CBlockIndex *pindexNewTip = nullptr; CBlockIndex *pindexNewTip = nullptr;
bool exited_ibd{false};
do { do {
// Block until the validation queue drains. This should largely // Block until the validation queue drains. This should largely
// never happen in normal operation, however may happen during // never happen in normal operation, however may happen during
@ -3205,6 +3206,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
LOCK(cs_main); LOCK(cs_main);
// Lock transaction pool for at least as long as it takes for connectTrace to be consumed // Lock transaction pool for at least as long as it takes for connectTrace to be consumed
LOCK(MempoolMutex()); LOCK(MempoolMutex());
const bool was_in_ibd = m_chainman.IsInitialBlockDownload();
CBlockIndex* starting_tip = m_chain.Tip(); CBlockIndex* starting_tip = m_chain.Tip();
bool blocks_connected = false; bool blocks_connected = false;
do { do {
@ -3252,16 +3254,21 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
if (!blocks_connected) return true; if (!blocks_connected) return true;
const CBlockIndex* pindexFork = m_chain.FindFork(starting_tip); const CBlockIndex* pindexFork = m_chain.FindFork(starting_tip);
bool fInitialDownload = m_chainman.IsInitialBlockDownload(); bool still_in_ibd = m_chainman.IsInitialBlockDownload();
if (was_in_ibd && !still_in_ibd) {
// Active chainstate has exited IBD.
exited_ibd = true;
}
// Notify external listeners about the new tip. // Notify external listeners about the new tip.
// Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected // Enqueue while holding cs_main to ensure that UpdatedBlockTip is called in the order in which blocks are connected
if (pindexFork != pindexNewTip) { if (pindexFork != pindexNewTip) {
// Notify ValidationInterface subscribers // Notify ValidationInterface subscribers
GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, fInitialDownload); GetMainSignals().UpdatedBlockTip(pindexNewTip, pindexFork, still_in_ibd);
// Always notify the UI if a new block tip was connected // Always notify the UI if a new block tip was connected
if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(fInitialDownload), *pindexNewTip))) { if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(still_in_ibd), *pindexNewTip))) {
// Just breaking and returning success for now. This could // Just breaking and returning success for now. This could
// be changed to bubble up the kernel::Interrupted value to // be changed to bubble up the kernel::Interrupted value to
// the caller so the caller could distinguish between // the caller so the caller could distinguish between
@ -3272,6 +3279,13 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
} }
// When we reach this point, we switched to a new tip (stored in pindexNewTip). // When we reach this point, we switched to a new tip (stored in pindexNewTip).
if (exited_ibd) {
// If a background chainstate is in use, we may need to rebalance our
// allocation of caches once a chainstate exits initial block download.
LOCK(::cs_main);
m_chainman.MaybeRebalanceCaches();
}
if (WITH_LOCK(::cs_main, return m_disabled)) { if (WITH_LOCK(::cs_main, return m_disabled)) {
// Background chainstate has reached the snapshot base block, so exit. // Background chainstate has reached the snapshot base block, so exit.
break; break;