nx_app_store.nx source
↩ module page · 92 lines · 3621 B
1// nx_app_store.nx -- the Nishi-native app registry, on the sovereign seg_store
2// (append-only, additive, crash-safe rename-commit). REPLACES the flat TSV --
3// "migrate to the nishi ecosystem everywhere". Each app is a record:
4// key = "app:<name>"
5// val = path<TAB>title<TAB>blurb<TAB>category<TAB>marker
6// plus an "__apps__" record (newline-separated names) maintained IN THE SAME COMMIT
7// so the hub + monitor can enumerate the whole registry atomically (no torn state).
8// Durable on disk under APP_PREFIX; history is never destroyed (additive law).
9// license_tier: ORIGINAL
10import "nx_syscalls.nx"
11import "nx_seg_store.nx"
12const APP_MAGIC_65536: i64 = 65536
13
14const APP_PREFIX: *u8 = "knowledge/appstore-" as *u8
15
16func aps_strlen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n }
17func aps_cat(dst: *u8, off: i64, s: *u8) -> i64 { var i: i64=0; while s[i]!=(0 as u8){ dst[off+i]=s[i]; i=i+1 } return off+i }
18
19// key "app:<name>" (NUL-terminated) into kbuf
20func aps_key(kbuf: *u8, name: *u8) -> i64 {
21 var o: i64 = aps_cat(kbuf, 0, "app:" as *u8)
22 o = aps_cat(kbuf, o, name)
23 kbuf[o] = 0 as u8
24 return o
25}
26
27// is `name` (namelen bytes) already a line in the newline-separated index buf[0..n)?
28func aps_name_present(buf: *u8, n: i64, name: *u8, namelen: i64) -> i64 {
29 var ls: i64 = 0
30 var i: i64 = 0
31 while i <= n {
32 var eol: i64 = 0
33 if i == n { eol = 1 } else { if buf[i] == 10 as u8 { eol = 1 } }
34 if eol == 1 {
35 if i - ls == namelen {
36 var m: i64 = 1
37 var c: i64 = 0
38 while c < namelen { if buf[ls + c] != name[c] { m = 0 } c = c + 1 }
39 if m == 1 { return 1 }
40 }
41 ls = i + 1
42 }
43 i = i + 1
44 }
45 return 0
46}
47
48// register/update an app (additive new version; __apps__ index advanced same commit)
49func nx_app_store_put(name: *u8, record: *u8, reclen: i64) -> i64 {
50 let kbuf: *u8 = sys_mmap(256)
51 aps_key(kbuf, name)
52 // fresh max+1 segid (ss_next_segid, uncapped) -- the capped ss_manifest count clobbers past the cap
53 let segid: i64 = ss_next_segid(APP_PREFIX)
54 let w: *i64 = ss_begin()
55 ss_add(w, 1, kbuf, record, reclen)
56 let ipo: *i64 = sys_mmap(16) as *i64
57 let ilo: *i64 = sys_mmap(16) as *i64
58 let idxbuf: *u8 = sys_mmap(APP_MAGIC_65536)
59 var ilen: i64 = 0
60 if ss_get(APP_PREFIX, "__apps__" as *u8, ipo, ilo) >= 0 {
61 let src: *u8 = ipo[0] as *u8
62 var c: i64 = 0
63 while c < ilo[0] { idxbuf[ilen] = src[c]; ilen = ilen + 1; c = c + 1 }
64 }
65 let nl: i64 = aps_strlen(name)
66 if aps_name_present(idxbuf, ilen, name, nl) == 0 {
67 var c2: i64 = 0
68 while c2 < nl { idxbuf[ilen] = name[c2]; ilen = ilen + 1; c2 = c2 + 1 }
69 idxbuf[ilen] = 10 as u8
70 ilen = ilen + 1
71 }
72 ss_add(w, 1, "__apps__" as *u8, idxbuf, ilen)
73 return ss_commit(APP_PREFIX, w, segid)
74}
75
76// copy the newline-separated app-name index into idxbuf; returns its length (0 if empty)
77func nx_app_store_index(idxbuf: *u8) -> i64 {
78 let ipo: *i64 = sys_mmap(16) as *i64
79 let ilo: *i64 = sys_mmap(16) as *i64
80 if ss_get(APP_PREFIX, "__apps__" as *u8, ipo, ilo) < 0 { return 0 }
81 let src: *u8 = ipo[0] as *u8
82 var i: i64 = 0
83 while i < ilo[0] { idxbuf[i] = src[i]; i = i + 1 }
84 return ilo[0]
85}
86
87// get app <name>'s current record -> ptrout[0]/lenout[0]; rc<0 if not found
88func nx_app_store_get(name: *u8, ptrout: *i64, lenout: *i64) -> i64 {
89 let kbuf: *u8 = sys_mmap(256)
90 aps_key(kbuf, name)
91 return ss_get(APP_PREFIX, kbuf, ptrout, lenout)
92}