mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-05 02:33:07 +02:00
Merge bitcoin/bitcoin#33866: refactor: Let CCoinsViewCache::BatchWrite return void
6da6f503a6refactor: Let CCoinsViewCache::BatchWrite return void (TheCharlatan) Pull request description: CCoinsViewCache::BatchWrite always returns true if called from a backed cache, so just return void instead. Also return void from ::Sync and ::Flush. This allows for dropping a FatalError condition and simplifying some dead error handling code a bit. Since we now no longer exercise the "error path" when returning from `CCoinsView::BatchWrite`, make the method clear the cache instead. This should only be exercised by tests and not change production behaviour. This might slightly improve the coins_view fuzz test's ability to generate better coverage. ACKs for top commit: l0rinc: ACK6da6f503a6andrewtoth: re-ACK6da6f503a6achow101: ACK6da6f503a6w0xlt: ACK6da6f503a6Tree-SHA512: dfaa325b0cf8108910aebf1b27434aaddb639d10d860e96797c77ea42eca9035a54a7dc1d6a5d4eae2b75fcc9356206d3d5672243d2c906e80d19024c8b95408
This commit is contained in:
@@ -16,7 +16,11 @@ TRACEPOINT_SEMAPHORE(utxocache, uncache);
|
|||||||
std::optional<Coin> CCoinsView::GetCoin(const COutPoint& outpoint) const { return std::nullopt; }
|
std::optional<Coin> CCoinsView::GetCoin(const COutPoint& outpoint) const { return std::nullopt; }
|
||||||
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
uint256 CCoinsView::GetBestBlock() const { return uint256(); }
|
||||||
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
|
std::vector<uint256> CCoinsView::GetHeadBlocks() const { return std::vector<uint256>(); }
|
||||||
bool CCoinsView::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) { return false; }
|
void CCoinsView::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock)
|
||||||
|
{
|
||||||
|
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) { }
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<CCoinsViewCursor> CCoinsView::Cursor() const { return nullptr; }
|
std::unique_ptr<CCoinsViewCursor> CCoinsView::Cursor() const { return nullptr; }
|
||||||
|
|
||||||
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
|
bool CCoinsView::HaveCoin(const COutPoint &outpoint) const
|
||||||
@@ -30,7 +34,7 @@ bool CCoinsViewBacked::HaveCoin(const COutPoint &outpoint) const { return base->
|
|||||||
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); }
|
||||||
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
|
std::vector<uint256> CCoinsViewBacked::GetHeadBlocks() const { return base->GetHeadBlocks(); }
|
||||||
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; }
|
||||||
bool CCoinsViewBacked::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) { return base->BatchWrite(cursor, hashBlock); }
|
void CCoinsViewBacked::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) { base->BatchWrite(cursor, hashBlock); }
|
||||||
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
std::unique_ptr<CCoinsViewCursor> CCoinsViewBacked::Cursor() const { return base->Cursor(); }
|
||||||
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
|
size_t CCoinsViewBacked::EstimateSize() const { return base->EstimateSize(); }
|
||||||
|
|
||||||
@@ -183,7 +187,8 @@ void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) {
|
|||||||
hashBlock = hashBlockIn;
|
hashBlock = hashBlockIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlockIn) {
|
void CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlockIn)
|
||||||
|
{
|
||||||
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
|
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
|
||||||
if (!it->second.IsDirty()) { // TODO a cursor can only contain dirty entries
|
if (!it->second.IsDirty()) { // TODO a cursor can only contain dirty entries
|
||||||
continue;
|
continue;
|
||||||
@@ -246,33 +251,27 @@ bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &ha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
hashBlock = hashBlockIn;
|
hashBlock = hashBlockIn;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::Flush(bool will_reuse_cache) {
|
void CCoinsViewCache::Flush(bool will_reuse_cache)
|
||||||
|
{
|
||||||
auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/true)};
|
auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/true)};
|
||||||
bool fOk = base->BatchWrite(cursor, hashBlock);
|
base->BatchWrite(cursor, hashBlock);
|
||||||
if (fOk) {
|
cacheCoins.clear();
|
||||||
cacheCoins.clear();
|
if (will_reuse_cache) {
|
||||||
if (will_reuse_cache) {
|
ReallocateCache();
|
||||||
ReallocateCache();
|
|
||||||
}
|
|
||||||
cachedCoinsUsage = 0;
|
|
||||||
}
|
}
|
||||||
return fOk;
|
cachedCoinsUsage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewCache::Sync()
|
void CCoinsViewCache::Sync()
|
||||||
{
|
{
|
||||||
auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/false)};
|
auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/false)};
|
||||||
bool fOk = base->BatchWrite(cursor, hashBlock);
|
base->BatchWrite(cursor, hashBlock);
|
||||||
if (fOk) {
|
if (m_sentinel.second.Next() != &m_sentinel) {
|
||||||
if (m_sentinel.second.Next() != &m_sentinel) {
|
/* BatchWrite must clear flags of all entries */
|
||||||
/* BatchWrite must clear flags of all entries */
|
throw std::logic_error("Not all unspent flagged entries were cleared");
|
||||||
throw std::logic_error("Not all unspent flagged entries were cleared");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return fOk;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCoinsViewCache::Uncache(const COutPoint& hash)
|
void CCoinsViewCache::Uncache(const COutPoint& hash)
|
||||||
|
|||||||
12
src/coins.h
12
src/coins.h
@@ -324,7 +324,7 @@ public:
|
|||||||
|
|
||||||
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
//! Do a bulk modification (multiple Coin changes + BestBlock change).
|
||||||
//! The passed cursor is used to iterate through the coins.
|
//! The passed cursor is used to iterate through the coins.
|
||||||
virtual bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock);
|
virtual void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock);
|
||||||
|
|
||||||
//! Get a cursor to iterate over the whole state
|
//! Get a cursor to iterate over the whole state
|
||||||
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const;
|
virtual std::unique_ptr<CCoinsViewCursor> Cursor() const;
|
||||||
@@ -350,7 +350,7 @@ public:
|
|||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
std::vector<uint256> GetHeadBlocks() const override;
|
std::vector<uint256> GetHeadBlocks() const override;
|
||||||
void SetBackend(CCoinsView &viewIn);
|
void SetBackend(CCoinsView &viewIn);
|
||||||
bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) override;
|
void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override;
|
||||||
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
|
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
|
||||||
size_t EstimateSize() const override;
|
size_t EstimateSize() const override;
|
||||||
};
|
};
|
||||||
@@ -389,7 +389,7 @@ public:
|
|||||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
void SetBestBlock(const uint256 &hashBlock);
|
void SetBestBlock(const uint256 &hashBlock);
|
||||||
bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) override;
|
void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override;
|
||||||
std::unique_ptr<CCoinsViewCursor> Cursor() const override {
|
std::unique_ptr<CCoinsViewCursor> Cursor() const override {
|
||||||
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
throw std::logic_error("CCoinsViewCache cursor iteration not supported.");
|
||||||
}
|
}
|
||||||
@@ -441,18 +441,16 @@ public:
|
|||||||
* to be forgotten.
|
* to be forgotten.
|
||||||
* If will_reuse_cache is false, the cache will retain the same memory footprint
|
* If will_reuse_cache is false, the cache will retain the same memory footprint
|
||||||
* after flushing and should be destroyed to deallocate.
|
* after flushing and should be destroyed to deallocate.
|
||||||
* If false is returned, the state of this cache (and its backing view) will be undefined.
|
|
||||||
*/
|
*/
|
||||||
bool Flush(bool will_reuse_cache = true);
|
void Flush(bool will_reuse_cache = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Push the modifications applied to this cache to its base while retaining
|
* Push the modifications applied to this cache to its base while retaining
|
||||||
* the contents of this cache (except for spent coins, which we erase).
|
* the contents of this cache (except for spent coins, which we erase).
|
||||||
* Failure to call this method or Flush() before destruction will cause the changes
|
* Failure to call this method or Flush() before destruction will cause the changes
|
||||||
* to be forgotten.
|
* to be forgotten.
|
||||||
* If false is returned, the state of this cache (and its backing view) will be undefined.
|
|
||||||
*/
|
*/
|
||||||
bool Sync();
|
void Sync();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the UTXO with the given outpoint from the cache, if it is
|
* Removes the UTXO with the given outpoint from the cache, if it is
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ public:
|
|||||||
|
|
||||||
uint256 GetBestBlock() const override { return hashBestBlock_; }
|
uint256 GetBestBlock() const override { return hashBestBlock_; }
|
||||||
|
|
||||||
bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override
|
void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override
|
||||||
{
|
{
|
||||||
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)){
|
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)){
|
||||||
if (it->second.IsDirty()) {
|
if (it->second.IsDirty()) {
|
||||||
@@ -72,7 +72,6 @@ public:
|
|||||||
}
|
}
|
||||||
if (!hashBlock.IsNull())
|
if (!hashBlock.IsNull())
|
||||||
hashBestBlock_ = hashBlock;
|
hashBestBlock_ = hashBlock;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -237,7 +236,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
|
|||||||
unsigned int flushIndex = m_rng.randrange(stack.size() - 1);
|
unsigned int flushIndex = m_rng.randrange(stack.size() - 1);
|
||||||
if (fake_best_block) stack[flushIndex]->SetBestBlock(m_rng.rand256());
|
if (fake_best_block) stack[flushIndex]->SetBestBlock(m_rng.rand256());
|
||||||
bool should_erase = m_rng.randrange(4) < 3;
|
bool should_erase = m_rng.randrange(4) < 3;
|
||||||
BOOST_CHECK(should_erase ? stack[flushIndex]->Flush() : stack[flushIndex]->Sync());
|
should_erase ? stack[flushIndex]->Flush() : stack[flushIndex]->Sync();
|
||||||
flushed_without_erase |= !should_erase;
|
flushed_without_erase |= !should_erase;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,7 +246,7 @@ void SimulationTest(CCoinsView* base, bool fake_best_block)
|
|||||||
//Remove the top cache
|
//Remove the top cache
|
||||||
if (fake_best_block) stack.back()->SetBestBlock(m_rng.rand256());
|
if (fake_best_block) stack.back()->SetBestBlock(m_rng.rand256());
|
||||||
bool should_erase = m_rng.randrange(4) < 3;
|
bool should_erase = m_rng.randrange(4) < 3;
|
||||||
BOOST_CHECK(should_erase ? stack.back()->Flush() : stack.back()->Sync());
|
should_erase ? stack.back()->Flush() : stack.back()->Sync();
|
||||||
flushed_without_erase |= !should_erase;
|
flushed_without_erase |= !should_erase;
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
}
|
}
|
||||||
@@ -496,13 +495,13 @@ BOOST_FIXTURE_TEST_CASE(updatecoins_simulation_test, UpdateTest)
|
|||||||
// Every 100 iterations, flush an intermediate cache
|
// Every 100 iterations, flush an intermediate cache
|
||||||
if (stack.size() > 1 && m_rng.randbool() == 0) {
|
if (stack.size() > 1 && m_rng.randbool() == 0) {
|
||||||
unsigned int flushIndex = m_rng.randrange(stack.size() - 1);
|
unsigned int flushIndex = m_rng.randrange(stack.size() - 1);
|
||||||
BOOST_CHECK(stack[flushIndex]->Flush());
|
stack[flushIndex]->Flush();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_rng.randrange(100) == 0) {
|
if (m_rng.randrange(100) == 0) {
|
||||||
// Every 100 iterations, change the cache stack.
|
// Every 100 iterations, change the cache stack.
|
||||||
if (stack.size() > 0 && m_rng.randbool() == 0) {
|
if (stack.size() > 0 && m_rng.randbool() == 0) {
|
||||||
BOOST_CHECK(stack.back()->Flush());
|
stack.back()->Flush();
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
}
|
}
|
||||||
if (stack.size() == 0 || (stack.size() < 4 && m_rng.randbool())) {
|
if (stack.size() == 0 || (stack.size() < 4 && m_rng.randbool())) {
|
||||||
@@ -664,7 +663,7 @@ static void WriteCoinsViewEntry(CCoinsView& view, const MaybeCoin& cache_coin)
|
|||||||
CCoinsMap map{0, CCoinsMap::hasher{}, CCoinsMap::key_equal{}, &resource};
|
CCoinsMap map{0, CCoinsMap::hasher{}, CCoinsMap::key_equal{}, &resource};
|
||||||
if (cache_coin) InsertCoinsMapEntry(map, sentinel, *cache_coin);
|
if (cache_coin) InsertCoinsMapEntry(map, sentinel, *cache_coin);
|
||||||
auto cursor{CoinsViewCacheCursor(sentinel, map, /*will_erase=*/true)};
|
auto cursor{CoinsViewCacheCursor(sentinel, map, /*will_erase=*/true)};
|
||||||
BOOST_CHECK(view.BatchWrite(cursor, {}));
|
view.BatchWrite(cursor, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SingleEntryCacheTest
|
class SingleEntryCacheTest
|
||||||
|
|||||||
@@ -74,10 +74,10 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&] {
|
[&] {
|
||||||
(void)coins_view_cache.Flush(/*will_reuse_cache=*/fuzzed_data_provider.ConsumeBool());
|
coins_view_cache.Flush(/*will_reuse_cache=*/fuzzed_data_provider.ConsumeBool());
|
||||||
},
|
},
|
||||||
[&] {
|
[&] {
|
||||||
(void)coins_view_cache.Sync();
|
coins_view_cache.Sync();
|
||||||
},
|
},
|
||||||
[&] {
|
[&] {
|
||||||
uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
|
uint256 best_block{ConsumeUInt256(fuzzed_data_provider)};
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ public:
|
|||||||
std::unique_ptr<CCoinsViewCursor> Cursor() const final { return {}; }
|
std::unique_ptr<CCoinsViewCursor> Cursor() const final { return {}; }
|
||||||
size_t EstimateSize() const final { return m_data.size(); }
|
size_t EstimateSize() const final { return m_data.size(); }
|
||||||
|
|
||||||
bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256&) final
|
void BatchWrite(CoinsViewCacheCursor& cursor, const uint256&) final
|
||||||
{
|
{
|
||||||
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
|
for (auto it{cursor.Begin()}; it != cursor.End(); it = cursor.NextAndMaybeErase(*it)) {
|
||||||
if (it->second.IsDirty()) {
|
if (it->second.IsDirty()) {
|
||||||
@@ -187,7 +187,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(getcoinscachesizestate)
|
|||||||
// CRITICAL → OK via Flush
|
// CRITICAL → OK via Flush
|
||||||
BOOST_CHECK_EQUAL(chainstate.GetCoinsCacheSizeState(MAX_COINS_BYTES, /*max_mempool_size_bytes=*/0), CoinsCacheSizeState::CRITICAL);
|
BOOST_CHECK_EQUAL(chainstate.GetCoinsCacheSizeState(MAX_COINS_BYTES, /*max_mempool_size_bytes=*/0), CoinsCacheSizeState::CRITICAL);
|
||||||
view.SetBestBlock(m_rng.rand256());
|
view.SetBestBlock(m_rng.rand256());
|
||||||
BOOST_REQUIRE(view.Flush());
|
view.Flush();
|
||||||
BOOST_CHECK_EQUAL(chainstate.GetCoinsCacheSizeState(MAX_COINS_BYTES, /*max_mempool_size_bytes=*/0), CoinsCacheSizeState::OK);
|
BOOST_CHECK_EQUAL(chainstate.GetCoinsCacheSizeState(MAX_COINS_BYTES, /*max_mempool_size_bytes=*/0), CoinsCacheSizeState::OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,7 +90,8 @@ std::vector<uint256> CCoinsViewDB::GetHeadBlocks() const {
|
|||||||
return vhashHeadBlocks;
|
return vhashHeadBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) {
|
void CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock)
|
||||||
|
{
|
||||||
CDBBatch batch(*m_db);
|
CDBBatch batch(*m_db);
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
size_t changed = 0;
|
size_t changed = 0;
|
||||||
@@ -151,7 +152,6 @@ bool CCoinsViewDB::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashB
|
|||||||
LogDebug(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.ApproximateSize() * (1.0 / 1048576.0));
|
LogDebug(BCLog::COINDB, "Writing final batch of %.2f MiB\n", batch.ApproximateSize() * (1.0 / 1048576.0));
|
||||||
m_db->WriteBatch(batch);
|
m_db->WriteBatch(batch);
|
||||||
LogDebug(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
|
LogDebug(BCLog::COINDB, "Committed %u changed transaction outputs (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CCoinsViewDB::EstimateSize() const
|
size_t CCoinsViewDB::EstimateSize() const
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
bool HaveCoin(const COutPoint &outpoint) const override;
|
bool HaveCoin(const COutPoint &outpoint) const override;
|
||||||
uint256 GetBestBlock() const override;
|
uint256 GetBestBlock() const override;
|
||||||
std::vector<uint256> GetHeadBlocks() const override;
|
std::vector<uint256> GetHeadBlocks() const override;
|
||||||
bool BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &hashBlock) override;
|
void BatchWrite(CoinsViewCacheCursor& cursor, const uint256& hashBlock) override;
|
||||||
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
|
std::unique_ptr<CCoinsViewCursor> Cursor() const override;
|
||||||
|
|
||||||
//! Whether an unsupported database format is used.
|
//! Whether an unsupported database format is used.
|
||||||
|
|||||||
@@ -2845,9 +2845,7 @@ bool Chainstate::FlushStateToDisk(
|
|||||||
}
|
}
|
||||||
// Flush the chainstate (which may refer to block index entries).
|
// Flush the chainstate (which may refer to block index entries).
|
||||||
const auto empty_cache{(mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical};
|
const auto empty_cache{(mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical};
|
||||||
if (empty_cache ? !CoinsTip().Flush() : !CoinsTip().Sync()) {
|
empty_cache ? CoinsTip().Flush() : CoinsTip().Sync();
|
||||||
return FatalError(m_chainman.GetNotifications(), state, _("Failed to write to coin database."));
|
|
||||||
}
|
|
||||||
full_flush_completed = true;
|
full_flush_completed = true;
|
||||||
TRACEPOINT(utxocache, flush,
|
TRACEPOINT(utxocache, flush,
|
||||||
int64_t{Ticks<std::chrono::microseconds>(NodeClock::now() - nNow)},
|
int64_t{Ticks<std::chrono::microseconds>(NodeClock::now() - nNow)},
|
||||||
@@ -2984,8 +2982,7 @@ bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTra
|
|||||||
LogError("DisconnectTip(): DisconnectBlock %s failed\n", pindexDelete->GetBlockHash().ToString());
|
LogError("DisconnectTip(): DisconnectBlock %s failed\n", pindexDelete->GetBlockHash().ToString());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool flushed = view.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope
|
view.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope
|
||||||
assert(flushed);
|
|
||||||
}
|
}
|
||||||
LogDebug(BCLog::BENCH, "- Disconnect block: %.2fms\n",
|
LogDebug(BCLog::BENCH, "- Disconnect block: %.2fms\n",
|
||||||
Ticks<MillisecondsDouble>(SteadyClock::now() - time_start));
|
Ticks<MillisecondsDouble>(SteadyClock::now() - time_start));
|
||||||
@@ -3119,8 +3116,7 @@ bool Chainstate::ConnectTip(
|
|||||||
Ticks<MillisecondsDouble>(time_3 - time_2),
|
Ticks<MillisecondsDouble>(time_3 - time_2),
|
||||||
Ticks<SecondsDouble>(m_chainman.time_connect_total),
|
Ticks<SecondsDouble>(m_chainman.time_connect_total),
|
||||||
Ticks<MillisecondsDouble>(m_chainman.time_connect_total) / m_chainman.num_blocks_total);
|
Ticks<MillisecondsDouble>(m_chainman.time_connect_total) / m_chainman.num_blocks_total);
|
||||||
bool flushed = view.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope
|
view.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope
|
||||||
assert(flushed);
|
|
||||||
}
|
}
|
||||||
const auto time_4{SteadyClock::now()};
|
const auto time_4{SteadyClock::now()};
|
||||||
m_chainman.time_flush += time_4 - time_3;
|
m_chainman.time_flush += time_4 - time_3;
|
||||||
|
|||||||
Reference in New Issue
Block a user