nx_framed_append_gate.nx source
↩ module page · 293 lines · 12238 B
1// nx_framed_append_gate.nx -- the REFEREE for WMS-R0 (atomic framed-append).
2//
3// Proves the nx_framed_append primitive defeats concurrent-appender tearing, AND
4// proves the test can actually DETECT tearing (the mandatory negative control).
5//
6// GOOD lane: N workers fork concurrently, each emits NRECS records via the NEW
7// single-write primitive fa_append(GOODPATH, ...). Expect ZERO torn
8// lines and ALL N*NRECS lines present (nothing lost, nothing torn).
9// BAD lane (NEGATIVE CONTROL): the SAME concurrency, but each record is emitted
10// the OLD way -- a SEQUENCE of separate sys_write() calls per record.
11// O_APPEND only makes ONE write atomic, not the sequence, so workers
12// interleave -> torn lines MUST appear. bad_torn == 0 => the detector
13// is worthless => RED (no false green).
14// TAMPER: an oversized record (rec_len+1 > cap) must be REJECTED with -2,
15// never silently written/torn.
16//
17// A line is WELL-FORMED iff it starts "FA w=" AND the bytes just before its '\n'
18// are "END" AND it contains exactly one " END" token. Any interleaving violates
19// one of those -> counted as torn. Output: rows -> stdout + the evidence log
20// knowledge/status/framed_append_gate.log, then a final verdict line. Exit 0 on
21// GREEN, 1 on RED. Sovereign: only nx_syscalls + nx_framed_append.
22// license_tier: ORIGINAL
23import "nx_syscalls.nx"
24import "nx_framed_append.nx"
25
26const NWORKERS: i64 = 16 // concurrency (raised so the neg-control tears robustly)
27const NRECS: i64 = 300 // records per worker
28const RECCAP: i64 = 256 // bounded record size for the primitive
29
30// dual-sink writer: stdout (fd 1) AND the evidence log fd
31func gp(logfd: i64, s: *u8) -> i64 {
32 var n: i64 = 0
33 while s[n] != (0 as u8) { n = n + 1 }
34 sys_write(1, s, n)
35 if logfd > 0 { sys_write(logfd, s, n) }
36 return 0
37}
38func gn(logfd: i64, v: i64) -> i64 {
39 let bb: *u8 = sys_mmap(28)
40 var m: i64 = v
41 if m < 0 { sys_write(1, "-\x00" as *u8, 1); if logfd > 0 { sys_write(logfd, "-\x00" as *u8, 1) } m = 0 - m }
42 let t: *u8 = sys_mmap(28)
43 var k: i64 = 0
44 if m == 0 { t[0] = 48 as u8; k = 1 }
45 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 }
46 var i: i64 = 0
47 while i < k { bb[i] = t[k - 1 - i]; i = i + 1 }
48 sys_write(1, bb, k)
49 if logfd > 0 { sys_write(logfd, bb, k) }
50 return 0
51}
52
53// assemble one record into buf (NO trailing newline): "FA w=<wid> i=<seq> pid=<pid> END"
54// returns rec_len. The trailing " END" sentinel is what the parser checks for.
55func build_rec(buf: *u8, wid: i64, seq: i64, pid: i64) -> i64 {
56 var o: i64 = 0
57 o = fa_cat(buf, o, "FA w=\x00" as *u8)
58 o = fa_catn(buf, o, wid)
59 o = fa_cat(buf, o, " i=\x00" as *u8)
60 o = fa_catn(buf, o, seq)
61 o = fa_cat(buf, o, " pid=\x00" as *u8)
62 o = fa_catn(buf, o, pid)
63 o = fa_cat(buf, o, " END\x00" as *u8)
64 return o
65}
66
67// GOOD worker: NRECS framed single-write appends, then exit.
68func good_worker(wid: i64) -> i64 {
69 let pid: i64 = __syscall(39, 0, 0, 0, 0, 0, 0) // getpid
70 let buf: *u8 = sys_mmap(RECCAP + 16)
71 var i: i64 = 0
72 while i < NRECS {
73 let rl: i64 = build_rec(buf, wid, i, pid)
74 fa_append("/tmp/fa_good.log\x00" as *u8, buf, rl, RECCAP)
75 i = i + 1
76 }
77 return 0
78}
79
80// BAD worker (NEGATIVE CONTROL): same records, but emitted as a SEQUENCE of
81// separate sys_write() calls per record -- exactly the torn-line bug. Opens the
82// file ONCE in O_APPEND, then per record: many little writes + a final newline.
83// Concurrent workers interleave between these writes -> torn lines.
84func bad_worker(wid: i64) -> i64 {
85 let pid: i64 = __syscall(39, 0, 0, 0, 0, 0, 0) // getpid
86 let fd: i64 = sys_openat_append("/tmp/fa_bad.log\x00" as *u8, 0x1a4)
87 if fd < 0 { return 0 - 1 }
88 let nb: *u8 = sys_mmap(28)
89 var i: i64 = 0
90 while i < NRECS {
91 sys_write(fd, "FA w=\x00" as *u8, 5)
92 var l: i64 = 0; var m: i64 = wid
93 if m == 0 { nb[0] = 48 as u8; l = 1 }
94 while m > 0 { nb[l] = (48 + (m % 10)) as u8; m = m / 10; l = l + 1 }
95 var x: i64 = 0
96 let d1: *u8 = sys_mmap(28)
97 while x < l { d1[x] = nb[l - 1 - x]; x = x + 1 }
98 sys_write(fd, d1, l)
99 sys_write(fd, " i=\x00" as *u8, 3)
100 l = 0; m = i
101 if m == 0 { nb[0] = 48 as u8; l = 1 }
102 while m > 0 { nb[l] = (48 + (m % 10)) as u8; m = m / 10; l = l + 1 }
103 let d2: *u8 = sys_mmap(28); x = 0
104 while x < l { d2[x] = nb[l - 1 - x]; x = x + 1 }
105 sys_write(fd, d2, l)
106 sys_write(fd, " pid=\x00" as *u8, 6)
107 l = 0; m = pid
108 if m == 0 { nb[0] = 48 as u8; l = 1 }
109 while m > 0 { nb[l] = (48 + (m % 10)) as u8; m = m / 10; l = l + 1 }
110 let d3: *u8 = sys_mmap(28); x = 0
111 while x < l { d3[x] = nb[l - 1 - x]; x = x + 1 }
112 sys_write(fd, d3, l)
113 sys_write(fd, " END\x00" as *u8, 4)
114 sys_write(fd, "\n\x00" as *u8, 1)
115 i = i + 1
116 }
117 sys_close(fd)
118 return 0
119}
120
121// spawn NWORKERS children running f(wid), wait all. which: 0=good, 1=bad.
122func spawn_all(which: i64) -> i64 {
123 let pids: *i64 = sys_mmap(8 * (NWORKERS + 4)) as *i64
124 var w: i64 = 0
125 while w < NWORKERS {
126 let pid: i64 = sys_fork()
127 if pid == 0 {
128 if which == 0 { good_worker(w) }
129 if which == 1 { bad_worker(w) }
130 sys_exit(0)
131 }
132 pids[w] = pid
133 w = w + 1
134 }
135 let st: *i64 = sys_mmap(16) as *i64
136 w = 0
137 while w < NWORKERS {
138 sys_wait4(pids[w], st, 0)
139 w = w + 1
140 }
141 return 0
142}
143
144// parse a file: total_lines into outs[0], torn_count returned.
145// A '\n'-terminated line is WELL-FORMED iff:
146// - it begins with "FA w="
147// - the 4 bytes immediately before the '\n' are " END" (space,E,N,D)
148// - it contains exactly one " END" occurrence (no embedded second record head)
149// Anything else (interleaved fragments, a record head mid-line, missing sentinel)
150// is TORN. An empty trailing segment (file ends with '\n') is not a line.
151func count_torn(path: *u8, outs: *i64) -> i64 {
152 let szp: *i64 = sys_mmap(16) as *i64
153 let b: *u8 = sys_read_file(path, szp)
154 let sz: i64 = szp[0]
155 var torn: i64 = 0
156 var lines: i64 = 0
157 var ls: i64 = 0
158 var i: i64 = 0
159 while i < sz {
160 if b[i] == (10 as u8) {
161 let llen: i64 = i - ls
162 lines = lines + 1
163 var ok: i64 = 1
164 // prefix "FA w=" (5 bytes)
165 if llen < 9 { ok = 0 }
166 if ok == 1 {
167 if b[ls] != (70 as u8) { ok = 0 } // F
168 if b[ls + 1] != (65 as u8) { ok = 0 } // A
169 if b[ls + 2] != (32 as u8) { ok = 0 } // space
170 if b[ls + 3] != (119 as u8) { ok = 0 } // w
171 if b[ls + 4] != (61 as u8) { ok = 0 } // =
172 }
173 // suffix " END" immediately before '\n'
174 if ok == 1 {
175 let e: i64 = i - 1
176 if b[e - 3] != (32 as u8) { ok = 0 } // space
177 if b[e - 2] != (69 as u8) { ok = 0 } // E
178 if b[e - 1] != (78 as u8) { ok = 0 } // N
179 if b[e] != (68 as u8) { ok = 0 } // D
180 }
181 // exactly one " END" token inside the line (no interleaved 2nd record)
182 if ok == 1 {
183 var ends: i64 = 0
184 var j: i64 = ls
185 while j + 3 < i + 1 {
186 if b[j] == (32 as u8) {
187 if b[j + 1] == (69 as u8) {
188 if b[j + 2] == (78 as u8) {
189 if b[j + 3] == (68 as u8) { ends = ends + 1 }
190 }
191 }
192 }
193 j = j + 1
194 }
195 if ends != 1 { ok = 0 }
196 // also: no second "FA w=" record-head embedded (head appears only at ls)
197 var k: i64 = ls + 1
198 while k + 4 < i + 1 {
199 if b[k] == (70 as u8) {
200 if b[k + 1] == (65 as u8) {
201 if b[k + 2] == (32 as u8) {
202 if b[k + 3] == (119 as u8) {
203 if b[k + 4] == (61 as u8) { ok = 0 }
204 }
205 }
206 }
207 }
208 k = k + 1
209 }
210 }
211 if ok == 0 { torn = torn + 1 }
212 ls = i + 1
213 }
214 i = i + 1
215 }
216 outs[0] = lines
217 return torn
218}
219
220func main() -> i64 {
221 let logfd: i64 = sys_openat_append("knowledge/status/framed_append_gate.log\x00" as *u8, 0x1a4)
222 gp(logfd, "FRAMED-APPEND epoch=\x00" as *u8)
223 gn(logfd, sys_now_realtime_sec())
224 gp(logfd, " workers=\x00" as *u8); gn(logfd, NWORKERS)
225 gp(logfd, " recs=\x00" as *u8); gn(logfd, NRECS)
226 gp(logfd, " cap=\x00" as *u8); gn(logfd, RECCAP)
227 gp(logfd, "\n\x00" as *u8)
228
229 // fresh files each run (truncate)
230 let gtr: i64 = sys_openat_wr("/tmp/fa_good.log\x00" as *u8, 0x1a4)
231 if gtr > 0 { sys_close(gtr) }
232 let btr: i64 = sys_openat_wr("/tmp/fa_bad.log\x00" as *u8, 0x1a4)
233 if btr > 0 { sys_close(btr) }
234
235 // GOOD lane: concurrent framed single-write appends
236 spawn_all(0)
237 // BAD lane (NEGATIVE CONTROL): same concurrency, OLD multi-write pattern
238 spawn_all(1)
239
240 let outs: *i64 = sys_mmap(16) as *i64
241 let good_torn: i64 = count_torn("/tmp/fa_good.log\x00" as *u8, outs)
242 let good_lines: i64 = outs[0]
243 let bad_torn: i64 = count_torn("/tmp/fa_bad.log\x00" as *u8, outs)
244 let bad_lines: i64 = outs[0]
245 let want_lines: i64 = NWORKERS * NRECS
246
247 // TAMPER: oversized record (rec_len+1 > cap=8) must be REJECTED with -2
248 let trec: *u8 = sys_mmap(64)
249 var ti: i64 = 0
250 while ti < 32 { trec[ti] = 65 as u8; ti = ti + 1 } // 32 'A's, way over cap=8
251 let tamper_rc: i64 = fa_append("/tmp/fa_tamper.log\x00" as *u8, trec, 32, 8)
252
253 gp(logfd, "FA row=good_lines got=\x00" as *u8); gn(logfd, good_lines)
254 gp(logfd, " want=\x00" as *u8); gn(logfd, want_lines)
255 if good_lines == want_lines { gp(logfd, " verdict=PASS\n\x00" as *u8) } else { gp(logfd, " verdict=FAIL\n\x00" as *u8) }
256
257 gp(logfd, "FA row=good_torn got=\x00" as *u8); gn(logfd, good_torn)
258 gp(logfd, " want=0\x00" as *u8)
259 if good_torn == 0 { gp(logfd, " verdict=PASS\n\x00" as *u8) } else { gp(logfd, " verdict=FAIL\n\x00" as *u8) }
260
261 gp(logfd, "FA row=neg_control bad_lines=\x00" as *u8); gn(logfd, bad_lines)
262 gp(logfd, " bad_torn=\x00" as *u8); gn(logfd, bad_torn)
263 gp(logfd, " want=POSITIVE\x00" as *u8)
264 if bad_torn > 0 { gp(logfd, " verdict=PASS(detector-sees-tearing)\n\x00" as *u8) } else { gp(logfd, " verdict=FAIL(no-tearing-detected)\n\x00" as *u8) }
265
266 gp(logfd, "FA row=tamper_oversize got=\x00" as *u8); gn(logfd, tamper_rc)
267 gp(logfd, " want=-2\x00" as *u8)
268 if tamper_rc == (0 - 2) { gp(logfd, " verdict=PASS\n\x00" as *u8) } else { gp(logfd, " verdict=FAIL\n\x00" as *u8) }
269
270 var green: i64 = 1
271 if good_lines != want_lines { green = 0 }
272 if good_torn != 0 { green = 0 }
273 if bad_torn <= 0 { green = 0 }
274 if tamper_rc != (0 - 2) { green = 0 }
275
276 gp(logfd, "FRAMED-APPEND verdict=\x00" as *u8)
277 if green == 1 { gp(logfd, "GREEN\x00" as *u8) } else { gp(logfd, "RED\x00" as *u8) }
278 gp(logfd, " good_lines=\x00" as *u8); gn(logfd, good_lines)
279 gp(logfd, " good_torn=\x00" as *u8); gn(logfd, good_torn)
280 gp(logfd, " bad_torn=\x00" as *u8); gn(logfd, bad_torn)
281 gp(logfd, " tamper=\x00" as *u8); gn(logfd, tamper_rc)
282 if green == 0 {
283 gp(logfd, " reason=\x00" as *u8)
284 if good_lines != want_lines { gp(logfd, "good-lines-lost \x00" as *u8) }
285 if good_torn != 0 { gp(logfd, "GOOD-TORE \x00" as *u8) }
286 if bad_torn <= 0 { gp(logfd, "neg-control-saw-no-tearing \x00" as *u8) }
287 if tamper_rc != (0 - 2) { gp(logfd, "oversize-not-rejected \x00" as *u8) }
288 }
289 gp(logfd, "\n\x00" as *u8)
290 if logfd > 0 { sys_close(logfd) }
291 if green == 1 { return 0 }
292 return 1
293}