1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// stats.rs — Maintenance layer (layer 7). A plain snapshot struct returned
// by Chisel::stats() for observability: handle count, page count, and raw
// file size. Defined as its own module so that lib.rs and the public API
// don't have to pull in transaction.rs just to expose these three numbers.
//
// This is a snapshot, not a live view — callers should not cache it across
// commits. Values reflect the state at the time stats() was called.
/// Read-only summary of database size/usage. Populated by the transaction
/// manager; no methods here because there are no invariants to enforce.
///
/// I36 (ISSUES.md, 2026-05-22): `#[non_exhaustive]` so adding a fifth
/// summary field (e.g. live-handle/total-handle ratio for retirement
/// pressure) is not a breaking change. The companion `ChiselCounters`
/// has carried the same attribute since the bench-suite series landed.
/// Cumulative engine-activity counters since `open()`.
///
/// Snapshot semantics: `Chisel::counters()` returns a value-type copy. The
/// returned struct does NOT update as the engine continues to do work — read
/// it again to observe new totals. Counters are cumulative from open; they
/// reset implicitly on `close()` + reopen because the underlying `PageCache`
/// and `PageIo` are reconstructed.
///
/// Intended use: the bench harness reads `counters()` before and after each
/// measurement, reports the delta. General-purpose introspection (debugging,
/// observability) is also supported — the counters are cheap (`Cell<u64>`
/// increment in single-writer code paths).
///
/// Fields:
/// - `cache_hits` — `PageCache::get` returned a cached page without disk I/O.
/// - `cache_misses` — `PageCache::get` had to load from disk (and validate
/// checksum). Hit rate is `hits / (hits + misses)`.
/// - `pages_allocated` — page allocations, counting BOTH file extensions
/// (`PageCache::new_page`, a new id past the high-water mark) AND freemap
/// reuses (`PageCache::claim_page`, a page id freed by a prior committed
/// transaction and handed back out). Reuse is the common case once the
/// handle table / membership index allocate COW pages through the
/// freemap-aware path, so a counter that ignored it would read ~0 for a
/// steady-state mutating workload. The actual disk write happens on the
/// next `flush()`.
/// - `fsync_calls` — `PageIo::fsync` invocations that SUCCEEDED. Three per
/// Chisel commit (pre-drain flush, data-page flush, then superblock fsync);
/// zero between commits in a normal txn. A failed fsync poisons the engine (I1 / fsyncgate) and
/// is not counted; `cache_misses` by contrast counts attempted misses
/// even when the subsequent load fails. The asymmetry is intentional —
/// see `PageIo::fsync` and I1 in ISSUES.md for the rationale.