nx_pub_release_lib.nx source
↩ module page · 145 lines · 5491 B
1// Versioned release identity records in the existing publication store. No q-row rewrite.
2import "nx_seg_store.nx"
3
4const PR_OK: i64 = 0
5const PR_CREATED: i64 = 1
6const PR_INVALID: i64 = 2
7const PR_IO: i64 = 4
8const PR_CONFLICT: i64 = 8
9const PR_SHA_HEX: i64 = 64
10const PR_KEY_PREFIX: *u8 = "pub-release:" as *u8
11const PR_RECORD_PREFIX: *u8 = "NPR1\tregistered\t" as *u8
12
13func pr_path_ok(path: *u8) -> i64 {
14 let root: *u8 = "releases/" as *u8
15 var i: i64 = 0
16 while root[i] != (0 as u8) {
17 if path[i] != root[i] { return 0 }
18 i = i + 1
19 }
20 if path[i] == (0 as u8) { return 0 }
21 var segment: i64 = 0
22 while path[i] != (0 as u8) {
23 let ch: i64 = path[i] as i64
24 if ch == 47 {
25 if segment == 0 { return 0 }
26 segment = 0
27 } else {
28 if ch == 46 {
29 if segment == 0 { return 0 }
30 if path[i+1] == (46 as u8) { return 0 }
31 } else {
32 var allowed: i64 = 0
33 if ch >= 48 && ch <= 57 { allowed = 1 }
34 if ch >= 65 && ch <= 90 { allowed = 1 }
35 if ch >= 97 && ch <= 122 { allowed = 1 }
36 if ch == 45 || ch == 95 { allowed = 1 }
37 if allowed == 0 { return 0 }
38 }
39 segment = segment + 1
40 }
41 i = i + 1
42 }
43 return (segment > 0) as i64
44}
45func pr_hash_ok(hash: *u8) -> i64 {
46 if ss_len(hash) != PR_SHA_HEX { return 0 }
47 var i: i64 = 0
48 while i < PR_SHA_HEX {
49 let ch: i64 = hash[i] as i64
50 var ok: i64 = 0
51 if ch >= 48 && ch <= 57 { ok = 1 }
52 if ch >= 97 && ch <= 102 { ok = 1 }
53 if ok == 0 { return 0 }
54 i = i + 1
55 }
56 return 1
57}
58func pr_key(path: *u8) -> *u8 {
59 let key: *u8 = sys_mmap(ss_len(PR_KEY_PREFIX)+ss_len(path)+1)
60 let n: i64 = ss_cat(key,0,PR_KEY_PREFIX)
61 let end: i64 = ss_cat(key,n,path)
62 key[end] = 0 as u8
63 return key
64}
65func pr_record(hash: *u8) -> *u8 {
66 let rec: *u8 = sys_mmap(ss_len(PR_RECORD_PREFIX)+PR_SHA_HEX+1)
67 let n: i64 = ss_cat(rec,0,PR_RECORD_PREFIX)
68 let end: i64 = ss_cat(rec,n,hash)
69 rec[end] = 0 as u8
70 return rec
71}
72func pr_same(a: *u8, an: i64, b: *u8, bn: i64) -> i64 {
73 if an != bn { return 0 }
74 var i: i64 = 0
75 while i < an { if a[i] != b[i] { return 0 }; i = i + 1 }
76 return 1
77}
78func pr_check(prefix: *u8, path: *u8, hash: *u8) -> i64 {
79 if pr_path_ok(path) == 0 { return PR_INVALID }
80 if pr_hash_ok(hash) == 0 { return PR_INVALID }
81 let key: *u8 = pr_key(path)
82 let rec: *u8 = pr_record(hash)
83 let ptr: *i64 = sys_mmap(16) as *i64
84 let len: *i64 = sys_mmap(16) as *i64
85 let found: i64 = ss_get_idx_required(prefix,key,ptr,len)
86 if found == (0-2) { return PR_IO }
87 if found != 1 { return PR_CONFLICT }
88 if pr_same(ptr[0] as *u8,len[0],rec,ss_len(rec)) == 0 { return PR_CONFLICT }
89 return PR_OK
90}
91func pr_register(prefix: *u8, path: *u8, hash: *u8) -> i64 {
92 if pr_path_ok(path) == 0 { return PR_INVALID }
93 if pr_hash_ok(hash) == 0 { return PR_INVALID }
94 let generation: i64 = ss_max_segid(prefix)
95 // Never create an independent catalogue accidentally: require the existing publication plane.
96 let ptr: *i64 = sys_mmap(16) as *i64
97 let len: *i64 = sys_mmap(16) as *i64
98 if ss_get_idx_required(prefix,"q:n" as *u8,ptr,len) != 1 { return PR_IO }
99 let key: *u8 = pr_key(path)
100 let rec: *u8 = pr_record(hash)
101 let existing: i64 = ss_get_idx_required(prefix,key,ptr,len)
102 if existing == 1 {
103 if pr_same(ptr[0] as *u8,len[0],rec,ss_len(rec)) == 1 { return PR_OK }
104 return PR_CONFLICT
105 }
106 if existing == (0-2) { return PR_IO }
107 if existing != (0-1) { return PR_CONFLICT }
108 // Capacity is the actual serialized entry length plus the store's entry-header requirement.
109 let writer: *i64 = ss_begin_cap(ss_len(key)+ss_len(rec)+16)
110 if ss_add(writer,1,key,rec,ss_len(rec)) < 0 { return PR_IO }
111 let rc: i64 = ss_commit_cas(prefix,writer,ss_next_segid(prefix),generation)
112 if rc == SS_ERR_STALE { return PR_CONFLICT }
113 if rc != 0 { return PR_IO }
114 if pr_check(prefix,path,hash) != PR_OK { return PR_IO }
115 return PR_CREATED
116}
117
118// Detailed read-only observation for release preparation; legacy pr_check codes stay unchanged.
119const PR_MISSING: i64 = 3
120func pr_observe(prefix: *u8,path: *u8,hash: *u8) -> i64 {
121 if pr_path_ok(path)!=1||pr_hash_ok(hash)!=1{return PR_INVALID}
122 let keybytes:i64=ss_len(PR_KEY_PREFIX)+ss_len(path)+1
123 let recbytes:i64=ss_len(PR_RECORD_PREFIX)+PR_SHA_HEX+1
124 let ptr:*i64=sys_mmap_try(16) as *i64;let len:*i64=sys_mmap_try(16) as *i64
125 let key:*u8=sys_mmap_try(keybytes);let rec:*u8=sys_mmap_try(recbytes)
126 var rc:i64=PR_IO
127 if (ptr as i64)>0&&(len as i64)>0&&(key as i64)>0&&(rec as i64)>0 {
128 if ss_get_idx_required(prefix,"q:n",ptr,len)==1{
129 let kp:i64=ss_cat(key,0,PR_KEY_PREFIX);key[ss_cat(key,kp,path)]=0
130 let rp:i64=ss_cat(rec,0,PR_RECORD_PREFIX);rec[ss_cat(rec,rp,hash)]=0
131 let found:i64=ss_get_idx_required(prefix,key,ptr,len)
132 rc=PR_CONFLICT
133 if found==(0-2){rc=PR_IO}else{
134 if found==(0-1){rc=PR_MISSING}else{
135 if found==1{if pr_same(ptr[0] as *u8,len[0],rec,ss_len(rec))==1{rc=PR_OK}}
136 }
137 }
138 }
139 }
140 if (key as i64)>0{if sys_munmap(key,keybytes)!=0{rc=PR_IO}}
141 if (rec as i64)>0{if sys_munmap(rec,recbytes)!=0{rc=PR_IO}}
142 if (ptr as i64)>0{if sys_munmap(ptr as *u8,16)!=0{rc=PR_IO}}
143 if (len as i64)>0{if sys_munmap(len as *u8,16)!=0{rc=PR_IO}}
144 return rc
145}