Skip to documentation
SLOP

tiny.sql.History

Reference tiny.sql History

Defined in tiny.sql.

API (109)

Actions

Public operations.

Types and contracts

Public types and contracts.

Fields and members

Public fields and members.

No direct callersNo direct callstiny.sqlHistory
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/sql/src/history/store.zig:126

zig
pub const History = struct {    pub const ByteRange = struct {        pub const Count = u64;        pub const unit_precision_bytes: Count = 1;        pub const maximum_units_per_second: Count = 512 * 1024 * 1024;        pub const maximum_seconds_per_year: Count = 366 * 24 * 60 * 60;        pub const service_lifetime_years: Count = 1_000;        pub const service_lifetime_seconds: Count =            maximum_seconds_per_year * service_lifetime_years;        pub const maximum_append_bytes: Count =            @as(Count, record_mod.record_header_size) + std.math.maxInt(u32);        pub const budget_bytes: Count = total(            maximum_units_per_second,            service_lifetime_seconds,        ).?;        pub fn total(            units_per_second: Count,            lifetime_seconds: Count,        ) ?Count {            const bytes_per_second = std.math.mul(                Count,                unit_precision_bytes,                units_per_second,            ) catch return null;            return std.math.mul(Count, bytes_per_second, lifetime_seconds) catch null;        }    };    comptime {        std.debug.assert(            @as(u128, ByteRange.budget_bytes) +                @as(u128, ByteRange.maximum_append_bytes) <=                std.math.maxInt(ByteRange.Count),        );        std.debug.assert(@bitSizeOf(usize) >= @bitSizeOf(ByteRange.Count));    }    allocator: Allocator,    io: std.Io,    file: ?std.Io.File = null,    read_only: bool = false,    sidecar_dir: ?std.Io.Dir = null,    sidecar_path: ?[]u8 = null,    /// The length of the history file once pending records are written.    /// The file holds every byte before the pending records and nothing    /// after them, so writing them ends the file where the write stops.    bytes_written: usize = 0,    recovery: Recovery = .clean,    needs_sync: bool = false,    write_batch_depth: usize = 0,    pending_write: std.ArrayList(u8) = .empty,    write_io: WriteIo = .{},    fast_forward: ?FastForwardRecovery = null,    recovery_required: bool = false,    database_roots: std.ArrayList(record_mod.DatabaseRootRecord) = .empty,    relation_roots: std.ArrayList(record_mod.RelationRootRecord) = .empty,    materialized_relation_roots: std.ArrayList(record_mod.MaterializedRelationRoot) = .empty,    relation_rows: std.ArrayList(record_mod.RelationRowsRecord) = .empty,    relation_spans: std.ArrayList(record_mod.RelationSpansRecord) = .empty,    row_chunks: std.ArrayList(record_mod.RowChunkRecord) = .empty,    index_pages: std.ArrayList(record_mod.IndexPageRecord) = .empty,    tree_nodes: std.ArrayList(record_mod.TreeNodeRecord) = .empty,    commits: std.ArrayList(record_mod.CommitRecord) = .empty,    refs: std.ArrayList(record_mod.RefRecord) = .empty,    conflicts: std.ArrayList(record_mod.ConflictRecord) = .empty,    conflict_roots: std.ArrayList(record_mod.ConflictRootRecord) = .empty,    lookup: RecordLookup = .{},    pub const SuffixPlan = struct {        reused: usize,        boundary: i64,    };    pub const RowsNeed = union(enum) {        none,        full,        suffix: SuffixPlan,    };    pub fn open(allocator: Allocator, dir: std.Io.Dir, options: Options) Error!History {        var history = History{            .allocator = allocator,            .io = options.io,            .read_only = options.read_only,        };        errdefer history.deinit();        const recorded_length: ?usize = if (dir.statFile(options.io, options.path, .{})) |stat|            @intCast(stat.size)        else |err| switch (err) {            error.FileNotFound => if (options.create) null else return error.HistoryNotFound,            else => return err,        };        history.file = if (options.read_only)            try dir.openFile(options.io, options.path, .{})        else            try dir.createFile(options.io, options.path, .{ .read = true, .truncate = false });        if (!options.read_only) {            if (dir.openDir(options.io, ".", .{})) |owned_dir| {                history.sidecar_dir = owned_dir;                history.sidecar_path = try allocator.dupe(u8, options.path);            } else |_| {}        }        if (recorded_length) |length| {            history.bytes_written = try recover_mod.replayFile(                &history,                length,                options.replay_instrumentation,                options.control,            );            if (length != history.bytes_written) {                if (options.read_only or options.recovery == .reject) return error.TruncatedHistory;                try history.file.?.setLength(options.io, history.bytes_written);                try history.file.?.sync(options.io);                history.recovery = .{ .truncated = .{                    .original_length = length,                    .valid_length = history.bytes_written,                } };            }            history.refreshRefsSidecar();        }        return history;    }    pub fn deinit(self: *History) void {        if (self.file) |*file| {            if (!self.recovery_required) {                if (self.pending_write.items.len != 0) self.flushPendingWrite() catch {};                if (self.needs_sync) file.sync(self.io) catch {};            }            file.close(self.io);        }        if (self.sidecar_dir) |*dir| dir.close(self.io);        if (self.sidecar_path) |path| self.allocator.free(path);        for (self.database_roots.items) |*record| record.deinit();        for (self.materialized_relation_roots.items) |*record| record.deinit();        for (self.relation_rows.items) |*record| record.deinit(self.allocator);        for (self.relation_spans.items) |*record| record.deinit(self.allocator);        for (self.index_pages.items) |*record| record.deinit(self.allocator);        for (self.commits.items) |*record| record.deinit(self.allocator);        for (self.refs.items) |*record| record.deinit(self.allocator);        for (self.conflicts.items) |*record| record.deinit(self.allocator);        for (self.conflict_roots.items) |*record| record.deinit(self.allocator);        self.database_roots.deinit(self.allocator);        self.relation_roots.deinit(self.allocator);        self.materialized_relation_roots.deinit(self.allocator);        self.relation_rows.deinit(self.allocator);        self.relation_spans.deinit(self.allocator);        self.row_chunks.deinit(self.allocator);        self.index_pages.deinit(self.allocator);        self.tree_nodes.deinit(self.allocator);        self.commits.deinit(self.allocator);        self.refs.deinit(self.allocator);        self.conflicts.deinit(self.allocator);        self.conflict_roots.deinit(self.allocator);        self.lookup.deinit(self.allocator);        self.pending_write.deinit(self.allocator);        self.* = undefined;    }    pub fn putDatabaseRoot(self: *History, root: version.DatabaseRoot) Error!void {        try self.ensureUsable();        if (self.findDatabaseRoot(root.hash) != null) return;        var owned = try root.clone(self.allocator);        errdefer owned.deinit();        try self.database_roots.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.database_roots.ensureUnusedCapacity(self.allocator, 1);        try self.appendDatabaseRootRecord(owned);        self.lookup.database_roots.putAssumeCapacity(owned.hash, self.database_roots.items.len);        self.database_roots.appendAssumeCapacity(.{ .root = owned });        try self.flushSync();    }    pub fn putRelationRoot(self: *History, root: version.RelationRoot) Error!void {        try self.ensureUsable();        if (self.hasRelationRoot(root.hash)) return;        var owned = try root.clone(self.allocator);        var owned_transferred = false;        errdefer if (!owned_transferred) owned.deinit();        var stage = NodeStage.init(self);        defer stage.deinit();        const index_keys = try self.allocator.alloc(?version.Hash, owned.indexes.len);        var index_keys_owned = true;        errdefer if (index_keys_owned) self.allocator.free(index_keys);        const table_key = try stage.mapKey(&owned.table);        for (owned.indexes, index_keys) |*index, *index_key| index_key.* = try stage.mapKey(&index.map);        try stage.flush();        try self.relation_roots.ensureUnusedCapacity(self.allocator, 1);        try self.materialized_relation_roots.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.relation_roots.ensureUnusedCapacity(self.allocator, 1);        try self.appendRelationRootRecord(owned, table_key, index_keys);        materialize_mod.shrinkRelationRootMaps(self.allocator, &owned);        self.lookup.relation_roots.putAssumeCapacity(owned.hash, self.relation_roots.items.len);        self.relation_roots.appendAssumeCapacity(.{            .hash = owned.hash,            .storage = .{ .materialized = self.materialized_relation_roots.items.len },        });        self.materialized_relation_roots.appendAssumeCapacity(.{            .root = owned,            .table_key = table_key,            .index_keys = index_keys,        });        owned_transferred = true;        index_keys_owned = false;        try self.flushSync();    }    pub fn putRelationRows(self: *History, root: version.Hash, rows: []const version.RelationRow) Error!void {        try self.ensureUsable();        if (self.hasRelationRows(root)) return;        const sorted = try self.allocator.dupe(version.RelationRow, rows);        defer if (sorted.len != 0) self.allocator.free(sorted);        std.mem.sort(version.RelationRow, sorted, {}, version.relationRowLessThan);        var writer = try self.beginRelationRows(root);        defer writer.deinit();        for (sorted) |row_value| try writer.append(row_value.rowid, row_value.bytes);        try writer.finish();    }    pub fn beginRelationRows(self: *History, root: version.Hash) Error!RelationRowsWriter {        try self.ensureMutable();        std.debug.assert(!self.hasRelationRows(root));        return .{ .history = self, .root = root, .boundary = null };    }    pub fn beginRelationRowsSuffix(        self: *History,        root: version.Hash,        base: IncrementalBase,        plan: SuffixPlan,    ) Error!RelationRowsWriter {        try self.ensureUsable();        std.debug.assert(!self.hasRelationRows(root));        var base_pages = (try self.relationRowsPages(self.allocator, base.root)) orelse return error.InvalidHistory;        defer base_pages.deinit();        var base_spans = (try self.relationSpans(self.allocator, base.root)) orelse return error.InvalidHistory;        defer base_spans.deinit();        if (plan.reused == 0 or plan.reused >= base_spans.items.len) return error.InvalidHistory;        if (base_spans.items[plan.reused - 1].last != plan.boundary) return error.InvalidHistory;        const base_chunks = try self.baseChunkList(self.allocator, base_pages.items);        defer if (base_chunks.len != 0) self.allocator.free(base_chunks);        if (base_chunks.len != base_spans.items.len) return error.InvalidHistory;        var writer = RelationRowsWriter{ .history = self, .root = root, .boundary = plan.boundary };        errdefer writer.deinit();        try writer.chunks.appendSlice(self.allocator, base_chunks[0..plan.reused]);        try writer.spans.appendSlice(self.allocator, base_spans.items[0..plan.reused]);        return writer;    }    pub fn relationRowsNeed(self: *const History, allocator: Allocator, root: version.Hash, base: ?IncrementalBase) Error!RowsNeed {        try self.ensureUsable();        if (self.hasRelationRows(root)) return .none;        const info = base orelse return .full;        var base_pages = (try self.relationRowsPages(allocator, info.root)) orelse return .full;        defer base_pages.deinit();        var base_spans = (try self.relationSpans(allocator, info.root)) orelse return .full;        defer base_spans.deinit();        if (base_spans.items.len == 0) return .full;        const base_chunks = try self.baseChunkList(allocator, base_pages.items);        defer allocator.free(base_chunks);        if (base_chunks.len != base_spans.items.len) return .full;        const first_affected = firstAffectedSpan(base_spans.items, info.edited);        if (first_affected == 0) return .full;        return .{ .suffix = .{            .reused = first_affected,            .boundary = base_spans.items[first_affected - 1].last,        } };    }    pub fn putRelationRowsSuffix(self: *History, root: version.Hash, base: IncrementalBase, plan: SuffixPlan, tail: []const version.RelationRow) Error!void {        try self.ensureUsable();        if (self.hasRelationRows(root)) return;        if (!relationRowsSorted(tail)) return error.InvalidHistory;        var writer = try self.beginRelationRowsSuffix(root, base, plan);        defer writer.deinit();        for (tail) |row_value| try writer.append(row_value.rowid, row_value.bytes);        try writer.finish();    }    pub fn finishRelationRows(self: *History, root: version.Hash, chunks: []const version.Hash, spans: []const record_mod.ChunkSpan) Error!void {        try self.ensureUsable();        const page_bounds = try chunk_mod.pageBoundaries(self.allocator, chunks);        defer if (page_bounds.len != 0) self.allocator.free(page_bounds);        const pages = try self.allocator.alloc(version.Hash, page_bounds.len);        errdefer if (pages.len != 0) self.allocator.free(pages);        for (page_bounds, pages) |bound, *digest| {            const slice = chunks[bound.start..bound.end];            digest.* = chunk_mod.pageDigest(slice);            try self.putIndexPage(digest.*, slice);        }        try self.relation_rows.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.relation_rows.ensureUnusedCapacity(self.allocator, 1);        try self.appendRelationRowsRecord(root, pages);        self.lookup.relation_rows.putAssumeCapacity(root, self.relation_rows.items.len);        self.relation_rows.appendAssumeCapacity(.{            .root = root,            .storage = .{ .materialized = pages },        });        try self.putRelationSpans(root, spans);        try self.flushSync();    }    pub fn relationSpans(self: *const History, allocator: Allocator, hash: version.Hash) Error!?record_mod.ChunkSpanView {        try self.ensureUsable();        const index = self.lookup.relation_spans.get(hash) orelse return null;        const record = &self.relation_spans.items[index];        return try materialize_mod.readRelationSpansRecord(self, allocator, record.root, record.storage);    }    pub fn putRelationSpans(self: *History, root: version.Hash, spans: []const record_mod.ChunkSpan) Error!void {        try self.ensureUsable();        if (self.lookup.relation_spans.get(root) != null) return;        const owned = try self.allocator.dupe(record_mod.ChunkSpan, spans);        errdefer self.allocator.free(owned);        try self.relation_spans.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.relation_spans.ensureUnusedCapacity(self.allocator, 1);        try self.appendRelationSpansRecord(root, owned);        self.lookup.relation_spans.putAssumeCapacity(root, self.relation_spans.items.len);        self.relation_spans.appendAssumeCapacity(.{            .root = root,            .storage = .{ .materialized = owned },        });    }    pub fn appendRelationSpansRecord(self: *History, root: version.Hash, spans: []const record_mod.ChunkSpan) Error!void {        try self.ensureUsable();        if (spans.len > std.math.maxInt(u32)) return error.InvalidHistory;        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendHash(self.allocator, &payload, root);        try record_mod.appendU32(self.allocator, &payload, @intCast(spans.len));        for (spans) |span| {            try record_mod.appendU64(self.allocator, &payload, @as(u64, @bitCast(span.first)));            try record_mod.appendU64(self.allocator, &payload, @as(u64, @bitCast(span.last)));        }        try self.appendRecord(.relation_spans, payload.items);    }    pub fn baseChunkList(self: *const History, allocator: Allocator, pages: []const version.Hash) Error![]version.Hash {        try self.ensureUsable();        var chunks: std.ArrayList(version.Hash) = .empty;        errdefer chunks.deinit(allocator);        for (pages) |page_digest| {            var page = (try self.indexPageChunks(allocator, page_digest)) orelse return error.InvalidHistory;            defer page.deinit();            try chunks.appendSlice(allocator, page.items);        }        return try chunks.toOwnedSlice(allocator);    }    pub fn putRowChunk(self: *History, digest: version.Hash, rows: []const version.RelationRow) Error!void {        try self.ensureUsable();        if (self.findRowChunk(digest) != null) return;        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendHash(self.allocator, &payload, digest);        try record_mod.appendRelationRows(self.allocator, &payload, rows);        try self.row_chunks.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.row_chunks.ensureUnusedCapacity(self.allocator, 1);        const payload_offset = self.bytes_written + record_mod.record_header_size;        const expected = record_mod.recordHash(@backingInt(record_mod.RecordKind.row_chunk), payload.items);        try self.appendRecord(.row_chunk, payload.items);        self.lookup.row_chunks.putAssumeCapacity(digest, self.row_chunks.items.len);        self.row_chunks.appendAssumeCapacity(.{            .digest = digest,            .payload = .{                .expected = expected,                .offset = payload_offset,                .len = payload.items.len,            },        });    }    pub fn putIndexPage(self: *History, digest: version.Hash, chunks: []const version.Hash) Error!void {        try self.ensureUsable();        if (self.hasIndexPage(digest)) return;        const owned = try self.allocator.dupe(version.Hash, chunks);        errdefer self.allocator.free(owned);        try self.index_pages.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.index_pages.ensureUnusedCapacity(self.allocator, 1);        try self.appendChunkIndexPageRecord(digest, owned);        self.lookup.index_pages.putAssumeCapacity(digest, self.index_pages.items.len);        self.index_pages.appendAssumeCapacity(.{            .digest = digest,            .storage = .{ .materialized = owned },        });    }    pub fn putDatabaseValue(self: *History, value: *const version.DatabaseValue) Error!void {        try self.ensureUsable();        var batch = try self.beginWriteBatch();        errdefer batch.deinit();        for (value.relations) |relation| {            try self.putRelationRoot(relation.root);            try self.putRelationRows(relation.root.hash, relation.rows);        }        try self.putDatabaseRoot(value.root);        try batch.finish();    }    pub fn putCommit(self: *History, commit: version.Commit) Error!void {        try self.ensureUsable();        const canonical = version.Commit.init(commit.root, commit.parents);        if (self.findCommit(canonical.hash) != null) return;        const parents = try self.allocator.dupe(version.Hash, commit.parents);        errdefer self.allocator.free(parents);        try self.commits.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.commits.ensureUnusedCapacity(self.allocator, 1);        try self.appendCommitRecord(canonical.root, parents);        try self.flushSync();        self.lookup.commits.putAssumeCapacity(canonical.hash, self.commits.items.len);        self.commits.appendAssumeCapacity(.{            .parents = parents,            .commit = .{                .root = canonical.root,                .parents = parents,                .hash = canonical.hash,            },        });    }    pub fn putRef(self: *History, ref_value: version.Ref) Error!void {        try self.ensureUsable();        if (self.findCommit(ref_value.target) == null) return error.CommitNotFound;        if (self.findRef(ref_value.name)) |record| {            try self.appendRefRecord(ref_value.name, ref_value.target);            try self.flushSync();            record.ref.target = ref_value.target;            self.refreshRefsSidecar();            return;        }        const name = try self.allocator.dupe(u8, ref_value.name);        errdefer self.allocator.free(name);        try self.refs.ensureUnusedCapacity(self.allocator, 1);        try self.appendRefRecord(name, ref_value.target);        try self.flushSync();        self.refs.appendAssumeCapacity(.{            .name = name,            .ref = .{                .name = name,                .target = ref_value.target,            },        });        self.refreshRefsSidecar();    }    pub fn putRefIfMatches(self: *History, ref_value: version.Ref, expected: ?version.Hash) Error!void {        try self.ensureUsable();        if (self.findCommit(ref_value.target) == null) return error.CommitNotFound;        if (self.findRef(ref_value.name)) |record| {            const expected_hash = expected orelse return error.RefChanged;            if (!version.same(record.ref.target, expected_hash)) return error.RefChanged;        } else if (expected != null) {            return error.RefChanged;        }        try self.putRef(ref_value);    }    pub fn beginFastForward(        self: *History,        name: []const u8,        expected: version.Hash,        target: version.Hash,    ) Error!FastForwardUpdate {        try self.ensureUsable();        if (self.fast_forward != null) return error.RecoveryRequired;        if (self.pending_write.items.len != 0 or            self.needs_sync or            self.write_batch_depth != 0)        {            self.poison();            return error.RecoveryRequired;        }        const ref_record = self.findRef(name) orelse return error.RefNotFound;        if (!version.same(ref_record.ref.target, expected)) return error.RefChanged;        if (self.findCommit(expected) == null or self.findCommit(target) == null) {            return error.CommitNotFound;        }        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendBytes(self.allocator, &payload, name);        try record_mod.appendHash(self.allocator, &payload, expected);        try record_mod.appendHash(self.allocator, &payload, target);        const id = record_mod.recordHash(            @backingInt(record_mod.RecordKind.fast_forward_prepare),            payload.items,        );        try self.appendCoordinatorRecord(.fast_forward_prepare, payload.items);        self.fast_forward = .{            .id = id,            .name = ref_record.name,            .expected = expected,            .target = target,        };        return .{ .history = self, .id = id };    }    pub fn fastForwardRecovery(self: *const History) ?*const FastForwardRecovery {        return if (self.fast_forward) |*recovery| recovery else null;    }    pub fn poison(self: *History) void {        self.recovery_required = true;    }    pub fn requiresRecovery(self: *const History) bool {        return self.recovery_required;    }    fn decideFastForward(        self: *History,        id: version.Hash,        decision: FastForwardDecision,    ) Error!void {        try self.ensureUsable();        const recovery = if (self.fast_forward) |*active| active else return error.InvalidHistory;        if (!version.same(recovery.id, id) or recovery.decision != .pending) {            return error.InvalidHistory;        }        const ref_record = self.findRef(recovery.name) orelse return error.InvalidHistory;        if (!version.same(ref_record.ref.target, recovery.expected)) return error.InvalidHistory;        const kind: record_mod.RecordKind = switch (decision) {            .pending => return error.InvalidHistory,            .baseline => .fast_forward_abort,            .target => .fast_forward_commit,        };        try self.appendCoordinatorHashRecord(kind, id);        if (decision == .target) ref_record.ref.target = recovery.target;        recovery.decision = decision;    }    fn completeFastForward(self: *History, id: version.Hash) Error!void {        try self.ensureUsable();        const recovery = if (self.fast_forward) |*active| active else return error.InvalidHistory;        if (!version.same(recovery.id, id) or recovery.decision == .pending) {            return error.InvalidHistory;        }        const ref_record = self.findRef(recovery.name) orelse return error.InvalidHistory;        const selected = switch (recovery.decision) {            .pending => unreachable,            .baseline => recovery.expected,            .target => recovery.target,        };        if (!version.same(ref_record.ref.target, selected)) return error.InvalidHistory;        try self.appendCoordinatorHashRecord(.fast_forward_complete, id);        self.fast_forward = null;        self.refreshRefsSidecar();    }    fn ensureUsable(self: *const History) Error!void {        if (self.recovery_required) return error.RecoveryRequired;    }    fn ensureMutable(self: *const History) Error!void {        try self.ensureUsable();        if (self.read_only) return error.ReadOnly;        if (self.fast_forward != null) return error.RecoveryRequired;    }    pub fn deleteRef(self: *History, name: []const u8) Error!void {        try self.ensureUsable();        const index = self.findRefIndex(name) orelse return error.RefNotFound;        try self.appendRefDeleteRecord(name);        try self.flushSync();        var removed = self.refs.orderedRemove(index);        removed.deinit(self.allocator);        self.refreshRefsSidecar();    }    pub fn createBranch(self: *History, name: []const u8, target: version.Hash) Error!version.Ref {        try self.ensureUsable();        if (self.findRef(name) != null) return error.RefExists;        if (self.findCommit(target) == null) return error.CommitNotFound;        const ref_value = version.Ref{            .name = name,            .target = target,        };        try self.putRef(ref_value);        return (try self.ref(name)).?;    }    pub fn checkoutBranch(self: *const History, name: []const u8) Error!branch.Checkout {        try self.ensureUsable();        const record = self.findRef(name) orelse return error.RefNotFound;        const commit = self.findCommit(record.ref.target) orelse return error.CommitNotFound;        return branch.checkout(record.ref, commit.commit.root);    }    pub fn fastForwardBranch(self: *History, allocator: Allocator, name: []const u8, target: version.Hash) Error!void {        try self.ensureUsable();        const record = self.findRef(name) orelse return error.RefNotFound;        var ref_value = record.ref;        const entries = try self.commitEntries(allocator);        defer allocator.free(entries);        try branch.fastForwardRef(allocator, entries, &ref_value, target);        try self.putRef(ref_value);    }    pub fn commitBranch(self: *History, name: []const u8, root: version.Hash) Error!version.Hash {        try self.ensureUsable();        const record = self.findRef(name) orelse return error.RefNotFound;        if (self.findCommit(record.ref.target) == null) return error.CommitNotFound;        var parents = [_]version.Hash{record.ref.target};        const commit = version.Commit.init(root, parents[0..]);        try self.putCommitAndRef(commit, record, commit.hash);        return commit.hash;    }    pub fn mergeCommitBranch(self: *History, name: []const u8, root: version.Hash, theirs: version.Hash) Error!version.Hash {        try self.ensureUsable();        const record = self.findRef(name) orelse return error.RefNotFound;        if (self.findCommit(record.ref.target) == null) return error.CommitNotFound;        if (self.findCommit(theirs) == null) return error.CommitNotFound;        var parents = [_]version.Hash{ record.ref.target, theirs };        const commit = version.Commit.init(root, parents[0..]);        try self.putCommitAndRef(commit, record, commit.hash);        return commit.hash;    }    pub fn putCommitAndRef(self: *History, commit: version.Commit, ref_record: *record_mod.RefRecord, target: version.Hash) Error!void {        try self.ensureUsable();        const canonical = version.Commit.init(commit.root, commit.parents);        const append_commit = self.findCommit(canonical.hash) == null;        var parents: []version.Hash = &.{};        if (append_commit) parents = try self.allocator.dupe(version.Hash, canonical.parents);        var parents_live = append_commit;        errdefer if (parents_live) self.allocator.free(parents);        if (append_commit) {            try self.commits.ensureUnusedCapacity(self.allocator, 1);            try self.lookup.commits.ensureUnusedCapacity(self.allocator, 1);            try self.appendCommitRecord(canonical.root, parents);        }        try self.appendRefRecord(ref_record.name, target);        try self.flushSync();        if (append_commit) {            self.lookup.commits.putAssumeCapacity(canonical.hash, self.commits.items.len);            self.commits.appendAssumeCapacity(.{                .parents = parents,                .commit = .{                    .root = canonical.root,                    .parents = parents,                    .hash = canonical.hash,                },            });            parents_live = false;        }        ref_record.ref.target = target;        self.refreshRefsSidecar();    }    pub fn putConflict(self: *History, artifact: version.ConflictArtifact) Error!void {        try self.ensureUsable();        const canonical = conflict_mod.canonicalConflictArtifact(artifact);        if (self.findConflict(canonical.hash) != null) return;        var owned = try conflict_mod.cloneConflictArtifact(self.allocator, artifact);        errdefer conflict_mod.deinitConflictArtifact(self.allocator, &owned);        try self.conflicts.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.conflicts.ensureUnusedCapacity(self.allocator, 1);        try self.appendConflictRecord(canonical);        try self.flushSync();        self.lookup.conflicts.putAssumeCapacity(canonical.hash, self.conflicts.items.len);        self.conflicts.appendAssumeCapacity(.{ .artifact = owned });    }    pub fn putConflictRoot(self: *History, entries: []const version.ConflictEntry) Error!version.ConflictRoot {        try self.ensureUsable();        if (entries.len == 0) return version.ConflictRoot.empty();        const owned = try conflict_mod.cloneConflictEntriesSorted(self.allocator, entries);        var owned_live = true;        errdefer if (owned_live) conflict_mod.deinitConflictEntries(self.allocator, owned);        try self.validateConflictEntries(owned);        const root = version.ConflictRoot.init(owned);        if (self.findConflictRoot(root.hash) != null) {            try self.validateConflictRoot(root.hash);            conflict_mod.deinitConflictEntries(self.allocator, owned);            owned_live = false;            return root;        }        try self.conflict_roots.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.conflict_roots.ensureUnusedCapacity(self.allocator, 1);        try self.appendConflictRootRecord(owned);        try self.flushSync();        self.lookup.conflict_roots.putAssumeCapacity(root.hash, self.conflict_roots.items.len);        self.conflict_roots.appendAssumeCapacity(.{            .root = root,            .entries = owned,        });        owned_live = false;        return root;    }    pub fn ref(self: *const History, name: []const u8) Error!?version.Ref {        try self.ensureUsable();        for (self.refs.items) |record| {            if (std.mem.eql(u8, record.name, name)) return record.ref;        }        return null;    }    pub fn refList(self: *const History, allocator: Allocator) Error![]version.Ref {        try self.ensureUsable();        const refs = try allocator.alloc(version.Ref, self.refs.items.len);        var count: usize = 0;        errdefer freeRefList(allocator, refs[0..count]);        for (self.refs.items, refs) |record, *target| {            const name = try allocator.dupe(u8, record.name);            target.* = .{                .name = name,                .target = record.ref.target,            };            count += 1;        }        return refs;    }    pub fn conflict(self: *const History, hash: version.Hash) ?version.ConflictArtifact {        if (self.findConflict(hash)) |record| return record.artifact;        return null;    }    pub fn hasCommit(self: *const History, hash: version.Hash) bool {        return self.findCommit(hash) != null;    }    pub fn hasDatabaseRoot(self: *const History, hash: version.Hash) bool {        return self.findDatabaseRoot(hash) != null;    }    pub fn hasConflict(self: *const History, hash: version.Hash) bool {        return self.findConflict(hash) != null;    }    pub fn hasConflictRoot(self: *const History, hash: version.Hash) Error!bool {        self.validateConflictRoot(hash) catch |err| switch (err) {            error.ConflictRootNotFound => return false,            else => return err,        };        return true;    }    pub fn validateConflictRoot(self: *const History, hash: version.Hash) Error!void {        try self.ensureUsable();        if (version.same(hash, version.ConflictRoot.empty().hash)) return;        const record = self.findConflictRoot(hash) orelse return error.ConflictRootNotFound;        const derived = version.ConflictRoot.init(record.entries);        if (!version.same(record.root.hash, hash) or            !version.same(derived.hash, hash) or            derived.count != record.root.count)        {            return error.InvalidHistory;        }        try self.validateConflictEntries(record.entries);    }    pub fn validateConflictEntries(        self: *const History,        entries: []const version.ConflictEntry,    ) error{ InvalidHistory, ConflictArtifactNotFound }!void {        var previous: ?version.ConflictEntry = null;        for (entries) |entry| {            if (previous) |prior| {                if (prior.sameSlot(entry) or                    !version.ConflictEntry.lessThan({}, prior, entry))                {                    return error.InvalidHistory;                }            }            const artifact_record = self.findConflict(entry.hash) orelse {                return error.ConflictArtifactNotFound;            };            if (!entry.eql(artifact_record.artifact.entry())) {                return error.InvalidHistory;            }            previous = entry;        }    }    pub fn conflictEntries(self: *const History, allocator: Allocator, root: version.Hash) Error!conflict_mod.ConflictEntries {        try self.ensureUsable();        if (version.same(root, version.ConflictRoot.empty().hash)) {            return .{                .allocator = allocator,                .root = version.ConflictRoot.empty(),                .entries = &.{},            };        }        try self.validateConflictRoot(root);        const record = self.findConflictRoot(root) orelse return error.ConflictRootNotFound;        const entries = try conflict_mod.cloneConflictEntries(allocator, record.entries);        errdefer conflict_mod.deinitConflictEntries(allocator, entries);        return .{            .allocator = allocator,            .root = record.root,            .entries = entries,        };    }    pub fn conflictArtifacts(self: *const History, allocator: Allocator, root: version.Hash) Error!conflict_mod.ConflictArtifacts {        try self.ensureUsable();        var entries = try self.conflictEntries(allocator, root);        defer entries.deinit();        if (entries.entries.len == 0) {            return .{                .allocator = allocator,                .root = entries.root,                .artifacts = &.{},            };        }        const artifacts = try allocator.alloc(version.ConflictArtifact, entries.entries.len);        var count: usize = 0;        errdefer {            for (artifacts[0..count]) |*artifact| conflict_mod.deinitConflictArtifact(allocator, artifact);            allocator.free(artifacts);        }        for (entries.entries, artifacts) |entry, *target| {            const record = self.findConflict(entry.hash) orelse return error.ConflictArtifactNotFound;            target.* = try conflict_mod.cloneConflictArtifact(allocator, record.artifact);            count += 1;        }        return .{            .allocator = allocator,            .root = entries.root,            .artifacts = artifacts,        };    }    pub fn commitValue(self: *const History, hash: version.Hash) Error!version.Commit {        try self.ensureUsable();        const record = self.findCommit(hash) orelse return error.CommitNotFound;        return record.commit;    }    pub fn databaseRoot(self: *const History, allocator: Allocator, root: version.Hash) Error!version.DatabaseRoot {        try self.ensureUsable();        const record = self.findDatabaseRoot(root) orelse return error.DatabaseRootNotFound;        return try record.root.clone(allocator);    }    pub fn databaseValue(self: *const History, allocator: Allocator, root: version.Hash) Error!version.DatabaseValue {        try self.ensureUsable();        var database_root = try self.databaseRoot(allocator, root);        defer database_root.deinit();        const relations = try allocator.alloc(version.RelationValue, database_root.entries.len);        var relation_count: usize = 0;        var relations_owned = true;        errdefer {            if (relations_owned) {                for (relations[0..relation_count]) |*relation| relation.deinit(allocator);                if (relations.len != 0) allocator.free(relations);            }        }        for (database_root.entries, relations) |entry, *relation| {            var relation_root = try self.relationRoot(allocator, entry.hash);            errdefer relation_root.deinit();            const rows = try self.relationRows(allocator, entry.hash);            errdefer version.freeRelationRows(allocator, rows);            relation.* = .{                .root = relation_root,                .rows = rows,            };            relation_count += 1;        }        var value = try version.databaseValueFromOwnedRelations(allocator, relations, database_root.conflicts);        relations_owned = false;        errdefer value.deinit();        if (!version.same(value.root.hash, database_root.hash)) return error.InvalidHistory;        return value;    }    pub fn relationRoot(self: *const History, allocator: Allocator, root: version.Hash) Error!version.RelationRoot {        try self.ensureUsable();        const record = self.findRelationRoot(root) orelse return error.RelationRootNotFound;        var out: version.RelationRoot = undefined;        var table_key: ?version.Hash = null;        var index_keys: []const ?version.Hash = &.{};        var owned_index_keys: ?[]?version.Hash = null;        defer if (owned_index_keys) |owned| allocator.free(owned);        switch (record.storage) {            .materialized => |index| {                const materialized = &self.materialized_relation_roots.items[index];                out = try materialized.root.clone(allocator);                table_key = materialized.table_key;                index_keys = materialized.index_keys;            },            .indexed => |location| {                const decoded = try materialize_mod.readIndexedRelationRoot(self, allocator, record.hash, location);                out = decoded.root;                table_key = decoded.table_key;                index_keys = decoded.index_keys;                owned_index_keys = decoded.index_keys;            },        }        errdefer out.deinit();        const table = try materialize_mod.merkleMapRoot(self, allocator, out.table.summary, out.table.hash, out.table.subtree, table_key);        var table_swapped = out.table;        out.table = table;        table_swapped.deinit();        for (out.indexes, index_keys) |*index, index_key| {            const map = try materialize_mod.merkleMapRoot(self, allocator, index.map.summary, index.map.hash, index.map.subtree, index_key);            var map_swapped = index.map;            index.map = map;            map_swapped.deinit();        }        return out;    }    pub fn relationRows(self: *const History, allocator: Allocator, root: version.Hash) Error![]version.RelationRow {        try self.ensureUsable();        var pages = (try self.relationRowsPages(allocator, root)) orelse return error.RelationRowsNotFound;        defer pages.deinit();        var rows: std.ArrayList(version.RelationRow) = .empty;        errdefer {            for (rows.items) |row_value| allocator.free(row_value.bytes);            rows.deinit(allocator);        }        for (pages.items) |page_digest| {            var chunks = (try self.indexPageChunks(allocator, page_digest)) orelse return error.RelationRowsNotFound;            defer chunks.deinit();            for (chunks.items) |digest| {                const chunk_record = self.findRowChunk(digest) orelse return error.RelationRowsNotFound;                try self.chunkRowsInto(allocator, chunk_record, &rows);            }        }        return try rows.toOwnedSlice(allocator);    }    pub fn chunkRowsInto(self: *const History, allocator: Allocator, record: *const record_mod.RowChunkRecord, rows: *std.ArrayList(version.RelationRow)) Error!void {        try self.ensureUsable();        const payload = try materialize_mod.readPayload(self, allocator, .row_chunk, record.payload);        defer allocator.free(payload);        var reader = record_mod.PayloadReader.init(payload);        const digest = try reader.hash();        if (!version.same(digest, record.digest)) return error.InvalidHistory;        const row_count = try reader.readU32();        try rows.ensureUnusedCapacity(allocator, row_count);        var read_rows: u32 = 0;        while (read_rows < row_count) : (read_rows += 1) {            const rowid = try reader.readI64();            const bytes = try allocator.dupe(u8, try reader.readBytes());            rows.appendAssumeCapacity(.{                .rowid = rowid,                .bytes = bytes,            });        }        try reader.finish();    }    pub fn commitDatabaseRoot(self: *const History, allocator: Allocator, commit_hash: version.Hash) Error!version.DatabaseRoot {        try self.ensureUsable();        const commit_value = try self.commitValue(commit_hash);        return try self.databaseRoot(allocator, commit_value.root);    }    pub fn commitEntries(self: *const History, allocator: Allocator) Error![]branch.CommitEntry {        try self.ensureUsable();        const entries = try allocator.alloc(branch.CommitEntry, self.commits.items.len);        for (self.commits.items, entries) |record, *entry| {            entry.* = branch.commitEntry(record.commit);        }        return entries;    }    pub fn len(self: *const History) usize {        return self.bytes_written;    }    pub fn hasRelationRoot(self: *const History, hash: version.Hash) bool {        return self.lookup.relation_roots.get(hash) != null;    }    pub fn hasRelationRows(self: *const History, root: version.Hash) bool {        return self.lookup.relation_rows.get(root) != null;    }    pub fn hasIndexPage(self: *const History, digest: version.Hash) bool {        return self.lookup.index_pages.get(digest) != null;    }    pub fn hasRowChunk(self: *const History, digest: version.Hash) bool {        return self.findRowChunk(digest) != null;    }    pub fn hasTreeNode(self: *const History, key: version.Hash) bool {        return self.findTreeNode(key) != null;    }    pub fn databaseRootView(self: *const History, hash: version.Hash) ?DatabaseRootView {        const record = self.findDatabaseRoot(hash) orelse return null;        return .{            .conflicts = record.root.conflicts,            .entries = record.root.entries,        };    }    pub fn relationKeysView(self: *const History, allocator: Allocator, hash: version.Hash) Error!?RelationKeysView {        try self.ensureUsable();        const record = self.findRelationRoot(hash) orelse return null;        switch (record.storage) {            .materialized => |index| {                const materialized = &self.materialized_relation_roots.items[index];                return .{                    .allocator = allocator,                    .table_key = materialized.table_key,                    .index_keys = materialized.index_keys,                };            },            .indexed => |location| {                var decoded = try materialize_mod.readIndexedRelationRoot(self, allocator, record.hash, location);                defer decoded.root.deinit();                return .{                    .allocator = allocator,                    .owned = decoded.index_keys,                    .table_key = decoded.table_key,                    .index_keys = decoded.index_keys,                };            },        }    }    pub fn relationRowsPages(self: *const History, allocator: Allocator, root: version.Hash) Error!?record_mod.HashListView {        try self.ensureUsable();        const index = self.lookup.relation_rows.get(root) orelse return null;        const record = &self.relation_rows.items[index];        return try materialize_mod.readHashListRecord(self, allocator, .relation_rows, record.root, record.storage);    }    pub fn indexPageChunks(self: *const History, allocator: Allocator, digest: version.Hash) Error!?record_mod.HashListView {        try self.ensureUsable();        const index = self.lookup.index_pages.get(digest) orelse return null;        const record = &self.index_pages.items[index];        return try materialize_mod.readHashListRecord(self, allocator, .chunk_index_page, record.digest, record.storage);    }    pub fn treeNodeChildren(self: *const History, allocator: Allocator, key: version.Hash) Error![]version.Hash {        try self.ensureUsable();        const index = self.lookup.tree_nodes.get(key) orelse return error.InvalidHistory;        const node = try materialize_mod.readTreeNodeRecord(self, allocator, &self.tree_nodes.items[index]);        allocator.free(node.node.lower);        if (node.node.upper) |upper| allocator.free(upper);        return node.children;    }    pub fn appendPackRecordPayload(self: *const History, allocator: Allocator, target: *std.ArrayList(u8), kind: record_mod.PackRecordKind, hash: version.Hash) Error!void {        try self.ensureUsable();        switch (kind) {            .row_chunk => try pack_mod.appendRowChunkPackPayload(self, allocator, target, hash),            .chunk_index_page => try pack_mod.appendChunkIndexPagePackPayload(self, allocator, target, hash),            .tree_node => try pack_mod.appendTreeNodePackPayload(self, allocator, target, hash),            .relation_rows => try pack_mod.appendRelationRowsPackPayload(self, allocator, target, hash),            .relation_root => try pack_mod.appendRelationRootPackPayload(self, allocator, target, hash),            .database_root => try pack_mod.appendDatabaseRootPackPayload(self, allocator, target, hash),            .conflict => try pack_mod.appendConflictPackPayload(self, allocator, target, hash),            .conflict_root => try pack_mod.appendConflictRootPackPayload(self, allocator, target, hash),        }    }    pub fn packRecordPresent(self: *const History, kind: record_mod.PackRecordKind, payload: []const u8) Error!bool {        try self.ensureUsable();        var reader = record_mod.PayloadReader.init(payload);        switch (kind) {            .row_chunk => return self.findRowChunk(try reader.hash()) != null,            .chunk_index_page => return self.hasIndexPage(try reader.hash()),            .tree_node => {                if (try reader.readU32() != 1) return error.InvalidHistory;                return self.findTreeNode(try reader.hash()) != null;            },            .relation_rows => return self.hasRelationRows(try reader.hash()),            .relation_root => {                var decoded = try materialize_mod.readRelationRootShallow(self.allocator, &reader);                defer decoded.root.deinit();                defer self.allocator.free(decoded.index_keys);                return self.findRelationRoot(decoded.root.hash) != null;            },            .database_root => {                const conflicts = try reader.hash();                const entry_count = try reader.readU32();                const entries = try self.allocator.alloc(version.RelationEntry, entry_count);                defer self.allocator.free(entries);                for (entries) |*entry| {                    const name = try reader.readBytes();                    const hash = try reader.hash();                    entry.* = .{                        .name = name,                        .hash = hash,                    };                }                var root = try version.DatabaseRoot.initSorted(self.allocator, entries, .{ .hash = conflicts });                const hash = root.hash;                root.deinit();                return self.findDatabaseRoot(hash) != null;            },            .conflict => {                const decoded = try conflict_mod.decodeConflictArtifactPayload(&reader);                return self.findConflict(decoded.hash) != null;            },            .conflict_root => {                const entries = try conflict_mod.readConflictEntries(self.allocator, &reader);                defer conflict_mod.deinitConflictEntries(self.allocator, entries);                try reader.finish();                self.validateConflictEntries(entries) catch {                    return error.InvalidHistory;                };                const root = version.ConflictRoot.init(entries);                if (self.findConflictRoot(root.hash) == null) return false;                try self.validateConflictRoot(root.hash);                return true;            },        }    }    pub fn importPackRecord(self: *History, kind: record_mod.PackRecordKind, payload: []const u8) Error!bool {        try self.ensureUsable();        return switch (kind) {            .row_chunk => try pack_mod.importRowChunkPayload(self, payload),            .chunk_index_page => try pack_mod.importChunkIndexPagePayload(self, payload),            .tree_node => try pack_mod.importTreeNodePayload(self, payload),            .relation_rows => try pack_mod.importRelationRowsPayload(self, payload),            .relation_root => try pack_mod.importRelationRootPayload(self, payload),            .database_root => try pack_mod.importDatabaseRootPayload(self, payload),            .conflict => try pack_mod.importConflictPayload(self, payload),            .conflict_root => try pack_mod.importConflictRootPayload(self, payload),        };    }    pub fn importPackCommit(self: *History, root: version.Hash, parents: []const version.Hash) Error!bool {        try self.ensureUsable();        const canonical = version.Commit.init(root, parents);        if (self.findCommit(canonical.hash) != null) return false;        if (self.findDatabaseRoot(root) == null) return error.InvalidHistory;        const owned = try self.allocator.dupe(version.Hash, parents);        errdefer self.allocator.free(owned);        try self.commits.ensureUnusedCapacity(self.allocator, 1);        try self.lookup.commits.ensureUnusedCapacity(self.allocator, 1);        try self.appendCommitRecord(canonical.root, owned);        self.lookup.commits.putAssumeCapacity(canonical.hash, self.commits.items.len);        self.commits.appendAssumeCapacity(.{            .parents = owned,            .commit = .{                .root = canonical.root,                .parents = owned,                .hash = canonical.hash,            },        });        return true;    }    fn appendDatabaseRootRecord(self: *History, root: version.DatabaseRoot) Error!void {        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendDatabaseRootValue(self.allocator, &payload, root);        try self.appendRecord(.database_root, payload.items);    }    fn appendRelationRootRecord(self: *History, root: version.RelationRoot, table_key: ?version.Hash, index_keys: []const ?version.Hash) Error!void {        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendRelationRootMerkle(self.allocator, &payload, root, table_key, index_keys);        try self.appendRecord(.relation_root, payload.items);    }    fn appendRelationRowsRecord(self: *History, root: version.Hash, pages: []const version.Hash) Error!void {        if (pages.len > std.math.maxInt(u32)) return error.InvalidHistory;        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendHash(self.allocator, &payload, root);        try record_mod.appendU32(self.allocator, &payload, @intCast(pages.len));        for (pages) |digest| try record_mod.appendHash(self.allocator, &payload, digest);        try self.appendRecord(.relation_rows, payload.items);    }    fn appendChunkIndexPageRecord(self: *History, digest: version.Hash, chunks: []const version.Hash) Error!void {        if (chunks.len > std.math.maxInt(u32)) return error.InvalidHistory;        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendHash(self.allocator, &payload, digest);        try record_mod.appendU32(self.allocator, &payload, @intCast(chunks.len));        for (chunks) |chunk_digest| try record_mod.appendHash(self.allocator, &payload, chunk_digest);        try self.appendRecord(.chunk_index_page, payload.items);    }    fn appendCommitRecord(self: *History, root: version.Hash, parents: []const version.Hash) Error!void {        if (parents.len > std.math.maxInt(u32)) return error.InvalidHistory;        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendHash(self.allocator, &payload, root);        try record_mod.appendU32(self.allocator, &payload, @intCast(parents.len));        for (parents) |parent| try record_mod.appendHash(self.allocator, &payload, parent);        try self.appendRecord(.commit, payload.items);    }    fn appendRefRecord(self: *History, name: []const u8, target: version.Hash) Error!void {        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendHash(self.allocator, &payload, target);        try record_mod.appendBytes(self.allocator, &payload, name);        try self.appendRecord(.ref, payload.items);    }    fn appendRefDeleteRecord(self: *History, name: []const u8) Error!void {        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try record_mod.appendBytes(self.allocator, &payload, name);        try self.appendRecord(.ref_delete, payload.items);    }    fn appendConflictRecord(self: *History, artifact: version.ConflictArtifact) Error!void {        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try conflict_mod.appendConflictArtifactRecordPayload(self.allocator, &payload, artifact);        try self.appendRecord(.conflict, payload.items);    }    fn appendConflictRootRecord(self: *History, entries: []const version.ConflictEntry) Error!void {        var payload: std.ArrayList(u8) = .empty;        defer payload.deinit(self.allocator);        try conflict_mod.appendConflictEntries(self.allocator, &payload, entries);        try self.appendRecord(.conflict_root, payload.items);    }    pub fn appendRecord(self: *History, kind: record_mod.RecordKind, payload: []const u8) Error!void {        try self.ensureMutable();        const record = try encodeRecord(self.allocator, kind, payload);        defer self.allocator.free(record);        const next_bytes_written = std.math.add(            usize,            self.bytes_written,            record.len,        ) catch return error.InvalidHistory;        try self.pending_write.appendSlice(self.allocator, record);        self.bytes_written = next_bytes_written;        self.needs_sync = true;        if (self.write_batch_depth == 0) {            try self.flushPendingWrite();            try self.flushSync();        }    }    fn appendCoordinatorRecord(self: *History, kind: record_mod.RecordKind, payload: []const u8) Error!void {        if (self.write_batch_depth != 0 or            self.pending_write.items.len != 0 or            self.needs_sync)        {            return error.InvalidHistory;        }        const record = try encodeRecord(self.allocator, kind, payload);        defer self.allocator.free(record);        try self.pending_write.ensureUnusedCapacity(self.allocator, record.len);        try self.persistCoordinatorRecord(record);    }    fn appendCoordinatorHashRecord(self: *History, kind: record_mod.RecordKind, id: version.Hash) Error!void {        if (self.write_batch_depth != 0 or            self.pending_write.items.len != 0 or            self.needs_sync)        {            return error.InvalidHistory;        }        var record: [record_mod.record_header_size + version.hash_bytes]u8 = undefined;        std.mem.writeInt(u32, record[0..4], record_mod.magic, .big);        std.mem.writeInt(u32, record[4..8], record_mod.format_version, .big);        std.mem.writeInt(u32, record[8..12], @backingInt(kind), .big);        std.mem.writeInt(u32, record[12..16], version.hash_bytes, .big);        const digest = record_mod.recordHash(@backingInt(kind), id[0..]);        @memcpy(record[16..record_mod.record_header_size], digest[0..]);        @memcpy(record[record_mod.record_header_size..], id[0..]);        try self.pending_write.ensureUnusedCapacity(self.allocator, record.len);        try self.persistCoordinatorRecord(record[0..]);    }    fn persistCoordinatorRecord(self: *History, record: []const u8) Error!void {        if (self.read_only) return error.ReadOnly;        const start = self.bytes_written;        self.pending_write.appendSliceAssumeCapacity(record);        self.bytes_written = std.math.add(usize, start, record.len) catch {            self.pending_write.clearRetainingCapacity();            return error.InvalidHistory;        };        self.needs_sync = true;        self.flushPendingWrite() catch |err| {            self.restorePreparedAppend(start) catch {                self.poison();                return error.RecoveryRequired;            };            return err;        };        self.flushSync() catch |err| {            self.restorePreparedAppend(start) catch {                self.poison();                return error.RecoveryRequired;            };            return err;        };    }    pub fn flushSync(self: *History) Error!void {        try self.ensureUsable();        if (!self.needs_sync) return;        if (self.write_batch_depth != 0) return;        try self.flushPendingWrite();        const file = self.file orelse return error.InvalidHistory;        try file.sync(self.io);        self.write_io.syncs += 1;        self.needs_sync = false;    }    fn refreshRefsSidecar(self: *History) void {        if (self.fast_forward != null or self.recovery_required) return;        const dir = self.sidecar_dir orelse return;        const path = self.sidecar_path orelse return;        if (self.needs_sync or self.write_batch_depth != 0) return;        if (self.pending_write.items.len != 0) return;        if (self.refs.items.len > refs_mod.max_entries) return;        const entries = self.allocator.alloc(refs_mod.Entry, self.refs.items.len) catch return;        defer self.allocator.free(entries);        for (self.refs.items, 0..) |record, index| {            std.debug.assert(record.ref.name.len != 0);            const commit = self.findCommit(record.ref.target) orelse return;            const root = self.findDatabaseRoot(commit.commit.root) orelse return;            entries[index] = .{                .name = record.ref.name,                .head = record.ref.target,                .root = commit.commit.root,                .conflicts = root.root.conflicts,            };        }        refs_mod.store(self.allocator, self.io, dir, path, self.bytes_written, entries) catch return;    }    fn flushPendingWrite(self: *History) Error!void {        if (self.pending_write.items.len == 0) return;        const file = self.file orelse return error.InvalidHistory;        const start = self.bytes_written - self.pending_write.items.len;        errdefer if (file.setLength(self.io, start)) {            self.write_io.resizes += 1;        } else |_| {};        try file.writePositionalAll(self.io, self.pending_write.items, start);        self.write_io.writes += 1;        self.pending_write.clearRetainingCapacity();    }    fn restorePreparedAppend(self: *History, bytes_written: usize) Error!void {        const file = self.file orelse return error.InvalidHistory;        try file.setLength(self.io, bytes_written);        self.write_io.resizes += 1;        self.pending_write.clearRetainingCapacity();        self.bytes_written = bytes_written;        self.needs_sync = false;        try file.sync(self.io);    }    pub fn beginWriteBatch(self: *History) Error!WriteBatch {        try self.ensureMutable();        self.write_batch_depth += 1;        return .{ .history = self };    }    pub fn findCommit(self: *const History, hash: version.Hash) ?*record_mod.CommitRecord {        const index = self.lookup.commits.get(hash) orelse return null;        return &self.commits.items[index];    }    pub fn findDatabaseRoot(self: *const History, hash: version.Hash) ?*record_mod.DatabaseRootRecord {        const index = self.lookup.database_roots.get(hash) orelse return null;        return &self.database_roots.items[index];    }    pub fn findRelationRoot(self: *const History, hash: version.Hash) ?*record_mod.RelationRootRecord {        const index = self.lookup.relation_roots.get(hash) orelse return null;        return &self.relation_roots.items[index];    }    pub fn findRowChunk(self: *const History, digest: version.Hash) ?*record_mod.RowChunkRecord {        const index = self.lookup.row_chunks.get(digest) orelse return null;        return &self.row_chunks.items[index];    }    pub fn findTreeNode(self: *const History, key: version.Hash) ?*record_mod.TreeNodeRecord {        const index = self.lookup.tree_nodes.get(key) orelse return null;        return &self.tree_nodes.items[index];    }    pub fn findRef(self: *const History, name: []const u8) ?*record_mod.RefRecord {        for (self.refs.items) |*record| {            if (std.mem.eql(u8, record.name, name)) return record;        }        return null;    }    pub fn findRefIndex(self: *const History, name: []const u8) ?usize {        for (self.refs.items, 0..) |record, index| {            if (std.mem.eql(u8, record.name, name)) return index;        }        return null;    }    pub fn findConflict(self: *const History, hash: version.Hash) ?*record_mod.ConflictRecord {        const index = self.lookup.conflicts.get(hash) orelse return null;        return &self.conflicts.items[index];    }    pub fn findConflictRoot(self: *const History, hash: version.Hash) ?*record_mod.ConflictRootRecord {        const index = self.lookup.conflict_roots.get(hash) orelse return null;        return &self.conflict_roots.items[index];    }};

Source: lib/sql/src/root.zig:84

zig
pub const History = history.History;
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryappendPackRecordPayload
Static calls · unresolved targets: 0 · external targets: 8.
Called byCallsprivate sourcelib.sql.src.history.store.HistoryappendChunkIndexPageRecordprivate sourcelib.sql.src.history.store.HistoryappendCommitRecordprivate sourcelib.sql.src.history.store.HistoryappendConflictRecordprivate sourcelib.sql.src.history.store.HistoryappendConflictRootRecordprivate sourcelib.sql.src.history.store.HistoryappendDatabaseRootRecord+6 moreprivate sourcelib.sql.src.history.store.HistoryensureMutableprivate sourcelib.sql.src.history.store.HistoryflushPendingWriteHistoryflushSyncprivate sourcelib.sql.src.history.storeencodeRecordHistoryappendRecord
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsHistoryputRelationSpansHistoryappendRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryappendRelationSpansRecord
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsHistorybeginRelationRowsSuffixHistoryrelationRowsNeedprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryindexPageChunksHistorybaseChunkList
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryappendCoordinatorRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistorypoisonversionsameHistorybeginFastForward
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsHistoryputRelationRowsprivate sourcelib.sql.src.history.store.HistoryensureMutableHistoryhasRelationRowsHistorybeginRelationRows
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsHistoryputRelationRowsSuffixHistorybaseChunkListprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryhasRelationRowsHistoryrelationRowsPagesHistoryrelationSpansHistorybeginRelationRowsSuffix
Static calls · unresolved targets: 1 · external targets: 5.
Called byCallsHistoryputDatabaseValueprivate sourcelib.sql.src.history.store.HistoryensureMutableHistorybeginWriteBatch
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersbranchcheckoutprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistorycheckoutBranch
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsHistoryrelationRowsprivate sourcelib.sql.src.history.store.HistoryensureUsableversionsameHistorychunkRowsInto
Static calls · unresolved targets: 0 · external targets: 11.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistoryputCommitAndRefCommitinitHistorycommitBranch
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistorycommitValueHistorydatabaseRootprivate sourcelib.sql.src.history.store.HistoryensureUsableHistorycommitDatabaseRoot
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsHistoryfastForwardBranchbranchcommitEntryprivate sourcelib.sql.src.history.store.HistoryensureUsableHistorycommitEntries
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsHistorycommitDatabaseRootprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistorycommitValue
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistoryfindConflictHistoryconflict
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistoryconflictEntriesprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindConflictHistoryconflictArtifacts
Static calls · unresolved targets: 0 · external targets: 5.
Called byCallsHistoryconflictArtifactsprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindConflictRootHistoryvalidateConflictRootConflictRootemptyversionsameHistoryconflictEntries
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistoryputRefHistoryrefHistorycreateBranch
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsHistorycommitDatabaseRootHistorydatabaseValueprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindDatabaseRootHistorydatabaseRoot
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersHistoryfindDatabaseRootHistorydatabaseRootView
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistorydatabaseRootprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryrelationRootHistoryrelationRowsversiondatabaseValueFromOwnedRelations+2 moreHistorydatabaseValue
Static calls · unresolved targets: 0 · external targets: 6.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryflushPendingWriteprivate sourcelib.sql.src.history.store.RecordLookupdeinitHistorydeinit
Static calls · unresolved targets: 3 · external targets: 3.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryappendRefDeleteRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindRefIndexHistoryflushSyncprivate sourcelib.sql.src.history.store.HistoryrefreshRefsSidecarHistorydeleteRef
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersbranchfastForwardRefHistorycommitEntriesprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindRefHistoryputRefHistoryfastForwardBranch
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callsHistorybeginFastForwardHistorycheckoutBranchHistorycommitBranchHistorycommitValueHistorycreateBranch+8 moreHistoryfindCommit
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistoryconflictHistoryconflictArtifactsHistoryhasConflictHistorypackRecordPresentHistoryputConflictHistoryvalidateConflictEntriesHistoryfindConflict
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistoryconflictEntriesHistorypackRecordPresentHistoryputConflictRootHistoryvalidateConflictRootHistoryfindConflictRoot
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistorydatabaseRootHistorydatabaseRootViewHistoryhasDatabaseRootHistoryimportPackCommitHistorypackRecordPresent+2 moreHistoryfindDatabaseRoot
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistorybeginFastForwardHistorycheckoutBranchHistorycommitBranchprivate sourcelib.sql.src.history.store.HistorycompleteFastForwardHistorycreateBranch+5 moreHistoryfindRef
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsHistorydeleteRefHistoryfindRefIndex
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsHistorypackRecordPresentHistoryrelationKeysViewHistoryrelationRootHistoryfindRelationRoot
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistoryhasRowChunkHistorypackRecordPresentHistoryputRowChunkHistoryrelationRowsHistoryfindRowChunk
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistoryhasTreeNodeHistorypackRecordPresentprivate sourcelib.sql.src.history.store.NodeStagenodeKeyHistoryfindTreeNode
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallshistory.RelationRowsWriterfinishprivate sourcelib.sql.src.history.store.HistoryappendRelationRowsRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryflushSyncHistoryputIndexPageHistoryputRelationSpansHistoryfinishRelationRows
Static calls · unresolved targets: 4 · external targets: 4.
Called byCallsHistoryappendRecordHistorydeleteRefHistoryfinishRelationRowsprivate sourcelib.sql.src.history.store.HistorypersistCoordinatorRecordHistoryputCommit+7 moreprivate sourcelib.sql.src.history.store.HistoryensureUsableprivate sourcelib.sql.src.history.store.HistoryflushPendingWriteHistoryflushSync
Static calls · unresolved targets: 0 · external targets: 1.
Called byCallsNo direct callersHistoryfindCommitHistoryhasCommit
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistoryfindConflictHistoryhasConflict
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistoryvalidateConflictRootHistoryhasConflictRoot
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistoryfindDatabaseRootHistoryhasDatabaseRoot
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsHistorypackRecordPresentHistoryputIndexPageHistoryhasIndexPage
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistoryputRelationRootHistoryhasRelationRoot
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsHistorybeginRelationRowsHistorybeginRelationRowsSuffixHistorypackRecordPresentHistoryputRelationRowsHistoryputRelationRowsSuffixHistoryrelationRowsNeedHistoryhasRelationRows
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callersHistoryfindRowChunkHistoryhasRowChunk
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersHistoryfindTreeNodeHistoryhasTreeNode
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryappendCommitRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindDatabaseRootCommitinitHistoryimportPackCommit
Static calls · unresolved targets: 4 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryimportPackRecord
Static calls · unresolved targets: 0 · external targets: 8.
Called byCallsHistorybaseChunkListHistoryrelationRowsprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryindexPageChunks
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistoryputCommitAndRefCommitinitHistorymergeCommitBranch
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callstest sourcelib.sql.src.history.storetest: fast forward coordinator fences...test sourcelib.sql.src.history.storetest: fast forward poisons an ambiguo...test sourcelib.sql.src.history.storetest: history appends after a truncat...test sourcelib.sql.src.history.storetest: history creates checkouts and a...test sourcelib.sql.src.history.storetest: history deletes refs durably+36 moreHistoryopen
Static calls · unresolved targets: 0 · external targets: 8.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindConflictHistoryfindConflictRootHistoryfindDatabaseRootHistoryfindRelationRoot+8 moreHistorypackRecordPresent
Static calls · unresolved targets: 2 · external targets: 11.
Called byCallsNo direct callsHistorybeginFastForwardprivate sourcelib.sql.src.history.store.HistorypersistCoordinatorRecordHistorypoison
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryappendCommitRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryflushSyncCommitinitHistoryputCommit
Static calls · unresolved targets: 4 · external targets: 2.
Called byCallsHistorycommitBranchHistorymergeCommitBranchprivate sourcelib.sql.src.history.store.HistoryappendCommitRecordprivate sourcelib.sql.src.history.store.HistoryappendRefRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryflushSync+2 moreHistoryputCommitAndRef
Static calls · unresolved targets: 4 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryappendConflictRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindConflictHistoryflushSyncHistoryputConflict
Static calls · unresolved targets: 2 · external targets: 5.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryappendConflictRootRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindConflictRootHistoryflushSyncHistoryvalidateConflictEntries+3 moreHistoryputConflictRoot
Static calls · unresolved targets: 2 · external targets: 4.
Called byCallsHistoryputDatabaseValueprivate sourcelib.sql.src.history.store.HistoryappendDatabaseRootRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindDatabaseRootHistoryflushSyncHistoryputDatabaseRoot
Static calls · unresolved targets: 2 · external targets: 4.
Called byCallsNo direct callersHistorybeginWriteBatchprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryputDatabaseRootHistoryputRelationRootHistoryputRelationRowsHistoryputDatabaseValue
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsHistoryfinishRelationRowsprivate sourcelib.sql.src.history.store.HistoryappendChunkIndexPageRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryhasIndexPageHistoryputIndexPage
Static calls · unresolved targets: 4 · external targets: 2.
Called byCallsHistorycreateBranchHistoryfastForwardBranchHistoryputRefIfMatchesprivate sourcelib.sql.src.history.store.HistoryappendRefRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistoryflushSyncprivate sourcelib.sql.src.history.store.HistoryrefreshRefsSidecarHistoryputRef
Static calls · unresolved targets: 2 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindCommitHistoryfindRefHistoryputRefversionsameHistoryputRefIfMatches
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsHistoryputDatabaseValueprivate sourcelib.sql.src.history.store.HistoryappendRelationRootRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryflushSyncHistoryhasRelationRootprivate sourcelib.sql.src.history.store.NodeStagedeinit+3 moreHistoryputRelationRoot
Static calls · unresolved targets: 4 · external targets: 5.
Called byCallsHistoryputDatabaseValueHistorybeginRelationRowsprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryhasRelationRowsHistoryputRelationRows
Static calls · unresolved targets: 3 · external targets: 2.
Called byCallsNo direct callersHistorybeginRelationRowsSuffixprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryhasRelationRowsprivate sourcelib.sql.src.history.storerelationRowsSortedHistoryputRelationRowsSuffix
Static calls · unresolved targets: 1 · external targets: 2.
Called byCallsHistoryfinishRelationRowsHistoryappendRelationSpansRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryputRelationSpans
Static calls · unresolved targets: 5 · external targets: 2.
Called byCallsprivate sourcelib.sql.src.history.store.RelationRowsWriteremitHistoryappendRecordprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindRowChunkHistoryputRowChunk
Static calls · unresolved targets: 2 · external targets: 6.
Called byCallsHistorycreateBranchprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryref
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsablehistoryfreeRefListHistoryrefList
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindRelationRootHistoryrelationKeysView
Static calls · unresolved targets: 0 · external targets: 2.
Called byCallsHistorydatabaseValueprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindRelationRootRelationRootdeinitHistoryrelationRoot
Static calls · unresolved targets: 0 · external targets: 6.
Called byCallsHistorydatabaseValueHistorychunkRowsIntoprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindRowChunkHistoryindexPageChunksHistoryrelationRowsPagesHistoryrelationRows
Static calls · unresolved targets: 0 · external targets: 5.
Called byCallsNo direct callersHistorybaseChunkListprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryhasRelationRowsHistoryrelationRowsPagesHistoryrelationSpansprivate sourcelib.sql.src.history.storefirstAffectedSpanHistoryrelationRowsNeed
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallsHistorybeginRelationRowsSuffixHistoryrelationRowsHistoryrelationRowsNeedprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryrelationRowsPages
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsHistorybeginRelationRowsSuffixHistoryrelationRowsNeedprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryrelationSpans
Static calls · unresolved targets: 1 · external targets: 1.
Called byCallsNo direct callersprivate sourcelib.sql.src.history.store.HistoryensureUsableHistorytreeNodeChildren
Static calls · unresolved targets: 1 · external targets: 2.
Called byCallsHistorypackRecordPresentHistoryputConflictRootHistoryvalidateConflictRootHistoryfindConflictConflictEntrylessThanHistoryvalidateConflictEntries
Static calls · unresolved targets: 0 · external targets: 3.
Called byCallsHistoryconflictEntriesHistoryhasConflictRootHistorypackRecordPresentHistoryputConflictRootprivate sourcelib.sql.src.history.store.HistoryensureUsableHistoryfindConflictRootHistoryvalidateConflictEntriesConflictRootemptyConflictRootinitversionsameHistoryvalidateConflictRoot
Static calls · unresolved targets: 0 · external targets: 0.

Also reachable as

history.History.

Complete caller list for History.appendRecord

11 direct callers.

Complete call list for History.databaseValue

7 direct calls.

Complete caller list for History.findCommit

13 direct callers.

Complete caller list for History.findDatabaseRoot

7 direct callers.

Complete caller list for History.findRef

10 direct callers.

Complete caller list for History.flushSync

12 direct callers.

Complete caller list for History.open

41 direct callers.

Complete call list for History.packRecordPresent

13 direct calls.

Complete call list for History.putCommitAndRef

7 direct calls.

Complete call list for History.putConflictRoot

8 direct calls.

Complete call list for History.putRelationRoot

8 direct calls.

Audit

Definitions82
Public names164
Members32
Version26.7.0
Revisiondaab053ee433