diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2043,13 +2043,12 @@ LOCK(cs_main); static int64_t nLastWrite = 0; static int64_t nLastFlush = 0; - static int64_t nLastSetChain = 0; std::set setFilesToPrune; - bool fFlushForPrune = false; - bool fDoFullFlush = false; - int64_t nNow = 0; + bool full_flush_completed = false; try { { + bool fFlushForPrune = false; + bool fDoFullFlush = false; LOCK(cs_LastBlockFile); if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) { @@ -2068,7 +2067,7 @@ } } } - nNow = GetTimeMicros(); + int64_t nNow = GetTimeMicros(); // Avoid writing/flushing immediately after startup. if (nLastWrite == 0) { nLastWrite = nNow; @@ -2076,9 +2075,6 @@ if (nLastFlush == 0) { nLastFlush = nNow; } - if (nLastSetChain == 0) { - nLastSetChain = nNow; - } int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000; int64_t cacheSize = pcoinsTip->DynamicMemoryUsage(); @@ -2168,17 +2164,13 @@ return AbortNode(state, "Failed to write to coin database"); } nLastFlush = nNow; + full_flush_completed = true; } } - if (fDoFullFlush || - ((mode == FlushStateMode::ALWAYS || - mode == FlushStateMode::PERIODIC) && - nNow > - nLastSetChain + (int64_t)DATABASE_WRITE_INTERVAL * 1000000)) { + if (full_flush_completed) { // Update best block in wallet (so we can detect restored wallets). GetMainSignals().ChainStateFlushed(chainActive.GetLocator()); - nLastSetChain = nNow; } } catch (const std::runtime_error &e) { return AbortNode(state, std::string("System error while flushing: ") + diff --git a/src/validationinterface.h b/src/validationinterface.h --- a/src/validationinterface.h +++ b/src/validationinterface.h @@ -97,7 +97,22 @@ /** Notifies listeners of a block being disconnected */ virtual void BlockDisconnected(const std::shared_ptr &block) { } - /** Notifies listeners of the new active block chain on-disk. */ + /** + * Notifies listeners of the new active block chain on-disk. + * + * Prior to this callback, any updates are not guaranteed to persist on disk + * (ie clients need to handle shutdown/restart safety by being able to + * understand when some updates were lost due to unclean shutdown). + * + * When this callback is invoked, the validation changes done by any prior + * callback are guaranteed to exist on disk and survive a restart, including + * an unclean shutdown. + * + * Provides a locator describing the best chain, which is likely useful for + * storing current state on disk in client DBs. + * + * Called on a background thread. + */ virtual void ChainStateFlushed(const CBlockLocator &locator) {} /** Notifies listeners about an inventory item being seen on the network. */ virtual void Inventory(const uint256 &hash) {}