code wiki / _hdl_build / nx_ecomat_put.nx
nx_ecomat_put.nx source
↩ module page · 102 lines · 5864 B
1// nx_ecomat_put.nx -- store-native autoid domain adder for the ecomat maturity plane (acl F771).
2// Adds ONE domain to the seg-store at the next CONTIGUOUS id, atomically under flock. ss_commit REPLACES
3// the store with the write-set (gate-proven), so this RELOADS every existing domain + adds the new one +
4// commits the whole set (load-all/write-all, like nx_frontier_put). Kills the two-edit-surface seeder
5// clobber (no seeder-source edit). No hw writes (Rule 26). Gate: nx_ecomat_put_gate 3/3 on a throwaway.
6// nx_ecomat_put addauto <axis> <layer> <cur> <bar> <weight> <domain> <bench> <nextrung> [evlog] [evpat] [prefix]
7// exit: 0 ok (ECOMAT-PUT id=N) | 2 usage | 1 fail-closed.
8// license_tier: ORIGINAL expect_exit: 0
9import "nx_ecomat_lib.nx"
10import "nx_seg_store.nx"
11import "nx_syscalls.nx"
12const EP_MAGIC_1024: i64 = 1024
13
14const EP_STDERR: i64 = 2
15const EP_MODE: i64 = 420
16const EP_LOCK_EX: i64 = 2
17
18func ep_puts(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(1, s, n); return 0 }
19func ep_werr(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(EP_STDERR, s, n); return 0 }
20func ep_vlen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
21func ep_atoi(s: *u8) -> i64 { var v: i64 = 0; var i: i64 = 0; while s[i] != (0 as u8) { let c: i64 = s[i] as i64; if c >= 48 { if c <= 57 { v = v * 10 + (c - 48) } } i = i + 1 } return v }
22func ep_catn(fd: i64, v: i64) -> i64 { var m: i64 = v; if m < 0 { m = 0 } let t: *u8 = sys_mmap(28); var k: i64 = 0; if m == 0 { t[0] = 48 as u8; k = 1 } while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } let o: *u8 = sys_mmap(28); var i: i64 = 0; while i < k { o[i] = t[k-1-i]; i = i + 1 } sys_write(fd, o, k); return 0 }
23func ep_lock(prefix: *u8) -> i64 {
24 let p: *u8 = sys_mmap(256)
25 var o: i64 = 0
26 var i: i64 = 0
27 while prefix[i] != (0 as u8) { p[o] = prefix[i]; o = o + 1; i = i + 1 }
28 let s: *u8 = "plock" as *u8
29 var j: i64 = 0
30 while s[j] != (0 as u8) { p[o] = s[j]; o = o + 1; j = j + 1 }
31 p[o] = 0 as u8
32 let fd: i64 = sys_openat_append(p, EP_MODE)
33 if fd < 0 { return 0 - 1 }
34 sys_flock(fd, EP_LOCK_EX)
35 return fd
36}
37func main(argc: i64, argv: *i64) -> i64 {
38 if argc < 10 { ep_werr("usage: nx_ecomat_put addauto <axis> <layer> <cur> <bar> <weight> <domain> <bench> <nextrung> [evlog] [evpat] [prefix]\n" as *u8); sys_exit(2); return 2 }
39 let verb: *u8 = argv[1] as *u8
40 if ep_vlen(verb) != 7 { ep_werr("PUT-FAIL only verb 'addauto' supported\n" as *u8); sys_exit(2); return 2 }
41 let axis: i64 = ep_atoi(argv[2] as *u8)
42 let layer: i64 = ep_atoi(argv[3] as *u8)
43 let cur: i64 = ep_atoi(argv[4] as *u8)
44 let bar: i64 = ep_atoi(argv[5] as *u8)
45 let weight: i64 = ep_atoi(argv[6] as *u8)
46 let domain: *u8 = argv[7] as *u8
47 let bench: *u8 = argv[8] as *u8
48 let nextrung: *u8 = argv[9] as *u8
49 var evlog: *u8 = "" as *u8
50 var evpat: *u8 = "" as *u8
51 var prefix: *u8 = ECOMAT_STORE
52 if argc > 10 { evlog = argv[10] as *u8 }
53 if argc > 11 { evpat = argv[11] as *u8 }
54 if argc > 12 { prefix = argv[12] as *u8 }
55 var ev: i64 = 0
56 var evkind: i64 = 0
57 if ep_vlen(evlog) > 0 { ev = 1; evkind = 2 }
58 if axis < 0 { ep_werr("PUT-FAIL axis must be 0..2\n" as *u8); sys_exit(1); return 1 }
59 if axis > 2 { ep_werr("PUT-FAIL axis must be 0..2\n" as *u8); sys_exit(1); return 1 }
60
61 let lk: i64 = ep_lock(prefix)
62 if lk < 0 { ep_werr("PUT-FAIL cannot lock\n" as *u8); sys_exit(1); return 1 }
63 let h: *i64 = ss_open(prefix)
64 let w: *i64 = ss_begin()
65 var nextid: i64 = 0
66 if (h as i64) != 0 {
67 let pq: *i64 = sys_mmap(16) as *i64
68 let lq: *i64 = sys_mmap(16) as *i64
69 var go: i64 = 1
70 while go == 1 {
71 let key: *u8 = sys_mmap(64)
72 ec_key(nextid, key)
73 if ss_hget(h, key, pq, lq) == 1 {
74 if ss_add(w, 1, key, pq[0] as *u8, lq[0]) != 0 { ep_werr("PUT-FAIL writeset overflow on reload\n" as *u8); sys_exit(1); return 1 }
75 nextid = nextid + 1
76 } else { go = 0 }
77 }
78 }
79 // Size the buffer from the DATA (ec_reclen), never a fixed guess: a long domain/bench/next-rung
80 // row used to overrun a fixed 1024 and then get blamed on a bogus "record too large".
81 let cap: i64 = ec_reclen(domain, bench, nextrung, evlog, evpat, "" as *u8, "" as *u8)
82 let val: *u8 = sys_mmap(cap)
83 let vlen: i64 = ec_pack(val, cap, axis, layer, cur, bar, weight, ev, evkind, 0, domain, bench, nextrung, evlog, evpat, "" as *u8, "" as *u8)
84 if vlen < 0 { ep_werr("PUT-FAIL pack refused: derived buffer too small (ec_reclen disagrees with ec_pack)\n" as *u8); sys_exit(1); return 1 }
85 let key2: *u8 = sys_mmap(64)
86 ec_key(nextid, key2)
87 // ss_add2 fail-closes ONLY on cumulative write-set overflow vs the ss_begin buffer -- there is no
88 // per-record size check anywhere in the store. Say what actually happened; the old "record too
89 // large" text misdescribed the sole failure this call can report and misdirected diagnosis.
90 if ss_add(w, 1, key2, val, vlen) != 0 { ep_werr("PUT-FAIL write-set full: reloaded domains plus this record exceed the ss_begin buffer\n" as *u8); sys_exit(1); return 1 }
91 let cnt: i64 = ss_commit(prefix, w, sys_now_realtime_sec())
92 if cnt < 0 { ep_werr("PUT-FAIL commit error\n" as *u8); sys_exit(1); return 1 }
93 ep_puts("ECOMAT-PUT id=" as *u8); ep_catn(1, nextid)
94 ep_puts(" domain=" as *u8); ep_puts(domain)
95 ep_puts(" axis=" as *u8); ep_catn(1, axis)
96 ep_puts(" cur=" as *u8); ep_catn(1, cur)
97 ep_puts(" bar=" as *u8); ep_catn(1, bar)
98 if ev == 1 { ep_puts(" ev=single-src" as *u8) } else { ep_puts(" ev=stored" as *u8) }
99 ep_puts(" (store-append RMW; seeder-clobber avoided)\n" as *u8)
100 sys_exit(0)
101 return 0
102}