nx_enginelab_store.nx
buildroot/runtime/nx_enginelab_store.nx
about
nx_enginelab_store.nx -- EL1: PERSIST A CAPTURE AND REOPEN IT, for the engine instrument.
WHY THIS IS A THIRD MODULE AND NOT PART OF THE SPINE. Same principle that moved golden-image out:
nx_enginelab_lib is PURE BUFFER OPS so a wasm world can adopt it, and file I/O is exactly the thing
that stops being portable. A consumer that only records frames and zones should not acquire an
openat/write/read dependency to do it. So the spine stays pure, and persistence lives here.
WHAT EL1 IS FOR. Until now a capture existed only inside the process that took it, which means it
could not be attached to a bug report, diffed across machines, or replayed. It also means EL3
(inspect real resource contents per draw) is impossible, because inspecting contents needs a
capture that OUTLIVES the process. This is that file.
THE LOAD-BEARING REQUIREMENT IS THE REFUSAL, NOT THE ROUND-TRIP. Anyone can write bytes and read
them back. The done-rule for this rung is that a TRUNCATED FILE IS REFUSED RATHER THAN PARTIALLY
PARSED, because a half-read capture parses into a SHORTER capture that looks completely healthy --
fewer frames, fewer draws, every analyzer happily computing a confident wrong answer over it. That
is the silent class this whole board exists to catch, and a persistence layer is where it is
easiest to introduce. Hence: a declared byte length, a checksum, and a NAMED reason per failure.
AND THE COVERAGE COUNTERS TRAVEL WITH THE DATA. The store header carries drop and error counts, and
they are serialised WITH the records. A capture that dropped events under load must not reload
claiming complete coverage -- if it did, persistence would launder a partial measurement into a
clean-looking one, which is worse than not persisting at all.
license_tier: ORIGINAL No hardware writes (Rule 26).
dependencies 2 imports · 2 importers
imports: nx_syscalls.nxnx_enginelab_lib.nx
imported by: nx_enginelab.nxnx_enginelab_gate.nx
structs
| none |
consts
| 28 | const ELS_MAGIC: i64 = 1162892876 // 'NXEL' as a decimal constant, one witness that this is our file |
| 29 | const ELS_VERSION: i64 = 1 |
| 30 | const ELS_PFX: i64 = 4 // magic, version, declared_bytes, checksum |
| 31 | const ELS_HASH_MUL: i64 = 1000003 |
| 32 | const ELS_HASH_MOD: i64 = 2147483647 |
| 36 | const ELS_OK: i64 = 0 |
| 37 | const ELS_UNREADABLE: i64 = 1 // could not read the path at all |
| 38 | const ELS_TOO_SMALL: i64 = 2 // shorter than the fixed prefix: cannot even be inspected |
| 39 | const ELS_BAD_MAGIC: i64 = 3 // not one of our captures |
| 40 | const ELS_BAD_VERSION: i64 = 4 // ours, but a format this build cannot read |
| 41 | const ELS_SIZE_MISMATCH: i64 = 5 // declared length disagrees with the bytes actually present |
| 42 | const ELS_CHECKSUM: i64 = 6 // right length, wrong content |
| 45 | const ELS_R_CODE: i64 = 0 |
| 46 | const ELS_R_DECLARED: i64 = 1 |
| 47 | const ELS_R_ACTUAL: i64 = 2 |
| 48 | const ELS_R_SLOTS: i64 = 3 |
functions
| 50 | func els_ck(w: *i64, from: i64, to: i64) -> i64 |
| 60 | func els_slots_for(n: i64) -> i64 { return ELS_PFX + EL_H + n * EL_REC } |
| 66 | func el_capture_write(st: *i64, path: *u8) -> i64 |
| 99 | func el_capture_read(path: *u8, rs: *i64) -> *i64 |