Skip to content

Commit f5af4de

Browse files
committed
Merge branch 'john/merge-PR-9830/OTP-19816'
* john/merge-PR-9830/OTP-19816: Update preloaded Optimise prim_file in write mode
2 parents 29a4dfc + 130fdee commit f5af4de

File tree

2 files changed

+63
-39
lines changed

2 files changed

+63
-39
lines changed

erts/preloaded/ebin/prim_file.beam

308 Bytes
Binary file not shown.

erts/preloaded/src/prim_file.erl

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -134,22 +134,22 @@ open(Name, Modes) ->
134134
%% the public file interface, which has leaked through for ages because of
135135
%% "raw files."
136136
try open_nif(encode_path(Name), Modes) of
137-
{ok, Ref} -> {ok, make_fd(Ref, Modes)};
137+
{ok, Ref} -> {ok, make_fd(Modes, Ref)};
138138
{error, Reason} -> {error, Reason}
139139
catch
140140
error:badarg -> {error, badarg}
141141
end.
142142

143143
file_desc_to_ref(FileDescriptorId, Modes) ->
144144
try file_desc_to_ref_nif(FileDescriptorId) of
145-
{ok, Ref} -> {ok, make_fd(Ref, Modes)};
145+
{ok, Ref} -> {ok, make_fd(Modes, Ref)};
146146
{error, Reason} -> {error, Reason}
147147
catch
148148
error:badarg -> {error, badarg}
149149
end.
150150

151-
make_fd(FRef, Modes) ->
152-
#file_descriptor{module = ?MODULE, data = build_fd_data(FRef, Modes) }.
151+
make_fd(Modes, FRef) ->
152+
#file_descriptor{module = ?MODULE, data = build_fd_data(Modes, FRef) }.
153153

154154
close(Fd) ->
155155
try
@@ -163,9 +163,10 @@ read(Fd, Size) ->
163163
try
164164
#{ handle := FRef,
165165
r_ahead_size := RASz,
166-
r_buffer := RBuf } = get_fd_data(Fd),
166+
r_buffer := RBuf } = get_fd_data_for_read(Fd),
167167
read_1(FRef, RBuf, prim_buffer:size(RBuf), RASz, Size)
168168
catch
169+
throw:Err -> Err;
169170
error:badarg -> {error, badarg}
170171
end.
171172

@@ -206,11 +207,12 @@ read_line(Fd) ->
206207
try
207208
#{ handle := FRef,
208209
r_ahead_size := RASz,
209-
r_buffer := RBuf } = get_fd_data(Fd),
210+
r_buffer := RBuf } = get_fd_data_for_read(Fd),
210211
SearchResult = prim_buffer:find_byte_index(RBuf, $\n),
211212
LineSize = max(?MIN_READLINE_SIZE, RASz),
212213
read_line_1(FRef, RBuf, SearchResult, LineSize)
213214
catch
215+
throw:Err -> Err;
214216
error:badarg -> {error, badarg}
215217
end.
216218

@@ -304,8 +306,10 @@ datasync(Fd) ->
304306
position(Fd, {cur, Offset}) ->
305307
try
306308
%% Adjust our current position according to how much we've read ahead.
307-
#{ r_buffer := RBuf } = get_fd_data(Fd),
308-
position_1(Fd, cur, Offset - prim_buffer:size(RBuf))
309+
case get_fd_data(Fd) of
310+
#{ r_buffer := RBuf } -> position_1(Fd, cur, Offset - prim_buffer:size(RBuf));
311+
#{} -> position_1(Fd, cur, Offset)
312+
end
309313
catch
310314
error:badarg -> {error, badarg}
311315
end;
@@ -321,9 +325,13 @@ position(Fd, eof) -> position(Fd, {eof, 0});
321325
position(Fd, Offset) -> position(Fd, {bof, Offset}).
322326

323327
position_1(Fd, Mark, Offset) ->
324-
#{ handle := FRef, r_buffer := RBuf } = get_fd_data(Fd),
325-
prim_buffer:wipe(RBuf),
326-
seek_nif(FRef, Mark, Offset).
328+
case get_fd_data(Fd) of
329+
#{ handle := FRef, r_buffer := RBuf } ->
330+
prim_buffer:wipe(RBuf),
331+
seek_nif(FRef, Mark, Offset);
332+
#{ handle := FRef } ->
333+
seek_nif(FRef, Mark, Offset)
334+
end.
327335

328336
pread(Fd, Offset, Size) ->
329337
try
@@ -361,9 +369,14 @@ pread_list(FRef, [{Offset, Size} | Rest], ResultList) ->
361369

362370
pwrite(Fd, Offset, IOData) ->
363371
try
364-
#{ handle := FRef, r_buffer := RBuf } = get_fd_data(Fd),
365-
prim_buffer:wipe(RBuf),
366-
pwrite_plain(FRef, Offset, erlang:iolist_to_iovec(IOData))
372+
IOVec = erlang:iolist_to_iovec(IOData),
373+
case get_fd_data(Fd) of
374+
#{ handle := FRef, r_buffer := RBuf } ->
375+
prim_buffer:wipe(RBuf),
376+
pwrite_plain(FRef, Offset, IOVec);
377+
#{ handle := FRef } ->
378+
pwrite_plain(FRef, Offset, IOVec)
379+
end
367380
catch
368381
error:badarg -> {error, badarg}
369382
end.
@@ -379,9 +392,13 @@ pwrite_plain(FRef, Offset, IOVec) ->
379392

380393
pwrite(Fd, LocBytes) ->
381394
try
382-
#{ handle := FRef, r_buffer := RBuf } = get_fd_data(Fd),
383-
prim_buffer:wipe(RBuf),
384-
pwrite_list(FRef, LocBytes, 0)
395+
case get_fd_data(Fd) of
396+
#{ handle := FRef, r_buffer := RBuf } ->
397+
prim_buffer:wipe(RBuf),
398+
pwrite_list(FRef, LocBytes, 0);
399+
#{ handle := FRef } ->
400+
pwrite_list(FRef, LocBytes, 0)
401+
end
385402
catch
386403
error:badarg -> {error, badarg}
387404
end.
@@ -470,10 +487,13 @@ get_handle(Fd) ->
470487
%% Resets the write head to the position the user believes we're at, which may
471488
%% not be the same as the real one when read caching is in effect.
472489
reset_write_position(Fd) ->
473-
#{ r_buffer := RBuf } = Fd#file_descriptor.data,
474-
case prim_buffer:size(RBuf) of
475-
Size when Size > 0 -> position(Fd, cur);
476-
Size when Size =:= 0 -> ok
490+
case Fd#file_descriptor.data of
491+
#{ r_buffer := RBuf } ->
492+
case prim_buffer:size(RBuf) of
493+
Size when Size > 0 -> position(Fd, cur);
494+
Size when Size =:= 0 -> ok
495+
end;
496+
_ -> ok
477497
end.
478498

479499
get_fd_data(#file_descriptor{ data = Data }) ->
@@ -483,24 +503,28 @@ get_fd_data(#file_descriptor{ data = Data }) ->
483503
_ -> error(not_on_controlling_process)
484504
end.
485505

486-
build_fd_data(FRef, Modes) ->
487-
Defaults =
488-
#{ owner => self(),
489-
handle => FRef,
490-
r_ahead_size => 0,
491-
r_buffer => prim_buffer:new() },
492-
fill_fd_option_map(Modes, Defaults).
493-
494-
fill_fd_option_map([], Map) ->
495-
Map;
496-
497-
fill_fd_option_map([read_ahead | Modes], Map) ->
498-
fill_fd_option_map([{read_ahead, 64 bsl 10} | Modes], Map);
499-
fill_fd_option_map([{read_ahead, Size} | Modes], Map) ->
500-
fill_fd_option_map(Modes, Map#{ r_ahead_size => Size });
501-
502-
fill_fd_option_map([_Ignored | Modes], Map) ->
503-
fill_fd_option_map(Modes, Map).
506+
get_fd_data_for_read(Fd) ->
507+
case get_fd_data(Fd) of
508+
#{ r_buffer := _ } = Data -> Data;
509+
_ -> throw({error, ebadf})
510+
end.
511+
512+
build_fd_data(Modes, FRef) -> build_fd_data(Modes, FRef, self(), 0, default).
513+
514+
build_fd_data([], FRef, Owner, _RASz, write) ->
515+
#{ handle => FRef, owner => Owner };
516+
build_fd_data([], FRef, Owner, RASz, Mode) when Mode =:= read; Mode =:= default ->
517+
#{ handle => FRef, owner => Owner, r_ahead_size => RASz, r_buffer => prim_buffer:new() };
518+
build_fd_data([read_ahead | Modes], FRef, Owner, _, Mode) ->
519+
build_fd_data(Modes, FRef, Owner, 64 bsl 10, Mode);
520+
build_fd_data([{read_ahead, RASz} | Modes], FRef, Owner, _, Mode) ->
521+
build_fd_data(Modes, FRef, Owner, RASz, Mode);
522+
build_fd_data([write | Modes], FRef, Owner, RASz, default) ->
523+
build_fd_data(Modes, FRef, Owner, RASz, write);
524+
build_fd_data([read | Modes], FRef, Owner, RASz, _Mode) ->
525+
build_fd_data(Modes, FRef, Owner, RASz, read);
526+
build_fd_data([_Ignored | Modes], FRef, Owner, RASz, Mode) ->
527+
build_fd_data(Modes, FRef, Owner, RASz, Mode).
504528

505529
open_nif(_Name, _Modes) ->
506530
erlang:nif_error(undef).

0 commit comments

Comments
 (0)