Skip to main content

Publishing replacement files and measuring cost

What this concept is​

Compaction has two contracts: produce equivalent content, then publish that content without losing the last recoverable version. Correct bytes in a temporary file do not by themselves establish crash-safe publication.

Why it matters here​

Overwriting the only live log in place can destroy both old and new state when interrupted. The supplied temporary-file check only reopens serialized bytes during an ordinary run. It deliberately does not simulate filesystem ordering or power loss.

Concrete example​

Write a complete candidate while retaining the old log. Before publication, recovery should select the old generation. After publication, recovery should select the new complete generation. A half-written candidate must never become authoritative. Removing the old file before establishing the new generation creates a gap where neither is usable.

Common confusion / misconception​

Rename visibility and persistence across a machine crash are different properties. A successful language-level write may still leave data buffered. Precise ordering depends on the operating system, filesystem and device; do not infer it from a passing in-memory recovery test.

How to use it​

For your file adapter, document temporary-file creation, content write, file synchronization, publication, directory metadata synchronization where required, and old-generation cleanup. Consult platform documentation and state assumptions. Make a crash matrix for before/after each stage: authoritative generation, orphan candidates and recovery action. Test process interruptions separately and label them accurately. Do not promote a candidate merely because it has the newest filename.

Check yourself​

Which stage makes the replacement visible, and which evidence supports its persistence? What happens if readers still hold the old file or offsets when cleanup starts?

Mini drill or application​

Measure input log bytes, compacted output bytes and peak simultaneous old-plus-new bytes. Define logical update bytes explicitly, then report rewrite bytes divided by that denominator. Keep read, write and space amplification separate. Compare two histories with the same final map but different overwrite rates; correctness can match while cost differs.

Read this only if stuck​

Use Database Internals for storage publication and SQLite atomic commit for why flushes and hardware assumptions matter. SQLite’s protocol is a comparison, not a proof for your custom replacement algorithm.