(**************************************************************************)
(*  Copyright 2014, 2015, Sebastien Mondet <seb@mondet.org>               *) (*                                                                        *) (*  Licensed under the Apache License, Version 2.0 (the "License");       *) (*  you may not use this file except in compliance with the License.      *) (*  You may obtain a copy of the License at                               *) (*                                                                        *) (*      http://www.apache.org/licenses/LICENSE-2.0                        *) (*                                                                        *) (*  Unless required by applicable law or agreed to in writing, software   *) (*  distributed under the License is distributed on an "AS IS" BASIS,     *) (*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or       *) (*  implied.  See the License for the specific language governing         *) (*  permissions and limitations under the License.                        *)
(**************************************************************************)
(** A key-value database API with basic transactions. *)
open Pvem_lwt_unix open Nonstd module Key_in_collection = struct   type t = {key: string ; collection: string option}   let create ?collection key = {key; collection}   let to_string {key; collection} =     sprintf "{%s/%s}" Option.(value collection ~default:"") key end module Action = struct   type t =     | Set of Key_in_collection.t * string     | Unset of Key_in_collection.t     | Sequence of t list     | Check of Key_in_collection.t * string option   let _key ?collection key = {Key_in_collection. key; collection}   let set ?collection ~key value = Set (_key ?collection key, value)   let seq l = Sequence l   let contains ?collection ~key v = Check (_key ?collection key, Some v)   let is_not_set ?collection key = Check (_key ?collection key, None)   let unset ?collection key = Unset (_key ?collection key)   let rec to_string (t: t) =     match t with     | Set (k, v) -> sprintf "(set %s %S)" (Key_in_collection.to_string k) v     | Unset k -> sprintf "(unset %s)" (Key_in_collection.to_string k)     | Sequence l -> sprintf "(sequence %s)" (List.map l ~f:to_string                                              |> StringLabels.concat ~sep:" ")     | Check (k, v) ->       sprintf "(check %s %s)" (Key_in_collection.to_string k)         (Option.value_map ~default:"None" v ~f:(sprintf "(Some %S)")) end module Error = struct   type t = [     | `Act of Action.t | `Get of Key_in_collection.t | `Get_all of string     | `Load of string | `Close     | `Iter of string   ] * string   let to_string (t : t) =     match t with     | (`Act k, e) -> sprintf "[Executing %s, Error: %s]" (Action.to_string k) e     | (`Close, e) -> sprintf "[Closing, %s]" e     | (`Get k, e) ->       sprintf "[Getting %s, Error: %s]" (Key_in_collection.to_string k) e     | (`Get_all c, e) -> sprintf "[Getting-all-in %s, Error: %s]" c e     | (`Load u, e) -> sprintf "[Loading %S, Error: %s]" u e     | (`Iter s, e) -> sprintf "[Iterating on %S, Error: %s]" s e end module type KEY_VALUE_STORE = sig   type t   val load :     string ->     (t, [> `Database of [> `Load of string ] * string ]) Deferred_result.t   val close: t ->     (unit, [> `Database of [> `Close ] * string ]) Deferred_result.t   val get : ?collection:string -> t -> key:string ->     (string option, [> `Database of [> `Get of Key_in_collection.t ] * string ])       Deferred_result.t   val get_all: t -> collection:string ->     (string list, [> `Database of [> `Get_all of string ] * string ])       Deferred_result.t   val iterator: t -> collection:string ->     (unit ->      (string option, [> `Database of [> `Iter of string ] * string ]) Deferred_result.t)   val act :     t ->     action:Action.t ->     ([ `Done | `Not_done ],      [> `Database of [> `Act of Action.t ] * string ]) Deferred_result.t end