summaryrefslogtreecommitdiff
path: root/src/app_utils.erl
diff options
context:
space:
mode:
authorTim Watson <watson.timothy@gmail.com>2013-11-20 12:13:05 +0000
committerTim Watson <watson.timothy@gmail.com>2013-11-20 12:13:05 +0000
commitbc371b7de17216b213ac3ef3638b42d31fcc7b79 (patch)
treec8ccb6a04efc835a5d59467449ca4b87be2598d6 /src/app_utils.erl
parent3f557dc14fc766f50e371a469aa092767acb98e3 (diff)
downloadrabbitmq-server-git-bc371b7de17216b213ac3ef3638b42d31fcc7b79.tar.gz
Various boot procedure improvements
We ensure that all dependent applications are stopped, but also that dependencies shared by multiple applications (e.g., amqp_client) are not.
Diffstat (limited to 'src/app_utils.erl')
-rw-r--r--src/app_utils.erl36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/app_utils.erl b/src/app_utils.erl
index 1231ea586a..d08dfe6a5a 100644
--- a/src/app_utils.erl
+++ b/src/app_utils.erl
@@ -18,6 +18,7 @@
-export([load_applications/1, start_applications/1, start_applications/2,
stop_applications/1, stop_applications/2, app_dependency_order/2,
running_applications/0, wait_for_applications/1, app_dependencies/1]).
+-export([direct_dependencies/1]).
-ifdef(use_specs).
@@ -31,6 +32,7 @@
-spec wait_for_applications([atom()]) -> 'ok'.
-spec app_dependency_order([atom()], boolean()) -> [digraph:vertex()].
-spec app_dependencies(atom()) -> [atom()].
+-spec direct_dependencies(atom()) -> [atom()].
-endif.
@@ -75,6 +77,40 @@ stop_applications(Apps, ErrorHandler) ->
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)} ||
+ {App, _Desc, _Vsn} <- Loaded],
+ Dep <- Deps],
+ 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
+ end,
+ sets:from_list([Root]),
+ digraph:out_edges(G, Root)),
+ sets:to_list(sets:del_element(rabbit, Deps))
+ catch {graph_error, Reason} ->
+ {error, Reason}
+ after
+ true = digraph:delete(G)
+ end.
+
+is_reachable(G, OutVertex, Root) ->
+ digraph_utils:reaching_neighbours([OutVertex], G) -- [Root].
+
app_dependency_order(RootApps, StripUnreachable) ->
{ok, G} = rabbit_misc:build_acyclic_graph(
fun (App, _Deps) -> [{App, App}] end,