Skip to content
This repository was archived by the owner on May 22, 2018. It is now read-only.

Commit 74dd252

Browse files
author
David Scott
committed
[O_DIRECT] Rather than overloading the existing Unixext.openfile function, create a Unixext.Direct namespace
Signed-off-by: David Scott <[email protected]>
1 parent 7b7865c commit 74dd252

File tree

4 files changed

+60
-42
lines changed

4 files changed

+60
-42
lines changed

stdext/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ stdext.cma: $(foreach obj,$(STDEXT_OBJS),$(obj).cmo)
7777
stdext_stubs.a: unixext_stubs.o zerocheck_stub.o
7878
ocamlmklib -o stdext_stubs $+
7979

80-
libstdext_stubs.a: unixext_open_stubs.o unixext_stubs.o zerocheck_stub.o
80+
libstdext_stubs.a: unixext_open_stubs.o unixext_write_stubs.o unixext_stubs.o zerocheck_stub.o
8181
ar rcs $@ $+
8282
ocamlmklib -o stdext_stubs $+
8383

stdext/unixext.ml

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -195,26 +195,26 @@ let execv_get_output cmd args =
195195
Unix.close pipe_entrance;
196196
pid, pipe_exit
197197

198-
(** Copy all data from an in_channel to an out_channel,
199-
* returning the total number of bytes *)
200-
let copy_file ?limit ifd ofd =
198+
let copy_file_internal ?limit reader writer =
201199
let buffer = String.make 65536 '\000' in
202200
let buffer_len = Int64.of_int (String.length buffer) in
203201
let finished = ref false in
204202
let total_bytes = ref 0L in
205203
let limit = ref limit in
206204
while not(!finished) do
207205
let requested = min (Opt.default buffer_len !limit) buffer_len in
208-
let num = Unix.read ifd buffer 0 (Int64.to_int requested) in
206+
let num = reader buffer 0 (Int64.to_int requested) in
209207
let num64 = Int64.of_int num in
210208

211209
limit := Opt.map (fun x -> Int64.sub x num64) !limit;
212-
ignore_int (Unix.write ofd buffer 0 num);
210+
ignore_int (writer buffer 0 num);
213211
total_bytes := Int64.add !total_bytes num64;
214212
finished := num = 0 || !limit = Some 0L;
215213
done;
216214
!total_bytes
217215

216+
let copy_file ?limit ifd ofd = copy_file_internal ?limit (Unix.read ifd) (Unix.write ofd)
217+
218218
let file_exists file_path =
219219
try Unix.access file_path [Unix.F_OK]; true
220220
with _ -> false
@@ -638,19 +638,27 @@ type statvfs_t = {
638638

639639
external statvfs : string -> statvfs_t = "stub_statvfs"
640640

641-
type open_flag =
642-
| O_DIRECT (* new *)
643-
| O_RDONLY
644-
| O_WRONLY
645-
| O_RDWR
646-
| O_NONBLOCK
647-
| O_APPEND
648-
| O_CREAT
649-
| O_TRUNC
650-
| O_EXCL
651-
| O_NOCTTY
652-
| O_DSYNC
653-
| O_SYNC
654-
| O_RSYNC
655-
656-
external openfile : string -> open_flag list -> Unix.file_perm -> Unix.file_descr = "stub_stdext_unix_open"
641+
module Direct = struct
642+
type t = Unix.file_descr
643+
644+
external openfile : string -> Unix.open_flag list -> Unix.file_perm -> t = "stub_stdext_unix_open_direct"
645+
646+
let close = Unix.close
647+
648+
let with_openfile path flags perms f =
649+
let t = openfile path flags perms in
650+
finally (fun () -> f t) (fun () -> close t)
651+
652+
external unsafe_write : t -> string -> int -> int -> int = "stub_stdext_unix_write"
653+
654+
let write fd buf ofs len =
655+
if ofs < 0 || len < 0 || ofs > String.length buf - len
656+
then invalid_arg "Unix.write"
657+
else unsafe_write fd buf ofs len
658+
659+
let copy_from_fd ?limit socket fd = copy_file_internal ?limit (Unix.read socket) (write fd)
660+
661+
let fsync x = fsync x
662+
663+
let lseek fd x cmd = Unix.LargeFile.lseek fd x cmd
664+
end

stdext/unixext.mli

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,20 +156,31 @@ type statvfs_t = {
156156

157157
val statvfs : string -> statvfs_t
158158

159-
type open_flag =
160-
| O_DIRECT (* new *)
161-
| O_RDONLY
162-
| O_WRONLY
163-
| O_RDWR
164-
| O_NONBLOCK
165-
| O_APPEND
166-
| O_CREAT
167-
| O_TRUNC
168-
| O_EXCL
169-
| O_NOCTTY
170-
| O_DSYNC
171-
| O_SYNC
172-
| O_RSYNC
173-
174-
external openfile : string -> open_flag list -> Unix.file_perm -> Unix.file_descr = "stub_stdext_unix_open"
175-
(** [openfile name flags perm] behaves the same as [Unix.openfile] but includes the O_DIRECT flag *)
159+
module Direct : sig
160+
(** Perform I/O in O_DIRECT mode using 4KiB page-aligned buffers *)
161+
162+
type t
163+
(** represents a file open in O_DIRECT mode *)
164+
165+
val openfile : string -> Unix.open_flag list -> Unix.file_perm -> t
166+
(** [openfile name flags perm] behaves the same as [Unix.openfile] but includes the O_DIRECT flag *)
167+
168+
val close : t -> unit
169+
(** [close t] closes [t], a file open in O_DIRECT mode *)
170+
171+
val with_openfile : string -> Unix.open_flag list -> Unix.file_perm -> (t -> 'a) -> 'a
172+
(** [with_openfile name flags perm f] opens [name], applies the result to [f] and closes *)
173+
174+
val write : t -> string -> int -> int -> int
175+
(** [write t buf ofs len] writes [len] bytes at offset [ofs] from buffer [buf] to
176+
[t] using page-aligned buffers. *)
177+
178+
val copy_from_fd : ?limit:int64 -> Unix.file_descr -> t -> int64
179+
(** [copy_from_fd ?limit fd t] copies from [fd] to [t] up to [limit] *)
180+
181+
val fsync : t -> unit
182+
(** [fsync t] commits all outstanding writes, throwing an error if necessary. *)
183+
184+
val lseek : t -> int64 -> Unix.seek_command -> int64
185+
(** [lseek t offset command]: see Unix.LargeFile.lseek *)
186+
end

stdext/unixext_open_stubs.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,17 @@
3737
#endif
3838

3939
static int open_flag_table[] = {
40-
O_DIRECT,
4140
O_RDONLY, O_WRONLY, O_RDWR, O_NONBLOCK, O_APPEND, O_CREAT, O_TRUNC, O_EXCL,
4241
O_NOCTTY, O_DSYNC, O_SYNC, O_RSYNC
4342
};
4443

45-
CAMLprim value stub_stdext_unix_open(value path, value flags, value perm)
44+
CAMLprim value stub_stdext_unix_open_direct(value path, value flags, value perm)
4645
{
4746
CAMLparam3(path, flags, perm);
4847
int ret, cv_flags;
4948
char * p;
5049

51-
cv_flags = convert_flag_list(flags, open_flag_table);
50+
cv_flags = convert_flag_list(flags, open_flag_table) | O_DIRECT;
5251
p = stat_alloc(string_length(path) + 1);
5352
strcpy(p, String_val(path));
5453
/* open on a named FIFO can block (PR#1533) */

0 commit comments

Comments
 (0)