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}