code wiki / (root) / nx_memory_lib.nx

nx_memory_lib.nx source

↩ module page · 113 lines · 6062 B

1// nx_memory_lib.nx -- CONSOLIDATED memory tool (MCP name: nx_memory, tool #6 of the 15), LIBRARY half. 2// READ-ONLY first increment over the sovereign seg-stores (the ecosystem's memory substrate): 3// stores <dir> -> discover every seg-store under a dir (by its manifest) + live segment count 4// get <prefix> <key> -> LATEST value bytes (version-resolved by the store, not raw file bytes) 5// history <prefix> <key> -> every version's kind+len (the time-travel surface, metadata only) 6// index <prefix> <idxkey> -> a registry's newline id-index (e.g. __toolidx__ / __works__ / __blidx__) 7// This is STRUCTURED state over MCP -- what raw file reads (nx_fs) cannot give: latest-version resolution, 8// tombstone semantics, version history. put/tombstone = a LATER increment behind its own write-cap. 9// license_tier: ORIGINAL 10import "nx_syscalls.nx" 11import "nx_itoa_lib.nx" // shared MSB-first emitter (zero-alloc) 12import "nx_seg_store.nx" // ss_get / ss_scan / ss_manifest_dyn -- the canonical store readers 13 14const MX_IDX_CAP: i64 = 1048576 // index copy buffer (mirrors reg_index sizing) 15const MX_VER_SLOTS: i64 = 260 // per-key version metadata slots (mirrors SS_VER_SLOTS) 16const MX_PATH_CAP: i64 = 1024 17const MX_DENT_BUF: i64 = 65536 // getdents64 batch buffer (proven sizing) 18const MX_ASCII_0: i64 = 48 // '0' 19 20func mx_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 } 21// MIGRATED to the shared emitter (debt 1785563586). The old body mmapped a scratch buffer 22// per call and never freed it. At PAGE granularity that is 4096B leaked PER CALL -- the 23// defect that took 28.5GB of a 36GB host in nx_ts_lumadiff (2MB input, ~3.66M calls). 24// nxi_* is MSB-first, allocates NOTHING, and emits identical bytes including the sign. 25func mx_putn(v: i64) -> i64 { nxi_out(v); return 0 } 26func mx_seq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 27func mx_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 28// does NUL-terminated s end with NUL-terminated suf? 29func mx_ends(s: *u8, suf: *u8) -> i64 { 30 let n: i64 = mx_slen(s) 31 let m: i64 = mx_slen(suf) 32 if m > n { return 0 } 33 var i: i64 = 0 34 while i < m { if s[n - m + i] != suf[i] { return 0 } i = i + 1 } 35 return 1 36} 37 38// get: print the LATEST value of key. Returns len | -1 absent | tombstone sentinel (0-(3 as i64)). 39func mx_get(prefix: *u8, key: *u8) -> i64 { 40 let po: *i64 = sys_mmap(16) as *i64 41 let lo: *i64 = sys_mmap(16) as *i64 42 let r: i64 = ss_get(prefix, key, po, lo) 43 if r < 0 { mx_puts("NX-MEMORY ABSENT: no such key in this store\n" as *u8); return 0 - 1 } 44 if r == 0 { mx_puts("NX-MEMORY TOMBSTONED: key exists but its latest version is a delete marker\n" as *u8); return 0 - (3 as i64) } 45 sys_write(1, po[0] as *u8, lo[0]) 46 return lo[0] 47} 48// history: one metadata line per version ("v<i> kind=<k> len=<n>"); returns version count (0 = absent). 49func mx_history(prefix: *u8, key: *u8) -> i64 { 50 let kinds: *i64 = sys_mmap(8 * MX_VER_SLOTS) as *i64 51 let ptrs: *i64 = sys_mmap(8 * MX_VER_SLOTS) as *i64 52 let lens: *i64 = sys_mmap(8 * MX_VER_SLOTS) as *i64 53 let n: i64 = ss_scan(prefix, key, kinds, ptrs, lens) 54 mx_puts("versions=" as *u8); mx_putn(n); mx_puts(" (most-recent window; oldest first)\n" as *u8) 55 var i: i64 = 0 56 while i < n { 57 mx_puts("v" as *u8); mx_putn(i) 58 mx_puts(" kind=" as *u8); mx_putn(kinds[i]) 59 mx_puts(" len=" as *u8); mx_putn(lens[i]) 60 mx_puts("\n" as *u8) 61 i = i + 1 62 } 63 return n 64} 65// index: print a registry's newline id-index; returns its length (0 empty/absent). 66func mx_index(prefix: *u8, idxkey: *u8) -> i64 { 67 let po: *i64 = sys_mmap(16) as *i64 68 let lo: *i64 = sys_mmap(16) as *i64 69 if ss_get(prefix, idxkey, po, lo) != 1 { mx_puts("NX-MEMORY: no index under that key\n" as *u8); return 0 } 70 sys_write(1, po[0] as *u8, lo[0]) 71 return lo[0] 72} 73// stores: discover seg-stores in `dir` by their "<prefix>manifest.txt"; print "prefix nsegs=<n>" per store. 74// Returns store count; -1 if the dir cannot be opened. (manifest-archive.txt does NOT end with manifest.txt.) 75func mx_stores(dir: *u8) -> i64 { 76 let fd: i64 = sys_openat_rd(dir) 77 if fd < 0 { mx_puts("NX-MEMORY ABSENT: cannot open dir " as *u8); mx_puts(dir); mx_puts("\n" as *u8); return 0 - 1 } 78 let dbuf: *u8 = sys_mmap(MX_DENT_BUF) 79 let pfx: *u8 = sys_mmap(MX_PATH_CAP) 80 let segp: *i64 = sys_mmap(16) as *i64 81 var cnt: i64 = 0 82 var run: i64 = 1 83 while run == 1 { 84 let n: i64 = sys_getdents64(fd, dbuf, MX_DENT_BUF) 85 if n <= 0 { run = 0 } else { 86 var off: i64 = 0 87 while off < n { 88 let rec: *u8 = ((dbuf as i64 + off) as *u8) 89 let reclen: i64 = dirent_reclen(rec) 90 if reclen <= 0 { off = n } else { 91 let name: *u8 = dirent_name(rec) 92 if mx_ends(name, "manifest.txt" as *u8) == 1 { 93 // prefix = dir + "/" + name minus the "manifest.txt" suffix 94 var o: i64 = 0 95 var i: i64 = 0 96 while dir[i] != (0 as u8) { pfx[o] = dir[i]; o = o + 1; i = i + 1 } 97 if o > 0 { if pfx[o-1] != (47 as u8) { pfx[o] = 47 as u8; o = o + 1 } } 98 let keep: i64 = mx_slen(name) - mx_slen("manifest.txt" as *u8) 99 i = 0 100 while i < keep { pfx[o] = name[i]; o = o + 1; i = i + 1 } 101 pfx[o] = 0 as u8 102 let ns: i64 = ss_manifest_dyn(pfx, segp) 103 mx_puts(pfx); mx_puts(" nsegs=" as *u8); mx_putn(ns); mx_puts("\n" as *u8) 104 cnt = cnt + 1 105 } 106 off = off + reclen 107 } 108 } 109 } 110 } 111 sys_close(fd) 112 return cnt 113}