code wiki / _hdl_build / nx_galx_put.nx
nx_galx_put.nx source
↩ module page · 138 lines · 6294 B
1// nx_galx_put.nx -- CLI + gate for the native cid->path insert. Retires the TSV write path.
2//
3// Usage:
4// nx_galx_put <idx> <blob> <cid> <path> [<cid> <path> ...] insert
5// nx_galx_put --gate <idx> <blob> self-check on COPIES only
6//
7// ⚠VISIBILITY, STATED PLAINLY: nx_gallery_serve loads the idx+blob into its own memory ONCE at
8// startup (sys_read_file, a copy -- not a shared mapping), so a live server does NOT see an insert
9// until it restarts. The insert itself is now native and O(1); making it visible without a restart
10// requires the server to map the index MAP_SHARED, which is a change to a running daemon and is
11// filed rather than smuggled in here.
12// ★ REPORTING "INSERTED" WOULD BE TRUE AND STILL MISLEAD -- the reader is the only judge of
13// whether an image is servable, so say which half you did.
14// license_tier: ORIGINAL
15
16import "nx_syscalls.nx"
17import "nx_strconv.nx"
18import "nx_galx_cid_index.nx"
19import "nx_galx_cidput.nx"
20const K_MAGIC_1024: i64 = 1024
21
22func gp_puts(s: *u8) -> i64 {
23 var n: i64 = 0
24 while s[n] != (0 as u8) { n = n + 1 }
25 return sys_write(1, s, n)
26}
27func gp_i(v: i64) -> i64 {
28 let b: *u8 = sys_mmap(32)
29 return sys_write(1, b, nx_strconv_format_i64(v, b))
30}
31func gp_verdict(rc: i64) -> i64 {
32 if rc == CP_INSERTED { return gp_puts("INSERTED\n" as *u8) }
33 if rc == CP_PRESENT { return gp_puts("present (idempotent no-op)\n" as *u8) }
34 if rc == CP_EFULL { return gp_puts("REFUSED: load factor exhausted -- rebuild the index to resize\n" as *u8) }
35 if rc == CP_EBADIDX { return gp_puts("REFUSED: index header unreadable\n" as *u8) }
36 return gp_puts("IO ERROR\n" as *u8)
37}
38
39// Does a lookup through the SAME reader the gallery uses find what we just wrote?
40// ★ AN INSERT VERIFIED BY THE WRITER IS NOT VERIFIED. Only the reader's answer counts.
41func gp_lookup(idx_path: *u8, blob_path: *u8, cid: *u8, out: *u8) -> i64 {
42 let ip: *i64 = sys_mmap(16) as *i64
43 let ib: *u8 = sys_read_file(idx_path, ip)
44 if (ib as i64) == 0 { return 0 - 1 }
45 let bp: *i64 = sys_mmap(16) as *i64
46 let bb: *u8 = sys_read_file(blob_path, bp)
47 if (bb as i64) == 0 { return 0 - 1 }
48 return gs_cidindex_lookup(ib, bb, cidx_rd64(ib, 0), cid, out)
49}
50
51func main(argc: i64, argv: *i64) -> i64 {
52 // ⚠ The arity guard must come AFTER the mode split: --gate takes 4 argv, insert takes 5+, and
53 // a single `argc < 5` check silently swallowed every gate invocation into the usage text.
54 if argc < 4 {
55 gp_puts("usage: nx_galx_put <idx> <blob> <cid> <path> [<cid> <path> ...]\n" as *u8)
56 gp_puts(" nx_galx_put --gate <idx_copy> <blob_copy>\n" as *u8)
57 return 2
58 }
59 let a1: *u8 = argv[1] as *u8
60
61 // ---------------- gate ----------------
62 if a1[0] == (0x2D as u8) {
63 let idx: *u8 = argv[2] as *u8
64 let blob: *u8 = argv[3] as *u8
65 var pass: i64 = 0
66 var total: i64 = 0
67 let got: *u8 = sys_mmap(K_MAGIC_1024)
68 // A CID that cannot already be present: 69 chars, nxc1- + 64 hex, all f's but one marker.
69 let cid: *u8 = "nxc1-fedcba9876543210fedcba9876543210fedcba9876543210fedcba98765432" as *u8
70 let want: *u8 = "/volume1/ai/gen/__gate_probe__.png" as *u8
71
72 // T1 insert
73 total = total + 1
74 let r1: i64 = nx_galx_cidput(idx, blob, cid, want)
75 if r1 == CP_INSERTED { pass = pass + 1; gp_puts("T1 insert ....................... ok\n" as *u8) }
76 else { gp_puts("T1 insert ....................... FAIL\n" as *u8) }
77
78 // T2 the READER resolves it, and to the right path
79 total = total + 1
80 if gp_lookup(idx, blob, cid, got) == 1 {
81 var i: i64 = 0
82 var same: i64 = 1
83 while want[i] != (0 as u8) { if got[i] != want[i] { same = 0 } i = i + 1 }
84 if got[i] != (0 as u8) { same = 0 }
85 if same == 1 { pass = pass + 1; gp_puts("T2 reader resolves it ........... ok\n" as *u8) }
86 else { gp_puts("T2 reader resolves it ........... FAIL (wrong path)\n" as *u8) }
87 } else { gp_puts("T2 reader resolves it ........... FAIL (not found)\n" as *u8) }
88
89 // T3 idempotent -- a second insert must NOT add a second bucket
90 total = total + 1
91 if nx_galx_cidput(idx, blob, cid, want) == CP_PRESENT { pass = pass + 1; gp_puts("T3 idempotent ................... ok\n" as *u8) }
92 else { gp_puts("T3 idempotent ................... FAIL\n" as *u8) }
93
94 // T4 NEGATIVE CONTROL: a cid never inserted must NOT resolve. Without this, a lookup that
95 // returned 1 for everything would pass T2 and the gate would be vacuous.
96 total = total + 1
97 let absent: *u8 = "nxc1-0000000000000000000000000000000000000000000000000000000000000001" as *u8
98 if gp_lookup(idx, blob, absent, got) == 0 { pass = pass + 1; gp_puts("T4 absent cid does NOT resolve .. ok\n" as *u8) }
99 else { gp_puts("T4 absent cid does NOT resolve .. FAIL\n" as *u8) }
100
101 gp_puts("GATE " as *u8); gp_i(pass); gp_puts("/" as *u8); gp_i(total)
102 if pass == total { gp_puts(" GREEN\n" as *u8); return 0 }
103 gp_puts(" RED\n" as *u8)
104 return 1
105 }
106
107 // ---------------- insert ----------------
108 if argc < 5 {
109 gp_puts("usage: nx_galx_put <idx> <blob> <cid> <path> [<cid> <path> ...]\n" as *u8)
110 return 2
111 }
112 let idx: *u8 = argv[1] as *u8
113 let blob: *u8 = argv[2] as *u8
114 var n_ins: i64 = 0
115 var n_dup: i64 = 0
116 var n_err: i64 = 0
117 var a: i64 = 3
118 while a + 1 < argc {
119 let cid: *u8 = argv[a] as *u8
120 let path: *u8 = argv[a + 1] as *u8
121 let rc: i64 = nx_galx_cidput(idx, blob, cid, path)
122 sys_write(1, cid, 20)
123 gp_puts("... " as *u8)
124 gp_verdict(rc)
125 if rc == CP_INSERTED { n_ins = n_ins + 1 }
126 else { if rc == CP_PRESENT { n_dup = n_dup + 1 } else { n_err = n_err + 1 } }
127 a = a + 2
128 }
129 gp_puts("inserted=" as *u8); gp_i(n_ins)
130 gp_puts(" present=" as *u8); gp_i(n_dup)
131 gp_puts(" errors=" as *u8); gp_i(n_err)
132 gp_puts("\n" as *u8)
133 if n_ins > 0 {
134 gp_puts("NOTE: a RUNNING gallery still holds its boot-time copy; restart it to serve these.\n" as *u8)
135 }
136 if n_err > 0 { return 1 }
137 return 0
138}