validation: pruning for multiple chainstates

Introduces ChainstateManager::GetPruneRange().

The prune budget is split evenly between the number of chainstates,
however the prune budget may be exceeded if the resulting shares are
beneath `MIN_DISK_SPACE_FOR_BLOCK_FILES`.
This commit is contained in:
James O'Beirne
2019-09-16 16:34:45 -04:00
committed by James O'Beirne
parent 373cf91531
commit 1019c39982
5 changed files with 102 additions and 30 deletions

View File

@@ -69,6 +69,7 @@
#include <optional>
#include <string>
#include <utility>
#include <tuple>
using kernel::CCoinsStats;
using kernel::CoinStatsHashType;
@@ -2552,11 +2553,14 @@ bool Chainstate::FlushStateToDisk(
if (nManualPruneHeight > 0) {
LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune (manual)", BCLog::BENCH);
m_blockman.FindFilesToPruneManual(setFilesToPrune, std::min(last_prune, nManualPruneHeight), m_chain.Height());
m_blockman.FindFilesToPruneManual(
setFilesToPrune,
std::min(last_prune, nManualPruneHeight),
*this, m_chainman);
} else {
LOG_TIME_MILLIS_WITH_CATEGORY("find files to prune", BCLog::BENCH);
m_blockman.FindFilesToPrune(setFilesToPrune, m_chainman.GetParams().PruneAfterHeight(), m_chain.Height(), last_prune, m_chainman.IsInitialBlockDownload());
m_blockman.FindFilesToPrune(setFilesToPrune, last_prune, *this, m_chainman);
m_blockman.m_check_for_pruning = false;
}
if (!setFilesToPrune.empty()) {
@@ -5939,3 +5943,30 @@ Chainstate& ChainstateManager::GetChainstateForIndexing()
// indexed.
return (this->GetAll().size() > 1) ? *m_ibd_chainstate : *m_active_chainstate;
}
std::pair<int, int> ChainstateManager::GetPruneRange(const Chainstate& chainstate, int last_height_can_prune)
{
if (chainstate.m_chain.Height() <= 0) {
return {0, 0};
}
int prune_start{0};
if (this->GetAll().size() > 1 && m_snapshot_chainstate.get() == &chainstate) {
// Leave the blocks in the background IBD chain alone if we're pruning
// the snapshot chain.
prune_start = *Assert(GetSnapshotBaseHeight()) + 1;
}
int max_prune = std::max<int>(
0, chainstate.m_chain.Height() - static_cast<int>(MIN_BLOCKS_TO_KEEP));
// last block to prune is the lesser of (caller-specified height, MIN_BLOCKS_TO_KEEP from the tip)
//
// While you might be tempted to prune the background chainstate more
// aggressively (i.e. fewer MIN_BLOCKS_TO_KEEP), this won't work with index
// building - specifically blockfilterindex requires undo data, and if
// we don't maintain this trailing window, we hit indexing failures.
int prune_end = std::min(last_height_can_prune, max_prune);
return {prune_start, prune_end};
}