summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmile Joubert <emile@rabbitmq.com>2013-08-01 12:06:01 +0100
committerEmile Joubert <emile@rabbitmq.com>2013-08-01 12:06:01 +0100
commit4b5d31ca5304687ac7b2fb3600efb0fa7260a9e6 (patch)
treec7447a31ec0b15e22c46dd10ce1325d6dab7b20d
parent99945fabb97d40f240bda8623092e58dec3519f3 (diff)
downloadrabbitmq-server-bug25617.tar.gz
Transplant of bug25617 to stablebug25617
-rw-r--r--src/rabbit_file.erl60
1 files changed, 42 insertions, 18 deletions
diff --git a/src/rabbit_file.erl b/src/rabbit_file.erl
index 0f429ae9..4cf314ca 100644
--- a/src/rabbit_file.erl
+++ b/src/rabbit_file.erl
@@ -24,6 +24,8 @@
-export([rename/2, delete/1, recursive_delete/1, recursive_copy/2]).
-export([lock_file/1]).
+-define(TMP_EXT, ".tmp").
+
%%----------------------------------------------------------------------------
-ifdef(use_specs).
@@ -136,29 +138,17 @@ write_term_file(File, Terms) ->
write_file(Path, Data) -> write_file(Path, Data, []).
-%% write_file/3 and make_binary/1 are both based on corresponding
-%% functions in the kernel/file.erl module of the Erlang R14B02
-%% release, which is licensed under the EPL. That implementation of
-%% write_file/3 does not do an fsync prior to closing the file, hence
-%% the existence of this version. APIs are otherwise identical.
write_file(Path, Data, Modes) ->
Modes1 = [binary, write | (Modes -- [binary, write])],
case make_binary(Data) of
- Bin when is_binary(Bin) ->
- with_fhc_handle(
- fun () -> case prim_file:open(Path, Modes1) of
- {ok, Hdl} -> try prim_file:write(Hdl, Bin) of
- ok -> prim_file:sync(Hdl);
- {error, _} = E -> E
- after
- prim_file:close(Hdl)
- end;
- {error, _} = E -> E
- end
- end);
- {error, _} = E -> E
+ Bin when is_binary(Bin) -> write_file1(Path, Bin, Modes1);
+ {error, _} = E -> E
end.
+%% make_binary/1 is based on the corresponding function in the
+%% kernel/file.erl module of the Erlang R14B02 release, which is
+%% licensed under the EPL.
+
make_binary(Bin) when is_binary(Bin) ->
Bin;
make_binary(List) ->
@@ -168,6 +158,40 @@ make_binary(List) ->
{error, Reason}
end.
+write_file1(Path, Bin, Modes) ->
+ try
+ with_synced_copy(Path, Modes,
+ fun (Hdl) ->
+ ok = prim_file:write(Hdl, Bin)
+ end)
+ catch
+ error:{badmatch, Error} -> Error;
+ _:{error, Error} -> {error, Error}
+ end.
+
+with_synced_copy(Path, Modes, Fun) ->
+ case lists:member(append, Modes) of
+ true ->
+ {error, append_not_supported, Path};
+ false ->
+ with_fhc_handle(
+ fun () ->
+ Bak = Path ++ ?TMP_EXT,
+ case prim_file:open(Bak, Modes) of
+ {ok, Hdl} ->
+ try
+ Result = Fun(Hdl),
+ ok = prim_file:rename(Bak, Path),
+ ok = prim_file:sync(Hdl),
+ Result
+ after
+ prim_file:close(Hdl)
+ end;
+ {error, _} = E -> E
+ end
+ end)
+ end.
+
%% TODO the semantics of this function are rather odd. But see bug 25021.
append_file(File, Suffix) ->
case read_file_info(File) of