tiny.trace.TraceReader
Defined in tiny.trace.
API (29)
Actions
Public operations.
Fields and members
Public fields and members.
block_bufferblock_viewchunk_byte_countchunk_event_countcurrentdatabase_workspacedatabase_workspace_openevent_hashereventsfilefile_openheaderinitializedloaded_block_bytesloaded_block_countloaded_chunk_countloaded_event_bytesloaded_event_countroot_pathsql_allocatorstorageverified
Source
Source: lib/trace/src/store/reader/stream.zig:20
zig
pub const Reader = struct { storage: ?*Storage = null, root_path: []u8 = &.{}, header: format.Header = undefined, block_buffer: []u8 = &.{}, block_view: ?block.View = null, sql_allocator: std.heap.FixedBufferAllocator = undefined, database_workspace: sql.FileDatabase.Workspace = undefined, database_workspace_open: bool = false, file: sql.FileDatabase = undefined, file_open: bool = false, events: sql.Tree = undefined, chunk_event_count: u64 = 0, chunk_byte_count: u64 = 0, event_hasher: std.hash.Wyhash = format.newHasher(), loaded_chunk_count: u64 = 0, loaded_event_count: u64 = 0, loaded_event_bytes: u64 = 0, loaded_block_count: u64 = 0, loaded_block_bytes: u64 = 0, current: ?event.Event = null, initialized: bool = false, verified: bool = false, pub fn open(self: *Reader, storage: *Storage, root_path: []const u8) !void { if (self.initialized) return error.TraceReaderAlreadyOpen; const regions = try storage.acquire(.{ .root_path_bytes = root_path.len }); var acquired = true; errdefer if (acquired) storage.release(); std.mem.copyForwards(u8, regions.root_path, root_path); const header_value = try readHeader( regions.root_path, regions.input, regions.path, regions.json_stack, storage.capacity.json_nesting, ); try storage.admit(header_value.limits); if (!header_value.status_closed) return error.TraceNotClosed; const block_bytes = block.capacity(header_value.limits.max_event_bytes) catch return error.InvalidTraceManifest; std.debug.assert(block_bytes <= regions.input.len); self.* = .{ .storage = storage, .root_path = regions.root_path, .header = header_value, .block_buffer = regions.input[0..block_bytes], .sql_allocator = std.heap.FixedBufferAllocator.init(regions.sql), .initialized = true, }; acquired = false; errdefer self.deinit(); self.database_workspace = try sql.FileDatabase.Workspace.allocate( self.sql_allocator.allocator(), database.workspaceLimits(storage.capacity.database), ); self.database_workspace_open = true; self.file = try database.openReader( self.sql_allocator.allocator(), &self.database_workspace, self.root_path, storage.capacity.database, ); self.file_open = true; self.events = try database.events(&self.file); const identity = try self.events.identity(); const expected_key_bytes = std.math.mul(u64, self.header.block_count, database.key_bytes) catch return error.InvalidTraceManifest; if (identity.entries != self.header.block_count or identity.key_bytes != expected_key_bytes or identity.value_bytes != self.header.block_bytes) { return error.InvalidTraceManifest; } } pub fn deinit(self: *Reader) void { if (!self.initialized) return; if (self.file_open) { self.file.deinit(); self.file_open = false; } if (self.database_workspace_open) { self.database_workspace.deallocate(self.sql_allocator.allocator()); self.database_workspace_open = false; } const storage = self.storage.?; self.* = .{}; storage.release(); } pub fn source(self: *Reader) event.Source { return .{ .context = self, .peekFn = peekFromSource, .advanceFn = advanceFromSource, .countFn = countFromSource, }; } pub fn peek(self: *Reader) !?*const event.Event { if (!self.initialized) return error.TraceReaderNotOpen; if (self.current) |*item| return item; if (self.verified) return null; const maybe_encoded = try self.peekEncoded(); if (self.loaded_event_count == self.header.event_count) { if (maybe_encoded != null) return error.InvalidTraceManifest; try self.finishTrace(); return null; } const encoded = maybe_encoded orelse return error.InvalidTraceManifest; if (encoded.len == 0 or encoded.len > self.header.limits.max_event_bytes) { return error.InvalidTraceEvent; } const prospective_chunk_bytes = std.math.add(u64, self.chunk_byte_count, encoded.len) catch return error.InvalidTraceManifest; var prior_chunk_event_count = self.chunk_event_count; var prior_chunk_byte_count = self.chunk_byte_count; var next_loaded_chunk_count = self.loaded_chunk_count; if (self.chunk_event_count != 0 and prospective_chunk_bytes > self.header.limits.max_chunk_bytes) { next_loaded_chunk_count = std.math.add(u64, self.loaded_chunk_count, 1) catch return error.InvalidTraceManifest; prior_chunk_event_count = 0; prior_chunk_byte_count = 0; } const next_chunk_event_count = std.math.add(u64, prior_chunk_event_count, 1) catch return error.InvalidTraceManifest; const next_chunk_byte_count = std.math.add(u64, prior_chunk_byte_count, encoded.len) catch return error.InvalidTraceManifest; const next_event_count = std.math.add(u64, self.loaded_event_count, 1) catch return error.InvalidTraceManifest; const next_event_bytes = std.math.add(u64, self.loaded_event_bytes, encoded.len) catch return error.InvalidTraceManifest; if (next_chunk_byte_count > self.header.limits.max_chunk_bytes or next_event_count > self.header.event_count or next_event_bytes > self.header.event_bytes) { return error.InvalidTraceManifest; } const parsed = codec.decode(encoded) catch return error.InvalidTraceEvent; var key_buffer: [database.key_bytes]u8 = undefined; const key = database.sequenceKey(&key_buffer, self.loaded_event_count); self.advanceEncoded(); database.updateChecksum(&self.event_hasher, key, encoded); self.loaded_chunk_count = next_loaded_chunk_count; self.chunk_event_count = next_chunk_event_count; self.chunk_byte_count = next_chunk_byte_count; self.loaded_event_count = next_event_count; self.loaded_event_bytes = next_event_bytes; self.current = parsed; return &self.current.?; } fn peekEncoded(self: *Reader) !?[]u8 { while (true) { if (self.block_view) |*view| { if (view.peek()) |encoded| return encoded; self.block_view = null; } if (self.loaded_block_count == self.header.block_count) return null; try self.loadBlock(); } } fn advanceEncoded(self: *Reader) void { self.block_view.?.advance(); } fn loadBlock(self: *Reader) !void { var key_buffer: [database.key_bytes]u8 = undefined; const key = database.sequenceKey(&key_buffer, self.loaded_block_count); const encoded = self.events.getInto(key, self.block_buffer) catch |err| switch (err) { error.OutputTooSmall => return error.InvalidTraceEvent, else => |read_err| return read_err, } orelse return error.InvalidTraceManifest; const view = block.View.init(encoded) catch return error.InvalidTraceEvent; const next_block_count = std.math.add(u64, self.loaded_block_count, 1) catch return error.InvalidTraceManifest; const next_block_bytes = std.math.add(u64, self.loaded_block_bytes, encoded.len) catch return error.InvalidTraceManifest; if (next_block_count > self.header.block_count or next_block_bytes > self.header.block_bytes) { return error.InvalidTraceManifest; } self.block_view = view; self.loaded_block_count = next_block_count; self.loaded_block_bytes = next_block_bytes; } pub fn advance(self: *Reader) void { std.debug.assert(self.current != null); self.current = null; } pub fn eventCount(self: *const Reader) u64 { return self.header.event_count; } pub fn verify(self: *Reader) !VerifyResult { while (try self.peek()) |_| self.advance(); return .{ .chunk_count = self.loaded_chunk_count, .event_count = self.loaded_event_count, .event_bytes = self.loaded_event_bytes, .checksum = self.event_hasher.final(), }; } fn finishTrace(self: *Reader) !void { if (self.chunk_event_count != 0) { self.loaded_chunk_count = std.math.add(u64, self.loaded_chunk_count, 1) catch return error.InvalidTraceManifest; self.chunk_event_count = 0; self.chunk_byte_count = 0; } if (self.loaded_chunk_count != self.header.chunk_count or self.loaded_event_count != self.header.event_count or self.loaded_event_bytes != self.header.event_bytes or self.loaded_block_count != self.header.block_count or self.loaded_block_bytes != self.header.block_bytes) { return error.InvalidTraceManifest; } if (self.event_hasher.final() != self.header.event_checksum) return error.TraceChecksumMismatch; self.verified = true; } fn peekFromSource(context: *anyopaque) !?*const event.Event { const self: *Reader = @ptrCast(@alignCast(context)); return try self.peek(); } fn advanceFromSource(context: *anyopaque) void { const self: *Reader = @ptrCast(@alignCast(context)); self.advance(); } fn countFromSource(context: *anyopaque) u64 { const self: *Reader = @ptrCast(@alignCast(context)); return self.eventCount(); }};Source: lib/trace/src/root.zig:57
zig
pub const TraceReader = store.Reader;Also reachable as
Audit
| Definitions | 8 |
|---|---|
| Public names | 16 |
| Members | 22 |
| Version | 26.7.0 |
| Revision | daab053ee433 |