Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file content_addressable.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148(*
* Copyright (c) 2018-2021 Tarides <contact@tarides.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*)open!ImportmodulePool:sigtype('k,'v)t(** Reference-counted pool of values with corresponding keys. *)valcreate:alloc:('k->'v)->('k,'v)t(** Get an empty pool, given a function for allocating new instances from IDs. *)valtake:('k,'v)t->'k->'v(** Get an instance from the pool by its key, allocating it if necessary. *)valdrop:('k,'v)t->'k->unit(** Reduce the reference count of an element, discarding it if the reference
count drops to 0. *)end=structtype'velt={mutablerefcount:int;instance:'v}type('k,'v)t={instances:('k,'velt)Hashtbl.t;alloc:'k->'v}letcreate~alloc={instances=Hashtbl.create0;alloc}lettaketk=matchHashtbl.find_optt.instanceskwith|Someelt->elt.refcount<-succelt.refcount;elt.instance|None->letinstance=t.allockinHashtbl.addt.instancesk{instance;refcount=1};instanceletdroptk=matchHashtbl.find_optt.instanceskwith|None->failwith"Pool.drop: double free"|Some{refcount;_}whenrefcount<=0->assertfalse|Some{refcount=1;_}->Hashtbl.removet.instancesk|Someelt->elt.refcount<-predelt.refcountendmoduleMaker(K:Irmin.Hash.S)=structtypekey=K.tmoduleMake(Val:Irmin_pack.Pack_value.Swithtypehash:=K.t)=structmoduleKMap=Map.Make(structtypet=K.tletcompare=Irmin.Type.(unstage(compareK.t))end)typekey=K.ttypevalue=Val.ttype'at={name:string;mutablet:valueKMap.t;mutablegeneration:int63;}letinstances=Pool.create~alloc:(funname->{name;t=KMap.empty;generation=Int63.zero})letvname=Lwt.return(Pool.takeinstancesname)letequal_key=Irmin.Type.(unstage(equalK.t))letclear_keep_generationt=Log.debug(funf->f"clear_keep_generation");t.t<-KMap.empty;Lwt.return_unitletcleart=Log.debug(funf->f"clear");t.t<-KMap.empty;t.generation<-Int63.succt.generation;Lwt.return_unitletcloset=Log.debug(funf->f"close");Pool.dropinstancest.name;Lwt.return_unitletcastt=(t:>read_writet)letbatchtf=f(castt)letpp_key=Irmin.Type.ppK.tletcheck_keykv=letk'=Val.hashvinifequal_keykk'thenOk()elseError(k,k')letfindtk=tryletv=KMap.findkt.tincheck_keykv|>Result.map(fun()->Somev)withNot_found->OkNoneletunsafe_find~check_integrity:_tk=Log.debug(funf->f"unsafe find %a"pp_keyk);findtk|>function|Okr->r|Error(k,k')->Fmt.invalid_arg"corrupted value: got %a, expecting %a"pp_keyk'pp_keykletfindtk=Log.debug(funf->f"find %a"pp_keyk);findtk|>function|Okr->Lwt.returnr|Error(k,k')->Fmt.kstrfLwt.fail_invalid_arg"corrupted value: got %a, expecting %a"pp_keyk'pp_keykletunsafe_memtk=Log.debug(funf->f"mem %a"pp_keyk);KMap.memkt.tletmemtk=Lwt.return(unsafe_memtk)letunsafe_append~ensure_unique:_~overcommit:_tkv=Log.debug(funf->f"add -> %a"pp_keyk);t.t<-KMap.addkvt.tletunsafe_addtkv=unsafe_append~ensure_unique:true~overcommit:truetkv;Lwt.return_unitletaddtv=letk=Val.hashvinunsafe_addtkv>|=fun()->kletgenerationt=t.generationendend