summaryrefslogtreecommitdiff
path: root/src
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
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')
-rw-r--r--src/app_utils.erl36
-rw-r--r--src/rabbit.erl10
-rw-r--r--src/rabbit_boot.erl47
-rw-r--r--src/rabbit_misc.erl35
4 files changed, 91 insertions, 37 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,
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 74efbf22d7..44cd275d3b 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -457,12 +457,12 @@ maybe_insert_default_data() ->
end.
insert_default_data() ->
- {ok, DefaultUser} = application:get_env(default_user),
- {ok, DefaultPass} = application:get_env(default_pass),
- {ok, DefaultTags} = application:get_env(default_user_tags),
- {ok, DefaultVHost} = application:get_env(default_vhost),
+ {ok, DefaultUser} = application:get_env(rabbit, default_user),
+ {ok, DefaultPass} = application:get_env(rabbit, default_pass),
+ {ok, DefaultTags} = application:get_env(rabbit, default_user_tags),
+ {ok, DefaultVHost} = application:get_env(rabbit, default_vhost),
{ok, [DefaultConfigurePerm, DefaultWritePerm, DefaultReadPerm]} =
- application:get_env(default_permissions),
+ application:get_env(rabbit, default_permissions),
ok = rabbit_vhost:add(DefaultVHost),
ok = rabbit_auth_backend_internal:add_user(DefaultUser, DefaultPass),
ok = rabbit_auth_backend_internal:set_tags(DefaultUser, DefaultTags),
diff --git a/src/rabbit_boot.erl b/src/rabbit_boot.erl
index 58361e2641..af2bc9c406 100644
--- a/src/rabbit_boot.erl
+++ b/src/rabbit_boot.erl
@@ -63,7 +63,8 @@ shutdown(Apps) ->
undefined -> ok;
_ -> await_startup(Apps)
end,
- rabbit_log:info("Stopping RabbitMQ~n"),
+ %% TODO: put this back in somewhere sensible...
+ %% rabbit_log:info("Stopping RabbitMQ~n"),
ok = app_utils:stop_applications(Apps)
after
delete_boot_table()
@@ -82,35 +83,32 @@ start(Apps) ->
stop(Apps) ->
ensure_boot_table(),
- TargetApps = lists:usort([app_utils:app_dependency_order(App, true) ||
- InitApp <- Apps,
- App <- app_utils:app_dependencies(InitApp)]),
- Ineligible = lists:usort(
- app_utils:app_dependency_order(
- [App || App <- app_utils:running_applications(),
- not lists:member(App, Apps)],
- true) ++ [rabbit]),
- ShutdownApps = TargetApps -- Ineligible,
- io:format("Shutdown apps = ~p~n", [ShutdownApps]),
+ TargetApps =
+ lists:usort(
+ lists:append([app_utils:direct_dependencies(App) || App <- Apps])),
try
ok = app_utils:stop_applications(
- ShutdownApps, handle_app_error(error_during_shutdown))
+ TargetApps, handle_app_error(error_during_shutdown))
after
- [run_steps(App, rabbit_cleanup_step) || App <- ShutdownApps]
+ try
+ [run_steps(App, rabbit_cleanup_step) || App <- TargetApps]
+ after
+ save_boot_table()
+ end
end.
run_boot_steps(App) ->
run_steps(App, rabbit_boot_step).
run_steps(App, StepType) ->
- RootApps = app_utils:app_dependencies(App),
- Steps =
+ RootApps = [App|app_utils:direct_dependencies(App)],
+ StepAttrs = rabbit_misc:all_app_module_attributes(StepType),
+ BootSteps =
sort_boot_steps(
- lists:usort(
- lists:append(
- [rabbit_misc:all_module_attributes(A, StepType) ||
- A <- [App|RootApps]]))),
- [ok = run_boot_step(Step, StepType) || Step <- Steps],
+ lists:usort(
+ [{Mod, Steps} || {AppName, Mod, Steps} <- StepAttrs,
+ lists:member(AppName, RootApps)])),
+ [ok = run_boot_step(Step, StepType) || Step <- BootSteps],
ok.
boot_error(Term={error, {timeout_waiting_for_tables, _}}, _Stacktrace) ->
@@ -165,8 +163,13 @@ clean_table() ->
ets:new(?MODULE, [named_table, public, ordered_set]).
load_table() ->
- {ok, _Tab} = ets:file2tab(boot_file(), [{verify, true}]),
- ok.
+ case ets:file2tab(boot_file(), [{verify, true}]) of
+ {error, _} -> error(fuck);
+ {ok, _Tab} -> ok,
+ io:format("Starting with pre-loaded boot table:~n~p~n"
+ "----------------~n",
+ [ets:tab2list(?MODULE)])
+ end.
save_boot_table() ->
delete_boot_table(),
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl
index 0fa3190a69..3f5bee55d7 100644
--- a/src/rabbit_misc.erl
+++ b/src/rabbit_misc.erl
@@ -51,8 +51,8 @@
-export([dict_cons/3, orddict_cons/3, gb_trees_cons/3]).
-export([gb_trees_fold/3, gb_trees_foreach/2]).
-export([parse_arguments/3]).
--export([all_module_attributes/1, all_module_attributes/2]).
--export([build_acyclic_graph/3]).
+-export([all_app_module_attributes/1]).
+-export([all_module_attributes/1, build_acyclic_graph/3]).
-export([now_ms/0]).
-export([const_ok/0, const/1]).
-export([ntoa/1, ntoab/1]).
@@ -210,7 +210,6 @@
-> {'ok', {atom(), [{string(), string()}], [string()]}} |
'no_command').
-spec(all_module_attributes/1 :: (atom()) -> [{atom(), [term()]}]).
--spec(all_module_attributes/2 :: (atom(), atom()) -> [{atom(), [term()]}]).
-spec(build_acyclic_graph/3 ::
(graph_vertex_fun(), graph_edge_fun(), [{atom(), [term()]}])
-> rabbit_types:ok_or_error2(digraph(),
@@ -852,21 +851,37 @@ module_attributes(Module) ->
V
end.
-all_module_attributes(App, Name) ->
- {ok, Modules} = application:get_key(App, modules),
+all_app_module_attributes(Name) ->
+ Modules =
+ lists:usort(
+ lists:flatten(
+ [{App, Module} ||
+ {App, _, _} <- application:loaded_applications(),
+ {ok, Modules} <- [application:get_key(App, modules)],
+ Module <- Modules])),
lists:foldl(
- fun (Module, Acc) ->
+ fun ({App, Module}, Acc) ->
case lists:append([Atts || {N, Atts} <- module_attributes(Module),
N =:= Name]) of
[] -> Acc;
- Atts -> [{Module, Atts} | Acc]
+ Atts -> [{App, Module, Atts} | Acc]
end
end, [], Modules).
all_module_attributes(Name) ->
- lists:usort(lists:append(
- [all_module_attributes(App, Name) ||
- {App, _, _} <- application:loaded_applications()])).
+ Modules =
+ lists:usort(
+ lists:append(
+ [Modules || {App, _, _} <- application:loaded_applications(),
+ {ok, Modules} <- [application:get_key(App, modules)]])),
+ lists:foldl(
+ fun (Module, Acc) ->
+ case lists:append([Atts || {N, Atts} <- module_attributes(Module),
+ N =:= Name]) of
+ [] -> Acc;
+ Atts -> [{Module, Atts} | Acc]
+ end
+ end, [], Modules).
build_acyclic_graph(VertexFun, EdgeFun, Graph) ->
G = digraph:new([acyclic]),