header

package
v0.0.0-...-5457911 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2026 License: Apache-2.0 Imports: 23 Imported by: 20

Documentation

Index

Constants

View Source
const (
	PageSize        = 4 << 10 // 4 KiB
	HugepageSize    = 2 << 20 // 2 MiB
	RootfsBlockSize = 4 << 10 // 4 KiB
)
View Source
const (
	SkippedBlockChar = '░'
	DirtyBlockChar1  = '▓'
	DirtyBlockChar2  = '█'
)
View Source
const (

	// MetadataVersionV4 is used for compressed builds (V4 headers with FrameTables).
	MetadataVersionV4 = 4
	// MetadataVersionV5 is V4 with a columnar, varint-encoded mapping section.
	// Same semantics as V4 (Builds map + FrameTables); only the on-disk mapping
	// layout differs. Far smaller and far more compressible for the large,
	// fragmented headers produced by page-granular memfile dedup.
	MetadataVersionV5 = 5
)
View Source
const NormalizeFixVersion = 3

Variables

View Source
var EmptyHugePage = make([]byte, HugepageSize)

Functions

func BlockCeilIdx

func BlockCeilIdx(off, blockSize int64) int64

BlockCeilIdx returns the index of the first block after byte offset off (ceiling division).

func BlockIdx

func BlockIdx(off, blockSize int64) int64

BlockIdx returns the index of the block containing byte offset off (floor division).

func BlockOffset

func BlockOffset(idx, blockSize int64) int64

func BlocksOffsets

func BlocksOffsets(size, blockSize int64) []int64

func Equal

func Equal(a, b []BuildMap) bool

func IsZero

func IsZero(b []byte) bool

IsZero reports whether b is all-zero. Samples first/middle/last byte to reject most non-zero buffers from one cache line, then falls back to bytes.Equal(b[:n-1], b[1:]): true exactly when every adjacent pair of bytes is equal, i.e. all bytes equal b[0] (which the sample already proved is zero).

func Layers

func Layers(mappings []BuildMap) *map[uuid.UUID]struct{}

Layers returns a map of buildIds that are present in the mappings.

func SerializeHeader

func SerializeHeader(h *Header) ([]byte, error)

SerializeHeader serializes a header, dispatching to the version-specific format.

V3 (Version <= 3): Metadata [v3 mappings…] V4 (Version >= 4): Metadata [uint8 flags] [uint32 uncompressedSize] [LZ4( Builds + v4 mappings )]

func StoreHeader

func StoreHeader(ctx context.Context, s storage.StorageProvider, path string, h *Header, opts ...storage.PutOption) (cfg storage.CompressConfig, stored, uncompressed int64, err error)

StoreHeader serializes a header, uploads it, and returns the effective compression config plus the stored and pre-compression byte counts. V3 has no inner compression so the counts match and cfg is the zero value. Refuses to persist a header still flagged as in-flight.

func TotalBlocks

func TotalBlocks(size, blockSize int64) int64

func ValidateMappings

func ValidateMappings(mappings []BuildMap, size, blockSize uint64) error

ValidateMappings validates the mappings. It is used to check if the mappings are valid.

It checks if the mappings are contiguous and if the length of each mapping is a multiple of the block size. It also checks if the mappings cover the whole size.

func Visualize

func Visualize(mappings []BuildMap, size, blockSize, cols uint64, bottomGroup, topGroup *map[uuid.UUID]struct{}) string

Visualize returns a string representation of the mappings as a grid of blocks. It is used for debugging and visualization.

You can pass maps to visualize different groups of buildIds.

Types

type BuildData

type BuildData struct {
	Size      int64               // uncompressed file size
	Checksum  [32]byte            // SHA-256 of uncompressed data; zero value means unknown
	FrameData *storage.FrameTable // nil for uncompressed builds
}

BuildData holds per-build metadata stored in V4 headers. Each layer's header carries a Builds map; child headers inherit parent entries for still-referenced build IDs via newDiffHeader.

type BuildMap

type BuildMap struct {
	// Offset is the starting position of this range in the block device.
	Offset             uint64
	Length             uint64
	BuildId            uuid.UUID
	BuildStorageOffset uint64
}

BuildMap maps a byte range in the block device to a region in a build's storage. Offset, Length, and BuildStorageOffset are in bytes.

func CreateMapping

func CreateMapping(
	buildId *uuid.UUID,
	dirty *roaring.Bitmap,
	blockSize int64,
) []BuildMap

func MergeMappings

func MergeMappings(
	baseMapping []BuildMap,
	diffMapping []BuildMap,
) []BuildMap

MergeMappings merges two sets of mappings.

The mapping are stored in a sorted order. The baseMapping must cover the whole size.

It returns a new set of mappings that covers the whole size.

func NormalizeMappings

func NormalizeMappings(mappings []BuildMap) []BuildMap

NormalizeMappings joins adjacent mappings that have the same buildId.

Same-build runs are only merged when their storage is contiguous, i.e. mp.BuildStorageOffset == current end. The read path resolves bytes as BuildStorageOffset + shift, so merging a run across a storage discontinuity would silently remap reads to the wrong bytes. Empty (uuid.Nil) regions are served as zeros and never read from storage (see build.ReadAt), so their storage offset is irrelevant and they always merge.

Clone the result so the oversized intermediate (cap == len(input)) is released; the merged Header is cached for up to 25h. slices.Clip will not do — it only retightens cap on the same backing array.

func (BuildMap) Equal

func (mapping BuildMap) Equal(other BuildMap) bool

func (BuildMap) Format

func (mapping BuildMap) Format(blockSize uint64) string

Format returns a string representation of the mapping as:

startBlock-endBlock [offset, offset+length) := [buildStorageOffset, buildStorageOffset+length) ⊂ buildId, length in bytes

It is used for debugging and visualization.

type DiffMetadata

type DiffMetadata struct {
	Dirty *roaring.Bitmap
	Empty *roaring.Bitmap

	BlockSize int64
}

func NewDiffMetadata

func NewDiffMetadata(blockSize int64, dirty, empty *roaring.Bitmap) *DiffMetadata

func (*DiffMetadata) ToDiffHeader

func (d *DiffMetadata) ToDiffHeader(
	ctx context.Context,
	originalHeader *Header,
	buildID uuid.UUID,
) (h *Header, e error)

func (*DiffMetadata) ToProvisionalDiffHeader

func (d *DiffMetadata) ToProvisionalDiffHeader(
	ctx context.Context,
	originalHeader *Header,
	buildID uuid.UUID,
) (*Header, error)

ToProvisionalDiffHeader builds a local-only header that describes the memfd directly — all dirty pages attributed to buildID with identity storage offsets (see createIdentityMapping), composed over originalHeader. Unlike ToDiffHeader it needs no dedup metadata, so it is available at pause time and lets a resume serve immediately. It must never be uploaded (the uploaded artifact always uses the deduped ToDiffHeader output).

func (*DiffMetadata) ToResizedDiffHeader

func (d *DiffMetadata) ToResizedDiffHeader(
	ctx context.Context,
	originalHeader *Header,
	buildID uuid.UUID,
	newSize uint64,
) (*Header, error)

ToResizedDiffHeader composes the diff over the original header while changing the rootfs logical size. It leaves the original header untouched and strictly validates that the resulting mapping covers the entire resized rootfs.

type DiffMetadataBuilder

type DiffMetadataBuilder struct {
	// contains filtered or unexported fields
}

func NewDiffMetadataBuilder

func NewDiffMetadataBuilder(blockSize int64) *DiffMetadataBuilder

func (*DiffMetadataBuilder) Build

func (b *DiffMetadataBuilder) Build() *DiffMetadata

func (*DiffMetadataBuilder) Process

func (b *DiffMetadataBuilder) Process(ctx context.Context, block []byte, out io.Writer, offset int64) error
type Header struct {
	Metadata *Metadata
	// Builds maps build IDs to per-build metadata (size, checksum, FrameTable).
	// nil for V3 (uncompressed) headers; the read path falls back to a Size()
	// RPC and reads uncompressed data when nil.
	Builds map[uuid.UUID]BuildData

	// Mapping is the per-block source map. Stored compactly (9-10 B/entry vs 40
	// for a BuildMap) so long-lived cached headers don't dominate orchestrator
	// heap. Read via At / All / Slice / Len, not indexing.
	Mapping Mapping

	// IncompletePendingUpload is set on diff headers produced by ToDiffHeader and
	// cleared on the finalized headers swapped in by the upload pipeline. It
	// is in-memory only (never serialized), and signals that the build's data
	// has not yet reached object storage — readers must serve from the local
	// cache and skip FrameTable lookups for the still-missing self entry.
	IncompletePendingUpload bool
}

func Deserialize

func Deserialize(ctx context.Context, in storage.Blob) (*Header, error)

Deserialize reads a header from a storage Blob (legacy API).

func DeserializeBytes

func DeserializeBytes(data []byte) (*Header, error)

DeserializeBytes auto-detects the header version and deserializes accordingly. See SerializeHeader for the binary layout.

func LoadHeader

func LoadHeader(ctx context.Context, s storage.StorageProvider, path string) (*Header, int, error)

LoadHeader fetches a serialized header from storage and deserializes it. Returns the on-wire byte count alongside the header so callers can attribute it to throughput telemetry. Errors (including storage.ErrObjectNotExist) are returned as-is.

func LoadStoredHeader

func LoadStoredHeader(ctx context.Context, s storage.StorageProvider, path string) (*Header, int, error)

LoadStoredHeader is LoadHeader without the V3 uncompressed-build backfill: its Builds map holds exactly the entries the serialized header carried.

func NewHeader

func NewHeader(metadata *Metadata, mapping []BuildMap) (*Header, error)

func (*Header) CloneForUpload

func (t *Header) CloneForUpload(version uint64) *Header

CloneForUpload returns a clone the upload path can mutate for serialization without racing with concurrent readers of the original. The version is set on the clone and the Builds map is copied (the upload path adds the self entry). Mapping is shared by reference: it is immutable once a Header is constructed.

func (*Header) GetBuildFrameData

func (t *Header) GetBuildFrameData(buildID uuid.UUID) *storage.FrameTable

GetBuildFrameData returns the FrameTable for a build: nil = no entry, storage.UncompressedFrameTable = authoritatively uncompressed, else compressed.

func (*Header) GetShiftedMapping

func (t *Header) GetShiftedMapping(ctx context.Context, offset int64) (BuildMap, error)

GetShiftedMapping resolves a virtual offset to a build-local range. The read path uses this to find which build owns the data, then calls GetBuildFrameData to get the FrameTable for C-space lookup.

func (*Header) IsNormalizeFixApplied

func (t *Header) IsNormalizeFixApplied() bool

IsNormalizeFixApplied is a helper method to soft fail for older versions of the header where fix for normalization was not applied. This should be removed in the future.

func (*Header) SelfBuildData

func (t *Header) SelfBuildData() (int64, *storage.FullFrameTable, error)

SelfBuildData returns the size and full FrameTable for the header's own build (t.Metadata.BuildId). Errors when the self entry is missing — only possible with peer-served incomplete headers, never with storage-uploaded ones (build_upload_v4 always populates self before publish).

This is the *only* place the FullFrameTable upcast happens in production: Builds[id].FrameData is typed *FrameTable to match the trimmed-FT case where our header carries only the frames we mapped from an ancestor. For the self entry, build_upload_v4 always stores the complete table, so the upcast via storage.FullFromTable is sound.

func (*Header) SetBuild

func (t *Header) SetBuild(buildID uuid.UUID, bd BuildData)

SetBuild adds or replaces build metadata for the given build ID.

func (*Header) String

func (t *Header) String() string

type Mapping

type Mapping struct {
	// contains filtered or unexported fields
}

Mapping is the compact in-memory representation of a Header's mapping list. A merged Header is cached for hours, so on snapshot-heavy nodes these slices dominate host RAM. It shrinks each entry from 40 bytes (a BuildMap) to 9 or 10 by encoding offset/storage as uint32 block indices, deduplicating BuildId into a per-header table addressed by one byte (two once a header references more than 255 builds), storing the columns as parallel slices, and deriving each entry's length from where the next one starts. Immutable; read via At / All / Slice.

func NewMapping

func NewMapping(blockSize uint64, src []BuildMap) (Mapping, error)

NewMapping packs src into the compact representation. blockSize is the unit for the block indices and must divide every Offset, Length, and BuildStorageOffset in src (callers pass PageSize, the universal granularity).

func (Mapping) All

func (m Mapping) All() iter.Seq2[int, BuildMap]

All iterates the mapping, materializing each entry as a BuildMap. This is the preferred read path for callers that don't need a backing []BuildMap.

func (Mapping) At

func (m Mapping) At(i int) BuildMap

At materializes the i-th entry as a BuildMap. Panics if i is out of range, matching `mapping[i]` semantics.

func (Mapping) BlockSize

func (m Mapping) BlockSize() uint64

BlockSize returns the block size used for block<->byte conversions.

func (Mapping) Builds

func (m Mapping) Builds() []uuid.UUID

Builds returns the deduplicated build IDs referenced by the mapping. The returned slice is shared with the Mapping; callers must not mutate it.

func (Mapping) ByteSize

func (m Mapping) ByteSize() int

ByteSize returns the approximate heap footprint of the mapping's columns, so callers can gauge how much RAM cached headers hold without knowing the encoding. It counts the per-entry columns — 9 bytes for the contiguous form, 4 more where lengths are stored explicitly and one more where the header needs the wide build index — plus the deduplicated build table (16 bytes per UUID); it excludes the struct header itself and any slice capacity beyond len.

func (Mapping) BytesByBuild

func (m Mapping) BytesByBuild() map[uuid.UUID]uint64

BytesByBuild sums the bytes attributed to each referenced build. It scans the columns directly (no BuildMap materialization or per-entry uuid hashing), accumulating into a small per-build slice, so it stays cheap even for mappings with millions of entries. Empty (nil-build) regions are skipped. The returned map is non-nil and addressable by the caller.

func (Mapping) Contiguous

func (m Mapping) Contiguous() bool

Contiguous reports whether every entry starts where the previous one ends. Such a mapping derives its lengths from the offsets column instead of storing them.

func (Mapping) Len

func (m Mapping) Len() int

Len returns the number of entries.

func (Mapping) SearchOffset

func (m Mapping) SearchOffset(off int64) int

SearchOffset returns the first index i whose byte offset is strictly greater than off, matching sort.Search semantics on Offset. It compares in block units, so entries are never materialized: entry.OffsetBlocks*blockSize > off iff entry.OffsetBlocks > off/blockSize (integer division).

func (Mapping) SharesStorageWith

func (m Mapping) SharesStorageWith(other Mapping) bool

SharesStorageWith reports whether m and other are backed by the same columns. Copying a Mapping by value — as Header.CloneForUpload does — shares its slices with the original, so two distinct Headers can hold one allocation between them. Callers measuring heap footprint need this to avoid counting that allocation once per Header. An empty mapping shares nothing: it holds no allocation to confuse.

func (Mapping) Slice

func (m Mapping) Slice() []BuildMap

Slice materializes the full mapping as []BuildMap (~40 bytes/entry). Use sparingly — for serialization fallbacks, CLI inspection, and tests. Hot paths and the cached form should use At / All instead.

func (Mapping) Validate

func (m Mapping) Validate(size, blockSize uint64) error

Validate checks that entries are contiguous, block-aligned to blockSize, and cover exactly `size` bytes. It is the compact-form equivalent of ValidateMappings(m.Slice(), size, blockSize) without the materialization.

type Metadata

type Metadata struct {
	Version    uint64
	BlockSize  uint64
	Size       uint64
	Generation uint64
	BuildId    uuid.UUID
	// TODO: Use the base build id when setting up the snapshot rootfs
	BaseBuildId uuid.UUID
}

func NewTemplateMetadata

func NewTemplateMetadata(buildId uuid.UUID, blockSize, size uint64) *Metadata

func (*Metadata) NextGeneration

func (m *Metadata) NextGeneration(buildID uuid.UUID) *Metadata

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL