mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-26 17:52:13 +01:00
Merge bitcoin/bitcoin#30132: indexes: Don't wipe indexes again when continuing a prior reindex
f68cba29b3be0dec7877022b18a193a3b78c1099 blockman: Replace m_reindexing with m_blockfiles_indexed (Ryan Ofsky) 1b1c6dcca0cc891bd35d29b61628c39098cd94ce test: Add functional test for continuing a reindex (TheCharlatan) 201c1a92824c71ae646d5bba9963871b1d704cc1 indexes: Don't wipe indexes again when already reindexing (TheCharlatan) 804f09dfa116300914e2aeef05ed9710dd504e8c kernel: Add less confusing reindex options (Ryan Ofsky) e17255322378076edce3ef6f06cd36ca58d2e236 validation: Remove needs_init from LoadBlockIndex (TheCharlatan) 533eab7d67d78f217f74909662133086b79ea808 bugfix: Streamline setting reindex option (TheCharlatan) Pull request description: When restarting `bitcoind` during an ongoing reindex without setting the `-reindex` flag again, the block and coins db is left intact, but any data from the optional indexes is discarded. While not a bug per se, wiping the data again is wasteful, both in terms of having to write it again, as well as potentially leading to longer startup times. So keep the index data instead when continuing a prior reindex. Also includes a bugfix and smaller code cleanups around the reindexing code. The bug was introduced in b47bd959207e82555f07e028cc2246943d32d4c3: "kernel: De-globalize fReindex". ACKs for top commit: stickies-v: ACK f68cba29b3be0dec7877022b18a193a3b78c1099 fjahr: Code review ACK f68cba29b3be0dec7877022b18a193a3b78c1099 furszy: Code review ACK f68cba29b3be0dec7877022b18a193a3b78c1099 ryanofsky: Code review ACK f68cba29b3be0dec7877022b18a193a3b78c1099. Only changes since last review were cherry-picking suggested commits that rename variables, improving comments, and making some tweaks to test code. Tree-SHA512: b252228cc76e9f1eaac56d5bd9e4eac23408e0fc04aeffd97a85417f046229364673ee1ca7410b9b6e7b692b03f13ece17c42a10176da0d7e975a8915deb98ca
This commit is contained in:
commit
b1ba1b178f
@ -151,7 +151,7 @@ int main(int argc, char* argv[])
|
||||
{
|
||||
LOCK(chainman.GetMutex());
|
||||
std::cout
|
||||
<< "\t" << "Reindexing: " << std::boolalpha << chainman.m_blockman.m_reindexing.load() << std::noboolalpha << std::endl
|
||||
<< "\t" << "Blockfiles Indexed: " << std::boolalpha << chainman.m_blockman.m_blockfiles_indexed.load() << std::noboolalpha << std::endl
|
||||
<< "\t" << "Snapshot Active: " << std::boolalpha << chainman.IsSnapshotActive() << std::noboolalpha << std::endl
|
||||
<< "\t" << "Active Height: " << chainman.ActiveHeight() << std::endl
|
||||
<< "\t" << "Active IBD: " << std::boolalpha << chainman.IsInitialBlockDownload() << std::noboolalpha << std::endl;
|
||||
|
22
src/init.cpp
22
src/init.cpp
@ -1482,7 +1482,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
|
||||
node.notifications = std::make_unique<KernelNotifications>(*Assert(node.shutdown), node.exit_status);
|
||||
ReadNotificationArgs(args, *node.notifications);
|
||||
bool fReindexChainState = args.GetBoolArg("-reindex-chainstate", false);
|
||||
ChainstateManager::Options chainman_opts{
|
||||
.chainparams = chainparams,
|
||||
.datadir = args.GetDataDirNet(),
|
||||
@ -1531,6 +1530,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
}
|
||||
LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of unused mempool space)\n", cache_sizes.coins * (1.0 / 1024 / 1024), mempool_opts.max_size_bytes * (1.0 / 1024 / 1024));
|
||||
|
||||
bool do_reindex{args.GetBoolArg("-reindex", false)};
|
||||
const bool do_reindex_chainstate{args.GetBoolArg("-reindex-chainstate", false)};
|
||||
|
||||
for (bool fLoaded = false; !fLoaded && !ShutdownRequested(node);) {
|
||||
node.mempool = std::make_unique<CTxMemPool>(mempool_opts);
|
||||
|
||||
@ -1558,8 +1560,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
|
||||
node::ChainstateLoadOptions options;
|
||||
options.mempool = Assert(node.mempool.get());
|
||||
options.reindex = chainman.m_blockman.m_reindexing;
|
||||
options.reindex_chainstate = fReindexChainState;
|
||||
options.wipe_block_tree_db = do_reindex;
|
||||
options.wipe_chainstate_db = do_reindex || do_reindex_chainstate;
|
||||
options.prune = chainman.m_blockman.IsPruneMode();
|
||||
options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
|
||||
options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
|
||||
@ -1600,13 +1602,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
|
||||
if (!fLoaded && !ShutdownRequested(node)) {
|
||||
// first suggest a reindex
|
||||
if (!options.reindex) {
|
||||
if (!do_reindex) {
|
||||
bool fRet = uiInterface.ThreadSafeQuestion(
|
||||
error + Untranslated(".\n\n") + _("Do you want to rebuild the block database now?"),
|
||||
error.original + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
|
||||
"", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
|
||||
if (fRet) {
|
||||
chainman.m_blockman.m_reindexing = true;
|
||||
do_reindex = true;
|
||||
if (!Assert(node.shutdown)->reset()) {
|
||||
LogPrintf("Internal error: failed to reset shutdown signal.\n");
|
||||
}
|
||||
@ -1639,17 +1641,17 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
// ********************************************************* Step 8: start indexers
|
||||
|
||||
if (args.GetBoolArg("-txindex", DEFAULT_TXINDEX)) {
|
||||
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), cache_sizes.tx_index, false, chainman.m_blockman.m_reindexing);
|
||||
g_txindex = std::make_unique<TxIndex>(interfaces::MakeChain(node), cache_sizes.tx_index, false, do_reindex);
|
||||
node.indexes.emplace_back(g_txindex.get());
|
||||
}
|
||||
|
||||
for (const auto& filter_type : g_enabled_filter_types) {
|
||||
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, cache_sizes.filter_index, false, chainman.m_blockman.m_reindexing);
|
||||
InitBlockFilterIndex([&]{ return interfaces::MakeChain(node); }, filter_type, cache_sizes.filter_index, false, do_reindex);
|
||||
node.indexes.emplace_back(GetBlockFilterIndex(filter_type));
|
||||
}
|
||||
|
||||
if (args.GetBoolArg("-coinstatsindex", DEFAULT_COINSTATSINDEX)) {
|
||||
g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, chainman.m_blockman.m_reindexing);
|
||||
g_coin_stats_index = std::make_unique<CoinStatsIndex>(interfaces::MakeChain(node), /*cache_size=*/0, false, do_reindex);
|
||||
node.indexes.emplace_back(g_coin_stats_index.get());
|
||||
}
|
||||
|
||||
@ -1668,7 +1670,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
// if pruning, perform the initial blockstore prune
|
||||
// after any wallet rescanning has taken place.
|
||||
if (chainman.m_blockman.IsPruneMode()) {
|
||||
if (!chainman.m_blockman.m_reindexing) {
|
||||
if (chainman.m_blockman.m_blockfiles_indexed) {
|
||||
LOCK(cs_main);
|
||||
for (Chainstate* chainstate : chainman.GetAll()) {
|
||||
uiInterface.InitMessage(_("Pruning blockstore…").translated);
|
||||
@ -1694,7 +1696,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||
int chain_active_height = WITH_LOCK(cs_main, return chainman.ActiveChain().Height());
|
||||
|
||||
// On first startup, warn on low block storage space
|
||||
if (!chainman.m_blockman.m_reindexing && !fReindexChainState && chain_active_height <= 1) {
|
||||
if (!do_reindex && !do_reindex_chainstate && chain_active_height <= 1) {
|
||||
uint64_t assumed_chain_bytes{chainparams.AssumedBlockchainSize() * 1024 * 1024 * 1024};
|
||||
uint64_t additional_bytes_needed{
|
||||
chainman.m_blockman.IsPruneMode() ?
|
||||
|
@ -24,7 +24,6 @@ struct BlockManagerOpts {
|
||||
bool fast_prune{false};
|
||||
const fs::path blocks_dir;
|
||||
Notifications& notifications;
|
||||
bool reindex{false};
|
||||
};
|
||||
|
||||
} // namespace kernel
|
||||
|
@ -33,8 +33,6 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& args, BlockManager::Op
|
||||
|
||||
if (auto value{args.GetBoolArg("-fastprune")}) opts.fast_prune = *value;
|
||||
|
||||
if (auto value{args.GetBoolArg("-reindex")}) opts.reindex = *value;
|
||||
|
||||
return {};
|
||||
}
|
||||
} // namespace node
|
||||
|
@ -551,7 +551,7 @@ bool BlockManager::LoadBlockIndexDB(const std::optional<uint256>& snapshot_block
|
||||
// Check whether we need to continue reindexing
|
||||
bool fReindexing = false;
|
||||
m_block_tree_db->ReadReindexing(fReindexing);
|
||||
if (fReindexing) m_reindexing = true;
|
||||
if (fReindexing) m_blockfiles_indexed = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1182,7 +1182,7 @@ void ImportBlocks(ChainstateManager& chainman, std::vector<fs::path> vImportFile
|
||||
ImportingNow imp{chainman.m_blockman.m_importing};
|
||||
|
||||
// -reindex
|
||||
if (chainman.m_blockman.m_reindexing) {
|
||||
if (!chainman.m_blockman.m_blockfiles_indexed) {
|
||||
int nFile = 0;
|
||||
// Map of disk positions for blocks with unknown parent (only used for reindex);
|
||||
// parent hash -> child disk position, multiple children can have the same parent.
|
||||
@ -1205,7 +1205,7 @@ void ImportBlocks(ChainstateManager& chainman, std::vector<fs::path> vImportFile
|
||||
nFile++;
|
||||
}
|
||||
WITH_LOCK(::cs_main, chainman.m_blockman.m_block_tree_db->WriteReindexing(false));
|
||||
chainman.m_blockman.m_reindexing = false;
|
||||
chainman.m_blockman.m_blockfiles_indexed = true;
|
||||
LogPrintf("Reindexing finished\n");
|
||||
// To avoid ending up in a situation without genesis block, re-try initializing (no-op if reindexing worked):
|
||||
chainman.ActiveChainstate().LoadGenesisBlock();
|
||||
|
@ -267,18 +267,18 @@ public:
|
||||
explicit BlockManager(const util::SignalInterrupt& interrupt, Options opts)
|
||||
: m_prune_mode{opts.prune_target > 0},
|
||||
m_opts{std::move(opts)},
|
||||
m_interrupt{interrupt},
|
||||
m_reindexing{m_opts.reindex} {};
|
||||
m_interrupt{interrupt} {}
|
||||
|
||||
const util::SignalInterrupt& m_interrupt;
|
||||
std::atomic<bool> m_importing{false};
|
||||
|
||||
/**
|
||||
* Tracks if a reindex is currently in progress. Set to true when a reindex
|
||||
* is requested and false when reindexing completes. Its value is persisted
|
||||
* in the BlockTreeDB across restarts.
|
||||
* Whether all blockfiles have been added to the block tree database.
|
||||
* Normally true, but set to false when a reindex is requested and the
|
||||
* database is wiped. The value is persisted in the database across restarts
|
||||
* and will be false until reindexing completes.
|
||||
*/
|
||||
std::atomic_bool m_reindexing;
|
||||
std::atomic_bool m_blockfiles_indexed{true};
|
||||
|
||||
BlockMap m_block_index GUARDED_BY(cs_main);
|
||||
|
||||
@ -359,7 +359,7 @@ public:
|
||||
[[nodiscard]] uint64_t GetPruneTarget() const { return m_opts.prune_target; }
|
||||
static constexpr auto PRUNE_TARGET_MANUAL{std::numeric_limits<uint64_t>::max()};
|
||||
|
||||
[[nodiscard]] bool LoadingBlocks() const { return m_importing || m_reindexing; }
|
||||
[[nodiscard]] bool LoadingBlocks() const { return m_importing || !m_blockfiles_indexed; }
|
||||
|
||||
/** Calculate the amount of disk space the block & undo files currently use */
|
||||
uint64_t CalculateCurrentUsage();
|
||||
|
@ -45,11 +45,12 @@ static ChainstateLoadResult CompleteChainstateInitialization(
|
||||
.path = chainman.m_options.datadir / "blocks" / "index",
|
||||
.cache_bytes = static_cast<size_t>(cache_sizes.block_tree_db),
|
||||
.memory_only = options.block_tree_db_in_memory,
|
||||
.wipe_data = options.reindex,
|
||||
.wipe_data = options.wipe_block_tree_db,
|
||||
.options = chainman.m_options.block_tree_db});
|
||||
|
||||
if (options.reindex) {
|
||||
if (options.wipe_block_tree_db) {
|
||||
pblocktree->WriteReindexing(true);
|
||||
chainman.m_blockman.m_blockfiles_indexed = false;
|
||||
//If we're reindexing in prune mode, wipe away unusable block files and all undo data files
|
||||
if (options.prune) {
|
||||
chainman.m_blockman.CleanupBlockRevFiles();
|
||||
@ -60,8 +61,7 @@ static ChainstateLoadResult CompleteChainstateInitialization(
|
||||
|
||||
// LoadBlockIndex will load m_have_pruned if we've ever removed a
|
||||
// block file from disk.
|
||||
// Note that it also sets m_reindexing based on the disk flag!
|
||||
// From here on, m_reindexing and options.reindex values may be different!
|
||||
// Note that it also sets m_blockfiles_indexed based on the disk flag!
|
||||
if (!chainman.LoadBlockIndex()) {
|
||||
if (chainman.m_interrupt) return {ChainstateLoadStatus::INTERRUPTED, {}};
|
||||
return {ChainstateLoadStatus::FAILURE, _("Error loading block database")};
|
||||
@ -84,12 +84,12 @@ static ChainstateLoadResult CompleteChainstateInitialization(
|
||||
// If we're not mid-reindex (based on disk + args), add a genesis block on disk
|
||||
// (otherwise we use the one already on disk).
|
||||
// This is called again in ImportBlocks after the reindex completes.
|
||||
if (!chainman.m_blockman.m_reindexing && !chainman.ActiveChainstate().LoadGenesisBlock()) {
|
||||
if (chainman.m_blockman.m_blockfiles_indexed && !chainman.ActiveChainstate().LoadGenesisBlock()) {
|
||||
return {ChainstateLoadStatus::FAILURE, _("Error initializing block database")};
|
||||
}
|
||||
|
||||
auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||
return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
|
||||
return options.wipe_chainstate_db || chainstate->CoinsTip().GetBestBlock().IsNull();
|
||||
};
|
||||
|
||||
assert(chainman.m_total_coinstip_cache > 0);
|
||||
@ -110,7 +110,7 @@ static ChainstateLoadResult CompleteChainstateInitialization(
|
||||
chainstate->InitCoinsDB(
|
||||
/*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);
|
||||
/*should_wipe=*/options.wipe_chainstate_db);
|
||||
|
||||
if (options.coins_error_cb) {
|
||||
chainstate->CoinsErrorCatcher().AddReadErrCallback(options.coins_error_cb);
|
||||
@ -142,7 +142,7 @@ static ChainstateLoadResult CompleteChainstateInitialization(
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.reindex) {
|
||||
if (!options.wipe_block_tree_db) {
|
||||
auto chainstates{chainman.GetAll()};
|
||||
if (std::any_of(chainstates.begin(), chainstates.end(),
|
||||
[](const Chainstate* cs) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return cs->NeedsRedownload(); })) {
|
||||
@ -188,7 +188,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
|
||||
// Load a chain created from a UTXO snapshot, if any exist.
|
||||
bool has_snapshot = chainman.DetectSnapshotChainstate();
|
||||
|
||||
if (has_snapshot && (options.reindex || options.reindex_chainstate)) {
|
||||
if (has_snapshot && options.wipe_chainstate_db) {
|
||||
LogPrintf("[snapshot] deleting snapshot chainstate due to reindexing\n");
|
||||
if (!chainman.DeleteSnapshotChainstate()) {
|
||||
return {ChainstateLoadStatus::FAILURE_FATAL, Untranslated("Couldn't remove snapshot chainstate.")};
|
||||
@ -247,7 +247,7 @@ ChainstateLoadResult LoadChainstate(ChainstateManager& chainman, const CacheSize
|
||||
ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const ChainstateLoadOptions& options)
|
||||
{
|
||||
auto is_coinsview_empty = [&](Chainstate* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
|
||||
return options.reindex || options.reindex_chainstate || chainstate->CoinsTip().GetBestBlock().IsNull();
|
||||
return options.wipe_chainstate_db || chainstate->CoinsTip().GetBestBlock().IsNull();
|
||||
};
|
||||
|
||||
LOCK(cs_main);
|
||||
|
@ -22,8 +22,13 @@ struct ChainstateLoadOptions {
|
||||
CTxMemPool* mempool{nullptr};
|
||||
bool block_tree_db_in_memory{false};
|
||||
bool coins_db_in_memory{false};
|
||||
bool reindex{false};
|
||||
bool reindex_chainstate{false};
|
||||
// Whether to wipe the block tree database when loading it. If set, this
|
||||
// will also set a reindexing flag so any existing block data files will be
|
||||
// scanned and added to the database.
|
||||
bool wipe_block_tree_db{false};
|
||||
// Whether to wipe the chainstate database when loading it. If set, this
|
||||
// will cause the chainstate database to be rebuilt starting from genesis.
|
||||
bool wipe_chainstate_db{false};
|
||||
bool prune{false};
|
||||
//! Setting require_full_verification to true will require all checks at
|
||||
//! check_level (below) to succeed for loading to succeed. Setting it to
|
||||
|
@ -276,8 +276,8 @@ void ChainTestingSetup::LoadVerifyActivateChainstate()
|
||||
options.mempool = Assert(m_node.mempool.get());
|
||||
options.block_tree_db_in_memory = m_block_tree_db_in_memory;
|
||||
options.coins_db_in_memory = m_coins_db_in_memory;
|
||||
options.reindex = chainman.m_blockman.m_reindexing;
|
||||
options.reindex_chainstate = m_args.GetBoolArg("-reindex-chainstate", false);
|
||||
options.wipe_block_tree_db = m_args.GetBoolArg("-reindex", false);
|
||||
options.wipe_chainstate_db = m_args.GetBoolArg("-reindex", false) || m_args.GetBoolArg("-reindex-chainstate", false);
|
||||
options.prune = chainman.m_blockman.IsPruneMode();
|
||||
options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
|
||||
options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
|
||||
|
@ -2700,7 +2700,7 @@ bool Chainstate::FlushStateToDisk(
|
||||
|
||||
CoinsCacheSizeState cache_state = GetCoinsCacheSizeState();
|
||||
LOCK(m_blockman.cs_LastBlockFile);
|
||||
if (m_blockman.IsPruneMode() && (m_blockman.m_check_for_pruning || nManualPruneHeight > 0) && !m_chainman.m_blockman.m_reindexing) {
|
||||
if (m_blockman.IsPruneMode() && (m_blockman.m_check_for_pruning || nManualPruneHeight > 0) && m_chainman.m_blockman.m_blockfiles_indexed) {
|
||||
// make sure we don't prune above any of the prune locks bestblocks
|
||||
// pruning is height-based
|
||||
int last_prune{m_chain.Height()}; // last height we can prune
|
||||
@ -3313,10 +3313,10 @@ bool Chainstate::ActivateBestChainStep(BlockValidationState& state, CBlockIndex*
|
||||
return true;
|
||||
}
|
||||
|
||||
static SynchronizationState GetSynchronizationState(bool init, bool reindexing)
|
||||
static SynchronizationState GetSynchronizationState(bool init, bool blockfiles_indexed)
|
||||
{
|
||||
if (!init) return SynchronizationState::POST_INIT;
|
||||
if (reindexing) return SynchronizationState::INIT_REINDEX;
|
||||
if (!blockfiles_indexed) return SynchronizationState::INIT_REINDEX;
|
||||
return SynchronizationState::INIT_DOWNLOAD;
|
||||
}
|
||||
|
||||
@ -3338,7 +3338,7 @@ static bool NotifyHeaderTip(ChainstateManager& chainman) LOCKS_EXCLUDED(cs_main)
|
||||
}
|
||||
// Send block tip changed notifications without cs_main
|
||||
if (fNotify) {
|
||||
chainman.GetNotifications().headerTip(GetSynchronizationState(fInitialBlockDownload, chainman.m_blockman.m_reindexing), pindexHeader->nHeight, pindexHeader->nTime, false);
|
||||
chainman.GetNotifications().headerTip(GetSynchronizationState(fInitialBlockDownload, chainman.m_blockman.m_blockfiles_indexed), pindexHeader->nHeight, pindexHeader->nTime, false);
|
||||
}
|
||||
return fNotify;
|
||||
}
|
||||
@ -3457,7 +3457,7 @@ bool Chainstate::ActivateBestChain(BlockValidationState& state, std::shared_ptr<
|
||||
}
|
||||
|
||||
// Always notify the UI if a new block tip was connected
|
||||
if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(still_in_ibd, m_chainman.m_blockman.m_reindexing), *pindexNewTip))) {
|
||||
if (kernel::IsInterrupted(m_chainman.GetNotifications().blockTip(GetSynchronizationState(still_in_ibd, m_chainman.m_blockman.m_blockfiles_indexed), *pindexNewTip))) {
|
||||
// Just breaking and returning success for now. This could
|
||||
// be changed to bubble up the kernel::Interrupted value to
|
||||
// the caller so the caller could distinguish between
|
||||
@ -3683,7 +3683,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
|
||||
// parameter indicating the source of the tip change so hooks can
|
||||
// distinguish user-initiated invalidateblock changes from other
|
||||
// changes.
|
||||
(void)m_chainman.GetNotifications().blockTip(GetSynchronizationState(m_chainman.IsInitialBlockDownload(), m_chainman.m_blockman.m_reindexing), *to_mark_failed->pprev);
|
||||
(void)m_chainman.GetNotifications().blockTip(GetSynchronizationState(m_chainman.IsInitialBlockDownload(), m_chainman.m_blockman.m_blockfiles_indexed), *to_mark_failed->pprev);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -4322,7 +4322,7 @@ void ChainstateManager::ReportHeadersPresync(const arith_uint256& work, int64_t
|
||||
m_last_presync_update = now;
|
||||
}
|
||||
bool initial_download = IsInitialBlockDownload();
|
||||
GetNotifications().headerTip(GetSynchronizationState(initial_download, m_blockman.m_reindexing), height, timestamp, /*presync=*/true);
|
||||
GetNotifications().headerTip(GetSynchronizationState(initial_download, m_blockman.m_blockfiles_indexed), height, timestamp, /*presync=*/true);
|
||||
if (initial_download) {
|
||||
int64_t blocks_left{(NodeClock::now() - NodeSeconds{std::chrono::seconds{timestamp}}) / GetConsensus().PowTargetSpacing()};
|
||||
blocks_left = std::max<int64_t>(0, blocks_left);
|
||||
@ -4849,8 +4849,7 @@ bool ChainstateManager::LoadBlockIndex()
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// Load block index from databases
|
||||
bool needs_init = m_blockman.m_reindexing;
|
||||
if (!m_blockman.m_reindexing) {
|
||||
if (m_blockman.m_blockfiles_indexed) {
|
||||
bool ret{m_blockman.LoadBlockIndexDB(SnapshotBlockhash())};
|
||||
if (!ret) return false;
|
||||
|
||||
@ -4881,18 +4880,6 @@ bool ChainstateManager::LoadBlockIndex()
|
||||
if (pindex->IsValid(BLOCK_VALID_TREE) && (m_best_header == nullptr || CBlockIndexWorkComparator()(m_best_header, pindex)))
|
||||
m_best_header = pindex;
|
||||
}
|
||||
|
||||
needs_init = m_blockman.m_block_index.empty();
|
||||
}
|
||||
|
||||
if (needs_init) {
|
||||
// Everything here is for *new* reindex/DBs. Thus, though
|
||||
// LoadBlockIndexDB may have set m_reindexing if we shut down
|
||||
// mid-reindex previously, we don't check m_reindexing and
|
||||
// instead only check it prior to LoadBlockIndexDB to set
|
||||
// needs_init.
|
||||
|
||||
LogPrintf("Initializing databases...\n");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -5033,7 +5020,7 @@ void ChainstateManager::LoadExternalBlockFile(
|
||||
}
|
||||
}
|
||||
|
||||
if (m_blockman.IsPruneMode() && !m_blockman.m_reindexing && pblock) {
|
||||
if (m_blockman.IsPruneMode() && m_blockman.m_blockfiles_indexed && pblock) {
|
||||
// must update the tip for pruning to work while importing with -loadblock.
|
||||
// this is a tradeoff to conserve disk space at the expense of time
|
||||
// spent updating the tip to be able to prune.
|
||||
|
@ -73,6 +73,25 @@ class ReindexTest(BitcoinTestFramework):
|
||||
# All blocks should be accepted and processed.
|
||||
assert_equal(self.nodes[0].getblockcount(), 12)
|
||||
|
||||
def continue_reindex_after_shutdown(self):
|
||||
node = self.nodes[0]
|
||||
self.generate(node, 1500)
|
||||
|
||||
# Restart node with reindex and stop reindex as soon as it starts reindexing
|
||||
self.log.info("Restarting node while reindexing..")
|
||||
node.stop_node()
|
||||
with node.busy_wait_for_debug_log([b'initload thread start']):
|
||||
node.start(['-blockfilterindex', '-reindex'])
|
||||
node.wait_for_rpc_connection(wait_for_import=False)
|
||||
node.stop_node()
|
||||
|
||||
# Start node without the reindex flag and verify it does not wipe the indexes data again
|
||||
db_path = node.chain_path / 'indexes' / 'blockfilter' / 'basic' / 'db'
|
||||
with node.assert_debug_log(expected_msgs=[f'Opening LevelDB in {db_path}'], unexpected_msgs=[f'Wiping LevelDB in {db_path}']):
|
||||
node.start(['-blockfilterindex'])
|
||||
node.wait_for_rpc_connection(wait_for_import=False)
|
||||
node.stop_node()
|
||||
|
||||
def run_test(self):
|
||||
self.reindex(False)
|
||||
self.reindex(True)
|
||||
@ -80,6 +99,7 @@ class ReindexTest(BitcoinTestFramework):
|
||||
self.reindex(True)
|
||||
|
||||
self.out_of_order()
|
||||
self.continue_reindex_after_shutdown()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -241,7 +241,7 @@ class TestNode():
|
||||
if self.start_perf:
|
||||
self._start_perf()
|
||||
|
||||
def wait_for_rpc_connection(self):
|
||||
def wait_for_rpc_connection(self, *, wait_for_import=True):
|
||||
"""Sets up an RPC connection to the bitcoind process. Returns False if unable to connect."""
|
||||
# Poll at a rate of four times per second
|
||||
poll_per_s = 4
|
||||
@ -263,7 +263,7 @@ class TestNode():
|
||||
)
|
||||
rpc.getblockcount()
|
||||
# If the call to getblockcount() succeeds then the RPC connection is up
|
||||
if self.version_is_at_least(190000):
|
||||
if self.version_is_at_least(190000) and wait_for_import:
|
||||
# getmempoolinfo.loaded is available since commit
|
||||
# bb8ae2c (version 0.19.0)
|
||||
self.wait_until(lambda: rpc.getmempoolinfo()['loaded'])
|
||||
|
Loading…
x
Reference in New Issue
Block a user