tiny.sql.history.segment
Defined in history.
API (40)
Actions
Public operations.
Iterator.nextSealer.Capacity.deriveSealer.activateSealer.addBlockSealer.addClosureSealer.deinitSealer.finishSealer.initView.demandView.iteratorverify
Types and contracts
Public types and contracts.
BlockErrorEventRangeIteratorRecordReplayDemandSealedSealerSealer.CapacitySealer.Capacity.DeriveErrorSealer.ExhaustionSealer.InitErrorSealer.LimitsSealer.StorageSegmentRangeSpecView
Namespaces
Public namespaces.
Values and defaults
Public values and defaults.
Sealer.claimSealer.storage_alignmentSealer.work_limitsblock_bytes_maxblock_header_bytesblocks_maxclosure_digests_maxclosure_record_bytesencoded_bytes_maxheader_bytestrailer_bytes
Source
Source: lib/sql/src/history/segment/format.zig:159
pub const Block = struct { first_event: EventRange.Count, event_count: u32, raw_bytes: u32, bytes: []const u8,};Source: lib/sql/src/history/segment/format.zig:136
pub const Error = error{ CapacityOverflow, CapacityExceeded, EmptySegment, InvalidSegment, SegmentBytesExceeded, StorageTooShort, TooManyBlocks, TooManyClosureDigests,};Source: lib/sql/src/history/segment/format.zig:524
pub const Iterator = struct { view: *const View, cursor: usize, closures_remaining: u32, blocks_remaining: u32, next_event: EventRange.Count, pub fn next(self: *Iterator) Error!?Record { if (self.closures_remaining != 0) { const end = self.cursor + closure_record_bytes; if (end > self.view.bytes.len - trailer_bytes) { return error.InvalidSegment; } const value = try readClosure(self.view.bytes[self.cursor..end]); self.cursor = end; self.closures_remaining -= 1; return .{ .closure = value }; } if (self.blocks_remaining == 0) { if (self.cursor != self.view.bytes.len - trailer_bytes) { return error.InvalidSegment; } return null; } const block = try readBlock(self.view.bytes, &self.cursor); if (block.first_event != self.next_event) return error.InvalidSegment; self.next_event = EventRange.advance( block.first_event, block.event_count, ) orelse return error.InvalidSegment; self.blocks_remaining -= 1; return .{ .block = block }; }};Source: lib/sql/src/history/segment/format.zig:519
Source: lib/sql/src/history/segment/format.zig:506
pub const ReplayDemand = struct { segments: u64 = 1, blocks: u64, events: u64, raw_event_bytes: u64 = 0, encoded_block_bytes: u64, max_record_bytes: u64 = closure_record_bytes, checkpoint_roots: u64, closure_digests: u64, segment_bytes: u64, io_operations: u64 = 1,};Source: lib/sql/src/history/segment/format.zig:166
Source: lib/sql/src/history/segment/format.zig:172
pub const Sealer = struct { pub const storage_alignment: usize = 8; pub const Storage = []align(storage_alignment) u8; pub const Limits = struct { blocks: usize, block_bytes: usize, closure_digests: usize, }; pub const Capacity = struct { blocks: usize, block_bytes: usize, closure_digests: usize, storage_bytes: usize, pub const DeriveError = error{ CapacityOverflow, CapacityExceeded, EmptySegment, }; pub fn derive(limits: Limits) DeriveError!Capacity { if (limits.blocks == 0 or limits.block_bytes == 0) { return error.EmptySegment; } if (limits.blocks > blocks_max or limits.closure_digests > closure_digests_max or limits.block_bytes > block_bytes_max) { return error.CapacityExceeded; } const block_headers = try multiply(limits.blocks, block_header_bytes); const closures = try multiply( limits.closure_digests, closure_record_bytes, ); var storage_bytes = try add(header_bytes, block_headers); storage_bytes = try add(storage_bytes, closures); storage_bytes = try add(storage_bytes, limits.block_bytes); storage_bytes = try add(storage_bytes, trailer_bytes); return .{ .blocks = limits.blocks, .block_bytes = limits.block_bytes, .closure_digests = limits.closure_digests, .storage_bytes = storage_bytes, }; } }; pub const Exhaustion = error{ InvalidSegment, SegmentBytesExceeded, TooManyBlocks, TooManyClosureDigests, }; pub const InitError = Capacity.DeriveError || error{StorageTooShort}; pub const work_limits: alloc_phase.capacity.WorkLimits = .{ .transition_steps_max = blocks_max + closure_digests_max, .cleanup_steps_per_call_max = 0, .cleanup_calls_at_capacity_max = 0, }; pub const claim: alloc_phase.capacity.Declaration = .{ .source = .{ .id = "sql.history_segment_sealer", .kind = .phase_static, .limit_source = .caller, .storage = .{ .covered = &.{.{ .id = "reserved_immutable_segment_output", .lifetime = .transferred, .detail = "exact header record payload and trailer output", }}, .excluded = &.{ "caller-owned event blocks and content closure digests", "filesystem writes manifest pages and archive transport", }, }, .capacity = .{ .inputs = &.{ alloc_phase.capacity.bindInput(Limits, "blocks", "blocks"), alloc_phase.capacity.bindInput( Limits, "block_bytes", "block_bytes", ), alloc_phase.capacity.bindInput( Limits, "closure_digests", "closure_digests", ), }, .type_selectors = &.{}, .nodes = &.{ .{ .input = 0 }, .{ .input = 1 }, .{ .input = 2 }, .{ .constant = 64 }, .{ .product = .{ .left = 0, .right = 3 } }, .{ .constant = 40 }, .{ .product = .{ .left = 2, .right = 5 } }, .{ .constant = 256 }, .{ .add = .{ .left = 7, .right = 4 } }, .{ .add = .{ .left = 8, .right = 6 } }, .{ .add = .{ .left = 9, .right = 1 } }, .{ .constant = 32 }, .{ .add = .{ .left = 10, .right = 11 } }, }, .assertions = &.{.{ .scope = .closure_total, .measure = .retained, .relation = .exact, .expression = 12, }}, }, .overload = .{ .kind = .reject_before_mutation, .detail = "record count and byte exhaustion reject before output changes", }, .risks = .{ .transitive = .{ .status = .witnessed, .detail = "sealing hashes and writes only the caller reservation", }, .foreign = .{ .status = .excluded, .detail = "durable file and archive publication are outside this owner", }, }, .work = .{ .equation = "record writes <= blocks + closure_digests", }, .obligations = &.{ .{ .key = "sql_history_segment_capacity", .role = .capacity_model, }, .{ .key = "sql_history_segment_overload", .role = .overload, }, .{ .key = "sql_history_segment_verification", .role = .transitive_risk, }, .{ .key = "sql_history_segment_work_bound", .role = .work_bound, }, }, }, .bindings = .{ .owner = @This(), .seal = .{ .family = alloc_phase.capacity.selector(@This().activate), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, .teardown = .{ .family = alloc_phase.capacity.selector(@This().deinit), .premise = .{ .class = .checked_semantic_fact, .authority = .checker, }, }, }, }; phase: alloc_phase.capacity.Phase, capacity: Capacity, storage: Storage, cursor: usize = header_bytes, blocks: usize = 0, block_bytes: usize = 0, closure_digests: usize = 0, first_event: ?EventRange.Count = null, next_event: EventRange.Count = 0, blocks_started: bool = false, pub fn init(storage: Storage, limits: Limits) InitError!Sealer { const capacity = try Capacity.derive(limits); if (storage.len < capacity.storage_bytes) return error.StorageTooShort; return .{ .phase = .initialization, .capacity = capacity, .storage = storage[0..capacity.storage_bytes], }; } pub fn activate(self: *Sealer) void { std.debug.assert(self.phase == .initialization); std.debug.assert(self.storage.len == self.capacity.storage_bytes); self.phase = .steady; } pub fn addClosure(self: *Sealer, value: Hash) Exhaustion!void { self.assertSteady(); if (self.blocks_started) return error.InvalidSegment; if (self.closure_digests == self.capacity.closure_digests) { return error.TooManyClosureDigests; } const end = self.cursor + closure_record_bytes; writeClosure(self.storage[self.cursor..end], value); self.cursor = end; self.closure_digests += 1; } pub fn addBlock(self: *Sealer, block: Block) Exhaustion!void { self.assertSteady(); if (block.event_count == 0 or block.raw_bytes == 0 or block.bytes.len == 0) { return error.InvalidSegment; } if (self.blocks == self.capacity.blocks) return error.TooManyBlocks; if (block.bytes.len > self.capacity.block_bytes - self.block_bytes) { return error.SegmentBytesExceeded; } const next_event = EventRange.advance( block.first_event, block.event_count, ) orelse return error.InvalidSegment; if (self.first_event) |_| { if (block.first_event != self.next_event) return error.InvalidSegment; } else self.first_event = block.first_event; const end = self.cursor + block_header_bytes + block.bytes.len; writeBlock(self.storage[self.cursor..end], block); self.cursor = end; self.blocks += 1; self.block_bytes += block.bytes.len; self.next_event = next_event; self.blocks_started = true; } pub fn finish(self: *Sealer, spec: Spec) Exhaustion!Sealed { self.assertSteady(); if (self.blocks != self.capacity.blocks or self.block_bytes != self.capacity.block_bytes or self.closure_digests != self.capacity.closure_digests) { return error.InvalidSegment; } if (!SegmentRange.containsOrdinal(spec.ordinal)) { return error.InvalidSegment; } const first_event = self.first_event orelse return error.InvalidSegment; if (spec.first_event != first_event) return error.InvalidSegment; const next_event = EventRange.advance( spec.first_event, spec.event_count, ) orelse return error.InvalidSegment; if (next_event != self.next_event) { return error.InvalidSegment; } std.debug.assert(self.cursor + trailer_bytes == self.storage.len); var records_digest: Hash = undefined; Sha256.hash(self.storage[header_bytes..self.cursor], &records_digest, .{}); writeHeader(self.storage[0..header_bytes], spec, self.capacity, records_digest); const trailer_digest = digest(self.storage[0..self.cursor]); @memcpy(self.storage[self.cursor..], &trailer_digest); const segment_digest = digest(self.storage); const view = verify(self.storage) catch return error.InvalidSegment; std.debug.assert(std.mem.eql(u8, &view.digest, &segment_digest)); return .{ .bytes = self.storage, .digest = segment_digest, .spec = spec }; } pub fn deinit(self: *Sealer) Storage { std.debug.assert(self.phase == .steady); const storage = self.storage; self.phase = .teardown; self.* = undefined; return storage; } fn assertSteady(self: *const Sealer) void { std.debug.assert(self.phase == .steady); std.debug.assert(self.storage.len == self.capacity.storage_bytes); std.debug.assert(self.blocks <= self.capacity.blocks); std.debug.assert(self.block_bytes <= self.capacity.block_bytes); std.debug.assert(self.closure_digests <= self.capacity.closure_digests); }};Source: lib/sql/src/history/segment/format.zig:147
pub const Spec = struct { epoch: u64, ordinal: SegmentRange.Count, first_event: EventRange.Count, event_count: EventRange.Count, previous_segment: Hash, event_chain: Hash, checkpoint_root: Hash, schema_identity: Hash, stream_identity: Hash,};Source: lib/sql/src/history/segment/format.zig:459
pub const View = struct { bytes: []const u8, digest: Hash, spec: Spec, block_count: u32, closure_count: u32, block_bytes: u64, pub fn iterator(self: *const View) Iterator { return .{ .view = self, .cursor = header_bytes, .closures_remaining = self.closure_count, .blocks_remaining = self.block_count, .next_event = self.spec.first_event, }; } pub fn demand(self: *const View) Error!ReplayDemand { var demand_value = ReplayDemand{ .blocks = self.block_count, .events = self.spec.event_count, .encoded_block_bytes = self.block_bytes, .closure_digests = self.closure_count, .checkpoint_roots = @intFromBool(!allZero(&self.spec.checkpoint_root)), .segment_bytes = @intCast(self.bytes.len), }; var iterator_value = self.iterator(); while (try iterator_value.next()) |record| switch (record) { .closure => {}, .block => |block| { demand_value.raw_event_bytes = std.math.add( u64, demand_value.raw_event_bytes, block.raw_bytes, ) catch return error.InvalidSegment; demand_value.max_record_bytes = @max( demand_value.max_record_bytes, @as(u64, block_header_bytes) + @as(u64, @intCast(block.bytes.len)), ); }, }; return demand_value; }};Source: lib/sql/src/history/segment/format.zig:14
pub const block_bytes_max: usize = 64 * 1024 * 1024;Source: lib/sql/src/history/segment/format.zig:9
pub const block_header_bytes: usize = 64;Source: lib/sql/src/history/segment/format.zig:12
pub const blocks_max: usize = 64;Source: lib/sql/src/history/segment/format.zig:13
pub const closure_digests_max: usize = 64 * 1024;Source: lib/sql/src/history/segment/format.zig:10
pub const closure_record_bytes: usize = 40;Source: lib/sql/src/history/segment/format.zig:15
pub const encoded_bytes_max: usize = header_bytes + blocks_max * block_header_bytes + closure_digests_max * closure_record_bytes + block_bytes_max + trailer_bytes;Source: lib/sql/src/history/segment/format.zig:8
pub const header_bytes: usize = 256;Source: lib/sql/src/history/segment/format.zig:559
pub fn verify(bytes: []const u8) Error!View { if (bytes.len < header_bytes + block_header_bytes + trailer_bytes) { return error.InvalidSegment; } const decoded = try readHeader(bytes[0..header_bytes]); const expected_len = try encodedBytes( decoded.block_count, decoded.block_bytes, decoded.closure_count, ); if (bytes.len != expected_len) return error.InvalidSegment; const records_end = bytes.len - trailer_bytes; if (!std.mem.eql( u8, &decoded.records_digest, &digest(bytes[header_bytes..records_end]), )) return error.InvalidSegment; const trailer_digest = digest(bytes[0..records_end]); if (!std.mem.eql(u8, &trailer_digest, bytes[records_end..])) { return error.InvalidSegment; } const segment_digest = digest(bytes); var view = View{ .bytes = bytes, .digest = segment_digest, .spec = decoded.spec, .block_count = decoded.block_count, .closure_count = decoded.closure_count, .block_bytes = decoded.block_bytes, }; try verifyRecords(&view); return view;}Source: lib/sql/src/history/segment/format.zig:11
pub const trailer_bytes: usize = Sha256.digest_length;Source: lib/sql/src/history/root.zig:9
pub const segment = @import("segment/root.zig");Source: lib/sql/src/history/segment/root.zig
const format = @import("format.zig");pub const manifest = @import("manifest.zig");pub const Error = format.Error;pub const SegmentRange = format.SegmentRange;pub const EventRange = format.EventRange;pub const Spec = format.Spec;pub const Block = format.Block;pub const Sealed = format.Sealed;pub const Sealer = format.Sealer;pub const View = format.View;pub const ReplayDemand = format.ReplayDemand;pub const Record = format.Record;pub const Iterator = format.Iterator;pub const header_bytes = format.header_bytes;pub const block_header_bytes = format.block_header_bytes;pub const closure_record_bytes = format.closure_record_bytes;pub const trailer_bytes = format.trailer_bytes;pub const blocks_max = format.blocks_max;pub const closure_digests_max = format.closure_digests_max;pub const block_bytes_max = format.block_bytes_max;pub const encoded_bytes_max = format.encoded_bytes_max;pub const verify = format.verify;Audit
| Definitions | 38 |
|---|---|
| Public names | 38 |
| Members | 71 |
| Version | 26.7.0 |
| Revision | daab053ee433 |