Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 19 additions & 27 deletions src/couch/src/couch_file.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
-record(file, {
fd,
is_sys,
eof = 0,
db_monitor,
filepath
}).
Expand Down Expand Up @@ -497,9 +496,8 @@ init({Filepath, Options, ReturnPid, Ref}) ->
put(couch_file_fd, {Fd, Filepath}),
ok = file:close(Fd_Read),
maybe_track_open_os_files(Options),
{ok, Eof} = file:position(Fd, eof),
erlang:send_after(?INITIAL_WAIT, self(), maybe_close),
{ok, dup(File#file{fd = Fd, eof = Eof})};
{ok, dup(File#file{fd = Fd})};
Error ->
init_status_error(ReturnPid, Ref, Error)
end;
Expand Down Expand Up @@ -568,7 +566,7 @@ handle_call({truncate, Pos}, _From, #file{fd = Fd} = File) ->
{ok, Pos} = file:position(Fd, Pos),
case file:truncate(Fd) of
ok ->
{reply, ok, File#file{eof = Pos}};
{reply, ok, File};
Error ->
{reply, Error, File}
end;
Expand Down Expand Up @@ -601,7 +599,8 @@ handle_call({write_header, Bin, Opts}, _From, #file{} = File) ->
% handle_call(sync, ...) why we're dropping the fd
{stop, {error, Error}, {error, Error}, #file{fd = nil}}
end;
handle_call(find_header, _From, #file{fd = Fd, eof = Pos} = File) ->
handle_call(find_header, _From, #file{fd = Fd} = File) ->
{ok, Pos} = eof(File),
{reply, find_header(Fd, Pos div ?SIZE_BLOCK), File}.

handle_cast(Msg, #file{} = File) ->
Expand All @@ -624,8 +623,9 @@ handle_info({'DOWN', Ref, process, _Pid, _Info}, #file{db_monitor = Ref} = File)
eof(#file{fd = Fd}) ->
file:position(Fd, eof).

append_bins(#file{fd = Fd, eof = Pos} = File, Bins) ->
{BlockResps, FinalPos} = lists:mapfoldl(
append_bins(#file{fd = Fd} = File, Bins) ->
{ok, Pos} = eof(File),
{BlockResps, _} = lists:mapfoldl(
fun(Bin, PosAcc) ->
Blocks = make_blocks(PosAcc rem ?SIZE_BLOCK, Bin),
Size = iolist_size(Blocks),
Expand All @@ -636,8 +636,8 @@ append_bins(#file{fd = Fd, eof = Pos} = File, Bins) ->
),
{AllBlocks, Resps} = lists:unzip(BlockResps),
case file:write(Fd, AllBlocks) of
ok -> {{ok, Resps}, File#file{eof = FinalPos}};
Error -> {Error, reset_eof(File)}
ok -> {{ok, Resps}, File};
Error -> {Error, File}
end.

pread(#file{} = File, PosL) ->
Expand Down Expand Up @@ -770,19 +770,17 @@ find_newest_header(Fd, [{Location, Size} | LocationSizes]) ->
find_newest_header(Fd, LocationSizes)
end.

handle_write_header(Bin, #file{fd = Fd, eof = Pos} = File) ->
handle_write_header(Bin, #file{fd = Fd} = File) ->
BinSize = byte_size(Bin),
{ok, Pos} = eof(File),
case Pos rem ?SIZE_BLOCK of
0 -> Padding = <<>>;
BlockOffset -> Padding = <<0:(8 * (?SIZE_BLOCK - BlockOffset))>>
end,
FinalBin = [Padding, <<1, BinSize:32/integer>> | make_blocks(5, [Bin])],
case file:write(Fd, FinalBin) of
ok -> {ok, File#file{eof = Pos + iolist_size(FinalBin)}};
{error, Error} -> {{error, Error}, reset_eof(File)}
end.
{file:write(Fd, FinalBin), File}.

read_multi_raw_iolists_int(#file{fd = Fd, eof = Eof} = File, PosLens) ->
read_multi_raw_iolists_int(#file{fd = Fd} = File, PosLens) ->
MapFun = fun({Pos, Len}) -> get_pread_locnum(File, Pos, Len) end,
LocNums = lists:map(MapFun, PosLens),
ZipFun = fun({Pos, TotalBytes}, Bin) ->
Expand All @@ -791,9 +789,9 @@ read_multi_raw_iolists_int(#file{fd = Fd, eof = Eof} = File, PosLens) ->
{remove_block_prefixes(Pos rem ?SIZE_BLOCK, Bin), Pos + TotalBytes};
false ->
couch_stats:increment_counter([pread, exceed_eof]),
{ok, CurEof} = file:position(File#file.fd, eof),
{ok, CurEof} = eof(File),
Filepath = File#file.filepath,
throw_stop({read_beyond_eof, Filepath, Pos, TotalBytes, Eof, CurEof}, File)
throw_stop({read_beyond_eof, Filepath, Pos, TotalBytes, CurEof}, File)
end
end,
case file:pread(Fd, LocNums) of
Expand All @@ -804,15 +802,15 @@ read_multi_raw_iolists_int(#file{fd = Fd, eof = Eof} = File, PosLens) ->
throw_stop({pread, Filepath, Error, hd(LocNums)}, File)
end.

get_pread_locnum(#file{eof = Eof} = File, Pos, Len) ->
get_pread_locnum(#file{} = File, Pos, Len) ->
BlockOffset = Pos rem ?SIZE_BLOCK,
TotalBytes = calculate_total_read_len(BlockOffset, Len),
{ok, Eof} = eof(File),
case Pos + TotalBytes of
Size when Size > Eof ->
couch_stats:increment_counter([pread, exceed_eof]),
{ok, CurEof} = file:position(File#file.fd, eof),
Filepath = File#file.filepath,
throw_stop({read_beyond_eof, Filepath, Pos, TotalBytes, Eof, CurEof}, File);
throw_stop({read_beyond_eof, Filepath, Pos, TotalBytes, Eof}, File);
_ ->
{Pos, TotalBytes}
end.
Expand Down Expand Up @@ -959,11 +957,6 @@ is_idle(#file{is_sys = false}) ->
process_info(Pid) ->
couch_util:process_dict_get(Pid, couch_file_fd).

%% in event of a partially successful write.
reset_eof(#file{} = File) ->
{ok, Eof} = file:position(File#file.fd, eof),
File#file{eof = Eof}.

-spec generate_checksum(binary()) -> <<_:128>>.
generate_checksum(Bin) when is_binary(Bin) ->
case generate_xxhash_checksums() of
Expand Down Expand Up @@ -1016,8 +1009,7 @@ dup(#file{fd = Fd} = File) ->
ok = file:close(Fd),
CFile = File#file{fd = CFd},
put(couch_file_fd, {CFd, CFile#file.filepath}),
% Use an effective infinity for eof max limit for now
put(?CFILE_HANDLE, CFile#file{eof = 1 bsl 60}),
put(?CFILE_HANDLE, CFile),
CFile;
{error, _Error} ->
File
Expand Down
6 changes: 3 additions & 3 deletions src/couch/test/eunit/couch_file_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ should_not_read_beyond_eof(_) ->
file:close(Io),
unlink(Fd),
?assertMatch(
{error, {read_beyond_eof, Filepath, _, _, _, _}}, couch_file:pread_binary(Fd, Pos)
{error, {read_beyond_eof, Filepath, _, _, _}}, couch_file:pread_binary(Fd, Pos)
),
catch file:close(Fd).

Expand All @@ -253,7 +253,7 @@ should_not_read_beyond_eof_when_externally_truncated(_) ->
file:close(Io),
unlink(Fd),
?assertMatch(
{error, {read_beyond_eof, Filepath, _, _, _, _}}, couch_file:pread_binary(Fd, Pos)
{error, {read_beyond_eof, Filepath, _, _, _}}, couch_file:pread_binary(Fd, Pos)
),
catch file:close(Fd).

Expand Down Expand Up @@ -319,7 +319,7 @@ should_apply_overwrite_create_option(Fd) ->
{ok, Fd1} = couch_file:open(Path, [create, overwrite]),
unlink(Fd1),
?assertMatch(
{error, {read_beyond_eof, Path, Pos, _, _, _}},
{error, {read_beyond_eof, Path, Pos, _, _}},
couch_file:pread_term(Fd1, Pos)
).

Expand Down