ADR-0009: compaction is old-id ascending remap (no re-sort)
Date: 2026-06-11 / Status: Accepted
Decision
Compaction reclaims tombstone rows and dead bytes in the pool. Live entries are renumbered in old-id ascending order — because relative order is preserved, every (key, id)-ordered structure (perm_name, FRN index) is carried over by an O(n) filter+remap copy with no re-sort. The volume thread evaluates the threshold on each batch apply: len≥100k AND (tombstone_ratio>12.5% OR dead_name_bytes>32MiB).
Rationale
- Tombstone rows and the name bytes abandoned by renames accumulate without bound — a slow leak against the B/entry RAM gate (previously reclaimable only by a full rescan)
- With old-id ascending remap, the relative order of live entries is preserved, so sorted structures can be filtered+remapped byte-equivalently (O(n), zero sort cost)
- The decision input is dead_name_bytes observability (IndexStats.pool_garbage_ratio). Thresholds are set on the premise of real-volume observation
Impact
- The copy build runs under a read guard (queries run concurrently; the only writer is the single volume thread). The swap goes through
install_indexwith a µs-scale write lock + structural generation bump - Result handles open across a compaction go hard STALE (
FMF_E_STALE) → the UI auto-reissues the same query (existing mechanism) - Children of dead directories are reparented to root (same as the orphan policy of push_raw)
- A defensive generation-check failure increments the
compaction_abortscounter + discards the copy (detection of a broken single-writer invariant; does not stay silent)
Re-examination trigger
- Observation of
compaction_aborts > 0(revisit the single-writer invariant) - If the thresholds show, in real operation, that compaction fires too often or reclaims too little (threshold re-tuning)