@@ -90,10 +90,8 @@ using node::SnapshotMetadata;
90
90
91
91
/* * Size threshold for warning about slow UTXO set flush to disk. */
92
92
static 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. */
94
94
static 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 };
97
95
/* * Maximum age of our tip for us to be considered current for fee estimation */
98
96
static constexpr std::chrono::hours MAX_FEE_ESTIMATION_TIP_AGE{3 };
99
97
const std::vector<std::string> CHECKLEVEL_DOC {
@@ -2883,21 +2881,16 @@ bool Chainstate::FlushStateToDisk(
2883
2881
if (m_last_write == decltype (m_last_write){}) {
2884
2882
m_last_write = nNow;
2885
2883
}
2886
- if (m_last_flush == decltype (m_last_flush){}) {
2887
- m_last_flush = nNow;
2888
- }
2889
2884
// 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).
2890
2885
bool fCacheLarge = mode == FlushStateMode::PERIODIC && cache_state >= CoinsCacheSizeState::LARGE;
2891
2886
// The cache is over the limit, we have to write now.
2892
2887
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.
2894
2889
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;
2897
2890
// 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 ) {
2901
2894
// Ensure we can write block index
2902
2895
if (!CheckDiskSpace (m_blockman.m_opts .blocks_dir )) {
2903
2896
return FatalError (m_chainman.GetNotifications (), state, _ (" Disk space is too low!" ));
@@ -2927,35 +2920,34 @@ bool Chainstate::FlushStateToDisk(
2927
2920
2928
2921
m_blockman.UnlinkPrunedFiles (setFilesToPrune);
2929
2922
}
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 );
2950
2949
}
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 ();
2959
2951
}
2960
2952
}
2961
2953
if (full_flush_completed && m_chainman.m_options .signals ) {
0 commit comments