init: add utxo snapshot detection

Add functionality for activating a snapshot-based chainstate if one is
detected on-disk.

Also cautiously initialize chainstate cache usages so that we don't
somehow blow past our cache allowances during initialization, then
rebalance at the end of init.

Co-authored-by: Russell Yanofsky <russ@yanofsky.org>
This commit is contained in:
James O'Beirne
2022-04-20 17:40:01 -04:00
parent f9f1735f13
commit 252abd1e8b
7 changed files with 87 additions and 34 deletions

View File

@@ -48,10 +48,15 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
}
LOCK(cs_main);
chainman.InitializeChainstate(options.mempool);
chainman.m_total_coinstip_cache = cache_sizes.coins;
chainman.m_total_coinsdb_cache = cache_sizes.coins_db;
// Load the fully validated chainstate.
chainman.InitializeChainstate(options.mempool);
// Load a chain created from a UTXO snapshot, if any exist.
chainman.DetectSnapshotChainstate(options.mempool);
auto& pblocktree{chainman.m_blockman.m_block_tree_db};
// new CBlockTreeDB tries to delete the existing file, which
// fails if it's still open from the previous loop. Close it first:
@@ -98,12 +103,20 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
}
// Conservative value which is arbitrarily chosen, as it will ultimately be changed
// by a call to `chainman.MaybeRebalanceCaches()`. We just need to make sure
// that the sum of the two caches (40%) does not exceed the allowable amount
// during this temporary initialization state.
double init_cache_fraction = 0.2;
// At this point we're either in reindex or we've loaded a useful
// block tree into BlockIndex()!
for (Chainstate* chainstate : chainman.GetAll()) {
LogPrintf("Initializing chainstate %s\n", chainstate->ToString());
chainstate->InitCoinsDB(
/*cache_size_bytes=*/cache_sizes.coins_db,
/*cache_size_bytes=*/chainman.m_total_coinsdb_cache * init_cache_fraction,
/*in_memory=*/options.coins_db_in_memory,
/*should_wipe=*/options.reindex || options.reindex_chainstate);
@@ -125,7 +138,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
}
// The on-disk coinsdb is now in a good state, create the cache
chainstate->InitCoinsCache(cache_sizes.coins);
chainstate->InitCoinsCache(chainman.m_total_coinstip_cache * init_cache_fraction);
assert(chainstate->CanFlushToDisk());
if (!is_coinsview_empty(chainstate)) {
@@ -146,6 +159,11 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
};
}
// Now that chainstates are loaded and we're able to flush to
// disk, rebalance the coins caches to desired levels based
// on the condition of each chainstate.
chainman.MaybeRebalanceCaches();
return {ChainstateLoadStatus::SUCCESS, {}};
}