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
| column | value |
|---|---|
relative_path | objects.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_size | the journal extent, unchanged |
uncompressed_size | the same length: a verbatim pack is stored raw |
compressed | false — the bytes on disk are the pack’s own |
chunk_seq / fdata_offset | 0 — one chunk per pack |
checksum | blake3 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.