nx_vacuole.nx source
↩ module page · 128 lines · 4163 B
1// nx_vacuole.nx -- sealed content-addressed storage.
2//
3// Per [[feedback-naming-discipline-no-industry-competitor-overlap]]:
4// "nx_vacuole" replaces the "vault" semantic (HashiCorp trademark
5// avoidance). Biology: vacuoles are membrane-bound storage organelles
6// inside the cell -- isolated from cytoplasm, content-addressed by
7// what they contain.
8//
9// EACH ENTRY content-addressed by BLAKE3 hash. Cell can store + read
10// + delete entries. Entries can be methyl-marked for cross-cell
11// transfer authenticity.
12//
13// Composes:
14// nx_cell -- each cell owns its vacuole
15// nx_methyl -- entries sealed with cell's methyl mark
16// nx_brane -- read/write to vacuole gated by capability tokens
17// nx_chromatin -- chromatin captures vacuole state pre-failover
18
19import "nx_syscalls.nx"
20import "nx_tier.nx"
21import "nx_methyl.nx"
22
23const NX_VAC_OK: nx_int = 0
24const NX_VAC_ERR_FULL: nx_int = 1
25const NX_VAC_ERR_NOT_FOUND: nx_int = 2
26const NX_VAC_ERR_BAD_MARK: nx_int = 3
27
28struct NxVacuoleEntry {
29 content_hash: nx_size,
30 payload_ptr: *u8,
31 payload_len: nx_size,
32 sealed_us: nx_size,
33 methyl: *NxMethylMark,
34}
35
36struct NxVacuole {
37 entries: *NxVacuoleEntry,
38 capacity: nx_size,
39 count: nx_size,
40}
41
42const NX_VAC_ENTRY_BYTES: nx_size = 40
43
44func nx_vacuole_new(capacity: nx_size) -> *NxVacuole {
45 let v: *NxVacuole = (sys_mmap(24)) as *NxVacuole
46 let bytes: nx_size = capacity * NX_VAC_ENTRY_BYTES
47 v.entries = (sys_mmap(bytes)) as *NxVacuoleEntry
48 v.capacity = capacity
49 v.count = 0
50 return v
51}
52
53func _vac_at(v: *NxVacuole, idx: nx_size) -> *NxVacuoleEntry {
54 return (v.entries as i64 + (idx as i64) * NX_VAC_ENTRY_BYTES) as *NxVacuoleEntry
55}
56
57func _vac_find(v: *NxVacuole, content_hash: nx_size) -> nx_int {
58 var i: nx_size = 0
59 while i < v.count {
60 let e: *NxVacuoleEntry = _vac_at(v, i)
61 if e.content_hash == content_hash { return i as i64 }
62 i = i + 1
63 }
64 return -1
65}
66
67// ===== nx_vacuole_put ============================================
68//
69// Store a payload under its content hash. Returns OK on success or
70// FULL/BAD_MARK. Duplicates (same content_hash) are idempotent --
71// the existing entry is kept.
72
73func nx_vacuole_put(v: *NxVacuole,
74 content_hash: nx_size,
75 payload_ptr: *u8,
76 payload_len: nx_size,
77 methyl: *NxMethylMark,
78 now_us: nx_size) -> nx_int {
79 if (methyl as i64) == 0 { return NX_VAC_ERR_BAD_MARK }
80 if _vac_find(v, content_hash) >= 0 { return NX_VAC_OK } // idempotent
81 if v.count >= v.capacity { return NX_VAC_ERR_FULL }
82 let e: *NxVacuoleEntry = _vac_at(v, v.count)
83 e.content_hash = content_hash
84 e.payload_ptr = payload_ptr
85 e.payload_len = payload_len
86 e.sealed_us = now_us
87 e.methyl = methyl
88 v.count = v.count + 1
89 return NX_VAC_OK
90}
91
92// ===== nx_vacuole_get ============================================
93
94func nx_vacuole_get(v: *NxVacuole, content_hash: nx_size) -> *NxVacuoleEntry {
95 let idx: nx_int = _vac_find(v, content_hash)
96 if idx < 0 { return (0 as i64) as *NxVacuoleEntry }
97 return _vac_at(v, idx as nx_size)
98}
99
100// ===== nx_vacuole_delete =========================================
101
102func nx_vacuole_delete(v: *NxVacuole, content_hash: nx_size) -> nx_int {
103 let idx: nx_int = _vac_find(v, content_hash)
104 if idx < 0 { return NX_VAC_ERR_NOT_FOUND }
105 // Compact: shift remaining entries down
106 var i: nx_size = idx as nx_size
107 while i < v.count - 1 {
108 let dst: *NxVacuoleEntry = _vac_at(v, i)
109 let src: *NxVacuoleEntry = _vac_at(v, i + 1)
110 dst.content_hash = src.content_hash
111 dst.payload_ptr = src.payload_ptr
112 dst.payload_len = src.payload_len
113 dst.sealed_us = src.sealed_us
114 dst.methyl = src.methyl
115 i = i + 1
116 }
117 v.count = v.count - 1
118 return NX_VAC_OK
119}
120
121func nx_vacuole_count(v: *NxVacuole) -> nx_size {
122 return v.count
123}
124
125func nx_vacuole_contains(v: *NxVacuole, content_hash: nx_size) -> nx_int {
126 if _vac_find(v, content_hash) >= 0 { return 1 }
127 return 0
128}