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}