code wiki / (root) / nx_galx_idx_backfill.nx

nx_galx_idx_backfill.nx source

↩ module page · 105 lines · 6637 B

1// nx_galx_idx_backfill.nx -- SOVEREIGN background indexer: build a NXVI index 2// (knowledge/status/galxidx_<id>.idx) for every recording that lacks one, so recordings get MSE 3// smooth-scrub (not just on first view). id = 0-indexed line in galx_vid_paths.tsv (matches gs_vid_line). 4// NEWEST-FIRST: the gallery's Recordings grid is reverse-ordered (highest id = newest = what the operator 5// clicks first), so we index from the highest id DOWN -> the visible recordings become smooth first. 6// Sequential fork+wait = one-at-a-time (concurrency bound). Idempotent: skips indexes already at NXVI v2; 7// (re)builds v1/missing/partial ones. Usage: nx_galx_idx_backfill [max_to_build] (default all). license_tier: ORIGINAL 8import "nx_syscalls.nx" 9const K_MAGIC_1000000: i64 = 1000000 10const K_MAGIC_4096: i64 = 4096 11 12func bp(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return sys_write(1,s,n) } 13func bn(v: i64) -> i64 { var m: i64=v; if m<0{m=0-m} let b: *u8=sys_mmap(32); var i: i64=32; if m==0{i=i-1;b[i]=(48 as u8)} while m>0{let q: i64=m/10; i=i-1; b[i]=((48+(m-q*10)) as u8); m=q} return sys_write(1,((b as i64)+i) as *u8,32-i) } 14func bitoa(v: i64, buf: *u8) -> i64 { var m: i64=v; let t: *u8=sys_mmap(32); var k: i64=0; if m==0{t[0]=(48 as u8);k=1} while m>0{let q: i64=m/10; t[k]=((48+(m-q*10)) as u8); m=q; k=k+1} var i: i64=0; while i<k{buf[i]=t[k-1-i];i=i+1} buf[k]=0 as u8; return k } 15func bexists(p: *u8) -> i64 { let fd: i64=sys_openat_rd(p); if fd<0 {return 0} sys_close(fd); return 1 } 16// 1 only if the index exists AND is NXVI v2 (big-endian ver==2 @ offset 4). v1/missing/partial -> 0 = rebuild. 17func bfsize(p: *u8) -> i64 { let fd: i64=sys_openat_rd(p); if fd<0 {return 0-1} let n: i64=sys_lseek(fd,0,2); sys_close(fd); return n } 18// An index is only VALID if it is v3 AND the size it recorded still matches the 19// file. Measured 2026-07-31: 79 of 150 live indexes pointed PAST EOF because the 20// source was truncated or replaced under the same name, and nothing could tell. 21// v2 has no srcsize at all, so v2 is treated as unverifiable and rebuilt. 22func bidx_ok(ip: *u8, tp: *u8) -> i64 { 23 let fd: i64=sys_openat_rd(ip) 24 if fd<0 { return 0 } 25 let h: *u8=sys_mmap(64) 26 let r: i64=sys_read(fd,h,40) 27 sys_close(fd) 28 if r<40 { return 0 } 29 if h[0]!=(78 as u8) { return 0 } 30 if h[4]!=(0 as u8) { return 0 } 31 if h[5]!=(0 as u8) { return 0 } 32 if h[6]!=(0 as u8) { return 0 } 33 if h[7]!=(3 as u8) { return 0 } 34 var ss: i64=0 35 var i: i64=0 36 while i<8 { ss=(ss<<8)|(h[32+i] as i64); i=i+1 } 37 let fs: i64=bfsize(tp) 38 if fs<0 { return 0 } 39 if fs < ss { return 0 } 40 return 1 41} 42 43func main(argc: i64, argv: *i64) -> i64 { 44 var maxc: i64 = K_MAGIC_1000000 45 if argc>=2 { let s: *u8=argv[1] as *u8; var v: i64=0; var i: i64=0; while s[i]!=(0 as u8){ if s[i]>=(48 as u8){ if s[i]<=(57 as u8){ v=v*10+((s[i]-(48 as u8)) as i64) } } i=i+1 } maxc=v } 46 let szp: *i64=sys_mmap(16) as *i64 47 let b: *u8=sys_read_file("knowledge/status/galx_vid_paths.tsv" as *u8, szp) 48 if (b as i64)==0 { bp("no vid index\n" as *u8); return 1 } 49 let sz: i64=szp[0] 50 // count line-starts and record their byte offsets (off[id] = start of recording id's line) 51 var n: i64=1; var c: i64=0 52 while c<sz { if b[c]==(10 as u8) { if c+1<sz { n=n+1 } } c=c+1 } 53 let off: *i64=sys_mmap(8*(n+16)) as *i64 54 off[0]=0; var cnt: i64=1; c=0 55 while c<sz { if b[c]==(10 as u8) { if c+1<sz { if cnt<n { off[cnt]=c+1; cnt=cnt+1 } } } c=c+1 } 56 let path: *u8=sys_mmap(K_MAGIC_4096) 57 let ipath: *u8=sys_mmap(512) 58 let st: *i64=sys_mmap(16) as *i64 59 var built: i64=0; var skipped: i64=0; var missing: i64=0 60 var refused: i64=0; var failed: i64=0; var processed: i64=0 61 bp("backfill NEWEST-FIRST: lines=" as *u8); bn(n); bp(" max=" as *u8); bn(maxc); bp("\n" as *u8) 62 // FIX 2026-07-14: nx_ts_index.elf path was HARDCODED to the dev tree (/mnt/c/.../_hdl_build), which is ABSENT 63 // on the Synology NAS -> the fork failed (exit 127) -> recordings NEVER got a NXVI index there = no duration/ 64 // seek/markers ("doesnt play to begin with"). Resolve NAS-first (/volume1/ai/galx) with a dev fallback. 65 let TS_NAS: *u8 = "/volume1/ai/galx/nx_ts_index.elf" as *u8 66 let TS_DEV: *u8 = "/mnt/c/Users/elder/nishi-core/nxc2/runtime/_hdl_build/nx_ts_index.elf" as *u8 67 var tsx: *u8 = TS_NAS 68 if bexists(TS_NAS) == 0 { tsx = TS_DEV } 69 bp(" ts_index=" as *u8); bp(tsx); bp("\n" as *u8) 70 var id: i64=n-1 71 while id >= 0 { 72 if processed >= maxc { bp("reached max; stopping\n" as *u8); return 0 } 73 let ls: i64=off[id] 74 var o: i64=0; var p: i64=ls 75 while p<sz { if b[p]==(10 as u8) { p=sz } else { if b[p]==(9 as u8) { p=sz } else { if b[p]==(13 as u8) { p=sz } else { path[o]=b[p]; o=o+1; p=p+1 } } } } 76 path[o]=0 as u8 77 if o > 0 { 78 var io: i64=0; let pre: *u8="knowledge/status/galxidx_" as *u8; var pi: i64=0; while pre[pi]!=(0 as u8){ ipath[io]=pre[pi]; io=io+1; pi=pi+1 } 79 let d: *u8=sys_mmap(32); let dl: i64=bitoa(id, d); var k: i64=0; while k<dl{ ipath[io]=d[k]; io=io+1; k=k+1 } 80 let sf: *u8=".idx" as *u8; var si: i64=0; while sf[si]!=(0 as u8){ ipath[io]=sf[si]; io=io+1; si=si+1 } ipath[io]=0 as u8 81 if bidx_ok(ipath, path)==1 { skipped=skipped+1 } else { 82 if bexists(path)==1 { 83 let pid: i64=sys_fork() 84 if pid==0 { 85 let av: *i64=sys_mmap(64) as *i64; av[0]=tsx as i64; av[1]=path as i64; av[2]=ipath as i64; av[3]=0 86 let ev: *i64=sys_mmap(8) as *i64; ev[0]=0 87 sys_execve(tsx, av, ev); sys_exit(127) 88 } 89 sys_wait4(pid, st, 0) 90 let crc: i64 = (st[0] >> 8) & 0xff 91 processed=processed+1 92 if crc == 0 { built=built+1 } 93 if crc == 12 { refused=refused+1 } 94 if crc != 0 { if crc != 12 { failed=failed+1 } } 95 if crc == 0 { bp("built id=" as *u8); bn(id); bp(" (built=" as *u8); bn(built); bp(")\n" as *u8) } 96 if crc != 0 { bp("NOT-built id=" as *u8); bn(id); bp(" rc=" as *u8); bn(crc); bp("\n" as *u8) } 97 sys_poll(0 as *u8, 0, 300) 98 } else { missing=missing+1 } 99 } 100 } 101 id=id-1 102 } 103 bp("DONE built=" as *u8); bn(built); bp(" refused_nonTS=" as *u8); bn(refused); bp(" failed=" as *u8); bn(failed); bp(" skipped(v2)=" as *u8); bn(skipped); bp(" missing=" as *u8); bn(missing); bp("\n" as *u8) 104 return 0 105}