diff options
| author | Tim Watson <watson.timothy@gmail.com> | 2014-01-12 12:38:38 +0000 |
|---|---|---|
| committer | Tim Watson <watson.timothy@gmail.com> | 2014-01-12 12:38:38 +0000 |
| commit | 15ddd5a5e6bcee80e0065112fb156fe14112b5f7 (patch) | |
| tree | dbfc5d692512cc3a3dc7491500fb0758ec1f6c30 | |
| parent | e52fb99e9b38ae2845d51951ac66dd8cb0e32c5d (diff) | |
| download | rabbitmq-server-git-15ddd5a5e6bcee80e0065112fb156fe14112b5f7.tar.gz | |
Refactor (simplify application stop handling)
The offline plugin handling does a fine job of detecting which apps
need to be stopped/unloaded when disabling a plugin at runtime. We
previously had problems accidentally stopping things like stdlib and
mnesia by accident, but only because we went searching for the app
dependencies ourselves! Instead, we stop only those applications
(i.e., plugins) that rabbit_plugins_main has requested. In doing so,
we remove a considerable amount of (new) digraph hacking from
app_utils and reduce the complexity of rabbit_boot somewhat.
| -rw-r--r-- | src/app_utils.erl | 36 | ||||
| -rw-r--r-- | src/rabbit_boot.erl | 21 |
2 files changed, 7 insertions, 50 deletions
diff --git a/src/app_utils.erl b/src/app_utils.erl index 1037fa3461..4622f6e0a8 100644 --- a/src/app_utils.erl +++ b/src/app_utils.erl @@ -18,7 +18,6 @@ -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([isolated_dependencies/1]). -ifdef(use_specs). @@ -32,7 +31,6 @@ -spec wait_for_applications([atom()]) -> 'ok'. -spec app_dependency_order([atom()], boolean()) -> [digraph:vertex()]. -spec app_dependencies(atom()) -> [atom()]. --spec isolated_dependencies(atom()) -> [atom()]. -endif. @@ -77,35 +75,6 @@ stop_applications(Apps, ErrorHandler) -> wait_for_applications(Apps) -> [wait_for_application(App) || App <- Apps], ok. -isolated_dependencies(Root) -> - Loaded = application:loaded_applications(), - {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] - 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 - end, - sets:from_list([Root]), - digraph:out_edges(G, Root)), - sets:to_list(Deps) - 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, @@ -127,11 +96,6 @@ app_dependency_order(RootApps, StripUnreachable) -> %%--------------------------------------------------------------------------- %% Private API -%% It might be worth documenting this on the plugin author's guide/page. -%% A plugin should expect its boot steps to run /before/ the application -%% is started, and its cleanup steps to run /after/ the application has -%% fully stopped. - wait_for_application(Application) -> case lists:keymember(Application, 1, rabbit_misc:which_applications()) of true -> ok; diff --git a/src/rabbit_boot.erl b/src/rabbit_boot.erl index 7112af7c05..12a0116168 100644 --- a/src/rabbit_boot.erl +++ b/src/rabbit_boot.erl @@ -118,23 +118,16 @@ start(Apps) -> stop(Apps) -> ensure_boot_table(), - TargetApps = - sets:to_list( - lists:foldl( - fun(App, Set) -> - lists:foldl(fun sets:add_element/2, Set, - app_utils:isolated_dependencies(App) -- [rabbit]) - end, sets:new(), Apps)), try ok = app_utils:stop_applications( - TargetApps, handle_app_error(error_during_shutdown)) + Apps, handle_app_error(error_during_shutdown)) after try BootSteps = load_steps(boot), ToDelete = [Step || {App, _, _}=Step <- BootSteps, - lists:member(App, TargetApps)], + lists:member(App, Apps)], [ets:delete(?MODULE, Step) || {_, Step, _} <- ToDelete], - run_cleanup_steps(TargetApps) + run_cleanup_steps(Apps) after save_boot_table() end, @@ -146,7 +139,7 @@ stop(Apps) -> false = code:is_loaded(Mod) end || Mod <- Mods], application:unload(App) - end || App <- TargetApps] + end || App <- Apps] end. run_cleanup_steps(Apps) -> @@ -170,7 +163,6 @@ run_boot_steps() -> ok. load_steps(Type) -> - io:format("Loading steps for ~p~n", [Type]), StepAttrs = rabbit_misc:all_app_module_attributes(rabbit_boot_step), sort_boot_steps( Type, @@ -347,8 +339,9 @@ vertices(_Module, {AppName, Steps}) -> edges(Type) -> %% When running "boot" steps, both hard _and_ soft dependencies are %% considered equally. When running "cleanup" steps however, we only - %% consider /hard/ dependencies (i.e., of the form {Key, {hard, StepName}}) - %% as needing to run before or after our own cleanup actions. + %% consider /hard/ dependencies (i.e., of the form + %% {DependencyType, {hard, StepName}}) as needing to run before or after + %% our own cleanup actions. fun (_Module, {_AppName, Steps}) -> [case Key of requires -> {StepName, strip_type(OtherStep)}; |
