Skip to main content

seal_generation_zero

Function seal_generation_zero 

Source
pub fn seal_generation_zero(
    blobs: &Path,
    journal: Option<&Path>,
    archive: &Path,
    reserved: Vec<ReservedSection>,
) -> Result<SealReport>
Expand description

Write generation 0.

Both Gc implementations compact an archive that already exists — NewGeneration writes repository.g1.znippy beside repository.znippy. Nothing created repository.znippy, so a gc() on a store that had never been sealed died on stat: No such file or directory. This is the function that had been missing.

§An archive is a blob region plus a metadata tail

The blob region here is the store’s objects.pack — the verbatim pushed packs, at the offsets the journal named — and it is copied whole and unchanged. That is not laziness: a journal extent is (offset, len) into that file, and the same extents are what the store’s objects table holds for every object. Rewriting the region to squeeze the dead packs out would move every offset after the first hole and invalidate every one of those rows. Reclaiming that payload is the compaction’s job, and it can do it precisely because a retired pack gets no row here.

The tail is written past the copied blob region by ArrowIpcSink — the same writer HotArchive::seal uses, with the same reserved-section hook, so there is one metadata writer in this constellation and not two (LAW 5).

§One row per acked pack

columnvalue
relative_pathobjects.pack.<ordinal> — gunnar’s synthetic_path convention, and the ordinal is the pack’s position among the journal’s JournalRow::Pack rows
blob_offset / blob_sizethe journal extent, unchanged
uncompressed_sizethe same length: a verbatim pack is stored raw
compressedfalse — the bytes on disk are the pack’s own
chunk_seq / fdata_offset0 — one chunk per pack
checksumblake3 over the stored bytes, which for compressed: false are also the original bytes — the domain write_blobs uses and the domain extract_file_verified checks against

A tombstoned pack is skipped, and so is one whose extent runs past the bytes that were copied — that second case is a pack acked after the copy began, and a row for it would point into a hole. Both are counted on the SealReport rather than swallowed.

§Ordering

The blob region is copied first and the journal is read second, because the blob file is append-only: anything the journal names within the copied length is certainly present, while the reverse order could name an extent the copy had not reached. The tail is written into a staging sibling and the archive’s own name appears only at the final rename(2), so an interruption at any byte leaves no half-sealed archive under the name a reader opens.