This is an automated email from the ASF dual-hosted git repository. rnewson pushed a commit to branch no-eof in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit c897c245bcf6c70260b3d122eb041355c3c354b9 Author: Robert Newson <[email protected]> AuthorDate: Tue May 26 12:44:59 2026 +0100 eliminate internal tracking of EOF --- src/couch/src/couch_file.erl | 46 +++++++++++++------------------ src/couch/test/eunit/couch_file_tests.erl | 6 ++-- 2 files changed, 22 insertions(+), 30 deletions(-) diff --git a/src/couch/src/couch_file.erl b/src/couch/src/couch_file.erl index 2d0920f7e..03b342988 100644 --- a/src/couch/src/couch_file.erl +++ b/src/couch/src/couch_file.erl @@ -34,7 +34,6 @@ -record(file, { fd, is_sys, - eof = 0, db_monitor, filepath }). @@ -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; @@ -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; @@ -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} = file:position(Fd, eof), {reply, find_header(Fd, Pos div ?SIZE_BLOCK), File}. handle_cast(Msg, #file{} = File) -> @@ -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} = file:position(Fd, eof), + {BlockResps, _} = lists:mapfoldl( fun(Bin, PosAcc) -> Blocks = make_blocks(PosAcc rem ?SIZE_BLOCK, Bin), Size = iolist_size(Blocks), @@ -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) -> @@ -770,19 +770,18 @@ 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} = file:position(Fd, eof), 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) -> + {ok, Eof} = file:position(Fd, eof), MapFun = fun({Pos, Len}) -> get_pread_locnum(File, Pos, Len) end, LocNums = lists:map(MapFun, PosLens), ZipFun = fun({Pos, TotalBytes}, Bin) -> @@ -791,9 +790,8 @@ 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), 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) end end, case file:pread(Fd, LocNums) of @@ -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) -> + {ok, Eof} = file:position(File#file.fd, eof), BlockOffset = Pos rem ?SIZE_BLOCK, TotalBytes = calculate_total_read_len(BlockOffset, Len), 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. @@ -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 @@ -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 diff --git a/src/couch/test/eunit/couch_file_tests.erl b/src/couch/test/eunit/couch_file_tests.erl index c138a9c0a..5efe211bd 100644 --- a/src/couch/test/eunit/couch_file_tests.erl +++ b/src/couch/test/eunit/couch_file_tests.erl @@ -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). @@ -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). @@ -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) ).
