diff --git a/src/coins.cpp b/src/coins.cpp index e650b81fe4b..b5dd7c62935 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -249,12 +249,14 @@ bool CCoinsViewCache::BatchWrite(CoinsViewCacheCursor& cursor, const uint256 &ha return true; } -bool CCoinsViewCache::Flush() { +bool CCoinsViewCache::Flush(bool will_reuse_cache) { auto cursor{CoinsViewCacheCursor(m_sentinel, cacheCoins, /*will_erase=*/true)}; bool fOk = base->BatchWrite(cursor, hashBlock); if (fOk) { cacheCoins.clear(); - ReallocateCache(); + if (will_reuse_cache) { + ReallocateCache(); + } cachedCoinsUsage = 0; } return fOk; diff --git a/src/coins.h b/src/coins.h index 2fcc764a3fd..8d07f7fe9fd 100644 --- a/src/coins.h +++ b/src/coins.h @@ -439,9 +439,11 @@ public: * Push the modifications applied to this cache to its base and wipe local state. * Failure to call this method or Sync() before destruction will cause the changes * to be forgotten. + * If will_reuse_cache is false, the cache will retain the same memory footprint + * 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 Flush(bool will_reuse_cache = true); /** * Push the modifications applied to this cache to its base while retaining diff --git a/src/test/fuzz/coins_view.cpp b/src/test/fuzz/coins_view.cpp index c687065423a..f277eadf763 100644 --- a/src/test/fuzz/coins_view.cpp +++ b/src/test/fuzz/coins_view.cpp @@ -74,7 +74,7 @@ void TestCoinsView(FuzzedDataProvider& fuzzed_data_provider, CCoinsView& backend } }, [&] { - (void)coins_view_cache.Flush(); + (void)coins_view_cache.Flush(/*will_reuse_cache=*/fuzzed_data_provider.ConsumeBool()); }, [&] { (void)coins_view_cache.Sync(); diff --git a/src/test/fuzz/coinscache_sim.cpp b/src/test/fuzz/coinscache_sim.cpp index 30845c2ef9c..82e5f1fc437 100644 --- a/src/test/fuzz/coinscache_sim.cpp +++ b/src/test/fuzz/coinscache_sim.cpp @@ -392,7 +392,7 @@ FUZZ_TARGET(coinscache_sim) // Apply to simulation data. flush(); // Apply to real caches. - caches.back()->Flush(); + caches.back()->Flush(/*will_reuse_cache=*/provider.ConsumeBool()); }, [&]() { // Sync. @@ -402,14 +402,6 @@ FUZZ_TARGET(coinscache_sim) caches.back()->Sync(); }, - [&]() { // Flush + ReallocateCache. - // Apply to simulation data. - flush(); - // Apply to real caches. - caches.back()->Flush(); - caches.back()->ReallocateCache(); - }, - [&]() { // GetCacheSize (void)caches.back()->GetCacheSize(); }, diff --git a/src/validation.cpp b/src/validation.cpp index af523b06d74..5906eef8a7b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3036,7 +3036,7 @@ bool Chainstate::DisconnectTip(BlockValidationState& state, DisconnectedBlockTra LogError("DisconnectTip(): DisconnectBlock %s failed\n", pindexDelete->GetBlockHash().ToString()); return false; } - bool flushed = view.Flush(); + bool flushed = view.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope assert(flushed); } LogDebug(BCLog::BENCH, "- Disconnect block: %.2fms\n", @@ -3171,7 +3171,7 @@ bool Chainstate::ConnectTip( Ticks(time_3 - time_2), Ticks(m_chainman.time_connect_total), Ticks(m_chainman.time_connect_total) / m_chainman.num_blocks_total); - bool flushed = view.Flush(); + bool flushed = view.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope assert(flushed); } const auto time_4{SteadyClock::now()}; @@ -4950,7 +4950,7 @@ bool Chainstate::ReplayBlocks() } cache.SetBestBlock(pindexNew->GetBlockHash()); - cache.Flush(); + cache.Flush(/*will_reuse_cache=*/false); // local CCoinsViewCache goes out of scope m_chainman.GetNotifications().progress(bilingual_str{}, 100, false); return true; }