code wiki / _hdl_build / nx_consul_kv.nx
nx_consul_kv.nx source
↩ module page · 40 lines · 2042 B
1// nx_consul_kv.nx -- sovereign KEY-VALUE store with COMPARE-AND-SWAP (HashiCorp Consul KV-class; CONSUL-002).
2// Each key carries a per-key version (Consul's ModifyIndex) that bumps on every modify. CAS applies a write
3// ONLY if the caller's expected version matches the current one (optimistic concurrency) -- this is the
4// primitive distributed LOCKS and leader-election are built on (a stale writer is rejected, never clobbers).
5// Pure logic over fixed-slot arrays. license_tier: ORIGINAL (composes into the sovereign-Consul arc)
6import "nx_syscalls.nx"
7
8// index of a present key, or -1.
9func ckv_get(keys: *i64, present: *i64, n: i64, key: i64) -> i64 {
10 var i: i64 = 0
11 while i < n { if present[i] == 1 { if keys[i] == key { return i } } i = i + 1 }
12 return 0 - 1
13}
14
15// create-or-update; bump the per-key version; return the new version (-1 if no free slot on create).
16func ckv_put(keys: *i64, vals: *i64, vers: *i64, present: *i64, n: i64, key: i64, val: i64) -> i64 {
17 let idx: i64 = ckv_get(keys, present, n, key)
18 if idx >= 0 { vals[idx] = val; vers[idx] = vers[idx] + 1; return vers[idx] }
19 var i: i64 = 0
20 while i < n {
21 if present[i] == 0 { present[i] = 1; keys[i] = key; vals[i] = val; vers[i] = 1; return 1 }
22 i = i + 1
23 }
24 return 0 - 1
25}
26
27// compare-and-swap: apply ONLY if current version == expected (expected==0 creates a missing key).
28// returns 1 = applied (version bumped), 0 = conflict (no change). The lock-safety primitive.
29func ckv_cas(keys: *i64, vals: *i64, vers: *i64, present: *i64, n: i64, key: i64, val: i64, expected: i64) -> i64 {
30 let idx: i64 = ckv_get(keys, present, n, key)
31 if idx < 0 {
32 if expected == 0 { if ckv_put(keys, vals, vers, present, n, key, val) > 0 { return 1 } return 0 }
33 return 0
34 }
35 if vers[idx] == expected { vals[idx] = val; vers[idx] = vers[idx] + 1; return 1 }
36 return 0
37}
38
39// delete a key by index (idempotent).
40func ckv_delete(present: *i64, idx: i64) -> i64 { if idx >= 0 { present[idx] = 0 } return 0 }