mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-08 10:31:50 -05:00
Merge 26e78f2ee4
into 85f96b01b7
This commit is contained in:
commit
ea0c954222
2 changed files with 31 additions and 9 deletions
24
src/txdb.cpp
24
src/txdb.cpp
|
@ -95,26 +95,32 @@ bool CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashB
|
|||
size_t count = 0;
|
||||
size_t changed = 0;
|
||||
assert(!hashBlock.IsNull());
|
||||
bool unfinished_replay{false};
|
||||
|
||||
uint256 old_tip = GetBestBlock();
|
||||
if (old_tip.IsNull()) {
|
||||
// We may be in the middle of replaying.
|
||||
// We may be in the process of replaying.
|
||||
std::vector<uint256> old_heads = GetHeadBlocks();
|
||||
if (old_heads.size() == 2) {
|
||||
if (old_heads[0] != hashBlock) {
|
||||
LogPrintLevel(BCLog::COINDB, BCLog::Level::Error, "The coins database detected an inconsistent state, likely due to a previous crash or shutdown. You will need to restart bitcoind with the -reindex-chainstate or -reindex configuration option.\n");
|
||||
}
|
||||
assert(old_heads[0] == hashBlock);
|
||||
// We haven't reached the target of replaying yet.
|
||||
// This happens if the replay was interrupted by the user.
|
||||
unfinished_replay = true;
|
||||
} else {
|
||||
// Replaying has reached its end, flush the results.
|
||||
old_tip = old_heads[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In the first batch, mark the database as being in the middle of a
|
||||
// transition from old_tip to hashBlock.
|
||||
// A vector is used for future extensibility, as we may want to support
|
||||
// interrupting after partial writes from multiple independent reorgs.
|
||||
if (!unfinished_replay) {
|
||||
batch.Erase(DB_BEST_BLOCK);
|
||||
batch.Write(DB_HEAD_BLOCKS, Vector(hashBlock, old_tip));
|
||||
}
|
||||
|
||||
for (auto it{cursor.Begin()}; it != cursor.End();) {
|
||||
if (it->second.IsDirty()) {
|
||||
|
@ -141,9 +147,19 @@ bool CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashB
|
|||
}
|
||||
}
|
||||
|
||||
if (unfinished_replay) {
|
||||
// This is called when, during ReplayBlocks, an interrupt is received.
|
||||
// Update the replay origin (saved in second place in DB_HEAD_BLOCKS)
|
||||
// so that the replay can pick up from here after restart.
|
||||
// The replay target remains unchanged.
|
||||
std::vector<uint256> old_heads = GetHeadBlocks();
|
||||
assert(old_heads.size() == 2);
|
||||
batch.Write(DB_HEAD_BLOCKS, Vector(old_heads[0], hashBlock));
|
||||
} else {
|
||||
// In the last batch, mark the database as consistent with hashBlock again.
|
||||
batch.Erase(DB_HEAD_BLOCKS);
|
||||
batch.Write(DB_BEST_BLOCK, hashBlock);
|
||||
}
|
||||
|
||||
LogDebug(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.SizeEstimate() * (1.0 / 1048576.0));
|
||||
bool ret = m_db->WriteBatch(batch);
|
||||
|
|
|
@ -4976,6 +4976,12 @@ bool Chainstate::ReplayBlocks()
|
|||
LogPrintf("Rolling forward %s (%i)\n", pindex.GetBlockHash().ToString(), nHeight);
|
||||
m_chainman.GetNotifications().progress(_("Replaying blocks…"), (int)((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)), false);
|
||||
if (!RollforwardBlock(&pindex, cache)) return false;
|
||||
if (m_chainman.m_interrupt) {
|
||||
LogInfo("Flushing intermediate state of replay\n");
|
||||
cache.SetBestBlock(pindex.GetBlockHash());
|
||||
cache.Flush();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cache.SetBestBlock(pindexNew->GetBlockHash());
|
||||
|
|
Loading…
Add table
Reference in a new issue