123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153(*****************************************************************************)(* *)(* 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. *)(* *)(*****************************************************************************)moduleRing=structtype'araw=Emptyofint|Initedof{data:'aarray;mutablepos:int}type'at='arawrefletcreatesize=ifsize<=0theninvalid_arg"Ring.create: size must be positive"elseref(Emptysize)letaddrv=match!rwith|Emptysize->r:=Inited{data=Array.makesizev;pos=0}|Initeds->s.pos<-(ifs.pos=(2*Array.lengths.data)-1thenArray.lengths.dataelses.pos+1);s.data.(s.posmodArray.lengths.data)<-vletadd_and_return_erasedrv=letreplaced=match!rwith|Empty_->None|Initeds->ifs.pos>=Array.lengths.data-1thenSomes.data.((s.pos+1)modArray.lengths.data)elseNoneinaddrv;replacedletclearr=match!rwith|Empty_->()|Inited{data;_}->r:=Empty(Array.lengthdata)letadd_listrl=List.iter(addr)lletlastr=match!rwith|Empty_->None|Inited{data;pos}->Somedata.(posmodArray.lengthdata)letfoldr~init~f=match!rwith|Empty_->init|Inited{data;pos}->letsize=Array.lengthdatainletacc=refinitinfori=0tominpos(size-1)doacc:=f!accdata.((pos-i)modsize)done;!accletelementst=foldt~init:[]~f:(funaccelt->elt::acc)exceptionEmptyletlast_exnr=matchlastrwithNone->raiseEmpty|Somed->dendincludeRing(** Ring Buffer Table *)moduletypeTABLE=sigtypettypevvalcreate:int->tvaladd:t->v->unitvaladd_and_return_erased:t->v->voptionvalmem:t->v->boolvalremove:t->v->unitvalclear:t->unitvalelements:t->vlistend(* fixed size set of Peers id. If the set exceed the maximal allowed capacity, the
element that was added first is removed when a new one is added *)moduleMakeTable(V:Hashtbl.HashedType)=structmoduleTable=Hashtbl.Make(V)typeraw={size:int;ring:V.tRing.t;table:unitTable.t}typet=rawreftypev=V.tletcreatesize=ref{size;ring=Ring.createsize;table=Table.createsize}letadd{contents=t}v=beginmatchRing.add_and_return_erasedt.ringvwith|Someerased->Table.removet.tableerased|None->()end;Table.addt.tablev()letadd_and_return_erased{contents=t}v=matchRing.add_and_return_erasedt.ringvwith|None->Table.addt.tablev();None|Someerased->Table.removet.tableerased;Table.addt.tablev();Someerasedletmem{contents=t}v=Table.memt.tablevletremove{contents=t}v=Table.removet.tablevletclear({contents=t}astt)=tt:={twithring=Ring.createt.size;table=Table.createt.size}letelements{contents=t}=Table.fold(funk_acc->k::acc)t.table[]end