diff options
| author | Tim Watson <tim@rabbitmq.com> | 2013-11-26 12:17:28 +0000 |
|---|---|---|
| committer | Tim Watson <tim@rabbitmq.com> | 2013-11-26 12:17:28 +0000 |
| commit | 2e8ddf161965fbf33f18b6d862bc2d91f1a6ad9d (patch) | |
| tree | da42a116968b061e80c52414877580f5a86eb735 | |
| parent | 40612c20f440f971dd7f97af8b77dcd208432829 (diff) | |
| download | rabbitmq-server-git-2e8ddf161965fbf33f18b6d862bc2d91f1a6ad9d.tar.gz | |
De-duplicate dependency/graph building functions
| -rw-r--r-- | src/app_utils.erl | 31 | ||||
| -rw-r--r-- | src/rabbit_misc.erl | 35 |
2 files changed, 40 insertions, 26 deletions
diff --git a/src/app_utils.erl b/src/app_utils.erl index 22e2df44bb..82e4e276fe 100644 --- a/src/app_utils.erl +++ b/src/app_utils.erl @@ -78,32 +78,27 @@ wait_for_applications(Apps) -> [wait_for_application(App) || App <- Apps], ok. direct_dependencies(Root) -> - G = digraph:new(), Loaded = application:loaded_applications(), - try - [begin - case digraph:vertex(G, App) of - false -> digraph:add_vertex(G, App, App); - _ -> ok = throw({graph_error, {vertex, duplicate, App}}) - end - end || {App, _, _} <- Loaded], - [digraph:add_edge(G, App, Dep) || - {App, Deps} <- [{App, app_dependencies(App)} || + {ok, G} = rabbit_misc:build_graph( + fun() -> [{App, App} || {App, _, _} <- Loaded] end, + fun() -> [{App, Dep} || + {App, Deps} <- [{App, app_dependencies(App)} || {App, _Desc, _Vsn} <- Loaded], - Dep <- Deps], + Dep <- Deps] + end, + digraph:new()), + try Deps = lists:foldl( fun(E, Acc) -> - {_, _InVertex, OutVertex, _Label} = digraph:edge(G, E), - case is_reachable(G, OutVertex, Root) of - [] -> sets:add_element(OutVertex, Acc); - _ -> Acc - end + {_, _InVertex, OutVertex, _Label} = digraph:edge(G, E), + case is_reachable(G, OutVertex, Root) of + [] -> sets:add_element(OutVertex, Acc); + _ -> Acc + end end, sets:from_list([Root]), digraph:out_edges(G, Root)), sets:to_list(Deps) - catch {graph_error, Reason} -> - {error, Reason} after true = digraph:delete(G) end. diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 26071a8aef..3708c625ef 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -52,7 +52,7 @@ -export([gb_trees_fold/3, gb_trees_foreach/2]). -export([parse_arguments/3]). -export([all_app_module_attributes/1]). --export([all_module_attributes/1, build_acyclic_graph/3]). +-export([all_module_attributes/1, build_graph/3, build_acyclic_graph/3]). -export([now_ms/0]). -export([const_ok/0, const/1]). -export([ntoa/1, ntoab/1]). @@ -91,8 +91,12 @@ :: rabbit_types:channel_exit() | rabbit_types:connection_exit()). -type(digraph_label() :: term()). -type(graph_vertex_fun() :: + fun (() -> [{digraph:vertex(), digraph_label()}])). +-type(acyclic_graph_vertex_fun() :: fun ((atom(), [term()]) -> [{digraph:vertex(), digraph_label()}])). -type(graph_edge_fun() :: + fun (() -> [{digraph:vertex(), digraph:vertex()}])). +-type(acyclic_graph_edge_fun() :: fun ((atom(), [term()]) -> [{digraph:vertex(), digraph:vertex()}])). -spec(method_record_type/1 :: (rabbit_framing:amqp_method_record()) @@ -210,8 +214,17 @@ -> {'ok', {atom(), [{string(), string()}], [string()]}} | 'no_command'). -spec(all_module_attributes/1 :: (atom()) -> [{atom(), [term()]}]). +-spec(build_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(build_acyclic_graph/3 :: - (graph_vertex_fun(), graph_edge_fun(), [{atom(), [term()]}]) + (acyclic_graph_vertex_fun(), + acyclic_graph_edge_fun(), [{atom(), [term()]}]) -> rabbit_types:ok_or_error2(digraph(), {'vertex', 'duplicate', digraph:vertex()} | {'edge', ({bad_vertex, digraph:vertex()} | @@ -884,25 +897,31 @@ find_module_attributes(Generator, Fold) -> {ok, Modules} <- [application:get_key(App, modules)]])), lists:foldl(Fold, [], Targets). -build_acyclic_graph(VertexFun, EdgeFun, Graph) -> - G = digraph:new([acyclic]), +build_graph(VertexFun, EdgeFun, 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)], + end || {Vertex, Label} <- VertexFun()], [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)], + end || {From, To} <- EdgeFun()], {ok, G} catch {graph_error, Reason} -> true = digraph:delete(G), {error, Reason} end. +build_acyclic_graph(VertexFun, EdgeFun, Graph) -> + build_graph(fun() -> [Vertex || {Module, Atts} <- Graph, + Vertex <- VertexFun(Module, Atts)] + end, + fun() -> [Edge || {Module, Atts} <- Graph, + Edge <- EdgeFun(Module, Atts)] + end, + digraph:new([acyclic])). + const_ok() -> ok. const(X) -> fun () -> X end. |
