Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file disk_persistence.ml
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 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. *)(* *)(*****************************************************************************)typeerror+=|Cannot_write_fileofstring|Cannot_create_dirofstring|Cannot_delete_fileofstring|Cannot_read_fileofstring|Io_errorof[`Close|`Open]Lwt_utils_unix.io_error|Unix_errorofUnix.error|Decoding_errorofData_encoding.Binary.read_errorlet()=register_error_kind~id:"rollups.injector.cannot_write_file"~title:"Cannot write file"~description:"An element for a persistent table could not be written"~pp:(funppfs->Format.fprintfppf"The persistent element %s could not be written"s)`TemporaryData_encoding.(obj1(req"file"string))(functionCannot_write_files->Somes|_->None)(funs->Cannot_write_files);register_error_kind~id:"rollups.injector.cannot_create_dir"~title:"Cannot create directory"~description:"Directory for persistent data structure could not be created"~pp:(funppfs->Format.fprintfppf"Directory %s for persistent data structure could not be created"s)`TemporaryData_encoding.(obj1(req"directory"string))(functionCannot_create_dirs->Somes|_->None)(funs->Cannot_create_dirs);register_error_kind~id:"rollups.injector.cannot_delete_file"~title:"Cannot delete file"~description:"An element for a persistent table could not be deleted"~pp:(funppfs->Format.fprintfppf"The persistent element %s could not be deleted"s)`TemporaryData_encoding.(obj1(req"file"string))(functionCannot_delete_files->Somes|_->None)(funs->Cannot_delete_files);register_error_kind~id:"rollups.injector.cannot_read_file"~title:"Cannot read file"~description:"A file for a persistent element could not be read"~pp:(funppfs->Format.fprintfppf"The persistent element %s could not be read"s)`TemporaryData_encoding.(obj1(req"file"string))(functionCannot_read_files->Somes|_->None)(funs->Cannot_read_files);register_error_kind~id:"rollups.injector.io_error"~title:"IO error"~description:"IO error"~pp:(funppf(_action,unix_code,caller,arg)->Format.fprintfppf"IO error in %s(%s): %s)"callerarg(Unix.error_messageunix_code))`TemporaryData_encoding.(obj4(req"action"(string_enum[("close",`Close);("open",`Open)]))(req"unix_code"Tezos_stdlib_unix.Unix_error.encoding)(req"caller"string)(req"arg"string))(function|Io_errorLwt_utils_unix.{action;unix_code;caller;arg}->Some(action,unix_code,caller,arg)|_->None)(fun(action,unix_code,caller,arg)->Io_errorLwt_utils_unix.{action;unix_code;caller;arg});register_error_kind~id:"rollups.injector.unix_error"~title:"Unix error"~description:"Unix error"~pp:(funppferror->Format.fprintfppf"Unix error: %s"(Unix.error_messageerror))`TemporaryData_encoding.(obj1(req"error"Tezos_stdlib_unix.Unix_error.encoding))(functionUnix_errore->Somee|_->None)(fune->Unix_errore);register_error_kind~id:"rollups.injector.decoding_error"~title:"Cannot decode file"~description:"A file for a persistent element could not be decoded"~pp:(funppferror->Format.fprintfppf"Decoding error: %a"Data_encoding.Json.pp(Data_encoding.Json.constructData_encoding.Binary.read_error_encodingerror))`PermanentData_encoding.(obj1(req"error"Data_encoding.Binary.read_error_encoding))(functionDecoding_errore->Somee|_->None)(fune->Decoding_errore);()moduletypeH=sigincludeHashtbl.SeededStypevaluevalname:stringvalstring_of_key:key->stringvalkey_of_string:string->keyoptionvalvalue_encoding:valueData_encoding.tendletcreate_dirdir=trace(Cannot_create_dirdir)@@protect@@fun()->letopenLwt_result_syntaxinlet*!()=Lwt_utils_unix.create_dirdirinreturn_unitletread_valuefileencoding=letopenLwt_syntaxintrace(Cannot_read_filefile)@@Lwt.catch(fun()->Lwt_io.with_file~flags:[Unix.O_RDONLY;O_CLOEXEC]~mode:Inputfile@@funchannel->let+bytes=Lwt_io.readchannelinResult.map_error(fune->[Decoding_errore])@@Data_encoding.Binary.of_bytesencoding(Bytes.unsafe_of_stringbytes))(function|Unix.Unix_error(e,_,_)->fail(Unix_errore)|e->fail(Exne))letmaybe_read_value~warnfileencoding=letopenLwt_syntaxinlet*v=read_valuefileencodinginmatchvwith|Errore->let+()=warnfileeinNone|Okv->return_somevletwrite_valuefileencodingvalue=trace(Cannot_write_filefile)@@protect@@fun()->Lwt_result.map_error(fune->[Io_errore])@@Lwt_utils_unix.with_open_out~overwrite:truefile@@funfd->letblock_bytes=Data_encoding.Binary.to_bytes_exnencodingvalueinLwt_utils_unix.write_bytesfdblock_bytesletdelete_filefile=trace(Cannot_delete_filefile)@@protect@@fun()->letopenLwt_result_syntaxinlet*!()=Lwt_unix.unlinkfileinreturn_unitmoduleMake_table(H:H)=structtypekey=H.keytypevalue=H.valuetypet={path:string;table:valueH.t}letfiledatatk=Filename.concatt.path(H.string_of_keyk)letcreate~data_dirn=letopenLwt_result_syntaxinlettable=H.createninletpath=Filename.concatdata_dirH.nameinlet+()=create_dirpathin{path;table}letreplacetkv=H.replacet.tablekv;write_value(filedatatk)H.value_encodingvletremovetk=H.removet.tablek;delete_file(filedatatk)letfindtk=H.findt.tablekletmemtk=H.memt.tablekletiter_sft=H.iter_sft.tableletiter_esft=H.iter_esft.tableletfoldft=H.foldft.tableletlengtht=H.lengtht.tableletreplace_seqtseq=H.replace_seqt.tableseq;Seq.ES.iter(fun(k,v)->write_value(filedatatk)H.value_encodingv)seqletload_from_disk~warn_unreadable~initial_size~data_dir~filter=letopenLwt_result_syntaxinlet*t=create~data_dirinitial_sizeinlet*!d=Lwt_unix.opendirt.pathinletrecbrowse()=let*!filename=letopenLwt_syntaxinLwt.catch(fun()->let+f=Lwt_unix.readdirdinSomef)(functionEnd_of_file->return_none|e->raisee)inmatchfilenamewith|None->return_unit|Somefilename->let*()=matchH.key_of_stringfilenamewith|None->return_unit|Somek->(let+v=matchwarn_unreadablewith|None->let+v=read_value(filedatatk)H.value_encodinginSomev|Somewarn->let*!v=maybe_read_value~warn(filedatatk)H.value_encodinginreturnvinmatchvwith|None->()|Somev->iffiltervthenH.addt.tablekv)inbrowse()inlet+()=browse()intendmoduleMake_queue(N:sigvalname:stringend)(K:Tezos_crypto.Intfs.HASH)(V:sigtypetvalencoding:tData_encoding.tend)=structmoduleQ=Hash_queue.Make(K)(V)typet={path:string;metadata_path:string;queue:Q.t}letcounter=refmin_intletfiledataqk=Filename.concatq.path(K.to_b58checkk)letfilemetadataqk=Filename.concatq.metadata_path(K.to_b58checkk)letcreate~data_dirn=letopenLwt_result_syntaxinletqueue=Q.createninletpath=Filename.concatdata_dirN.nameinletmetadata_path=Filename.concatpath"metadata"inlet*()=create_dirpathinlet+()=create_dirmetadata_pathin{path;metadata_path;queue}letremoveqk=letopenLwt_result_syntaxinQ.removeq.queuek;let*()=delete_file(filedataqk)and*()=delete_file(filemetadataqk)inreturn_unitletcreate_metadata()=lettime=Time.System.now()inletd,ps=Ptime.to_spantime|>Ptime.Span.to_d_psinletc=!counterinincrcounter;(d,ps,c)letmetadata_encoding=letopenData_encodinginconv(fun(d,ps,c)->(Int64.of_intd,ps,Int64.of_intc))(fun(d,ps,c)->(Int64.to_intd,ps,Int64.to_intc))@@tup3int64int64int64letreplaceqkv=letopenLwt_result_syntaxinQ.replaceq.queuekv;let*()=write_value(filedataqk)V.encodingvand*()=write_value(filemetadataqk)metadata_encoding(create_metadata())inreturn_unitletfoldfq=Q.foldfq.queueletlengthq=Q.lengthq.queueletfind_optqk=Q.find_optq.queuekletload_from_disk~warn_unreadable~capacity~data_dir~filter=letopenLwt_result_syntaxinlet*q=create~data_dircapacityinlet*!d=Lwt_unix.opendirq.pathinletrecbrowseacc=let*!filename=letopenLwt_syntaxinLwt.catch(fun()->let+f=Lwt_unix.readdirdinSomef)(functionEnd_of_file->return_none|e->raisee)inmatchfilenamewith|None->returnacc|Somefilename->let*acc=matchK.of_b58check_optfilenamewith|None->returnacc|Somek->(let+v_meta=matchwarn_unreadablewith|None->let*v=read_value(filedataqk)V.encodingand*meta=read_value(filemetadataqk)metadata_encodinginreturn_some(v,meta)|Somewarn->letopenLwt_syntaxinlet*v=maybe_read_value~warn(filedataqk)V.encodingand*meta=maybe_read_value~warn(filemetadataqk)metadata_encodinginreturn_ok@@Option.bindv@@funv->Option.bindmeta@@funmeta->Some(v,meta)inmatchv_metawith|None->acc|Some(v,meta)->iffiltervthen(k,v,meta)::accelseacc)inbrowseaccinlet*list=browse[]inletlist=List.fast_sort(fun(_,_,meta1)(_,_,meta2)->Stdlib.comparemeta1meta2)listinList.iter(fun(k,v,_)->Q.replaceq.queuekv)list;returnqend