diff options
author | Tony Garnock-Jones <tonyg@lshift.net> | 2009-12-14 21:45:31 +0000 |
---|---|---|
committer | Tony Garnock-Jones <tonyg@lshift.net> | 2009-12-14 21:45:31 +0000 |
commit | fa6b56dbba4f507dc643a6c872731aa2c9dc770b (patch) | |
tree | 3b79390a1600a3884b20c4ff3b9e950e0c81037b | |
parent | 9b9bc357ab121d268e06ca317537091fe230de79 (diff) | |
download | rabbitmq-server-fa6b56dbba4f507dc643a6c872731aa2c9dc770b.tar.gz |
Move planning code out of activator and into rabbit proper.
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | src/rabbit.erl | 120 | ||||
-rw-r--r-- | src/rabbit_plugin_activator.erl | 77 |
3 files changed, 95 insertions, 103 deletions
@@ -57,7 +57,6 @@ ERL_CALL=erl_call -sname $(RABBITMQ_NODENAME) -e ERL_EBIN=erl -noinput -pa $(EBIN_DIR) all: $(TARGETS) - ./scripts/rabbitmq-activate-plugins $(EBIN_DIR)/rabbit.app: $(EBIN_DIR)/rabbit_app.in $(BEAM_TARGETS) generate_app escript generate_app $(EBIN_DIR) $@ < $< diff --git a/src/rabbit.erl b/src/rabbit.erl index 78bf7e38..dd5f221a 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -33,7 +33,7 @@ -behaviour(application). --export([prepare/0, start/0, finish_boot/1, stop/0, stop_and_halt/0, status/0, rotate_logs/1]). +-export([prepare/0, start/0, stop/0, stop_and_halt/0, status/0, rotate_logs/1]). -export([start/2, stop/1]). @@ -80,11 +80,9 @@ -type(log_location() :: 'tty' | 'undefined' | string()). -type(file_suffix() :: binary()). --type(boot_step() :: {{atom(), {atom(), 0}}, [{atom(), any()}]}). -spec(prepare/0 :: () -> 'ok'). -spec(start/0 :: () -> 'ok'). --spec(finish_boot/1 :: ([boot_step()]) -> 'ok'). -spec(stop/0 :: () -> 'ok'). -spec(stop_and_halt/0 :: () -> 'ok'). -spec(rotate_logs/1 :: (file_suffix()) -> 'ok' | {'error', any()}). @@ -141,24 +139,33 @@ rotate_logs(BinarySuffix) -> %%-------------------------------------------------------------------- start(normal, []) -> - {ok, _SupPid} = rabbit_sup:start_link(). - -finish_boot(BootSteps) -> - %% We set our group_leader so we appear to OTP to be part of the - %% rabbit application. - case application_controller:get_master(rabbit) of - undefined -> - exit({?MODULE, finish_boot, could_not_find_rabbit}); - MasterPid when is_pid(MasterPid) -> - group_leader(MasterPid, self()) - end, + {ok, SupPid} = rabbit_sup:start_link(), print_banner(), - [ok = run_boot_step(Step) || Step <- BootSteps], + [ok = run_boot_step(Step) || Step <- boot_steps()], io:format("~nbroker running~n"), + + {ok, SupPid}. + + +stop(_State) -> + terminated_ok = error_logger:delete_report_handler(rabbit_error_logger), + ok = rabbit_alarm:stop(), + ok = case rabbit_mnesia:is_clustered() of + true -> rabbit_amqqueue:on_node_down(node()); + false -> rabbit_mnesia:empty_ram_only_tables() + end, ok. -run_boot_step({ModFunSpec = {Module, {Fun, 0}}, Attributes}) -> +%%--------------------------------------------------------------------------- + +boot_error(Format, Args) -> + io:format(Format, Args), + error_logger:error_msg(Format, Args), + timer:sleep(1000), + exit({?MODULE, failure_during_boot}). + +run_boot_step({{Module, {Fun, 0}}, Attributes}) -> Description = case lists:keysearch(description, 1, Attributes) of {value, {_, D}} -> D; false -> lists:flatten(io_lib:format("~w:~w", [Module, Fun])) @@ -166,16 +173,78 @@ run_boot_step({ModFunSpec = {Module, {Fun, 0}}, Attributes}) -> io:format("starting ~-20s ...", [Description]), case catch Module:Fun() of {'EXIT', Reason} -> - io:format("FAILED~nReason: ~p~n", [Reason]), - ChainedReason = {?MODULE, finish_boot, failed, ModFunSpec, Reason}, - error_logger:error_report(ChainedReason), - timer:sleep(1000), - exit(ChainedReason); + boot_error("FAILED~nReason: ~p~n", [Reason]); ok -> io:format("done~n"), ok end. +boot_steps() -> + AllApps = [App || {App, _, _} <- application:loaded_applications()], + Modules = lists:usort( + lists:append([Modules + || {ok, Modules} <- [application:get_key(App, modules) + || App <- AllApps]])), + UnsortedSteps = + lists:flatmap(fun (Module) -> + [{{Module, FunSpec}, Attributes} + || {rabbit_boot_step, [{FunSpec, Attributes}]} + <- Module:module_info(attributes)] + end, Modules), + sort_boot_steps(UnsortedSteps). + +sort_boot_steps(UnsortedSteps) -> + G = digraph:new([acyclic]), + [digraph:add_vertex(G, ModFunSpec, Step) || Step = {ModFunSpec, _Attrs} <- UnsortedSteps], + lists:foreach(fun ({ModFunSpec, Attributes}) -> + [add_boot_step_dep(G, ModFunSpec, PostModFunSpec) + || {post, PostModFunSpec} <- Attributes], + [add_boot_step_dep(G, PreModFunSpec, ModFunSpec) + || {pre, PreModFunSpec} <- Attributes] + end, UnsortedSteps), + SortedStepsRev = [begin + {ModFunSpec, Step} = digraph:vertex(G, ModFunSpec), + Step + end || ModFunSpec <- digraph_utils:topsort(G)], + SortedSteps = lists:reverse(SortedStepsRev), + digraph:delete(G), + check_boot_steps(SortedSteps). + +add_boot_step_dep(G, RunsSecond, RunsFirst) -> + case digraph:add_edge(G, RunsSecond, RunsFirst) of + {error, Reason} -> + boot_error( + "Could not add boot step dependency of ~s on ~s:~n~s", + [format_modfunspec(RunsSecond), format_modfunspec(RunsFirst), + case Reason of + {bad_vertex, V} -> + io_lib:format("Boot step not registered: ~s~n", + [format_modfunspec(V)]); + {bad_edge, [First | Rest]} -> + [io_lib:format("Cyclic dependency: ~s", [format_modfunspec(First)]), + [io_lib:format(" depends on ~s", [format_modfunspec(Next)]) + || Next <- Rest], + io_lib:format(" depends on ~s~n", [format_modfunspec(First)])] + end]); + _ -> + ok + end. + +check_boot_steps(SortedSteps) -> + case [ModFunSpec || {ModFunSpec = {Module, {Fun, Arity}}, _} <- SortedSteps, + not erlang:function_exported(Module, Fun, Arity)] of + [] -> + SortedSteps; + MissingFunctions -> + boot_error("Boot steps not exported:~s~n", + [[[" ", format_modfunspec(MFS)] || MFS <- MissingFunctions]]) + end. + +format_modfunspec({Module, {Fun, Arity}}) -> + lists:flatten(io_lib:format("~w:~w/~b", [Module, Fun, Arity])). + +%%--------------------------------------------------------------------------- + boot_database() -> ok = rabbit_mnesia:init(). @@ -235,15 +304,6 @@ boot_ssl_listeners() -> ok end. -stop(_State) -> - terminated_ok = error_logger:delete_report_handler(rabbit_error_logger), - ok = rabbit_alarm:stop(), - ok = case rabbit_mnesia:is_clustered() of - true -> rabbit_amqqueue:on_node_down(node()); - false -> rabbit_mnesia:empty_ram_only_tables() - end, - ok. - %--------------------------------------------------------------------------- log_location(Type) -> diff --git a/src/rabbit_plugin_activator.erl b/src/rabbit_plugin_activator.erl index 8bf16bec..4fcfab78 100644 --- a/src/rabbit_plugin_activator.erl +++ b/src/rabbit_plugin_activator.erl @@ -121,7 +121,7 @@ start() -> [ScriptFile, Module:format_error(Error)]) end, - case post_process_script(ScriptFile, boot_steps(AllApps)) of + case post_process_script(ScriptFile) of ok -> ok; {error, Reason} -> error("post processing of boot script file ~s failed:~n~w", @@ -148,69 +148,6 @@ determine_version(App) -> {ok, Vsn} = application:get_key(App, vsn), {App, Vsn}. -boot_steps(AllApps) -> - [application:load(App) || App <- AllApps], - Modules = lists:usort( - lists:append([Modules - || {ok, Modules} <- [application:get_key(App, modules) - || App <- AllApps]])), - UnsortedSteps = - lists:flatmap(fun (Module) -> - [{{Module, FunSpec}, Attributes} - || {rabbit_boot_step, [{FunSpec, Attributes}]} - <- Module:module_info(attributes)] - end, Modules), - sort_boot_steps(UnsortedSteps). - -sort_boot_steps(UnsortedSteps) -> - G = digraph:new([acyclic]), - [digraph:add_vertex(G, ModFunSpec, Step) || Step = {ModFunSpec, _Attrs} <- UnsortedSteps], - lists:foreach(fun ({ModFunSpec, Attributes}) -> - [add_boot_step_dep(G, ModFunSpec, PostModFunSpec) - || {post, PostModFunSpec} <- Attributes], - [add_boot_step_dep(G, PreModFunSpec, ModFunSpec) - || {pre, PreModFunSpec} <- Attributes] - end, UnsortedSteps), - SortedStepsRev = [begin - {ModFunSpec, Step} = digraph:vertex(G, ModFunSpec), - Step - end || ModFunSpec <- digraph_utils:topsort(G)], - SortedSteps = lists:reverse(SortedStepsRev), - digraph:delete(G), - check_boot_steps(SortedSteps). - -add_boot_step_dep(G, RunsSecond, RunsFirst) -> - case digraph:add_edge(G, RunsSecond, RunsFirst) of - {error, Reason} -> - error("Could not add boot step dependency of ~s on ~s:~n~s", - [format_modfunspec(RunsSecond), format_modfunspec(RunsFirst), - case Reason of - {bad_vertex, V} -> - io_lib:format("Boot step not registered: ~s~n", - [format_modfunspec(V)]); - {bad_edge, [First | Rest]} -> - [io_lib:format("Cyclic dependency: ~s", [format_modfunspec(First)]), - [io_lib:format(" depends on ~s", [format_modfunspec(Next)]) - || Next <- Rest], - io_lib:format(" depends on ~s~n", [format_modfunspec(First)])] - end]); - _ -> - ok - end. - -check_boot_steps(SortedSteps) -> - case [ModFunSpec || {ModFunSpec = {Module, {Fun, Arity}}, _} <- SortedSteps, - not erlang:function_exported(Module, Fun, Arity)] of - [] -> - SortedSteps; - MissingFunctions -> - error("Boot steps not exported:~s~n", - [[[" ", format_modfunspec(MFS)] || MFS <- MissingFunctions]]) - end. - -format_modfunspec({Module, {Fun, Arity}}) -> - lists:flatten(io_lib:format("~w:~w/~b", [Module, Fun, Arity])). - assert_dir(Dir) -> case filelib:is_dir(Dir) of true -> ok; @@ -290,12 +227,10 @@ expand_dependencies(Current, [Next|Rest]) -> expand_dependencies(sets:add_element(Next, Current), Rest ++ Unique) end. -post_process_script(ScriptFile, BootSteps) -> +post_process_script(ScriptFile) -> case file:consult(ScriptFile) of {ok, [{script, Name, Entries}]} -> - NewEntries = lists:flatmap(fun (Entry) -> - process_entry(Entry, BootSteps) - end, Entries), + NewEntries = lists:flatmap(fun process_entry/1, Entries), case file:open(ScriptFile, [write]) of {ok, Fd} -> io:format(Fd, "%% script generated at ~w ~w~n~p.~n", @@ -309,11 +244,9 @@ post_process_script(ScriptFile, BootSteps) -> {error, {failed_to_load_script, Reason}} end. -process_entry(Entry = {apply,{application,start_boot,[stdlib,permanent]}}, _BootSteps) -> +process_entry(Entry = {apply,{application,start_boot,[stdlib,permanent]}}) -> [Entry, {apply,{rabbit,prepare,[]}}]; -process_entry(Entry = {progress, started}, BootSteps) -> - [{apply,{rabbit,finish_boot,[BootSteps]}}, Entry]; -process_entry(Entry, _BootSteps) -> +process_entry(Entry) -> [Entry]. error(Fmt, Args) -> |