diff options
author | Emile Joubert <emile@rabbitmq.com> | 2013-08-01 12:06:01 +0100 |
---|---|---|
committer | Emile Joubert <emile@rabbitmq.com> | 2013-08-01 12:06:01 +0100 |
commit | 4b5d31ca5304687ac7b2fb3600efb0fa7260a9e6 (patch) | |
tree | c7447a31ec0b15e22c46dd10ce1325d6dab7b20d | |
parent | 99945fabb97d40f240bda8623092e58dec3519f3 (diff) | |
download | rabbitmq-server-bug25617.tar.gz |
Transplant of bug25617 to stablebug25617
-rw-r--r-- | src/rabbit_file.erl | 60 |
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 |