diff options
Diffstat (limited to '')
| -rw-r--r-- | lib/kernel/BranchManager.ml | 63 | ||||
| -rw-r--r-- | lib/kernel/BranchManager.mli | 8 |
2 files changed, 37 insertions, 34 deletions
diff --git a/lib/kernel/BranchManager.ml b/lib/kernel/BranchManager.ml index 03a2765..a698a87 100644 --- a/lib/kernel/BranchManager.ml +++ b/lib/kernel/BranchManager.ml @@ -9,8 +9,8 @@ module Error = struct condition "no-such-branch" "A branch with the specified name was not found" ("branch" |=| Concepts.Value.String branch_name) - let comparison_failed branch_name reference head = - condition "comparison-failed" "The HEAD of the branch did not match what was expected" + let branch_head_mismatch branch_name reference head = + condition "branch-head-mismatch" "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)) @@ -20,17 +20,45 @@ module Make (S : Abstract.Storage.STORAGE) = struct module M = Merkle.Make (S) (Merkle.StringKey) module SI = Storage.Make (S) - type manager = { storage: S.connection; - label : string; - head: M.node Atomic.t } - let root_for tx label = let open Utilities.Result in let* label = S.get tx (S.Label label) in let label = Option.map Concepts.Hash.hash_of_blob label in Ok label - let initialize storage label = + class manager storage label head = object (self) + inherit Lifecycle.null + + val storage : S.connection = storage + val label : string = label + val head : M.node Atomic.t = Atomic.make head + + method fetch branch_name = + SI.with_transaction storage (fun tx -> + let head = Atomic.get head in + M.lookup tx branch_name head) + + method update branch_name reference new_branch = + let open Utilities.Result in + SI.with_transaction storage (fun tx -> + Utilities.Atomic.mswap head (fun head -> + let* branch = M.lookup tx branch_name head + |> fmap (Option.to_result ~none:(Error.no_such_branch branch_name)) in + if branch = reference then + let* new_head = M.insert tx label new_branch head in + Ok new_head + else + Error (Error.branch_head_mismatch branch_name reference branch))) + |> Result.map ignore + + method protocols = Protocols.[Directory.make self] + + method list = SI.with_transaction storage (fun tx -> Atomic.get head |> M.keys tx) + + method find _ = failwith "TODO" + end + + let make storage label = let open Utilities.Result in SI.with_transaction storage (fun tx -> let* addr = root_for tx label in @@ -39,25 +67,6 @@ module Make (S : Abstract.Storage.STORAGE) = struct | Some addr -> 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 - M.lookup tx branch_name head) - - let update { storage; head; label } 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 = M.lookup tx branch_name head - |> Result.map (Option.to_result ~none:(Error.no_such_branch branch_name)) - |> Result.join in - if branch = reference then - let* new_head = M.insert tx label new_branch head in - Ok new_head - else - Error (Error.comparison_failed branch_name reference branch))) in - Ok () + Ok (new manager storage label head |> Protocols.Handle.make)) end diff --git a/lib/kernel/BranchManager.mli b/lib/kernel/BranchManager.mli index 052f9a1..a75875f 100644 --- a/lib/kernel/BranchManager.mli +++ b/lib/kernel/BranchManager.mli @@ -1,9 +1,3 @@ module Make (S : Abstract.Storage.STORAGE) : sig - type manager - - val initialize : S.connection -> string -> (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 *) + val make : S.connection -> string -> (Protocols.Handle.t, Concepts.Condition.condition) result end |
