Merge bitcoin/bitcoin#32414: validation: periodically flush dbcache during reindex-chainstate

c1e554d3e5 refactor: consolidate 3 separate locks into one block (Andrew Toth)
41479ed1d2 test: add test for periodic flush inside ActivateBestChain (Andrew Toth)
84820561dc validation: periodically flush dbcache during reindex-chainstate (Andrew Toth)

Pull request description:

  After #30611 we periodically do a non-erasing flush of the dbcache to disk roughly every hour during IBD.
  The intention was to also do this periodic flush during reindex-chainstate, so we would not risk losing progress during a system failure when reindexing with a high dbcache value.

  It was discovered that reindex-chainstate does not perform a PERIODIC flush until it has already reached the tip. Since reindexing to tip usually happens within 24 hours, this behaviour was unnoticed with the previous periodic flush interval. Note that reindex-chainstate still does IF_NEEDED flushes during `ConnectBlock`, so this also would not be noticed when running with a lower dbcache value.

  This patch moves the PERIODIC flush from after the outer loop in `ActivateBestChain` to inside the outer loop after we release `cs_main`. This will periodically flush during IBD, reindex-chainstate, and steady state.

ACKs for top commit:
  l0rinc:
    ACK c1e554d3e5
  achow101:
    ACK c1e554d3e5
  sipa:
    utACK c1e554d3e5

Tree-SHA512: c447ad03e16c9978b8ed2c285b38e1b4c56e7778ab93b6f64435116f47b8931017f5f56ab53eb61656693146aaced776f666af573a41ab28e8f2b6d8657fa756
This commit is contained in:
Ava Chow
2025-12-11 11:56:01 -08:00
2 changed files with 75 additions and 13 deletions

View File

@@ -3486,14 +3486,24 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
} // release cs_main
// 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();
bool disabled{false};
{
LOCK(m_chainman.GetMutex());
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.
m_chainman.MaybeRebalanceCaches();
}
// Write changes periodically to disk, after relay.
if (!FlushStateToDisk(state, FlushStateMode::PERIODIC)) {
return false;
}
disabled = m_disabled;
}
if (WITH_LOCK(::cs_main, return m_disabled)) {
if (disabled) {
// Background chainstate has reached the snapshot base block, so exit.
// Restart indexes to resume indexing for all blocks unique to the snapshot
@@ -3517,11 +3527,6 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
m_chainman.CheckBlockIndex();
// Write changes periodically to disk, after relay.
if (!FlushStateToDisk(state, FlushStateMode::PERIODIC)) {
return false;
}
return true;
}