code wiki / _hdl_build / nx_logtail_gate.nx

nx_logtail_gate.nx source

↩ module page · 135 lines · 6625 B

1// nx_logtail_gate.nx -- TEETH FOR THE SHARED HONEST TAIL READER (nx_logtail.nx, debt 1786054115). 2// Inherits nx_gate_verdict (gv_ctr/gv_head/gv_check/gv_verdict) rather than rolling its own counter, 3// per the D001 MIGRATE-ON-TOUCH law -- a new gate that hand-rolls a verdict is a new D001 row. 4// THE LOAD-BEARING TOOTH IS T4, THE NEG-CONTROL. Asserting only "the newest record survived" would 5// ALSO pass for a reader that quietly returned the entire file, so it cannot discriminate a tail read 6// from no read at all. T4 demands the OLDEST record be ABSENT, which is the only assertion that 7// distinguishes "kept the tail" from "kept everything" -- and keeping the wrong end silently is the 8// entire defect class this lib exists to close. 9// license_tier: ORIGINAL No hw writes (Rule 26). expect_exit: 0 10import "nx_syscalls.nx" 11import "nx_logtail.nx" 12import "nx_gate_verdict.nx" 13 14const LG_BUF: i64 = 65536 15const LG_SMALL: i64 = 512 16const LG_MODE: i64 = 0x1a4 17const LG_FILL: i64 = 400 18 19func lg_append(path: *u8, s: *u8) -> i64 { 20 var n: i64 = 0 21 while s[n] != (0 as u8) { n = n + 1 } 22 let fd: i64 = sys_openat_append(path, LG_MODE) 23 if fd < 0 { return 0 - 1 } 24 sys_write(fd, s, n) 25 sys_close(fd) 26 return 0 27} 28func lg_contains(hay: *u8, hn: i64, needle: *u8) -> i64 { 29 var m: i64 = 0 30 while needle[m] != (0 as u8) { m = m + 1 } 31 if m == 0 { return 0 } 32 if hn < m { return 0 } 33 var i: i64 = 0 34 while i <= hn - m { 35 var j: i64 = 0 36 var ok: i64 = 1 37 while j < m { if hay[i + j] != needle[j] { ok = 0; j = m } else { j = j + 1 } } 38 if ok == 1 { return 1 } 39 i = i + 1 40 } 41 return 0 42} 43 44func main(argc: i64, argv: *i64) -> i64 { 45 gv_head("nx_logtail_gate -- shared honest tail reader for append-only logs" as *u8) 46 let ctr: *i64 = gv_ctr() 47 // Hermetic by construction: a unique path per run, so the gate never inherits a previous run's 48 // fixture. A gate whose result depends on leftovers is measuring its own history. 49 let p: *u8 = sys_mmap(256) 50 var o: i64 = gv_cat(p, 0, "/tmp/nx_logtail_gate_" as *u8) 51 o = gv_catn(p, o, sys_now_realtime_sec()) 52 o = gv_cat(p, o, ".log" as *u8) 53 p[o] = 0 as u8 54 55 lg_append(p, "OLDESTAAA first record\n" as *u8) 56 var f: i64 = 0 57 while f < LG_FILL { 58 lg_append(p, "FILLER-0123456789-0123456789-0123456789-0123456789-012345678\n" as *u8) 59 f = f + 1 60 } 61 lg_append(p, "NEWESTZZZ last record\n" as *u8) 62 63 let e1: *i64 = sys_mmap(64) as *i64 64 let b1: *u8 = sys_mmap(LG_BUF) 65 let n1: i64 = lt_read_tail(p, b1, LG_BUF, e1) 66 67 // T1 COMPLETE READ IS REPORTED COMPLETE, AND EXACTLY. file_bytes is the whole file because the 68 // reader streams it -- this is the number nx_fs cannot give you (debt 1786054029). 69 var t1: i64 = 0 70 if n1 > 0 { if e1[3] == 0 { if e1[2] == 0 { if e1[0] == n1 { if e1[1] == n1 { t1 = 1 } } } } } 71 gv_check("T1 whole file retained, envelope says complete and exact" as *u8, t1, ctr) 72 73 var t2: i64 = 0 74 if lg_contains(b1, n1, "OLDESTAAA" as *u8) == 1 { if lg_contains(b1, n1, "NEWESTZZZ" as *u8) == 1 { t2 = 1 } } 75 gv_check("T2 complete read carries BOTH oldest and newest records" as *u8, t2, ctr) 76 77 let e2: *i64 = sys_mmap(64) as *i64 78 let b2: *u8 = sys_mmap(LG_BUF) 79 let n2: i64 = lt_read_tail(p, b2, LG_SMALL, e2) 80 81 // T3 TRUNCATION IS DECLARED AND THE ARITHMETIC CLOSES. A partial read that reports complete is the 82 // defect; a partial read whose numbers do not sum is a different lie with the same effect. 83 var t3: i64 = 0 84 if e2[3] == 1 { if e2[1] == n2 { if e2[0] > n2 { if e2[2] == e2[0] - e2[1] { t3 = 1 } } } } 85 gv_check("T3 truncated read DECLARES it and dropped+scanned==file_bytes" as *u8, t3, ctr) 86 87 var t4: i64 = 0 88 if lg_contains(b2, n2, "NEWESTZZZ" as *u8) == 1 { t4 = 1 } 89 gv_check("T4a NEWEST record survives the tail window" as *u8, t4, ctr) 90 91 // T4b THE DISCRIMINATOR. Without this a reader that ignored `cap` entirely would pass every other 92 // tooth in this file. 93 var t5: i64 = 0 94 if lg_contains(b2, n2, "OLDESTAAA" as *u8) == 0 { t5 = 1 } 95 gv_check("T4b NEG-CONTROL: OLDEST record is ABSENT (proves tail, not whole-file)" as *u8, t5, ctr) 96 97 // T5 no torn first record. Every filler line starts with 'F' and the last with 'N', so a buffer 98 // beginning mid-line would start on some other byte. A half record parsed as a whole one is how a 99 // truncated journal invents a frame that was never written. 100 var t6: i64 = 0 101 if n2 > 0 { if b2[0] == (70 as u8) { t6 = 1 } else { if b2[0] == (78 as u8) { t6 = 1 } } } 102 gv_check("T5 truncated buffer starts on a RECORD boundary, never mid-line" as *u8, t6, ctr) 103 104 // T6a/T6b ABSENT AND EMPTY ARE DIFFERENT FACTS AND MUST NOT SHARE A RETURN VALUE. Collapsing them is 105 // how a MISSING supervisor log becomes a healthy verdict over zero bytes: nx_govern_sweep exits 4 on 106 // ABSENT specifically, and v1 of this lib returned 0 for both, which would have quietly turned that 107 // into GOVERNED. The pair below is a neg-control on each other -- asserting only the absent case would 108 // still pass for a lib that returned -1 for every file it read. 109 let e3: *i64 = sys_mmap(64) as *i64 110 let b3: *u8 = sys_mmap(LG_SMALL) 111 let n3: i64 = lt_read_tail("/tmp/nx_logtail_gate_definitely_absent_path" as *u8, b3, LG_SMALL, e3) 112 var t7: i64 = 0 113 if n3 < 0 { if e3[0] == 0 { if e3[1] == 0 { if e3[2] == 0 { t7 = 1 } } } } 114 gv_check("T6a ABSENT file returns -1 with a zeroed envelope, never a false complete" as *u8, t7, ctr) 115 let ep: *u8 = sys_mmap(256) 116 var o2: i64 = gv_cat(ep, 0, "/tmp/nx_logtail_gate_empty_" as *u8) 117 o2 = gv_catn(ep, o2, sys_now_realtime_sec()) 118 ep[o2] = 0 as u8 119 lg_append(ep, "" as *u8) 120 let e4: *i64 = sys_mmap(64) as *i64 121 let n4: i64 = lt_read_tail(ep, b3, LG_SMALL, e4) 122 var t7b: i64 = 0 123 if n4 == 0 { if e4[0] == 0 { if e4[3] == 0 { t7b = 1 } } } 124 gv_check("T6b EMPTY-but-PRESENT file returns 0, distinguishable from ABSENT" as *u8, t7b, ctr) 125 sys_unlinkat(ep) 126 127 // T7 the one-line accessor must agree with the raw flag in BOTH directions, because the whole point 128 // of providing it is that callers forget env[3] exists. 129 var t8: i64 = 0 130 if lt_complete(e1) == 1 { if lt_complete(e2) == 0 { t8 = 1 } } 131 gv_check("T7 lt_complete agrees with env[3] both ways" as *u8, t8, ctr) 132 133 sys_unlinkat(p) 134 return gv_verdict("nx_logtail_gate" as *u8, ctr, "shared tail reader: exact size, tail retention, declared truncation, record-boundary safety, absent-file fail-safe" as *u8) 135}