diff options
| author | Alvaro Videla <videlalvaro@gmail.com> | 2015-05-20 20:36:28 +0200 |
|---|---|---|
| committer | Michael Klishin <mklishin@pivotal.io> | 2015-05-28 06:26:07 +0300 |
| commit | 6461dd3f33a9f09dc7c6c94e0178b0848d165727 (patch) | |
| tree | f12136e82869fe037cfa5a77be55926cc1f8ff5f | |
| parent | 6a6c42d7ea6bc206f97bf59b82c4d223dec2c6da (diff) | |
| download | rabbitmq-server-git-6461dd3f33a9f09dc7c6c94e0178b0848d165727.tar.gz | |
moves boot steps to its own module
| -rw-r--r-- | src/rabbit.erl | 82 | ||||
| -rw-r--r-- | src/rabbit_boot_steps.erl | 96 |
2 files changed, 101 insertions, 77 deletions
diff --git a/src/rabbit.erl b/src/rabbit.erl index 84aaf4e20c..5898c66726 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -390,7 +390,7 @@ start_apps(Apps) -> app_utils:load_applications(Apps), OrderedApps = app_utils:app_dependency_order(Apps, false), case lists:member(rabbit, Apps) of - false -> run_boot_steps(Apps); %% plugin activation + false -> rabbit_boot_steps:run_boot_steps(Apps); %% plugin activation true -> ok %% will run during start of rabbit app end, ok = app_utils:start_applications(OrderedApps, @@ -400,8 +400,9 @@ stop_apps(Apps) -> ok = app_utils:stop_applications( Apps, handle_app_error(error_during_shutdown)), case lists:member(rabbit, Apps) of - false -> run_cleanup_steps(Apps); %% plugin deactivation - true -> ok %% it's all going anyway + %% plugin deactivation + false -> rabbit_boot_steps:run_cleanup_steps(Apps); + true -> ok %% it's all going anyway end, ok. @@ -412,10 +413,6 @@ handle_app_error(Term) -> throw({Term, App, Reason}) end. -run_cleanup_steps(Apps) -> - [run_step(Attrs, cleanup) || Attrs <- find_steps(Apps)], - ok. - await_startup() -> await_startup(false). @@ -520,7 +517,7 @@ start(normal, []) -> print_banner(), log_banner(), warn_if_kernel_config_dubious(), - run_boot_steps(), + rabbit_boot_steps:run_boot_steps(), {ok, SupPid}; Error -> Error @@ -534,75 +531,6 @@ stop(_State) -> end, ok. -%%--------------------------------------------------------------------------- -%% boot step logic - -run_boot_steps() -> - run_boot_steps([App || {App, _, _} <- application:loaded_applications()]). - -run_boot_steps(Apps) -> - [ok = run_step(Attrs, mfa) || Attrs <- find_steps(Apps)], - ok. - -find_steps(Apps) -> - All = sort_boot_steps(rabbit_misc:all_module_attributes(rabbit_boot_step)), - [Attrs || {App, _, Attrs} <- All, lists:member(App, Apps)]. - -run_step(Attributes, AttributeName) -> - case [MFA || {Key, MFA} <- Attributes, - Key =:= AttributeName] of - [] -> - ok; - MFAs -> - [case apply(M,F,A) of - ok -> ok; - {error, Reason} -> exit({error, Reason}) - end || {M,F,A} <- MFAs], - ok - end. - -vertices({AppName, _Module, Steps}) -> - [{StepName, {AppName, StepName, Atts}} || {StepName, Atts} <- Steps]. - -edges({_AppName, _Module, Steps}) -> - EnsureList = fun (L) when is_list(L) -> L; - (T) -> [T] - end, - [case Key of - requires -> {StepName, OtherStep}; - enables -> {OtherStep, StepName} - end || {StepName, Atts} <- Steps, - {Key, OtherStepOrSteps} <- Atts, - OtherStep <- EnsureList(OtherStepOrSteps), - Key =:= requires orelse Key =:= enables]. - -sort_boot_steps(UnsortedSteps) -> - case rabbit_misc:build_acyclic_graph(fun vertices/1, fun edges/1, - UnsortedSteps) of - {ok, G} -> - %% Use topological sort to find a consistent ordering (if - %% there is one, otherwise fail). - SortedSteps = lists:reverse( - [begin - {StepName, Step} = digraph:vertex(G, - StepName), - Step - end || StepName <- digraph_utils:topsort(G)]), - digraph:delete(G), - %% Check that all mentioned {M,F,A} triples are exported. - case [{StepName, {M,F,A}} || - {_App, StepName, Attributes} <- SortedSteps, - {mfa, {M,F,A}} <- Attributes, - not erlang:function_exported(M, F, length(A))] of - [] -> SortedSteps; - MissingFns -> exit({boot_functions_not_exported, MissingFns}) - end; - {error, {vertex, duplicate, StepName}} -> - exit({duplicate_boot_step, StepName}); - {error, {edge, Reason, From, To}} -> - exit({invalid_boot_step_dependency, From, To, Reason}) - end. - -ifdef(use_specs). -spec(boot_error/2 :: (term(), not_available | [tuple()]) -> no_return()). -endif. diff --git a/src/rabbit_boot_steps.erl b/src/rabbit_boot_steps.erl new file mode 100644 index 0000000000..7232635560 --- /dev/null +++ b/src/rabbit_boot_steps.erl @@ -0,0 +1,96 @@ +%% The contents of this file are subject to the Mozilla Public License +%% Version 1.1 (the "License"); you may not use this file except in +%% compliance with the License. You may obtain a copy of the License +%% at http://www.mozilla.org/MPL/ +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and +%% limitations under the License. +%% +%% The Original Code is RabbitMQ. +%% +%% The Initial Developer of the Original Code is GoPivotal, Inc. +%% Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved. +%% + +-module(rabbit_boot_steps). + +-export([run_boot_steps/0, run_boot_steps/1, run_cleanup_steps/1]). +-export([find_steps/0, find_steps/1]). + +run_boot_steps() -> + run_boot_steps(loaded_applications()). + +run_boot_steps(Apps) -> + [ok = run_step(Attrs, mfa) || {_, _, Attrs} <- find_steps(Apps)], + ok. + +run_cleanup_steps(Apps) -> + [run_step(Attrs, cleanup) || {_, _, Attrs} <- find_steps(Apps)], + ok. + +loaded_applications() -> + [App || {App, _, _} <- application:loaded_applications()]. + +find_steps() -> + find_steps(loaded_applications()). + +find_steps(Apps) -> + All = sort_boot_steps(rabbit_misc:all_module_attributes(rabbit_boot_step)), + [Step || {App, _, _} = Step <- All, lists:member(App, Apps)]. + +run_step(Attributes, AttributeName) -> + case [MFA || {Key, MFA} <- Attributes, + Key =:= AttributeName] of + [] -> + ok; + MFAs -> + [case apply(M,F,A) of + ok -> ok; + {error, Reason} -> exit({error, Reason}) + end || {M,F,A} <- MFAs], + ok + end. + +vertices({AppName, _Module, Steps}) -> + [{StepName, {AppName, StepName, Atts}} || {StepName, Atts} <- Steps]. + +edges({_AppName, _Module, Steps}) -> + EnsureList = fun (L) when is_list(L) -> L; + (T) -> [T] + end, + [case Key of + requires -> {StepName, OtherStep}; + enables -> {OtherStep, StepName} + end || {StepName, Atts} <- Steps, + {Key, OtherStepOrSteps} <- Atts, + OtherStep <- EnsureList(OtherStepOrSteps), + Key =:= requires orelse Key =:= enables]. + +sort_boot_steps(UnsortedSteps) -> + case rabbit_misc:build_acyclic_graph(fun vertices/1, fun edges/1, + UnsortedSteps) of + {ok, G} -> + %% Use topological sort to find a consistent ordering (if + %% there is one, otherwise fail). + SortedSteps = lists:reverse( + [begin + {StepName, Step} = digraph:vertex(G, + StepName), + Step + end || StepName <- digraph_utils:topsort(G)]), + digraph:delete(G), + %% Check that all mentioned {M,F,A} triples are exported. + case [{StepName, {M,F,A}} || + {_App, StepName, Attributes} <- SortedSteps, + {mfa, {M,F,A}} <- Attributes, + not erlang:function_exported(M, F, length(A))] of + [] -> SortedSteps; + MissingFns -> exit({boot_functions_not_exported, MissingFns}) + end; + {error, {vertex, duplicate, StepName}} -> + exit({duplicate_boot_step, StepName}); + {error, {edge, Reason, From, To}} -> + exit({invalid_boot_step_dependency, From, To, Reason}) + end. |
