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
open! Import
module Stats = Index.Stats
let ( ++ ) = Int63.add
type t = { fd : Unix.file_descr } [@@unboxed]
let v fd = { fd }
let really_write fd fd_offset buffer buffer_offset length =
let rec aux fd_offset buffer_offset length =
let w = Syscalls.pwrite ~fd ~fd_offset ~buffer ~buffer_offset ~length in
if w = 0 || w = length then ()
else
(aux [@tailcall])
(fd_offset ++ Int63.of_int w)
(buffer_offset + w) (length - w)
in
aux fd_offset buffer_offset length
let really_read fd fd_offset length buffer =
let rec aux fd_offset buffer_offset length =
let r = Syscalls.pread ~fd ~fd_offset ~buffer ~buffer_offset ~length in
if r = 0 then buffer_offset
else if r = length then buffer_offset + r
else
(aux [@tailcall])
(fd_offset ++ Int63.of_int r)
(buffer_offset + r) (length - r)
in
aux fd_offset 0 length
let fsync t = Unix.fsync t.fd
let close t = Unix.close t.fd
let fstat t = Unix.fstat t.fd
let unsafe_write t ~off buffer buffer_offset length =
let buffer = Bytes.unsafe_of_string buffer in
really_write t.fd off buffer buffer_offset length;
Stats.add_write length
let unsafe_read t ~off ~len buf =
let n = really_read t.fd off len buf in
Stats.add_read n;
n
let encode_int63 n =
let buf = Bytes.create Int63.encoded_size in
Int63.encode buf ~off:0 n;
Bytes.unsafe_to_string buf
let decode_int63 buf = Int63.decode ~off:0 buf
exception Not_written
let assert_read ~len n =
if n = 0 && n <> len then raise Not_written;
assert (
if Int.equal n len then true
else (
Printf.eprintf "Attempted to read %d bytes, but got %d bytes instead!\n%!"
len n;
false))
[@@inline always]
module Offset = struct
let off = Int63.zero
let set t n = unsafe_write t ~off (encode_int63 n) 0 8
let get t =
let len = 8 in
let buf = Bytes.create len in
let n = unsafe_read t ~off ~len buf in
assert_read ~len n;
decode_int63 (Bytes.unsafe_to_string buf)
end
module Version = struct
let off = Int63.of_int 8
let get t =
let len = 8 in
let buf = Bytes.create len in
let n = unsafe_read t ~off ~len buf in
assert_read ~len n;
Bytes.unsafe_to_string buf
let set t v = unsafe_write t ~off v 0 8
end
module Generation = struct
let off = Int63.of_int 16
let get t =
let len = 8 in
let buf = Bytes.create len in
let n = unsafe_read t ~off ~len buf in
assert_read ~len n;
decode_int63 (Bytes.unsafe_to_string buf)
let set t gen = unsafe_write t ~off (encode_int63 gen) 0 8
end
module Fan = struct
let off = Int63.of_int 24
let set t buf =
let buf_len = String.length buf in
let size = encode_int63 (Int63.of_int buf_len) in
unsafe_write t ~off size 0 8;
if buf <> "" then unsafe_write t ~off:(off ++ Int63.of_int 8) buf 0 buf_len
let get_size t =
let len = 8 in
let size_buf = Bytes.create len in
let n = unsafe_read t ~off ~len size_buf in
assert_read ~len n;
decode_int63 (Bytes.unsafe_to_string size_buf)
let set_size t size =
let buf = encode_int63 size in
unsafe_write t ~off buf 0 8
let get t =
let size = Int63.to_int (get_size t) in
let buf = Bytes.create size in
let n = unsafe_read t ~off:(off ++ Int63.of_int 8) ~len:size buf in
assert_read ~len:size n;
Bytes.unsafe_to_string buf
end