nx_index_migrate_gate.nx source
↩ module page · 125 lines · 8188 B
1// nx_index_migrate_gate.nx -- THE MIGRATION-PROOF gate (operator headline: "migratable to bigger + more sophisticated
2// hardware"). Proves the sovereign inverted index is a PORTABLE BYTE ARTIFACT: build on "hw-A", save, COPY the file to
3// a different path (= migrate to a different host/disk/hardware), LOAD from the copy, re-query -> BYTE-IDENTICAL. Plus
4// pin the format endian/word-size (i64 LE MAGIC round-trips) so it ports to different/more-sophisticated ISAs incl.
5// our own sovereign silicon. WHY it works: vocab slots store OFFSETS not pointers -> load needs ZERO relocation; no
6// JVM/OS lock-in. Format is byte-compatible with nx_search_inverted_persist (NXINV magic); serializer inlined here to
7// keep a single clean syscalls lineage (the _hdl_build persist cross-import trips the compiler on this graph -- a known
8// large-graph double-import limitation, filed). license_tier: ORIGINAL
9import "nx_search_inverted.nx"
10
11const MIG_MAGIC: i64 = 336659591510 // "NXINV" -- byte-identical to nx_search_inverted_persist
12
13func gw(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 }
14func gn(v: i64) -> i64 { if v==0 { sys_write(1,"0" as *u8,1); return 0 } var m: i64=v; if m<0 { sys_write(1,"-" as *u8,1); m=0-m } let t: *u8=sys_mmap(28); var k: i64=0; while m>0 { t[k]=48+(m%10); m=m/10; k=k+1 } while k>0 { k=k-1; sys_write(1,(((t as i64)+k) as *u8),1) } return 0 }
15func mig_slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
16func mig_wall(fd: i64, buf: *u8, n: i64) -> i64 { var off: i64=0; while off<n { let w: i64=sys_write(fd, ((buf as i64)+off) as *u8, n-off); if w<=0 { return 0-1 } off=off+w } return off }
17
18// SAVE (format-compatible with nx_search_inverted_persist): header[40] + vocab slots[cap*32] + postings[used].
19func mig_save(idx: *NxInvIndex, path: *u8) -> i64 {
20 let fd: i64 = sys_openat_wr(path, 0x1a4); if fd<0 { return 0 }
21 let hdr: *i64 = sys_mmap(40) as *i64
22 hdr[0]=MIG_MAGIC; hdr[1]=idx.n_rows; hdr[2]=idx.vocab_capacity; hdr[3]=idx.vocab_occupied; hdr[4]=idx.postings_used
23 if mig_wall(fd, hdr as *u8, 40) < 0 { sys_close(fd); return 0 }
24 if mig_wall(fd, idx.vocab_slots_ptr, idx.vocab_capacity*NX_INV_SLOT_BYTES) < 0 { sys_close(fd); return 0 }
25 if idx.postings_used > 0 { if mig_wall(fd, idx.postings_ptr, idx.postings_used) < 0 { sys_close(fd); return 0 } }
26 sys_close(fd); return 1
27}
28// LOAD: read whole file; point the struct INTO the buffer (offsets -> zero relocation). NULL on missing/bad-magic.
29func mig_load(path: *u8) -> *NxInvIndex {
30 let lb: *i64 = sys_mmap(8) as *i64
31 let buf: *u8 = sys_read_file(path, lb)
32 if buf == 0 as *u8 { return 0 as *NxInvIndex }
33 if lb[0] < 40 { return 0 as *NxInvIndex }
34 let hdr: *i64 = buf as *i64
35 if hdr[0] != MIG_MAGIC { return 0 as *NxInvIndex }
36 let idx: *NxInvIndex = sys_mmap(NX_INV_INDEX_BYTES) as *NxInvIndex
37 idx.n_rows = hdr[1]; idx.vocab_capacity = hdr[2]; idx.vocab_occupied = hdr[3]
38 idx.postings_used = hdr[4]; idx.postings_capacity = hdr[4]
39 idx.vocab_slots_ptr = ((buf as i64) + 40) as *u8
40 idx.postings_ptr = ((buf as i64) + 40 + hdr[2]*NX_INV_SLOT_BYTES) as *u8
41 return idx
42}
43// byte-copy src -> dst (= migrate the artifact to a different location/host).
44func mig_copy(src: *u8, dst: *u8) -> i64 {
45 let lb: *i64 = sys_mmap(8) as *i64
46 let buf: *u8 = sys_read_file(src, lb); if buf == 0 as *u8 { return 0 }
47 let fd: i64 = sys_openat_wr(dst, 0x1a4); if fd < 0 { return 0 }
48 let r: i64 = mig_wall(fd, buf, lb[0]); sys_close(fd)
49 if r < 0 { return 0 }
50 return 1
51}
52// query `term`; fill out_ids[count] with little-endian 4-byte row-ids; return count.
53func mig_query(idx: *NxInvIndex, term: *u8, out_ids: *i64) -> i64 {
54 let h: i64 = nx_inv_hash_bytes_lower(term, mig_slen(term))
55 let slot: *u8 = nx_inv_lookup_slot(idx, h)
56 if (slot as i64) == 0 { return 0 }
57 let cnt: i64 = nx_inv_slot_postings_count(slot)
58 let off: i64 = nx_inv_slot_postings_offset(slot)
59 var k: i64 = 0
60 while k < cnt {
61 let p: *u8 = ((idx.postings_ptr as i64) + off + k*4) as *u8
62 out_ids[k] = (p[0] as i64) | ((p[1] as i64)<<8) | ((p[2] as i64)<<16) | ((p[3] as i64)<<24)
63 k = k + 1
64 }
65 return cnt
66}
67func mig_ids_eq(a: *i64, an: i64, b: *i64, bn: i64) -> i64 { if an!=bn { return 0 } var i: i64=0; while i<an { if a[i]!=b[i] { return 0 } i=i+1 } return 1 }
68
69func main() -> i64 {
70 gw("=== nx_index_migrate_gate: the sovereign index is a PORTABLE BYTE ARTIFACT (build->save->migrate->load->identical) ===\n" as *u8)
71 var pass: i64=0; var tot: i64=0
72 sys_mkdir("web_assets" as *u8, 0x1ed)
73
74 let d0: *u8 = "sovereign index alpha" as *u8
75 let d1: *u8 = "mojeek beta gamma" as *u8
76 let d2: *u8 = "sovereign delta epsilon" as *u8
77 let idx: *NxInvIndex = nx_inv_new(4096)
78 nx_inv_index_row(idx, d0, mig_slen(d0), 0); nx_inv_index_row(idx, d1, mig_slen(d1), 1); nx_inv_index_row(idx, d2, mig_slen(d2), 2)
79 nx_inv_finalize_offsets(idx)
80 nx_inv_emit_row(idx, d0, mig_slen(d0), 0); nx_inv_emit_row(idx, d1, mig_slen(d1), 1); nx_inv_emit_row(idx, d2, mig_slen(d2), 2)
81 idx.n_rows = 3
82
83 let a0: *i64 = sys_mmap(8*64) as *i64
84 let c0: i64 = mig_query(idx, "sovereign" as *u8, a0)
85 var t1: i64=0; if c0==2 { if a0[0]==0 { if a0[1]==2 { t1=1 } } }
86 tot=tot+1; if t1==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
87 gw("T1 build+query hw-A: 'sovereign' -> docs {0,2} (cnt=" as *u8); gn(c0); gw(")\n" as *u8)
88
89 let rc_save: i64 = mig_save(idx, "web_assets/mig_a.nxinv" as *u8)
90 let rc_copy: i64 = mig_copy("web_assets/mig_a.nxinv" as *u8, "web_assets/mig_b.nxinv" as *u8)
91 let idx2: *NxInvIndex = mig_load("web_assets/mig_b.nxinv" as *u8)
92 var t2: i64=0; if rc_save==1 { if rc_copy==1 { if (idx2 as i64)!=0 { t2=1 } } }
93 tot=tot+1; if t2==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
94 gw("T2 save -> migrate(copy to hw-B) -> load (relocation-free, MAGIC-verified)\n" as *u8)
95
96 let a1: *i64 = sys_mmap(8*64) as *i64
97 let c1: i64 = mig_query(idx2, "sovereign" as *u8, a1)
98 let a2: *i64 = sys_mmap(8*64) as *i64
99 let c2: i64 = mig_query(idx2, "mojeek" as *u8, a2)
100 var t3: i64=0; if mig_ids_eq(a0, c0, a1, c1)==1 { if c2==1 { if a2[0]==1 { t3=1 } } }
101 tot=tot+1; if t3==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
102 gw("T3 post-migration query IDENTICAL: 'sovereign'->{0,2} 'mojeek'->{1} (cnt=" as *u8); gn(c1); gw("," as *u8); gn(c2); gw(")\n" as *u8)
103
104 let az: *i64 = sys_mmap(8*64) as *i64
105 let cz: i64 = mig_query(idx2, "zzzznotintheindex" as *u8, az)
106 tot=tot+1; if cz==0 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
107 gw("T4 negative control: absent term -> 0 postings (cnt=" as *u8); gn(cz); gw(")\n" as *u8)
108
109 let lb: *i64 = sys_mmap(8) as *i64
110 let fb: *u8 = sys_read_file("web_assets/mig_b.nxinv" as *u8, lb)
111 var magic: i64 = 0
112 if fb != 0 as *u8 { if lb[0] >= 8 { magic = (fb[0] as i64) | ((fb[1] as i64)<<8) | ((fb[2] as i64)<<16) | ((fb[3] as i64)<<24) | ((fb[4] as i64)<<32) | ((fb[5] as i64)<<40) | ((fb[6] as i64)<<48) | ((fb[7] as i64)<<56) } }
113 tot=tot+1; if magic==MIG_MAGIC { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
114 gw("T5 endian/word-size pinned: i64 LE MAGIC (NXINV) round-trips (magic=" as *u8); gn(magic); gw(")\n" as *u8)
115
116 gw("\n=== nx_index_migrate_gate " as *u8); gn(pass); gw("/" as *u8); gn(tot); gw(" ===\n" as *u8)
117 let lfd: i64 = sys_openat_append("knowledge/status/index_migrate_gate.log" as *u8, 420)
118 if pass==tot {
119 if lfd>=0 { sys_write(lfd, "INDEX-MIGRATE-GATE verdict=GREEN portable-byte-artifact relocation-free endian-pinned\n" as *u8, 84); sys_close(lfd) }
120 gw("MIGRATE GREEN -- built hw-A, migrated (copied), byte-identical query on hw-B. Portable byte artifact, no JVM/OS lock-in; ports laptop->NAS->cluster->sovereign-silicon.\n" as *u8)
121 sys_exit(0); return 0
122 }
123 if lfd>=0 { sys_write(lfd, "INDEX-MIGRATE-GATE verdict=RED\n" as *u8, 30); sys_close(lfd) }
124 gw("MIGRATE RED\n" as *u8); sys_exit(1); return 1
125}