diff options
Diffstat (limited to 'src/rabbit_misc.erl')
| -rw-r--r-- | src/rabbit_misc.erl | 103 |
1 files changed, 71 insertions, 32 deletions
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 0522afdc..52d76ac4 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -50,7 +50,7 @@ -export([execute_mnesia_transaction/1]). -export([ensure_ok/2]). -export([makenode/1, nodeparts/1, cookie_hash/0, tcp_name/3]). --export([intersperse/2, upmap/2, map_in_order/2]). +-export([upmap/2, map_in_order/2]). -export([table_fold/3]). -export([dirty_read_all/1, dirty_foreach_key/2, dirty_dump_log/1]). -export([read_term_file/1, write_term_file/2]). @@ -61,16 +61,12 @@ -export([sort_field_table/1]). -export([pid_to_string/1, string_to_pid/1]). -export([version_compare/2, version_compare/3]). --export([recursive_delete/1, dict_cons/3, orddict_cons/3, +-export([recursive_delete/1, recursive_copy/2, dict_cons/3, orddict_cons/3, unlink_and_capture_exit/1]). -export([get_options/2]). --export([all_module_attributes/1, build_acyclic_graph/4]). +-export([all_module_attributes/1, build_acyclic_graph/3]). -export([now_ms/0]). - --import(mnesia). --import(lists). --import(cover). --import(disk_log). +-export([lock_file/1]). %%---------------------------------------------------------------------------- @@ -86,10 +82,9 @@ :: rabbit_types:channel_exit() | rabbit_types:connection_exit()). -type(digraph_label() :: term()). -type(graph_vertex_fun() :: - fun ((atom(), [term()]) -> {digraph:vertex(), digraph_label()})). + fun ((atom(), [term()]) -> [{digraph:vertex(), digraph_label()}])). -type(graph_edge_fun() :: - fun ((atom(), [term()]) -> {digraph:vertex(), digraph:vertex()})). --type(graph_error_fun() :: fun ((any()) -> any() | no_return())). + fun ((atom(), [term()]) -> [{digraph:vertex(), digraph:vertex()}])). -spec(method_record_type/1 :: (rabbit_framing:amqp_method_record()) -> rabbit_framing:amqp_method_name()). @@ -155,7 +150,6 @@ -spec(tcp_name/3 :: (atom(), inet:ip_address(), rabbit_networking:ip_port()) -> atom()). --spec(intersperse/2 :: (A, [A]) -> [A]). -spec(upmap/2 :: (fun ((A) -> B), [A]) -> [B]). -spec(map_in_order/2 :: (fun ((A) -> B), [A]) -> [B]). -spec(table_fold/3 :: (fun ((any(), A) -> A), A, atom()) -> A). @@ -185,16 +179,24 @@ -spec(recursive_delete/1 :: ([file:filename()]) -> rabbit_types:ok_or_error({file:filename(), any()})). +-spec(recursive_copy/2 :: + (file:filename(), file:filename()) + -> rabbit_types:ok_or_error({file:filename(), file:filename(), any()})). -spec(dict_cons/3 :: (any(), any(), dict()) -> dict()). -spec(orddict_cons/3 :: (any(), any(), orddict:orddict()) -> orddict:orddict()). -spec(unlink_and_capture_exit/1 :: (pid()) -> 'ok'). -spec(get_options/2 :: ([optdef()], [string()]) -> {[string()], [{string(), any()}]}). -spec(all_module_attributes/1 :: (atom()) -> [{atom(), [term()]}]). --spec(build_acyclic_graph/4 :: (graph_vertex_fun(), graph_edge_fun(), - graph_error_fun(), [{atom(), [term()]}]) -> - digraph()). +-spec(build_acyclic_graph/3 :: + (graph_vertex_fun(), graph_edge_fun(), [{atom(), [term()]}]) + -> rabbit_types:ok_or_error2(digraph(), + {'vertex', 'duplicate', digraph:vertex()} | + {'edge', ({bad_vertex, digraph:vertex()} | + {bad_edge, [digraph:vertex()]}), + digraph:vertex(), digraph:vertex()})). -spec(now_ms/0 :: () -> non_neg_integer()). +-spec(lock_file/1 :: (file:filename()) -> rabbit_types:ok_or_error('eexist')). -endif. @@ -240,7 +242,7 @@ assert_args_equivalence1(Orig, New, Name, Key) -> case {table_lookup(Orig, Key), table_lookup(New, Key)} of {Same, Same} -> ok; {Orig1, New1} -> protocol_error( - not_allowed, + precondition_failed, "inequivalent arg '~s' for ~s: " "required ~w, received ~w", [Key, rabbit_misc:rs(Name), New1, Orig1]) @@ -414,10 +416,6 @@ tcp_name(Prefix, IPAddress, Port) io_lib:format("~w_~s:~w", [Prefix, inet_parse:ntoa(IPAddress), Port]))). -intersperse(_, []) -> []; -intersperse(_, [E]) -> [E]; -intersperse(Sep, [E|T]) -> [E, Sep | intersperse(Sep, T)]. - %% This is a modified version of Luke Gorrie's pmap - %% http://lukego.livejournal.com/6753.html - that doesn't care about %% the order in which results are received. @@ -689,6 +687,33 @@ recursive_delete1(Path) -> end end. +recursive_copy(Src, Dest) -> + case filelib:is_dir(Src) of + false -> case file:copy(Src, Dest) of + {ok, _Bytes} -> ok; + {error, enoent} -> ok; %% Path doesn't exist anyway + {error, Err} -> {error, {Src, Dest, Err}} + end; + true -> case file:list_dir(Src) of + {ok, FileNames} -> + case file:make_dir(Dest) of + ok -> + lists:foldl( + fun (FileName, ok) -> + recursive_copy( + filename:join(Src, FileName), + filename:join(Dest, FileName)); + (_FileName, Error) -> + Error + end, ok, FileNames); + {error, Err} -> + {error, {Src, Dest, Err}} + end; + {error, Err} -> + {error, {Src, Dest, Err}} + end + end. + dict_cons(Key, Value, Dict) -> dict:update(Key, fun (List) -> [Value | List] end, [Value], Dict). @@ -765,16 +790,30 @@ all_module_attributes(Name) -> end, [], Modules). -build_acyclic_graph(VertexFun, EdgeFun, ErrorFun, Graph) -> +build_acyclic_graph(VertexFun, EdgeFun, Graph) -> G = digraph:new([acyclic]), - [ case digraph:vertex(G, Vertex) of - false -> digraph:add_vertex(G, Vertex, Label); - _ -> ErrorFun({vertex, duplicate, Vertex}) - end || {Module, Atts} <- Graph, - {Vertex, Label} <- VertexFun(Module, Atts) ], - [ case digraph:add_edge(G, From, To) of - {error, E} -> ErrorFun({edge, E, From, To}); - _ -> ok - end || {Module, Atts} <- Graph, - {From, To} <- EdgeFun(Module, Atts) ], - G. + try + [case digraph:vertex(G, Vertex) of + false -> digraph:add_vertex(G, Vertex, Label); + _ -> ok = throw({graph_error, {vertex, duplicate, Vertex}}) + end || {Module, Atts} <- Graph, + {Vertex, Label} <- VertexFun(Module, Atts)], + [case digraph:add_edge(G, From, To) of + {error, E} -> throw({graph_error, {edge, E, From, To}}); + _ -> ok + end || {Module, Atts} <- Graph, + {From, To} <- EdgeFun(Module, Atts)], + {ok, G} + catch {graph_error, Reason} -> + true = digraph:delete(G), + {error, Reason} + end. + +%% TODO: When we stop supporting Erlang prior to R14, this should be +%% replaced with file:open [write, exclusive] +lock_file(Path) -> + case filelib:is_file(Path) of + true -> {error, eexist}; + false -> {ok, Lock} = file:open(Path, [write]), + ok = file:close(Lock) + end. |
