summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2013-07-30 10:49:37 +0100
committerSimon MacMullen <simon@rabbitmq.com>2013-07-30 10:49:37 +0100
commiteca1603cb34523396c0a8dd6ca926bb0fb940332 (patch)
treec27c16d56328d6e86afba3bdfd17b691e81b5090
parent8cc6b6d4fba89ab3c445cf0ff13507196367c3fa (diff)
parent6928e7a1063c657b4ffacd0631a32f66d5a2960a (diff)
downloadrabbitmq-server-eca1603cb34523396c0a8dd6ca926bb0fb940332.tar.gz
Merge bug25617
-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 3ceb4989..93b9c901 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