diff options
| author | Estevan Castilho <tevo@riajuu.net> | 2026-08-20 00:18:32 +0000 |
|---|---|---|
| committer | Estevan Castilho <tevo@riajuu.net> | 2026-08-23 03:06:57 +0000 |
| commit | ebea139a01d1ca3f53df9671ff4ebf7990ac26d4 (patch) | |
| tree | a897b2bacad96ce763ec9b22cd0f68fd5710a5a7 | |
| parent | 465f3378daea5a6f0d44f3729c3551a9cda78ed9 (diff) | |
| download | RNT-ebea139a01d1ca3f53df9671ff4ebf7990ac26d4.tar.gz RNT-ebea139a01d1ca3f53df9671ff4ebf7990ac26d4.zip | |
Make `update` a bit more like compare-and-swap
Diffstat (limited to '')
| -rw-r--r-- | lib/kernel/BranchManager.ml | 36 | ||||
| -rw-r--r-- | lib/kernel/BranchManager.mli | 6 |
2 files changed, 23 insertions, 19 deletions
diff --git a/lib/kernel/BranchManager.ml b/lib/kernel/BranchManager.ml index 71a25b3..80e32a4 100644 --- a/lib/kernel/BranchManager.ml +++ b/lib/kernel/BranchManager.ml @@ -1,21 +1,26 @@ -module BranchValue = Merkle.StringKey (* FIXME *) - type branch = string module Error = struct open Concepts.Condition - let invalid_root head = condition "invalid-root" "The root hash for the database state is missing from the backend. Either your storage is corrupted, or this is a bug in RNT!" - ("hash" |=| (Concepts.Value.String (Concepts.Hash.to_hum_string head))) + let invalid_root head = + condition "invalid-root" "The root hash for the database state is missing from the backend. Either your storage is corrupted, or this is a bug in RNT!" + ("hash" |=| (Concepts.Value.String (Concepts.Hash.to_hum_string head))) + + let comparison_failed branch_name reference head = + condition "comparison-failed" "The HEAD of the branch did not match what was expected" + ("branch" |=| Concepts.Value.String branch_name & + "reference" |=| Concepts.Value.String (Concepts.Hash.to_hum_string reference) & + "head" |=| Concepts.Value.String (Concepts.Hash.to_hum_string head)) end module Make (S : Abstract.Storage.STORAGE) = struct - module I = Merkle.Interface (S) (Merkle.StringKey) (BranchValue) + module M = Merkle.Make (S) (Merkle.StringKey) module SI = Storage.Make (S) type manager = { storage: S.connection; label : string; - head: I.node Atomic.t } + head: M.node Atomic.t } let root_for tx label = let open Utilities.Result in @@ -23,8 +28,6 @@ module Make (S : Abstract.Storage.STORAGE) = struct let label = Option.map Concepts.Hash.hash_of_blob label in Ok label - let persist_root tx label new_branch = failwith "TODO" - let initialize storage label = let open Utilities.Result in SI.with_transaction storage (fun tx -> @@ -32,22 +35,25 @@ module Make (S : Abstract.Storage.STORAGE) = struct match addr with | None -> failwith "TODO" | Some addr -> - let* head = I.find tx addr in + let* head = M.find tx addr in let* head = Option.to_result ~none:(Error.invalid_root addr) head in Ok { storage; label; head = Atomic.make head }) let fetch { storage; head; _ } branch_name = SI.with_transaction storage (fun tx -> let head = Atomic.get head in - I.lookup tx branch_name head) + M.lookup tx branch_name head) - let update ({ storage; head; label } as manager) branch_name f = + let update ({ storage; head; label } as manager) branch_name reference new_branch = let open Utilities.Result in let* _ = SI.with_transaction storage (fun tx -> Utilities.Atomic.mswap head (fun head -> - let* branch = I.lookup tx branch_name head in - let new_branch = f branch in - let* () = persist_root tx label new_branch in - new_branch)) in + let* branch = M.lookup tx branch_name head in + if branch = reference then + let* new_head = M.insert tx label new_branch head in + new_head + else + Error.comparison_failed branch_name reference branch)) in Ok () + end diff --git a/lib/kernel/BranchManager.mli b/lib/kernel/BranchManager.mli index 063f8a7..052f9a1 100644 --- a/lib/kernel/BranchManager.mli +++ b/lib/kernel/BranchManager.mli @@ -1,11 +1,9 @@ -type branch = string (* FIXME *) - module Make (S : Abstract.Storage.STORAGE) : sig type manager val initialize : S.connection -> string -> (manager, Concepts.Condition.condition) result - val fetch : manager -> string -> (branch option, Concepts.Condition.condition) result - val update : manager -> string -> (branch -> branch) -> (manager, Concepts.Condition.condition) result + val fetch : manager -> string -> (Concepts.Hash.hash option, Concepts.Condition.condition) result + val update : manager -> string -> Concepts.Hash.hash -> Concepts.Hash.hash -> (unit, Concepts.Condition.condition) result (* TODO: fork, join *) end |
