Skip to documentation
SLOP

tiny.trace.TraceReader

Reference tiny.trace TraceReader

Defined in tiny.trace.

API (29)

Actions

Public operations.

Fields and members

Public fields and members.

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

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;
Called byCallsNo direct callsprivate sourcelib.trace.src.store.reader.stream.ReaderadvanceFromSourceTraceReaderverifyTraceReaderadvance
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsTraceReaderopenTraceReaderdeinit
Static calls · unresolved targets: 0 · external targets: 4.
Called byCallsNo direct callsprivate sourcelib.trace.src.store.reader.stream.ReadercountFromSourceTraceReadereventCount
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersstore.format.blockcapacitystore.format.databaseeventsstore.format.databaseopenReaderstore.format.databaseworkspaceLimitsTraceReaderdeinitprivate sourcelib.trace.src.store.reader.streamreadHeaderTraceReaderopen
Static calls · unresolved targets: 0 · external targets: 6.
Called byCallsprivate sourcelib.trace.src.store.reader.stream.ReaderpeekFromSourceTraceReaderverifystore.format.databasesequenceKeystore.format.databaseupdateChecksumprivate sourcelib.trace.src.store.reader.stream.ReaderadvanceEncodedprivate sourcelib.trace.src.store.reader.stream.ReaderfinishTraceprivate sourcelib.trace.src.store.reader.stream.ReaderpeekEncodedTraceReaderpeek
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callstest sourcelib.trace.src.store.testtest: SQL trace round trips across lo...TraceReadersource
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallstest sourcelib.trace.src.store.reader.testtest: trace reader remains allocator-...storeverifytest sourcelib.trace.src.store.testtest: SQL trace groups events into bo...test sourcelib.trace.src.store.testtest: SQL trace round trips across lo...test sourcelib.trace.src.store.testtest: reader reports caller-selected ...TraceReaderadvanceTraceReaderpeekTraceReaderverify
Static calls · unresolved targets: 0 · external targets: 1.

Also reachable as

store.Reader.

Audit

Definitions8
Public names16
Members22
Version26.7.0
Revisiondaab053ee433