123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153(*
* Copyright (c) 2018-2022 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.
*)openImportincludeDispatcher_intfmodulePayload=Control_file.Payload.Upper.Latest(* The following [with module Io = Io.Unix] forces unix *)moduleMake(Fm:File_manager.SwithmoduleIo=Io.Unix):SwithmoduleFm=Fm=structmoduleFm=FmmoduleIo=Fm.IomoduleSuffix=Fm.SuffixmoduleSparse=Fm.SparsemoduleLower=Fm.LowermoduleErrs=Fm.ErrsmoduleControl=Fm.Controltypet={fm:Fm.t}letvfm=lett={fm}inOktletget_prefixt=matchFm.prefixt.fmwith|Someprefix->prefix|None->raise(Errors.Pack_error(`Invalid_prefix_read"no prefix found"))letget_suffixt=Fm.suffixt.fmletsuffix_start_offsett=letpl=Control.payload(Fm.controlt.fm)inmatchpl.statuswith|Payload.From_v1_v2_post_upgrade_|Used_non_minimal_indexing_strategy|No_gc_yet->Int63.zero|T1|T2|T3|T4|T5|T6|T7|T8|T9|T10|T11|T12|T13|T14|T15->assertfalse|Gced{suffix_start_offset;_}->suffix_start_offsetletsuffix_dead_bytest=letpl=Control.payload(Fm.controlt.fm)inmatchpl.statuswith|Payload.From_v1_v2_post_upgrade_|Used_non_minimal_indexing_strategy|No_gc_yet->Int63.zero|T1|T2|T3|T4|T5|T6|T7|T8|T9|T10|T11|T12|T13|T14|T15->assertfalse|Gced{suffix_dead_bytes;_}->suffix_dead_bytes(* Adjust the read in suffix, as the global offset [off] is
[off] = [suffix_start_offset] + [soff] - [suffix_dead_bytes]. *)letsoff_of_offsettoff=letopenInt63.Syntaxinletsuffix_start_offset=suffix_start_offsettinletsuffix_dead_bytes=suffix_dead_bytestinoff-suffix_start_offset+suffix_dead_bytesletoffset_of_sofftsoff=letopenInt63.Syntaxinletsuffix_start_offset=suffix_start_offsettinletsuffix_dead_bytes=suffix_dead_bytestinsuffix_start_offset+soff-suffix_dead_bytesletend_offsett=letend_soff=Suffix.end_soff(Fm.suffixt.fm)inoffset_of_sofftend_soffletdispatch_suffixt~off=letopenInt63.Syntaxinifoff>=suffix_start_offsettthenSome(soff_of_offsettoff)elseNoneletread_range_exnt~off~min_len~max_len?volume_identifierbuf=[%log.debug"read_range_exn ~off:%a ~min_len:%i ~max_len:%i"Int63.ppoffmin_lenmax_len];letread_lower?volumelower=letlen,volume=Lower.read_range_exnlower?volume~off~min_len~max_lenbufin(len,Somevolume)inletread_sparse()=try(Sparse.read_range_exn(get_prefixt)~off~min_len~max_lenbuf,None)withErrors.Pack_error(`Invalid_sparse_read_)asexn->(matchFm.lowert.fmwith|None->raiseexn|Somelower->read_lowerlower)inmatchdispatch_suffixt~offwith|Someoff->(Suffix.read_range_exn(get_suffixt)~off~min_len~max_lenbuf,None)|None->(match(volume_identifier,Fm.lowert.fm)with|None,_->read_sparse()|volume,Somelower->read_lower?volumelower|Some_,None->assertfalse)letread_exnt~off~len?volume_identifierbuf=let_,volume=read_range_exnt~off~min_len:len~max_len:len?volume_identifierbufinvolumeletread_seq_exnt~off~len=letlen=Int63.to_intleniniflen<=0thenSeq.emptyelseletmax_read_size=min8192leninletbuffer=Bytes.createmax_read_sizeinletrecaux~off~len()=iflen<=0thenSeq.Nilelseletread_len=minlenmax_read_sizeinletread_len,_=read_range_exnt~off~min_len:1~max_len:read_lenbufferinSeq.Cons(Bytes.sub_stringbuffer0read_len,aux~off:Int63.Syntax.(off+Int63.of_intread_len)~len:(len-read_len))inaux~off~lenletread_bytes_exnt~f~off~len=Seq.iterf(read_seq_exnt~off~len)letnext_valid_offsett~off=letopenInt63.Syntaxinmatchdispatch_suffixt~offwith|Somesoffwhensoff>=Suffix.end_soff(get_suffixt)->None|Some_->Someoff|None->(matchSparse.next_valid_offset(get_prefixt)~offwith|None->Some(suffix_start_offsett)|some_off->some_off)end