@@ -90,10 +90,8 @@ using node::SnapshotMetadata;
9090
9191/* * Size threshold for warning about slow UTXO set flush to disk. */
9292static constexpr size_t WARN_FLUSH_COINS_SIZE = 1 << 30 ; // 1 GiB
93- /* * Time to wait between writing blocks/block index to disk. */
93+ /* * Time to wait between writing blocks/block index and chainstate to disk. */
9494static constexpr std::chrono::hours DATABASE_WRITE_INTERVAL{1 };
95- /* * Time to wait between flushing chainstate to disk. */
96- static constexpr std::chrono::hours DATABASE_FLUSH_INTERVAL{24 };
9795/* * Maximum age of our tip for us to be considered current for fee estimation */
9896static constexpr std::chrono::hours MAX_FEE_ESTIMATION_TIP_AGE{3 };
9997const std::vector<std::string> CHECKLEVEL_DOC {
@@ -2883,21 +2881,16 @@ bool Chainstate::FlushStateToDisk(
28832881 if (m_last_write == decltype (m_last_write){}) {
28842882 m_last_write = nNow;
28852883 }
2886- if (m_last_flush == decltype (m_last_flush){}) {
2887- m_last_flush = nNow;
2888- }
28892884 // The cache is large and we're within 10% and 10 MiB of the limit, but we have time now (not in the middle of a block processing).
28902885 bool fCacheLarge = mode == FlushStateMode::PERIODIC && cache_state >= CoinsCacheSizeState::LARGE;
28912886 // The cache is over the limit, we have to write now.
28922887 bool fCacheCritical = mode == FlushStateMode::IF_NEEDED && cache_state >= CoinsCacheSizeState::CRITICAL;
2893- // It's been a while since we wrote the block index to disk. Do this frequently, so we don't need to redownload after a crash.
2888+ // It's been a while since we wrote the block index and chain state to disk. Do this frequently, so we don't need to redownload or reindex after a crash.
28942889 bool fPeriodicWrite = mode == FlushStateMode::PERIODIC && nNow > m_last_write + DATABASE_WRITE_INTERVAL;
2895- // It's been very long since we flushed the cache. Do this infrequently, to optimize cache usage.
2896- bool fPeriodicFlush = mode == FlushStateMode::PERIODIC && nNow > m_last_flush + DATABASE_FLUSH_INTERVAL;
28972890 // Combine all conditions that result in a full cache flush.
2898- fDoFullFlush = (mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicFlush || fFlushForPrune ;
2899- // Write blocks and block index to disk.
2900- if (fDoFullFlush || fPeriodicWrite ) {
2891+ fDoFullFlush = (mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicWrite || fFlushForPrune ;
2892+ // Write blocks, block index and best chain related state to disk.
2893+ if (fDoFullFlush ) {
29012894 // Ensure we can write block index
29022895 if (!CheckDiskSpace (m_blockman.m_opts .blocks_dir )) {
29032896 return FatalError (m_chainman.GetNotifications (), state, _ (" Disk space is too low!" ));
@@ -2927,35 +2920,34 @@ bool Chainstate::FlushStateToDisk(
29272920
29282921 m_blockman.UnlinkPrunedFiles (setFilesToPrune);
29292922 }
2930- m_last_write = nNow;
2931- }
2932- // Flush best chain related state. This can only be done if the blocks / block index write was also done.
2933- if (fDoFullFlush && !CoinsTip ().GetBestBlock ().IsNull ()) {
2934- if (coins_mem_usage >= WARN_FLUSH_COINS_SIZE) LogWarning (" Flushing large (%d GiB) UTXO set to disk, it may take several minutes" , coins_mem_usage >> 30 );
2935- LOG_TIME_MILLIS_WITH_CATEGORY (strprintf (" write coins cache to disk (%d coins, %.2fKiB)" ,
2936- coins_count, coins_mem_usage >> 10 ), BCLog::BENCH);
2937-
2938- // Typical Coin structures on disk are around 48 bytes in size.
2939- // Pushing a new one to the database can cause it to be written
2940- // twice (once in the log, and once in the tables). This is already
2941- // an overestimation, as most will delete an existing entry or
2942- // overwrite one. Still, use a conservative safety factor of 2.
2943- if (!CheckDiskSpace (m_chainman.m_options .datadir , 48 * 2 * 2 * CoinsTip ().GetCacheSize ())) {
2944- return FatalError (m_chainman.GetNotifications (), state, _ (" Disk space is too low!" ));
2945- }
2946- // Flush the chainstate (which may refer to block index entries).
2947- const auto empty_cache{(mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical };
2948- if (empty_cache ? !CoinsTip ().Flush () : !CoinsTip ().Sync ()) {
2949- return FatalError (m_chainman.GetNotifications (), state, _ (" Failed to write to coin database." ));
2923+
2924+ if (!CoinsTip ().GetBestBlock ().IsNull ()) {
2925+ if (coins_mem_usage >= WARN_FLUSH_COINS_SIZE) LogWarning (" Flushing large (%d GiB) UTXO set to disk, it may take several minutes" , coins_mem_usage >> 30 );
2926+ LOG_TIME_MILLIS_WITH_CATEGORY (strprintf (" write coins cache to disk (%d coins, %.2fKiB)" ,
2927+ coins_count, coins_mem_usage >> 10 ), BCLog::BENCH);
2928+
2929+ // Typical Coin structures on disk are around 48 bytes in size.
2930+ // Pushing a new one to the database can cause it to be written
2931+ // twice (once in the log, and once in the tables). This is already
2932+ // an overestimation, as most will delete an existing entry or
2933+ // overwrite one. Still, use a conservative safety factor of 2.
2934+ if (!CheckDiskSpace (m_chainman.m_options .datadir , 48 * 2 * 2 * CoinsTip ().GetCacheSize ())) {
2935+ return FatalError (m_chainman.GetNotifications (), state, _ (" Disk space is too low!" ));
2936+ }
2937+ // Flush the chainstate (which may refer to block index entries).
2938+ const auto empty_cache{(mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical };
2939+ if (empty_cache ? !CoinsTip ().Flush () : !CoinsTip ().Sync ()) {
2940+ return FatalError (m_chainman.GetNotifications (), state, _ (" Failed to write to coin database." ));
2941+ }
2942+ full_flush_completed = true ;
2943+ TRACEPOINT (utxocache, flush,
2944+ int64_t {Ticks<std::chrono::microseconds>(NodeClock::now () - nNow)},
2945+ (uint32_t )mode,
2946+ (uint64_t )coins_count,
2947+ (uint64_t )coins_mem_usage,
2948+ (bool )fFlushForPrune );
29502949 }
2951- m_last_flush = nNow;
2952- full_flush_completed = true ;
2953- TRACEPOINT (utxocache, flush,
2954- int64_t {Ticks<std::chrono::microseconds>(NodeClock::now () - nNow)},
2955- (uint32_t )mode,
2956- (uint64_t )coins_count,
2957- (uint64_t )coins_mem_usage,
2958- (bool )fFlushForPrune );
2950+ m_last_write = NodeClock::now ();
29592951 }
29602952 }
29612953 if (full_flush_completed && m_chainman.m_options .signals ) {
0 commit comments