Create a rw instance of t by opening an existing file at path.
End Offset
The file has an end offset at which new data will be saved. While this information could be computed by looking at the size of the file, we prefer storing that information elsewhere (i.e. in the control file). This is why open_rw and open_ro take an end_poff parameter, and also why refresh_end_poff exists. The abstractions above Append_only_file are responsible for reading/writing the offsets from/to the control file.
dead_header_size
Designates a small area at the beginning of the file that should be ignored. The offsets start after that area.
The actual persisted size of a file is end_poff + dead_header_size.
This concept exists in order to keep supporting `V1 and `V2 pack stores with `V3.
end_poff t is the number of bytes of the file. That function doesn't perform IO.
RW mode
It also counts the bytes not flushed yet.
RO mode
This information originates from the latest reload of the control file. Calling refresh_end_poff t updates end_poff.
val read_to_string :
t->off:Optint.Int63.t ->len:int ->(string, [> Io.read_error ])Stdlib.result
val read_exn : t->off:Optint.Int63.t ->len:int ->bytes -> unit
read_exn t ~off ~len b puts the len bytes of t at off to b.
read_to_string should always be favored over read_exn, except when performences matter.
It is not possible to read from an offset further than end_poff t.
Raises Io.Read_error and Errors.Pack_error `Read_out_of_bounds.
RW mode
Attempting to read from the append buffer results in an `Read_out_of_bounds error. This feature could easily be implemented in the future if ever needed.