123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2021 Nomadic Labs, <contact@nomadic-labs.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. *)(* *)(*****************************************************************************)(** This module contains various helpers to obtain
* instances of {!Requester} *)(** Wrapper for the types being used, to avoid repetitions. *)moduletypePARAMETERS=sigtypekeytypevalueend(** A disk table, that is in fact entirely in memory. *)moduleDisk_memory_table(P:PARAMETERS)=structincludeHashtbl.Make(structtypet=P.keylethash=Hashtbl.hashletequal=(=)end)typestore=P.valuettypevalue=P.valueletknown(st:store)(k:P.key)=Lwt.return@@memstkletreadstk=letopenLwt_result_syntaxinmatchfindstkwithSomev->returnv|None->fail_with_exnNot_foundletread_optstk=Lwt.return@@findstkend(** A simple memory table backed by [Hashtbl] *)moduleMemory_table(P:PARAMETERS):Requester.MEMORY_TABLEwithtypekey=P.key=structmoduleHtbl=Hashtbl.MakeSeeded(structtypet=P.key(* See [src/lib_base/tzPervasives.ml] for an explanation *)[@@@ocaml.warning"-32"]lethash=Hashtbl.seeded_hashletseeded_hash=Hashtbl.seeded_hash[@@@ocaml.warning"+32"]letequal=(=)end)typekey=Htbl.keytype'at='aHtbl.tletcreate~entry_type:_?randoms=Htbl.create?randomsletfind=Htbl.findletadd=Htbl.addletreplace=Htbl.replaceletremove=Htbl.removeletlength=Htbl.lengthletfold=Htbl.foldend(** An instance of [PROBE] that uses a [bool] parameter
* to decide whether the check goes through or not *)moduleSimple_probe(P:PARAMETERS):Requester.PROBEwithtypekey=P.keyandtypeparam=boolandtypenotified_value=P.valueandtypevalue=P.value=structtypekey=P.keytypeparam=booltypenotified_value=P.valuetypevalue=P.valueletprobe(_:key)(p:param)(nv:notified_value)=ifpthenSomenvelseNoneend(** An instance of [REQUEST] that solely registers incoming requests *)moduleSimple_request(P:PARAMETERS):sigincludeRequester.REQUESTwithtypekey=P.keyandtypeparam=unitvalregistered_requests:(param*P2p_peer.Set.elt*keylist)listrefvalclear_registered_requests:unit->unitend=structtypekey=P.keytypeparam=unitletinitial_delay=Time.System.Span.of_seconds_exn0.01letactive(_:param)=P2p_peer.Set.of_list[P2p_peer.Id.zero]letregistered_requests:(param*P2p_peer.Id.t*keylist)listref=ref[]letsend(requester:param)(id:P2p_peer.Id.t)(kl:keylist)=registered_requests:=(requester,id,kl)::!registered_requests;()letclear_registered_requests()=registered_requests:=[]end(** A helper to avoid having to use the full-fledged [Requester.Make]
* functor. We take the [Requester.REQUEST] module as parameter (instead
* of hardcoding the use of [Simple_request]), because
* callers that use [Simple_request] likely want to observe
* the underlying effects (see the [ref] in [Simple_request]) and hence
* want to pass their own instance.
*
* Like {!Requester.Make}, this returns an instance of [FULL_REQUESTER].
* Note that, contrary to a production requester, the instance returned
* by this functor does not use the disk, it runs entirely in memory. *)moduleMake_memory_full_requester(H:Requester.HASH)(P:PARAMETERSwithtypekey=H.t)(R:Requester.REQUESTwithtypeparam=unitandtypekey=H.t):Requester.FULL_REQUESTERwithtypekey=H.tandtypevalue=P.valueandtypeparam=boolandtyperequest_param=unitandtypenotified_value=P.valueandtypestore=Disk_memory_table(P).store=Requester.Make(H)(Disk_memory_table(P))(Memory_table(P))(R)(Simple_probe(P))