package irmin-pack

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file control_file_intf.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
(*
 * Copyright (c) 2022-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.
 *)
open! Import

module Payload_v3 = struct
  type from_v1_v2_post_upgrade = { entry_offset_at_upgrade_to_v3 : int63 }
  [@@deriving irmin]
  (** [entry_offset_at_upgrade_to_v3] is the offset of the first entry that is
      known to have been created using [irmin_pack_version = `V2] or more. The
      entries before that point may be v1 entries. V1 entries need an entry in
      index because it is the only place their lenght is stored. *)

  type from_v3_gced = { suffix_start_offset : int63; generation : int }
  [@@deriving irmin]
  (** [suffix_start_offset] is 0 if the suffix file was never garbage collected.
      Otherwise it is the offset of the very first entry of the suffix file.
      Note that offsets in the suffix file are virtual. The garbage collections
      don't reset the offsets.

      [generation] is the number of past GCs. A suffix file, a prefix file and a
      mapping containing that integer in their filename exist. *)

  (** [From_v1_v2_post_upgrade] corresponds to a pack store that was upgraded to
      [`V3]. It contains infos related to backward compatibility. GCs are
      forbidden on it.

      [From_v3_no_gc_yet] corresponds to a pack store that was created using
      [`V3] code. It never underwent a GC.

      [From_v3_used_non_minimal_indexing_strategy] corresponds to a pack store
      that was created using [`V3] code. It never underwent a GC and it will
      never be possible to GC it because entries were pushed using a non-minimal
      indexing strategy.

      [From_v3_gced] is a store that was GCed at least once.

      The [T*] tags are provisional tags that the binary decoder is aware of and
      that may in the future be used to add features to the [`V3] payload. *)
  type status =
    | From_v1_v2_post_upgrade of from_v1_v2_post_upgrade
    | From_v3_no_gc_yet
    | From_v3_used_non_minimal_indexing_strategy
    | From_v3_gced of from_v3_gced
    | T1
    | T2
    | T3
    | T4
    | T5
    | T6
    | T7
    | T8
    | T9
    | T10
    | T11
    | T12
    | T13
    | T14
    | T15
  [@@deriving irmin]

  type t = {
    dict_end_poff : int63;
    suffix_end_poff : int63;
    status : status; (* must be last to allow extensions *)
  }
  [@@deriving irmin]
  (** The [`V3] payload of the irmin-pack control file. [`V3] is a major
      version. If [`V4] ever exists, it will have its own dedicated payload, but
      the [`V3] definition will still have to stick in the codebase for backward
      compatibilty of old pack stores.

      A store may only change its major version during an [open_rw] in
      [File_manager]. Note that upgrading a major version is the only reason why
      [open_rw] would modify files in an irmin-pack directory.

      For a given major version, the format of a payload may change, but only in
      a backward compatible way. I.e., all versions of irmin-pack should forever
      be able to decode a [`V3] control file, it allows for control file
      corruption and out-of-date code to be distinguishable.

      It is legal for the payload decoder to not fully consume the input buffer.
      Remaining bytes means that the definition of a payload was changed.

      {3 Fields}

      [dict_end_poff] is the offset in the dict file just after the last valid
      dict bytes. The next data to be pushed to the dict will be pushed at this
      offset.

      [suffix_end_poff] is similar to [dict_end_poff] but for the suffix file.

      [status] is a variant that encode the state of the irmin-pack directory.
      This field MUST be the last field of the record, in order to allow
      extensions *)
end

module Payload_v4 = struct
  type gced = {
    suffix_start_offset : int63;
    generation : int;
    latest_gc_target_offset : int63;
    suffix_dead_bytes : int63;
  }
  [@@deriving irmin]
  (** Similar to [from_v3_gced]. New fields:

      [latest_gc_target_offset] is the commit on which the latest gc was called
      on.

      [suffix_dead_bytes] is the number of bytes at the beginning of the suffix
      that should be considered unreachable after a GC. *)

  (** [From_v1_v2_post_upgrade] similar to [Payload_v3.From_v1_v2_post_upgrade]

      [No_gc_yet] corresponds to a pack store that was created using [`V3] or
      above. It never underwent a GC.

      [Used_non_minimal_indexing_strategy] corresponds to a pack store that was
      created using [`V3] or above. It never underwent a GC and it will never be
      possible to GC it because entries were pushed using a non-minimal indexing
      strategy.

      [Gced] is a [`V3] or [`V4] store that was GCed at least once.

      The [T*] tags are provisional tags that the binary decoder is aware of and
      that may in the future be used to add features to the [`V4] payload. *)
  type status =
    | From_v1_v2_post_upgrade of Payload_v3.from_v1_v2_post_upgrade
    | No_gc_yet
    | Used_non_minimal_indexing_strategy
    | Gced of gced
    | T1
    | T2
    | T3
    | T4
    | T5
    | T6
    | T7
    | T8
    | T9
    | T10
    | T11
    | T12
    | T13
    | T14
    | T15
  [@@deriving irmin]

  type t = {
    dict_end_poff : int63;
    appendable_chunk_poff : int63;
    upgraded_from_v3_to_v4 : bool;
    checksum : int63;
    chunk_start_idx : int;
    chunk_num : int;
    status : status; (* must be last to allow extensions *)
  }
  [@@deriving irmin]
  (** The same as {!Payload_v3.t}, with the following modifications:

      New fields

      - [upgraded_from_v3_to_v4] recalls if the store was originally created in
        [`V3].
      - [chunk_start_idx] is the index for the starting chunk of the suffix
      - [chunk_num] is the number of chunks in the suffix
      - [checksum] for storing a checksum of the payload
      - [appendable_chunk_poff] is a value used by the chunked suffix. See
        {!Chunked_suffix.S.appendable_chunk_poff} for more details.

      Removed fields

      - [suffix_end_poff] is replaced by [appendable_chunk_poff] *)
end

module Latest_payload = Payload_v4

module type S = sig
  (** Abstraction for irmin-pack's control file.

      It is parameterized with [Io], a file system abstraction (e.g. unix,
      mirage, eio_linux).

      None of the functions raise exceptions. *)

  module Io : Io.S

  type t

  val create_rw :
    path:string ->
    overwrite:bool ->
    Latest_payload.t ->
    (t, [> Io.create_error | Io.write_error ]) result
  (** Create a rw instance of [t] by creating a control file. *)

  type open_error :=
    [ `Corrupted_control_file
    | `Io_misc of Io.misc_error
    | `No_such_file_or_directory
    | `Not_a_file
    | `Closed
    | `Unknown_major_pack_version of string ]

  val open_ : path:string -> readonly:bool -> (t, [> open_error ]) result
  (** Create a rw instance of [t] by reading an existing file at [path]. *)

  val close : t -> (unit, [> Io.close_error ]) result

  val payload : t -> Latest_payload.t
  (** [payload t] is the payload in [t].

      That function doesn't perform IO.

      {3 RW mode}

      [payload t] is the payload, as it was written to the file system.

      {3 RO mode}

      [payload t] is the [payload], as it was seen during [open_] or during the
      most recent [reload]. *)

  type reload_error :=
    [ `Corrupted_control_file
    | `Io_misc of Io.misc_error
    | `Closed
    | `Rw_not_allowed
    | `Unknown_major_pack_version of string ]

  val reload : t -> (unit, [> reload_error ]) result
  (** {3 RW mode}

      Always returns an error.

      {3 RO mode}

      Reread the file on disk.

      If the file changed since the last read, the payload in [t] is updated to
      match the content of the file. *)

  val set_payload : t -> Latest_payload.t -> (unit, [> Io.write_error ]) result
  (** {3 RW mode}

      Write a new payload on disk.

      {3 RO mode}

      Always returns an error. *)

  val readonly : t -> bool

  val fsync : t -> (unit, [> Io.write_error ]) result
  (** {3 RW mode}

      Tell the OS to fush its internal buffers.

      {3 RO mode}

      Always returns [Error `Ro_not_allowed]. *)
end

module type Sigs = sig
  module Latest_payload = Payload_v4
  module Payload_v3 = Payload_v3
  module Payload_v4 = Payload_v4

  module type S = S

  module Make (Io : Io.S) : S with module Io = Io
end
OCaml

Innovation. Community. Security.