diff options
Diffstat (limited to 'lib/management/physical.ml')
| -rw-r--r-- | lib/management/physical.ml | 198 |
1 files changed, 0 insertions, 198 deletions
diff --git a/lib/management/physical.ml b/lib/management/physical.ml deleted file mode 100644 index b896330..0000000 --- a/lib/management/physical.ml +++ /dev/null @@ -1,198 +0,0 @@ -(** Physical storage abstraction. - - This module defines a functor-based storage interface that can be backed by - any key-value store (etcd, Redis, DynamoDB, PostgreSQL, filesystem, etc.). - - All data is content-addressed: keys are hashes, values are serialized - objects. The storage is append-only - objects are never modified, only new - versions are written with new hashes. *) - -(** Backend module signature that any storage driver must implement *) -module type BACKEND = sig - include Configuration.CONFIGURABLE - - type connection - - (** Connect to the storage backend *) - val connect : configuration -> (connection, Condition.t) result - - (** Disconnect from the backend *) - val disconnect : connection -> unit - - (** Get a value by its hash. Returns None if not found. *) - val get : connection -> Conventions.Hash.t -> (bytes option, Condition.t) result - - (** Store a value at its hash *) - val put : connection -> Conventions.Hash.t -> bytes -> (unit, Condition.t) result - - (** Check if a hash exists *) - val exists : connection -> Conventions.Hash.t -> (bool, Condition.t) result - - (** Begin a transaction *) - val begin_transaction : connection -> (unit, Condition.t) result - - (** Commit a transaction *) - val commit : connection -> (unit, Condition.t) result - - (** Rollback a transaction *) - val rollback : connection -> (unit, Condition.t) result - - (** Batch get multiple values *) - val get_many : connection -> Conventions.Hash.t list -> (bytes option list, Condition.t) result - - (** Batch put multiple values *) - val put_many : connection -> (Conventions.Hash.t * bytes) list -> (unit, Condition.t) result -end - -(** Storage operations built on top of a backend *) -module type S = sig - include Configuration.CONFIGURABLE - - type t - - (** Create a storage instance from a backend connection *) - val create : configuration -> (t, Condition.t) result - - (** Close the storage *) - val close : t -> unit - - (** Store an attribute value, returns its hash *) - val store_attribute : t -> Conventions.AbstractValue.t -> (Conventions.Hash.t, Condition.t) result - - (** Load an attribute value by hash *) - val load_attribute : - t -> Conventions.Hash.t -> (Conventions.AbstractValue.t option, Condition.t) result - - (** Store raw bytes at a hash *) - val store_raw : t -> Conventions.Hash.t -> bytes -> (unit, Condition.t) result - - (** Load raw bytes by hash *) - val load_raw : t -> Conventions.Hash.t -> (bytes option, Condition.t) result - - (** Check if a hash exists *) - val exists : t -> Conventions.Hash.t -> (bool, Condition.t) result - - (** Execute a function within a transaction *) - val with_transaction : t -> (unit -> ('a, Condition.t) result) -> ('a, Condition.t) result -end - -(** Functor to create storage operations from a backend *) -module Make (B : BACKEND) : S with type configuration = B.configuration = struct - type configuration = B.configuration - type t = B.connection - - let parse = B.parse - let create config = B.connect config - let close = B.disconnect - - let store_attribute conn value = - let bytes = Marshal.to_bytes value [] in - let hash = Conventions.AbstractValue.hash value in - match B.put conn hash bytes with Ok () -> Ok hash | Error e -> Error e - - let load_attribute conn hash = - match B.get conn hash with - | Ok (Some bytes) -> Ok (Some (Marshal.from_bytes bytes 0)) - | Ok None -> Ok None - | Error e -> Error e - - let store_raw conn hash bytes = B.put conn hash bytes - let load_raw conn hash = B.get conn hash - let exists conn hash = B.exists conn hash - - let with_transaction conn f = - match B.begin_transaction conn with - | Error e -> Error e - | Ok () -> ( - match f () with - | Ok result -> ( match B.commit conn with Ok () -> Ok result | Error e -> Error e ) - | Error e -> - let _ = B.rollback conn in - Error e ) -end - -(** In-memory backend for testing and development *) -module MemoryBackend : BACKEND with type configuration = unit = struct - type configuration = unit - - type connection = - { data: (string, bytes) Hashtbl.t; - mutable in_transaction: bool; - mutable transaction_buffer: (string * bytes) list } - - module Error = struct - open Condition - - (* TODO: more structure *) - let parse_error msg = condition "parse-error" msg empty - - let already_in_transaction = - condition "already-in-transaction" "Already inside a transaction" empty - - let not_in_transaction = condition "not-in-transaction" "Not inside a transaction" empty - end - - let parse sexp = - match sexp with - | Sexplib.Sexp.List [] -> Ok () - | _ -> - Error - (Error.parse_error - (Printf.sprintf "memory backend takes no configuration, got: %s" - (Sexplib.Sexp.to_string sexp) ) ) - - let connect () = Ok {data= Hashtbl.create 1024; in_transaction= false; transaction_buffer= []} - let disconnect _ = () - let get conn hash = Ok (Hashtbl.find_opt conn.data hash) - - let put conn hash value = - if conn.in_transaction then begin - conn.transaction_buffer <- (hash, value) :: conn.transaction_buffer; - Ok () - end - else begin - Hashtbl.replace conn.data hash value; - Ok () - end - - let exists conn hash = Ok (Hashtbl.mem conn.data hash) - - let begin_transaction conn = - if conn.in_transaction then Error Error.already_in_transaction - else begin - conn.in_transaction <- true; - conn.transaction_buffer <- []; - Ok () - end - - let commit conn = - if not conn.in_transaction then Error Error.not_in_transaction - else begin - List.iter (fun (hash, value) -> Hashtbl.replace conn.data hash value) conn.transaction_buffer; - conn.in_transaction <- false; - conn.transaction_buffer <- []; - Ok () - end - - let rollback conn = - if not conn.in_transaction then Error Error.not_in_transaction - else begin - conn.in_transaction <- false; - conn.transaction_buffer <- []; - Ok () - end - - let get_many conn hashes = Ok (List.map (fun h -> Hashtbl.find_opt conn.data h) hashes) - - let put_many conn pairs = - List.iter - (fun (hash, value) -> - if conn.in_transaction then - conn.transaction_buffer <- (hash, value) :: conn.transaction_buffer - else Hashtbl.replace conn.data hash value ) - pairs; - Ok () -end - -(** Default in-memory storage for development *) -module Memory = Make (MemoryBackend) |
