2018-06-29 16:08:08 +04:00
|
|
|
(*****************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Open Source License *)
|
|
|
|
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
|
|
|
(* *)
|
|
|
|
(* Permission is hereby granted, free of charge, to any person obtaining a *)
|
|
|
|
(* copy of this software and associated documentation files (the "Software"),*)
|
|
|
|
(* to deal in the Software without restriction, including without limitation *)
|
|
|
|
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
|
|
|
|
(* and/or sell copies of the Software, and to permit persons to whom the *)
|
|
|
|
(* Software is furnished to do so, subject to the following conditions: *)
|
|
|
|
(* *)
|
|
|
|
(* The above copyright notice and this permission notice shall be included *)
|
|
|
|
(* in all copies or substantial portions of the Software. *)
|
|
|
|
(* *)
|
|
|
|
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
|
|
|
|
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
|
|
|
|
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
|
|
|
|
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
|
|
|
|
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
|
|
|
|
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
|
|
|
|
(* DEALINGS IN THE SOFTWARE. *)
|
|
|
|
(* *)
|
|
|
|
(*****************************************************************************)
|
2017-02-24 20:17:53 +04:00
|
|
|
|
2017-11-13 22:06:30 +04:00
|
|
|
(** Tezos Shell - High-level API for the Gossip network and local
|
|
|
|
storage (helpers). *)
|
|
|
|
|
2018-02-14 20:27:14 +04:00
|
|
|
(** {1 Indexes} *)
|
|
|
|
|
|
|
|
(** Generic interface for a "distributed" index.
|
|
|
|
|
|
|
|
By "distributed", it means that this interface abstract the p2p
|
|
|
|
gossip layer and it is able to fetch missing data from known
|
|
|
|
peers in a "synchronous" interface.
|
|
|
|
|
|
|
|
*)
|
2017-04-19 23:46:10 +04:00
|
|
|
module type DISTRIBUTED_DB = sig
|
2017-03-28 15:31:41 +04:00
|
|
|
|
2017-02-24 20:17:53 +04:00
|
|
|
type t
|
2018-02-14 20:27:14 +04:00
|
|
|
|
|
|
|
(** The index key *)
|
2017-02-24 20:17:53 +04:00
|
|
|
type key
|
2018-02-14 20:27:14 +04:00
|
|
|
|
|
|
|
(** The indexed data *)
|
2017-02-24 20:17:53 +04:00
|
|
|
type value
|
2018-02-14 20:27:14 +04:00
|
|
|
|
|
|
|
(** An extra parameter for the network lookup, usually
|
|
|
|
used for prevalidating data. *)
|
2017-03-28 15:31:41 +04:00
|
|
|
type param
|
|
|
|
|
2018-02-14 20:27:14 +04:00
|
|
|
(** Is the value known locally? *)
|
2017-02-24 20:17:53 +04:00
|
|
|
val known: t -> key -> bool Lwt.t
|
2017-04-19 23:46:10 +04:00
|
|
|
|
|
|
|
type error += Missing_data of key
|
2017-11-08 15:42:09 +04:00
|
|
|
type error += Canceled of key
|
2017-11-08 15:52:10 +04:00
|
|
|
type error += Timeout of key
|
|
|
|
|
2018-02-14 20:27:14 +04:00
|
|
|
(** Return the value if it is known locally, otherwise fail with
|
|
|
|
the error [Missing_data]. *)
|
2017-04-19 23:46:10 +04:00
|
|
|
val read: t -> key -> value tzresult Lwt.t
|
2018-02-14 20:27:14 +04:00
|
|
|
|
|
|
|
(** Return the value if it is known locally, otherwise fail with
|
|
|
|
the value [None]. *)
|
2017-04-19 23:46:10 +04:00
|
|
|
val read_opt: t -> key -> value option Lwt.t
|
2018-02-14 20:27:14 +04:00
|
|
|
|
|
|
|
(** Return the value if it is known locally, otherwise fail with
|
|
|
|
the exception [Not_found]. *)
|
2017-02-24 20:17:53 +04:00
|
|
|
val read_exn: t -> key -> value Lwt.t
|
2017-03-28 15:31:41 +04:00
|
|
|
|
2018-02-14 20:27:14 +04:00
|
|
|
(** Same as `fetch` but the call is non-blocking: the data will be
|
|
|
|
stored in the local index when received. *)
|
2017-11-10 23:30:29 +04:00
|
|
|
val prefetch:
|
|
|
|
t ->
|
2018-01-24 15:48:25 +04:00
|
|
|
?peer:P2p_peer.Id.t ->
|
2017-11-10 23:30:29 +04:00
|
|
|
?timeout:float ->
|
|
|
|
key -> param -> unit
|
|
|
|
|
2018-02-14 20:27:14 +04:00
|
|
|
(** Return the value if it is known locally, or block until the data
|
|
|
|
is received from the network. By default, the data will be
|
|
|
|
requested to all the active peers in the network; if the [peer]
|
|
|
|
argument is provided, the data will only be requested to the
|
|
|
|
provided peer. By default, the resulting promise will block
|
|
|
|
forever if the data is never received. If [timeout] is provided
|
|
|
|
the promise will be resolved with the error [Timeout] after the
|
|
|
|
provided amount of seconds.
|
|
|
|
|
|
|
|
A internal scheduler is able to re-send the request with an
|
|
|
|
exponential back-off until the data is received. If the function
|
|
|
|
is called multiple time with the same key but with disctinct
|
|
|
|
peers, the internal scheduler randomly chooses the requested
|
|
|
|
peer (at each retry). *)
|
2017-11-08 15:42:09 +04:00
|
|
|
val fetch:
|
2017-11-08 15:52:10 +04:00
|
|
|
t ->
|
2018-01-24 15:48:25 +04:00
|
|
|
?peer:P2p_peer.Id.t ->
|
2017-11-08 15:52:10 +04:00
|
|
|
?timeout:float ->
|
|
|
|
key -> param -> value tzresult Lwt.t
|
2017-03-28 15:31:41 +04:00
|
|
|
|
2018-02-14 20:27:14 +04:00
|
|
|
(** Remove the data from the local index or cancel all pending
|
|
|
|
request. Any pending [fetch] promises are resolved with the
|
|
|
|
error [Canceled]. *)
|
2017-11-06 18:23:06 +04:00
|
|
|
val clear_or_cancel: t -> key -> unit
|
2018-02-14 20:27:14 +04:00
|
|
|
|
2017-02-24 20:17:53 +04:00
|
|
|
val inject: t -> key -> value -> bool Lwt.t
|
2018-02-14 20:27:14 +04:00
|
|
|
|
|
|
|
(** Monitor all the fetched data. A given data will appear only
|
|
|
|
once. *)
|
2017-11-27 09:13:12 +04:00
|
|
|
val watch: t -> (key * value) Lwt_stream.t * Lwt_watcher.stopper
|
2017-03-28 15:31:41 +04:00
|
|
|
|
2017-11-14 05:41:37 +04:00
|
|
|
val pending: t -> key -> bool
|
|
|
|
|
2017-03-28 15:31:41 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module type DISK_TABLE = sig
|
|
|
|
type store
|
|
|
|
type key
|
|
|
|
type value
|
|
|
|
val known: store -> key -> bool Lwt.t
|
|
|
|
val read: store -> key -> value tzresult Lwt.t
|
|
|
|
val read_opt: store -> key -> value option Lwt.t
|
|
|
|
val read_exn: store -> key -> value Lwt.t
|
|
|
|
end
|
|
|
|
|
|
|
|
module type MEMORY_TABLE = sig
|
|
|
|
(* A subtype of Hashtbl.S *)
|
|
|
|
type 'a t
|
|
|
|
type key
|
|
|
|
val create: int -> 'a t
|
|
|
|
val find: 'a t -> key -> 'a
|
2018-06-30 14:04:06 +04:00
|
|
|
val find_opt: 'a t -> key -> 'a option
|
2017-03-28 15:31:41 +04:00
|
|
|
val add: 'a t -> key -> 'a -> unit
|
|
|
|
val replace: 'a t -> key -> 'a -> unit
|
|
|
|
val remove: 'a t -> key -> unit
|
|
|
|
val fold: (key -> 'a -> 'b -> 'b) -> 'a t -> 'b -> 'b
|
2017-02-24 20:17:53 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module type SCHEDULER_EVENTS = sig
|
|
|
|
type t
|
|
|
|
type key
|
2018-01-24 15:48:25 +04:00
|
|
|
val request: t -> P2p_peer.Id.t option -> key -> unit
|
|
|
|
val notify: t -> P2p_peer.Id.t -> key -> unit
|
2017-11-06 18:23:06 +04:00
|
|
|
val notify_cancelation: t -> key -> unit
|
2018-01-24 15:48:25 +04:00
|
|
|
val notify_unrequested: t -> P2p_peer.Id.t -> key -> unit
|
|
|
|
val notify_duplicate: t -> P2p_peer.Id.t -> key -> unit
|
|
|
|
val notify_invalid: t -> P2p_peer.Id.t -> key -> unit
|
2017-03-28 15:31:41 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module type PRECHECK = sig
|
|
|
|
type key
|
|
|
|
type param
|
2017-04-19 23:46:10 +04:00
|
|
|
type notified_value
|
2017-03-28 15:31:41 +04:00
|
|
|
type value
|
2017-04-19 23:46:10 +04:00
|
|
|
val precheck: key -> param -> notified_value -> value option
|
2017-02-24 20:17:53 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module Make_table
|
2017-07-21 18:16:39 +04:00
|
|
|
(Hash : sig
|
|
|
|
type t
|
|
|
|
val name : string
|
|
|
|
val encoding : t Data_encoding.t
|
|
|
|
val pp : Format.formatter -> t -> unit
|
|
|
|
end)
|
2017-03-28 15:31:41 +04:00
|
|
|
(Disk_table : DISK_TABLE with type key := Hash.t)
|
|
|
|
(Memory_table : MEMORY_TABLE with type key := Hash.t)
|
|
|
|
(Scheduler : SCHEDULER_EVENTS with type key := Hash.t)
|
|
|
|
(Precheck : PRECHECK with type key := Hash.t
|
|
|
|
and type value := Disk_table.value) : sig
|
2017-02-24 20:17:53 +04:00
|
|
|
|
2017-04-19 23:46:10 +04:00
|
|
|
include DISTRIBUTED_DB with type key = Hash.t
|
|
|
|
and type value = Disk_table.value
|
|
|
|
and type param = Precheck.param
|
2017-02-24 20:17:53 +04:00
|
|
|
val create:
|
2017-11-27 09:13:12 +04:00
|
|
|
?global_input:(key * value) Lwt_watcher.input ->
|
2017-02-24 20:17:53 +04:00
|
|
|
Scheduler.t -> Disk_table.store -> t
|
2018-01-24 15:48:25 +04:00
|
|
|
val notify: t -> P2p_peer.Id.t -> key -> Precheck.notified_value -> unit Lwt.t
|
2017-02-24 20:17:53 +04:00
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
module type REQUEST = sig
|
|
|
|
type key
|
|
|
|
type param
|
2018-10-23 12:47:37 +04:00
|
|
|
val initial_delay : float
|
2018-01-24 15:48:25 +04:00
|
|
|
val active : param -> P2p_peer.Set.t
|
|
|
|
val send : param -> P2p_peer.Id.t -> key list -> unit
|
2017-02-24 20:17:53 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module Make_request_scheduler
|
2017-09-29 20:43:13 +04:00
|
|
|
(Hash : sig
|
|
|
|
type t
|
|
|
|
val name : string
|
|
|
|
val encoding : t Data_encoding.t
|
|
|
|
val pp : Format.formatter -> t -> unit
|
2018-06-12 23:07:50 +04:00
|
|
|
|
|
|
|
module Logging : sig
|
|
|
|
val tag : t Tag.def
|
|
|
|
end
|
2017-09-29 20:43:13 +04:00
|
|
|
end)
|
2017-03-28 15:31:41 +04:00
|
|
|
(Table : MEMORY_TABLE with type key := Hash.t)
|
2017-02-24 20:17:53 +04:00
|
|
|
(Request : REQUEST with type key := Hash.t) : sig
|
|
|
|
|
|
|
|
type t
|
|
|
|
val create: Request.param -> t
|
|
|
|
val shutdown: t -> unit Lwt.t
|
|
|
|
include SCHEDULER_EVENTS with type t := t and type key := Hash.t
|
|
|
|
|
|
|
|
end
|