code wiki / (root) / nx_vacuole.nx

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}