code wiki / (root) / nx_galx_vidindex_nas.nx

nx_galx_vidindex_nas.nx source

↩ module page · 93 lines · 4906 B

1// nx_galx_vidindex_nas.nx -- NAS-NATIVE recordings reindex (operator 2026-06-23: "investigate and resolve"). 2// ROOT CAUSE FOUND: the gallery's video catalog pointed at /volume1/logging/#recycle/<model>/*.ts (the 3// Synology TRASH) while the LIVE recordings are at /volume1/logging/<model>/*.ts -> serve 404s on every 4// video. This runs ON THE NAS (via nx_nas_run): scans /volume1/logging natively (sys_getdents64), SKIPS 5// #recycle + @eaDir + .trickplay, writes the fresh catalog to a .new STAGING file (reversible; promote 6// after verify). NAS-native /volume1/... paths = exactly what the serve opens. No sh. license_tier: ORIGINAL 7import "nx_syscalls.nx" 8import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 9const VI_MAGIC_2048: i64 = 2048 10 11const GBUF: i64 = 65536 12const VI_SCAN: *u8 = "/volume1/logging" 13const VI_SCAN2: *u8 = "/volume1/logs" // 2026-07-11: the SECOND recordings tree (29.3 TB / ~14k .ts) was never indexed 14const VI_OUT: *u8 = "/volume1/ai/galx/knowledge/status/galx_vid_paths.tsv.new" // STAGING; promote after verify 15 16func vi_p(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(1,s,n); return 0 } 17// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 18// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 19// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 20// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 21func vi_n(v: i64) -> i64 { nxi_out(v); return 0 } 22func vi_len(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 23func vi_is_vid(name: *u8) -> i64 { 24 let n: i64 = vi_len(name) 25 if n >= 3 { if name[n-3]==(46 as u8) { if name[n-2]==(116 as u8) { if name[n-1]==(115 as u8) { return 1 } } } } // .ts 26 if n >= 4 { if name[n-4]==(46 as u8) { 27 if name[n-3]==(109 as u8) { if name[n-2]==(112 as u8) { if name[n-1]==(52 as u8) { return 1 } } } // .mp4 28 if name[n-3]==(109 as u8) { if name[n-2]==(107 as u8) { if name[n-1]==(118 as u8) { return 1 } } } // .mkv 29 if name[n-3]==(102 as u8) { if name[n-2]==(108 as u8) { if name[n-1]==(118 as u8) { return 1 } } } // .flv 30 } } 31 return 0 32} 33func vi_is_trick(name: *u8) -> i64 { 34 let n: i64 = vi_len(name) 35 let suf: *u8 = ".trickplay" as *u8 36 if n < 10 { return 0 } 37 var i: i64 = 0 38 while i < 10 { if name[n-10+i] != suf[i] { return 0 } i = i + 1 } 39 return 1 40} 41func vi_walk(dir: *u8, depth: i64, outfd: i64, cntp: *i64) -> i64 { 42 if depth > 6 { return 0 } 43 let fd: i64 = sys_openat_rd(dir) 44 if fd < 0 { return 0 } 45 let gbuf: *u8 = sys_mmap(GBUF) 46 let child: *u8 = sys_mmap(VI_MAGIC_2048) 47 let dlen: i64 = vi_len(dir) 48 var go: i64 = 1 49 while go == 1 { 50 let n: i64 = sys_getdents64(fd, gbuf, GBUF) 51 if n <= 0 { go = 0 } else { 52 var off: i64 = 0 53 while off < n { 54 let rec: *u8 = ((gbuf as i64) + off) as *u8 55 let reclen: i64 = dirent_reclen(rec) 56 let typ: i64 = dirent_type(rec) 57 let name: *u8 = dirent_name(rec) 58 var skip: i64 = 0 59 if name[0]==(46 as u8) { if name[1]==(0 as u8) { skip=1 } else { if name[1]==(46 as u8) { if name[2]==(0 as u8) { skip=1 } } } } 60 if name[0]==(35 as u8) { skip=1 } // '#recycle' 61 if name[0]==(64 as u8) { skip=1 } // '@eaDir' (Synology metadata) 62 if skip == 0 { 63 var co: i64 = 0 64 while co < dlen { child[co]=dir[co]; co=co+1 } 65 child[co]=47 as u8; co=co+1 66 var ni: i64 = 0 67 while name[ni]!=(0 as u8) { child[co]=name[ni]; co=co+1; ni=ni+1 } 68 child[co]=0 as u8 69 if vi_is_vid(name)==1 { 70 sys_write(outfd, child, co); sys_write(outfd, "\n" as *u8, 1); cntp[0]=cntp[0]+1 71 } else { 72 if vi_is_trick(name)==0 { if typ != DT_REG { vi_walk(child, depth+1, outfd, cntp) } } 73 } 74 } 75 if reclen <= 0 { off = n } else { off = off + reclen } 76 } 77 } 78 } 79 sys_close(fd) 80 return 0 81} 82func main(argc: i64, argv: *i64) -> i64 { 83 let outfd: i64 = sys_openat_wr(VI_OUT, 0x1a4) 84 if outfd < 0 { vi_p("VIDINDEX-NAS FAIL: cannot write " as *u8); vi_p(VI_OUT); vi_p(" (run ON the NAS)\n" as *u8); sys_exit(1); return 1 } 85 let cntp: *i64 = sys_mmap(16) as *i64 86 cntp[0] = 0 87 vi_walk(VI_SCAN, 0, outfd, cntp) 88 vi_walk(VI_SCAN2, 0, outfd, cntp) // index the second recordings tree too (/volume1/logs) 89 sys_close(outfd) 90 vi_p("VIDINDEX-NAS OK live_recordings=" as *u8); vi_n(cntp[0]); vi_p(" -> " as *u8); vi_p(VI_OUT); vi_p("\n" as *u8) 91 sys_exit(0) 92 return 0 93}