package granary

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module Granary_storage.HeaderSource

Alternating two-header commit protocol for crash safety. Pages 0 and 1 hold the two alternating file headers. The header with the higher txn_id and valid CRC is the live state.

Sourcetype encryption = {
  1. canary_nonce : string;
    (*

    16 bytes at header bytes 72–87

    *)
  2. canary_tag : string;
    (*

    16 bytes at header bytes 88–103

    *)
}

Encryption marker and key-check canary persisted in the header (#84).

Sourcetype t = {
  1. txn_id : int64;
  2. root_page : int64;
  3. freelist_page : int64;
  4. n_pages_total : int64;
  5. schema_version : int64;
  6. format_version : int32;
    (*

    On-disk format version (#174). Preserved across commits; only a fresh init stamps current_format_version.

    *)
  7. geom : Geometry.t;
    (*

    Page geometry persisted in the header (#95): page_size + reserved bytes, fixed at creation, preserved verbatim across commits.

    *)
  8. enc : encryption option;
    (*

    Encryption marker and key-check canary (#84). None for plaintext databases; Some _ when the "SENC" magic is present on disk.

    *)
}
Sourceval current_format_version : int32

On-disk format version this build writes for freshly-initialised databases. v1 = pre-#174 (no fingerprints); v2 = #174 (schema fingerprints, redundant catalog mirror, per-page fingerprint stamp).

Sourceval max_supported_format_version : int32

Highest on-disk format version this build can open. read_live fails with Unsupported_format for any database stamped above this.

Sourcetype error =
  1. | Io of string
  2. | Both_headers_corrupt
  3. | Unsupported_format of int32
    (*

    on-disk format_version exceeds support

    *)
Sourceval pp : Format.formatter -> t -> unit

Pretty-print all header fields.

Sourceval pp_error : Format.formatter -> error -> unit

Pretty-print an error.

Sourceval peek_geometry : Cstruct.t -> Geometry.t option

#95 bootstrap: discover a file's page geometry from the leading bytes of page 0 (page_size at byte 56, reserved at byte 64) WITHOUT verifying the CRC — the CRC covers the whole real page, whose size is what we're trying to learn. Pass at least the first 68 bytes of page 0 (a default 4096-byte read suffices). Returns None for a fresh/zeroed page or garbage, in which case the caller uses a supplied/default geometry. Once the geometry is known, read_live re-reads and CRC-verifies the full header pages.

Sourceval read_live : Pager.t -> (t, error) result Lwt.t

Read both headers (pages 0 and 1) from the pager. Pick the live one: the valid header (passes CRC) with the higher txn_id. If one is corrupt and the other valid, use the valid one. Returns Error Both_headers_corrupt if neither passes CRC.

Sourceval commit : Pager.t -> prev_header:t -> new_state:t -> (unit, error) result Lwt.t

Commit a new header state. Writes to the INACTIVE header page (the one NOT used by prev_header), computes and seals CRC, then calls Pager.flush (which writes all dirty pages + syncs). The txn_id of the new header is prev_header.txn_id + 1. new_state provides root_page, freelist_page, n_pages_total, schema_version.

Sourceval commit_no_sync : Pager.t -> prev_header:t -> new_state:t -> (unit, error) result Lwt.t

Like commit but defers the device sync to a later Pager.wal_sync. Stages the next header into its inactive slot and pushes all dirty pages through Pager.flush_no_sync; group-commit callers coalesce the actual fsync across multiple writers. On non-WAL backends this falls through to the regular sync flush, so it is safe to call regardless of backend.

Sourceval init : ?enc:encryption option -> Pager.t -> (unit, error) result Lwt.t

Initialise a brand-new empty file: write both header pages with txn_id=0 and zeroed root/freelist. Called once on new file creation. After init, a subsequent read_live returns the zeroed header. ?enc sets the encryption marker and canary on the freshly-created DB (None by default — plaintext).