refactor: rename FlushStateMode::ALWAYS to FORCE_FLUSH

This prepares the addition of `FORCE_SYNC`.

`empty_cache` in `FlushStateToDisk` was moved up to be reusable and `FlushStateMode::FORCE_FLUSH` was used as a placeholder before we properly split the two new states.
`log_utxocache_flush.py` was regenerated and the alignment adjusted for the wider `FlushStateMode` values.

Co-authored-by: Pieter Wuille <pieter@wuille.net>
Co-authored-by: optout <13562139+optout21@users.noreply.github.com>
This commit is contained in:
Lőrinc 2025-11-01 20:58:25 +01:00
parent ab233255d4
commit 7099e93d0a
No known key found for this signature in database
GPG Key ID: 669FFF0FFA477A76
7 changed files with 22 additions and 22 deletions

View File

@ -246,10 +246,10 @@ $ python3 contrib/tracing/log_utxocache_flush.py $(pidof bitcoind)
```
Logging utxocache flushes. Ctrl-C to end...
Duration (µs) Mode Coins Count Memory Usage Prune
730451 IF_NEEDED 22990 3323.54 kB True
637657 ALWAYS 122320 17124.80 kB False
81349 ALWAYS 0 1383.49 kB False
Duration (µs) Mode Coins Count Memory Usage Flush for Prune
2556340 IF_NEEDED 2899141 394844.34 kB False
2005788 FORCE_FLUSH 2238117 310189.68 kB False
2685 FORCE_FLUSH 0 262.24 kB False
```
### log_utxos.bt

View File

@ -10,7 +10,7 @@ from bcc import BPF, USDT
"""Example logging Bitcoin Core utxo set cache flushes utilizing
the utxocache:flush tracepoint."""
# USAGE: ./contrib/tracing/log_utxocache_flush.py path/to/bitcoind
# USAGE: ./contrib/tracing/log_utxocache_flush.py <pid of bitcoind>
# BCC: The C program to be compiled to an eBPF program (by BCC) and loaded into
# a sandboxed Linux kernel VM.
@ -45,7 +45,7 @@ FLUSH_MODES = [
'NONE',
'IF_NEEDED',
'PERIODIC',
'ALWAYS'
'FORCE_FLUSH',
]
@ -61,7 +61,7 @@ class Data(ctypes.Structure):
def print_event(event):
print("%-15d %-10s %-15d %-15s %-8s" % (
print("%-15d %-12s %-15d %-15s %-8s" % (
event.duration,
FLUSH_MODES[event.mode],
event.coins_count,
@ -88,7 +88,7 @@ def main(pid):
b["flush"].open_perf_buffer(handle_flush)
print("Logging utxocache flushes. Ctrl-C to end...")
print("%-15s %-10s %-15s %-15s %-8s" % ("Duration (µs)", "Mode",
print("%-15s %-12s %-15s %-15s %-8s" % ("Duration (µs)", "Mode",
"Coins Count", "Memory Usage",
"Flush for Prune"))

View File

@ -185,8 +185,8 @@ Is called *after* the in-memory UTXO cache is flushed.
Arguments passed:
1. Time it took to flush the cache microseconds as `int64`
2. Flush state mode as `uint32`. It's an enumerator class with values `0`
(`NONE`), `1` (`IF_NEEDED`), `2` (`PERIODIC`), `3` (`ALWAYS`)
2. Flush state mode as `uint32`. It's an enumerator class with values
`0` (`NONE`), `1` (`IF_NEEDED`), `2` (`PERIODIC`), `3` (`FORCE_FLUSH`),
3. Cache size (number of coins) before the flush as `uint64`
4. Cache memory usage in bytes as `uint64`
5. If pruning caused the flush as `bool`

View File

@ -82,7 +82,7 @@ BOOST_FIXTURE_TEST_CASE(write_during_multiblock_activation, TestChain100Setup)
BOOST_CHECK_EQUAL(second_from_tip->pprev, chainstate.m_chain.Tip());
// Set m_next_write to current time
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::ALWAYS);
chainstate.FlushStateToDisk(state_dummy, FlushStateMode::FORCE_FLUSH);
m_node.validation_signals->SyncWithValidationInterfaceQueue();
// The periodic flush interval is between 50 and 70 minutes (inclusive)
// The next call to a PERIODIC write will flush

View File

@ -2795,8 +2795,9 @@ bool Chainstate::FlushStateToDisk(
bool fCacheCritical = mode == FlushStateMode::IF_NEEDED && cache_state >= CoinsCacheSizeState::CRITICAL;
// 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.
bool fPeriodicWrite = mode == FlushStateMode::PERIODIC && nNow >= m_next_write;
const auto empty_cache{(mode == FlushStateMode::FORCE_FLUSH) || fCacheLarge || fCacheCritical};
// Combine all conditions that result in a write to disk.
bool should_write = (mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical || fPeriodicWrite || fFlushForPrune;
bool should_write = empty_cache || fPeriodicWrite || fFlushForPrune;
// Write blocks, block index and best chain related state to disk.
if (should_write) {
LogDebug(BCLog::COINDB, "Writing chainstate to disk: flush mode=%s, prune=%d, large=%d, critical=%d, periodic=%d",
@ -2844,7 +2845,6 @@ bool Chainstate::FlushStateToDisk(
return FatalError(m_chainman.GetNotifications(), state, _("Disk space is too low!"));
}
// Flush the chainstate (which may refer to block index entries).
const auto empty_cache{(mode == FlushStateMode::ALWAYS) || fCacheLarge || fCacheCritical};
empty_cache ? CoinsTip().Flush() : CoinsTip().Sync();
full_flush_completed = true;
TRACEPOINT(utxocache, flush,
@ -2874,7 +2874,7 @@ bool Chainstate::FlushStateToDisk(
void Chainstate::ForceFlushStateToDisk()
{
BlockValidationState state;
if (!this->FlushStateToDisk(state, FlushStateMode::ALWAYS)) {
if (!this->FlushStateToDisk(state, FlushStateMode::FORCE_FLUSH)) {
LogWarning("Failed to force flush state (%s)", state.ToString());
}
}
@ -5546,7 +5546,7 @@ bool Chainstate::ResizeCoinsCaches(size_t coinstip_size, size_t coinsdb_size)
ret = FlushStateToDisk(state, FlushStateMode::IF_NEEDED);
} else {
// Otherwise, flush state to disk and deallocate the in-memory coins map.
ret = FlushStateToDisk(state, FlushStateMode::ALWAYS);
ret = FlushStateToDisk(state, FlushStateMode::FORCE_FLUSH);
}
return ret;
}
@ -5992,7 +5992,7 @@ util::Result<void> ChainstateManager::PopulateAndValidateSnapshot(
// returns in `ActivateSnapshot()`, when `MaybeRebalanceCaches()` is
// called, since we've added a snapshot chainstate and therefore will
// have to downsize the IBD chainstate, which will result in a call to
// `FlushStateToDisk(ALWAYS)`.
// `FlushStateToDisk(FORCE_FLUSH)`.
}
assert(index);

View File

@ -457,12 +457,12 @@ enum DisconnectResult
class ConnectTrace;
/** @see Chainstate::FlushStateToDisk */
inline constexpr std::array FlushStateModeNames{"NONE", "IF_NEEDED", "PERIODIC", "ALWAYS"};
inline constexpr std::array FlushStateModeNames{"NONE", "IF_NEEDED", "PERIODIC", "FORCE_FLUSH"};
enum class FlushStateMode: uint8_t {
NONE,
IF_NEEDED,
PERIODIC,
ALWAYS
FORCE_FLUSH,
};
/**
@ -735,7 +735,7 @@ public:
FlushStateMode mode,
int nManualPruneHeight = 0);
//! Unconditionally flush all changes to disk.
//! Flush all changes to disk.
void ForceFlushStateToDisk();
//! Prune blockfiles from the disk if necessary and then flush chainstate changes

View File

@ -109,7 +109,7 @@ FLUSHMODE_NAME = {
0: "NONE",
1: "IF_NEEDED",
2: "PERIODIC",
3: "ALWAYS",
3: "FORCE_FLUSH",
}
@ -389,8 +389,8 @@ class UTXOCacheTracepointTest(BitcoinTestFramework):
# A node shutdown causes two flushes. One that flushes UTXOS_IN_CACHE
# UTXOs and one that flushes 0 UTXOs. Normally the 0-UTXO-flush is the
# second flush, however it can happen that the order changes.
expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": UTXOS_IN_CACHE})
expected_flushes.append({"mode": "ALWAYS", "for_prune": False, "size": 0})
expected_flushes.append({"mode": "FORCE_FLUSH", "for_prune": False, "size": UTXOS_IN_CACHE})
expected_flushes.append({"mode": "FORCE_FLUSH", "for_prune": False, "size": 0})
self.stop_node(0)
bpf.perf_buffer_poll(timeout=200)