Skip to content

Commit 6a49e3e

Browse files
authored
Merge pull request #14178 from rabbitmq/loic-cqv2-index-open-eventually
CQ: Retry opening write file when writing messages
2 parents e44eff2 + af8c0af commit 6a49e3e

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

deps/rabbit/src/rabbit_classic_queue_index_v2.erl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,9 @@ publish(MsgId, SeqId, Location, Props, IsPersistent, ShouldConfirm, TargetRamCou
591591
new_segment_file(Segment, SegmentEntryCount, State = #qi{ segments = Segments }) ->
592592
#qi{ fds = OpenFds } = reduce_fd_usage(Segment, State),
593593
false = maps:is_key(Segment, OpenFds), %% assert
594-
{ok, Fd} = file:open(segment_file(Segment, State), [read, write, raw, binary]),
594+
{ok, Fd} = rabbit_file:open_eventually(
595+
segment_file(Segment, State),
596+
[read, write, raw, binary]),
595597
%% We then write the segment file header. It contains
596598
%% some useful info and some reserved bytes for future use.
597599
%% We currently do not make use of this information. It is

deps/rabbit/src/rabbit_classic_queue_store_v2.erl

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -194,25 +194,6 @@ maybe_flush_buffer(State = #qs{ write_buffer_size = WriteBufferSize }) ->
194194
false -> State
195195
end.
196196

197-
open_eventually(File, Modes) ->
198-
open_eventually(File, Modes, 3).
199-
200-
open_eventually(_, _, 0) ->
201-
{error, eacces};
202-
open_eventually(File, Modes, N) ->
203-
case file:open(File, Modes) of
204-
OK = {ok, _} ->
205-
OK;
206-
%% When the current write file was recently deleted it
207-
%% is possible on Windows to get an {error,eacces}.
208-
%% Sometimes Windows sets the files to "DELETE PENDING"
209-
%% state and delays deletion a bit. So we wait 10ms and
210-
%% try again up to 3 times.
211-
{error, eacces} ->
212-
timer:sleep(10),
213-
open_eventually(File, Modes, N - 1)
214-
end.
215-
216197
flush_buffer(State = #qs{ write_buffer_size = 0 }, _) ->
217198
State;
218199
flush_buffer(State0 = #qs{ write_buffer = WriteBuffer }, FsyncFun) ->
@@ -223,7 +204,9 @@ flush_buffer(State0 = #qs{ write_buffer = WriteBuffer }, FsyncFun) ->
223204
Writes = flush_buffer_build(WriteList, CheckCRC32, SegmentEntryCount),
224205
%% Then we do the writes for each segment.
225206
State = lists:foldl(fun({Segment, LocBytes}, FoldState) ->
226-
{ok, Fd} = open_eventually(segment_file(Segment, FoldState), [read, write, raw, binary]),
207+
{ok, Fd} = rabbit_file:open_eventually(
208+
segment_file(Segment, FoldState),
209+
[read, write, raw, binary]),
227210
case file:position(Fd, eof) of
228211
{ok, 0} ->
229212
%% We write the file header if it does not exist.

deps/rabbit/src/rabbit_file.erl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
-export([read_file_info/1]).
1818
-export([filename_as_a_directory/1]).
1919
-export([filename_to_binary/1, binary_to_filename/1]).
20+
-export([open_eventually/2]).
2021

2122
-define(TMP_EXT, ".tmp").
2223

@@ -338,3 +339,34 @@ binary_to_filename(Bin) when is_binary(Bin) ->
338339
Other ->
339340
erlang:error(Other)
340341
end.
342+
343+
%% On Windows the file may be in "DELETE PENDING" state following
344+
%% its deletion (when the last message was acked). A subsequent
345+
%% open may fail with an {error,eacces}. In that case we wait 10ms
346+
%% and retry up to 3 times.
347+
348+
-spec open_eventually(File, Modes) -> {ok, IoDevice} | {error, Reason} when
349+
File :: Filename | iodata(),
350+
Filename :: file:name_all(),
351+
Modes :: [file:mode() | ram | directory],
352+
IoDevice :: file:io_device(),
353+
Reason :: file:posix() | badarg | system_limit.
354+
355+
open_eventually(File, Modes) ->
356+
open_eventually(File, Modes, 3).
357+
358+
open_eventually(_, _, 0) ->
359+
{error, eacces};
360+
open_eventually(File, Modes, N) ->
361+
case file:open(File, Modes) of
362+
OK = {ok, _} ->
363+
OK;
364+
%% When the current write file was recently deleted it
365+
%% is possible on Windows to get an {error,eacces}.
366+
%% Sometimes Windows sets the files to "DELETE PENDING"
367+
%% state and delays deletion a bit. So we wait 10ms and
368+
%% try again up to 3 times.
369+
{error, eacces} ->
370+
timer:sleep(10),
371+
open_eventually(File, Modes, N - 1)
372+
end.

0 commit comments

Comments
 (0)