From bc9d3766b4a226d37136a102b0040fba96e85138 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 30 Nov 2009 21:55:52 +0000 Subject: Initial stab at the problem --- src/rabbit.erl | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index c6dde385..c4ea0653 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -120,19 +120,26 @@ start(normal, []) -> print_banner(), + HookModules = discover_hooks(startup_hook), + io:format("Hooks: ~p~n", [HookModules]), %% TODO: DEBUG removeme + lists:foreach( - fun ({Msg, Thunk}) -> + fun ({Phase, Msg, Thunk}) -> io:format("starting ~-20s ...", [Msg]), + ok = run_hooks(HookModules, startup_hook, {pre, Phase}), Thunk(), + ok = run_hooks(HookModules, startup_hook, {post, Phase}), io:format("done~n"); - ({Msg, M, F, A}) -> + ({Phase, Msg, M, F, A}) -> io:format("starting ~-20s ...", [Msg]), + ok = run_hooks(HookModules, startup_hook, {pre, Phase}), apply(M, F, A), + ok = run_hooks(HookModules, startup_hook, {post, Phase}), io:format("done~n") end, - [{"database", + [{database, "database", fun () -> ok = rabbit_mnesia:init() end}, - {"core processes", + {core_processes, "core processes", fun () -> ok = start_child(rabbit_log), ok = rabbit_hooks:start(), @@ -156,28 +163,28 @@ start(normal, []) -> ok = start_child(rabbit_router), ok = start_child(rabbit_node_monitor) end}, - {"recovery", + {recovery, "recovery", fun () -> ok = maybe_insert_default_data(), ok = rabbit_exchange:recover(), ok = rabbit_amqqueue:recover() end}, - {"persister", + {persister, "persister", fun () -> ok = start_child(rabbit_persister) end}, - {"guid generator", + {guid_generator, "guid generator", fun () -> ok = start_child(rabbit_guid) end}, - {"builtin applications", + {builtin_applications, "builtin applications", fun () -> {ok, DefaultVHost} = application:get_env(default_vhost), ok = error_logger:add_report_handler( rabbit_error_logger, [DefaultVHost]), ok = start_builtin_amq_applications() end}, - {"TCP listeners", + {tcp_listeners, "TCP listeners", fun () -> ok = rabbit_networking:start(), {ok, TcpListeners} = application:get_env(tcp_listeners), @@ -187,7 +194,7 @@ start(normal, []) -> end, TcpListeners) end}, - {"SSL listeners", + {ssl_listeners, "SSL listeners", fun () -> case application:get_env(ssl_listeners) of {ok, []} -> @@ -369,3 +376,16 @@ log_rotation_result(ok, {error, SaslLogError}) -> {error, {cannot_rotate_sasl_logs, SaslLogError}}; log_rotation_result(ok, ok) -> ok. + +discover_hooks(Hook) -> + %% We rely here on the fact that plugins have all their code + %% loaded before rabbit is started, so we will be able to find + %% hook modules by name. + [M || {M, _} <- code:all_loaded(), + ok == io:format("? ~p~n", [M]), %% TODO: DEBUG removeme + case atom_to_list(M) of "rabbit_hook_" ++ _ -> true; _ -> false end, + erlang:function_exported(M, Hook, 1)]. + +run_hooks(HookModules, Hook, Event) -> + _ = [{M, Hook, ok} = {M, Hook, M:Hook(Event)} || M <- HookModules], + ok. -- cgit v1.2.1 From bd4453bc6bca299f1f706951970b5f58a83003b8 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 30 Nov 2009 22:31:40 +0000 Subject: Change tactic to examine modules in .app files for rabbit_static_hook_* modules --- src/rabbit.erl | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index c4ea0653..b85af6ad 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -120,21 +120,20 @@ start(normal, []) -> print_banner(), - HookModules = discover_hooks(startup_hook), - io:format("Hooks: ~p~n", [HookModules]), %% TODO: DEBUG removeme + HookModules = discover_static_hooks(startup_hook), lists:foreach( fun ({Phase, Msg, Thunk}) -> io:format("starting ~-20s ...", [Msg]), - ok = run_hooks(HookModules, startup_hook, {pre, Phase}), + ok = run_static_hooks(HookModules, startup_hook, {pre, Phase}), Thunk(), - ok = run_hooks(HookModules, startup_hook, {post, Phase}), + ok = run_static_hooks(HookModules, startup_hook, {post, Phase}), io:format("done~n"); ({Phase, Msg, M, F, A}) -> io:format("starting ~-20s ...", [Msg]), - ok = run_hooks(HookModules, startup_hook, {pre, Phase}), + ok = run_static_hooks(HookModules, startup_hook, {pre, Phase}), apply(M, F, A), - ok = run_hooks(HookModules, startup_hook, {post, Phase}), + ok = run_static_hooks(HookModules, startup_hook, {post, Phase}), io:format("done~n") end, [{database, "database", @@ -377,15 +376,18 @@ log_rotation_result(ok, {error, SaslLogError}) -> log_rotation_result(ok, ok) -> ok. -discover_hooks(Hook) -> - %% We rely here on the fact that plugins have all their code - %% loaded before rabbit is started, so we will be able to find - %% hook modules by name. - [M || {M, _} <- code:all_loaded(), - ok == io:format("? ~p~n", [M]), %% TODO: DEBUG removeme - case atom_to_list(M) of "rabbit_hook_" ++ _ -> true; _ -> false end, +discover_static_hooks(Hook) -> + %% App files don't let us stick arbitrary keys in, so we do + %% something a bit icky here and go for "convention over + %% configuration", choosing to examine modules with names starting + %% with 'rabbit_static_hook_' to see if they have appropriate + %% exported hook functions. + [M || {App, _, _} <- application:loaded_applications(), + M <- begin {ok, Ms} = application:get_key(App, modules), Ms end, + case atom_to_list(M) of "rabbit_static_hook_" ++ _ -> true; _ -> false end, + {module, M} == code:load_file(M), erlang:function_exported(M, Hook, 1)]. -run_hooks(HookModules, Hook, Event) -> +run_static_hooks(HookModules, Hook, Event) -> _ = [{M, Hook, ok} = {M, Hook, M:Hook(Event)} || M <- HookModules], ok. -- cgit v1.2.1 From 3842a84dd811717628119d172fec5b4ab1cd180f Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 30 Nov 2009 22:50:05 +0000 Subject: Avoid compiler warning about unused term; weirdly, the replaced idiom works elsewhere --- src/rabbit.erl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index b85af6ad..4d6bd009 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -389,5 +389,6 @@ discover_static_hooks(Hook) -> erlang:function_exported(M, Hook, 1)]. run_static_hooks(HookModules, Hook, Event) -> - _ = [{M, Hook, ok} = {M, Hook, M:Hook(Event)} || M <- HookModules], - ok. + ok = lists:foreach(fun (M) -> + {M, Hook, ok} = {M, Hook, M:Hook(Event)} + end, HookModules). -- cgit v1.2.1 From aaba4cd2812af39f63d087373b8442f0c4e4696c Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 14 Dec 2009 17:32:28 +0000 Subject: Add "-rabbit_boot_step" module attribute to specify startup sequence. - The plugin activator prepares the startup plan. - This means that it's no longer going to work to run without a boot script. Consequently, I've added a call to rabbitmq-activate-plugins to the Makefile for the 'all' target. - I've refactored the old boot sequence to use the new method for specifying boot steps. I've conservatively put dependencies forcing them into a straight line, as they were before. - Since the plugin activator runs so frequently, I've made it suppress the (spurious) warnings we get about core beam files being out of date on Ubuntu. --- Makefile | 1 + src/rabbit.erl | 223 ++++++++++++++++++++-------------------- src/rabbit_plugin_activator.erl | 64 +++++++++--- 3 files changed, 167 insertions(+), 121 deletions(-) diff --git a/Makefile b/Makefile index 1cd48df2..f9af1cbe 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,7 @@ 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 4d6bd009..e5507063 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -33,12 +33,36 @@ -behaviour(application). --export([prepare/0, start/0, stop/0, stop_and_halt/0, status/0, rotate_logs/1]). +-export([prepare/0, start/0, finish_boot/1, stop/0, stop_and_halt/0, status/0, rotate_logs/1]). -export([start/2, stop/1]). -export([log_location/1]). +%%--------------------------------------------------------------------------- +%% Boot steps. +-export([boot_database/0, boot_core_processes/0, boot_recovery/0, + boot_persister/0, boot_guid_generator/0, + boot_builtin_applications/0, boot_tcp_listeners/0, + boot_ssl_listeners/0]). + +-rabbit_boot_step({boot_database/0, [{description, "database"}]}). +-rabbit_boot_step({boot_core_processes/0, [{description, "core processes"}, + {post, {?MODULE, boot_database/0}}]}). +-rabbit_boot_step({boot_recovery/0, [{description, "recovery"}, + {post, {?MODULE, boot_core_processes/0}}]}). +-rabbit_boot_step({boot_persister/0, [{description, "persister"}, + {post, {?MODULE, boot_recovery/0}}]}). +-rabbit_boot_step({boot_guid_generator/0, [{description, "guid generator"}, + {post, {?MODULE, boot_persister/0}}]}). +-rabbit_boot_step({boot_builtin_applications/0, [{description, "builtin applications"}, + {post, {?MODULE, boot_guid_generator/0}}]}). +-rabbit_boot_step({boot_tcp_listeners/0, [{description, "TCP listeners"}, + {post, {?MODULE, boot_builtin_applications/0}}]}). +-rabbit_boot_step({boot_ssl_listeners/0, [{description, "SSL listeners"}, + {post, {?MODULE, boot_tcp_listeners/0}}]}). +%%--------------------------------------------------------------------------- + -import(application). -import(mnesia). -import(lists). @@ -59,6 +83,8 @@ -spec(prepare/0 :: () -> 'ok'). -spec(start/0 :: () -> 'ok'). +-spec(finish_boot/1 :: ([any()]) -> 'ok'). +-spec(run_boot_steps/0 :: () -> 'ok'). -spec(stop/0 :: () -> 'ok'). -spec(stop_and_halt/0 :: () -> 'ok'). -spec(rotate_logs/1 :: (file_suffix()) -> 'ok' | {'error', any()}). @@ -115,103 +141,99 @@ rotate_logs(BinarySuffix) -> %%-------------------------------------------------------------------- start(normal, []) -> - - {ok, SupPid} = rabbit_sup:start_link(), + {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, print_banner(), + [ok = run_boot_step(Step) || Step <- BootSteps], + io:format("~nbroker running~n"), + ok. - HookModules = discover_static_hooks(startup_hook), - - lists:foreach( - fun ({Phase, Msg, Thunk}) -> - io:format("starting ~-20s ...", [Msg]), - ok = run_static_hooks(HookModules, startup_hook, {pre, Phase}), - Thunk(), - ok = run_static_hooks(HookModules, startup_hook, {post, Phase}), - io:format("done~n"); - ({Phase, Msg, M, F, A}) -> - io:format("starting ~-20s ...", [Msg]), - ok = run_static_hooks(HookModules, startup_hook, {pre, Phase}), - apply(M, F, A), - ok = run_static_hooks(HookModules, startup_hook, {post, Phase}), - io:format("done~n") - end, - [{database, "database", - fun () -> ok = rabbit_mnesia:init() end}, - {core_processes, "core processes", - fun () -> - ok = start_child(rabbit_log), - ok = rabbit_hooks:start(), - - ok = rabbit_binary_generator: - check_empty_content_body_frame_size(), - - ok = rabbit_alarm:start(), - - {ok, MemoryWatermark} = - application:get_env(vm_memory_high_watermark), - ok = case MemoryWatermark == 0 of - true -> - ok; - false -> - start_child(vm_memory_monitor, [MemoryWatermark]) - end, - - ok = rabbit_amqqueue:start(), - - ok = start_child(rabbit_router), - ok = start_child(rabbit_node_monitor) - end}, - {recovery, "recovery", - fun () -> - ok = maybe_insert_default_data(), - ok = rabbit_exchange:recover(), - ok = rabbit_amqqueue:recover() - end}, - {persister, "persister", - fun () -> - ok = start_child(rabbit_persister) - end}, - {guid_generator, "guid generator", - fun () -> - ok = start_child(rabbit_guid) - end}, - {builtin_applications, "builtin applications", - fun () -> - {ok, DefaultVHost} = application:get_env(default_vhost), - ok = error_logger:add_report_handler( - rabbit_error_logger, [DefaultVHost]), - ok = start_builtin_amq_applications() - end}, - {tcp_listeners, "TCP listeners", - fun () -> - ok = rabbit_networking:start(), - {ok, TcpListeners} = application:get_env(tcp_listeners), - lists:foreach( - fun ({Host, Port}) -> - ok = rabbit_networking:start_tcp_listener(Host, Port) +run_boot_step({ModFunSpec = {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])) end, - TcpListeners) - end}, - {ssl_listeners, "SSL listeners", - fun () -> - case application:get_env(ssl_listeners) of - {ok, []} -> - ok; - {ok, SslListeners} -> - ok = rabbit_misc:start_applications([crypto, ssl]), - - {ok, SslOpts} = application:get_env(ssl_options), - - [rabbit_networking:start_ssl_listener - (Host, Port, SslOpts) || {Host, Port} <- SslListeners], - ok - end - end}]), + 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); + ok -> + io:format("done~n"), + ok + end. - io:format("~nbroker running~n"), +boot_database() -> + ok = rabbit_mnesia:init(). + +boot_core_processes() -> + ok = start_child(rabbit_log), + ok = rabbit_hooks:start(), + + ok = rabbit_binary_generator:check_empty_content_body_frame_size(), + + ok = rabbit_alarm:start(), + + {ok, MemoryWatermark} = application:get_env(vm_memory_high_watermark), + ok = case MemoryWatermark == 0 of + true -> + ok; + false -> + start_child(vm_memory_monitor, [MemoryWatermark]) + end, + + ok = rabbit_amqqueue:start(), + + ok = start_child(rabbit_router), + ok = start_child(rabbit_node_monitor). - {ok, SupPid}. +boot_recovery() -> + ok = maybe_insert_default_data(), + ok = rabbit_exchange:recover(), + ok = rabbit_amqqueue:recover(). + +boot_persister() -> + ok = start_child(rabbit_persister). + +boot_guid_generator() -> + ok = start_child(rabbit_guid). + +boot_builtin_applications() -> + {ok, DefaultVHost} = application:get_env(default_vhost), + ok = error_logger:add_report_handler(rabbit_error_logger, [DefaultVHost]), + ok = start_builtin_amq_applications(). + +boot_tcp_listeners() -> + ok = rabbit_networking:start(), + {ok, TcpListeners} = application:get_env(tcp_listeners), + [ok = rabbit_networking:start_tcp_listener(Host, Port) + || {Host, Port} <- TcpListeners], + ok. + +boot_ssl_listeners() -> + case application:get_env(ssl_listeners) of + {ok, []} -> + ok; + {ok, SslListeners} -> + ok = rabbit_misc:start_applications([crypto, ssl]), + {ok, SslOpts} = application:get_env(ssl_options), + [rabbit_networking:start_ssl_listener(Host, Port, SslOpts) + || {Host, Port} <- SslListeners], + ok + end. stop(_State) -> terminated_ok = error_logger:delete_report_handler(rabbit_error_logger), @@ -375,20 +397,3 @@ log_rotation_result(ok, {error, SaslLogError}) -> {error, {cannot_rotate_sasl_logs, SaslLogError}}; log_rotation_result(ok, ok) -> ok. - -discover_static_hooks(Hook) -> - %% App files don't let us stick arbitrary keys in, so we do - %% something a bit icky here and go for "convention over - %% configuration", choosing to examine modules with names starting - %% with 'rabbit_static_hook_' to see if they have appropriate - %% exported hook functions. - [M || {App, _, _} <- application:loaded_applications(), - M <- begin {ok, Ms} = application:get_key(App, modules), Ms end, - case atom_to_list(M) of "rabbit_static_hook_" ++ _ -> true; _ -> false end, - {module, M} == code:load_file(M), - erlang:function_exported(M, Hook, 1)]. - -run_static_hooks(HookModules, Hook, Event) -> - ok = lists:foreach(fun (M) -> - {M, Hook, ok} = {M, Hook, M:Hook(Event)} - end, HookModules). diff --git a/src/rabbit_plugin_activator.erl b/src/rabbit_plugin_activator.erl index 9f787920..6f6dd2ed 100644 --- a/src/rabbit_plugin_activator.erl +++ b/src/rabbit_plugin_activator.erl @@ -96,12 +96,20 @@ start() -> {ok, Module, Warnings} -> %% This gets lots of spurious no-source warnings when we %% have .ez files, so we want to supress them to prevent - %% hiding real issues. + %% hiding real issues. On Ubuntu, we also get warnings + %% about kernel/stdlib sources being out of date, which we + %% also ignore for the same reason. WarningStr = Module:format_warning( [W || W <- Warnings, case W of {warning, {source_not_found, _}} -> false; - _ -> true + {warning, {obj_out_of_date, {_,_,WApp,_,_}}} + when WApp == mnesia; + WApp == stdlib; + WApp == kernel; + WApp == sasl; + WApp == os_mon -> false; + _ -> true end]), case length(WarningStr) of 0 -> ok; @@ -113,7 +121,7 @@ start() -> [ScriptFile, Module:format_error(Error)]) end, - case post_process_script(ScriptFile) of + case post_process_script(ScriptFile, boot_steps(AllApps)) of ok -> ok; {error, Reason} -> error("post processing of boot script file ~s failed:~n~w", @@ -140,6 +148,37 @@ 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(), + [digraph:add_vertex(G, ModFunSpec, Step) || Step = {ModFunSpec, _Attrs} <- UnsortedSteps], + lists:foreach(fun ({ModFunSpec, Attributes}) -> + [digraph:add_edge(G, ModFunSpec, PostModFunSpec) + || {post, PostModFunSpec} <- Attributes], + [digraph:add_edge(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), + SortedSteps. + assert_dir(Dir) -> case filelib:is_dir(Dir) of true -> ok; @@ -219,10 +258,12 @@ expand_dependencies(Current, [Next|Rest]) -> expand_dependencies(sets:add_element(Next, Current), Rest ++ Unique) end. -post_process_script(ScriptFile) -> +post_process_script(ScriptFile, BootSteps) -> case file:consult(ScriptFile) of {ok, [{script, Name, Entries}]} -> - NewEntries = process_entries(Entries), + NewEntries = lists:flatmap(fun (Entry) -> + process_entry(Entry, BootSteps) + end, Entries), case file:open(ScriptFile, [write]) of {ok, Fd} -> io:format(Fd, "%% script generated at ~w ~w~n~p.~n", @@ -236,13 +277,12 @@ post_process_script(ScriptFile) -> {error, {failed_to_load_script, Reason}} end. -process_entries([]) -> - []; -process_entries([Entry = {apply,{application,start_boot,[stdlib,permanent]}} | - Rest]) -> - [Entry, {apply,{rabbit,prepare,[]}} | Rest]; -process_entries([Entry|Rest]) -> - [Entry | process_entries(Rest)]. +process_entry(Entry = {apply,{application,start_boot,[stdlib,permanent]}}, _BootSteps) -> + [Entry, {apply,{rabbit,prepare,[]}}]; +process_entry(Entry = {progress, started}, BootSteps) -> + [{apply,{rabbit,finish_boot,[BootSteps]}}, Entry]; +process_entry(Entry, _BootSteps) -> + [Entry]. error(Fmt, Args) -> io:format("ERROR: " ++ Fmt ++ "~n", Args), -- cgit v1.2.1 From 3bddf43fcd9f52e5f0d7d66f2a39d458bd739de7 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 14 Dec 2009 17:38:01 +0000 Subject: Fixup specs. --- src/rabbit.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index e5507063..78bf7e38 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -80,11 +80,11 @@ -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 :: ([any()]) -> 'ok'). --spec(run_boot_steps/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()}). -- cgit v1.2.1 From 9b9bc357ab121d268e06ca317537091fe230de79 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 14 Dec 2009 18:31:30 +0000 Subject: Enforce acyclicity; check presence and export of steps. --- src/rabbit_plugin_activator.erl | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/rabbit_plugin_activator.erl b/src/rabbit_plugin_activator.erl index 6f6dd2ed..8bf16bec 100644 --- a/src/rabbit_plugin_activator.erl +++ b/src/rabbit_plugin_activator.erl @@ -163,12 +163,12 @@ boot_steps(AllApps) -> sort_boot_steps(UnsortedSteps). sort_boot_steps(UnsortedSteps) -> - G = digraph:new(), + G = digraph:new([acyclic]), [digraph:add_vertex(G, ModFunSpec, Step) || Step = {ModFunSpec, _Attrs} <- UnsortedSteps], lists:foreach(fun ({ModFunSpec, Attributes}) -> - [digraph:add_edge(G, ModFunSpec, PostModFunSpec) + [add_boot_step_dep(G, ModFunSpec, PostModFunSpec) || {post, PostModFunSpec} <- Attributes], - [digraph:add_edge(G, PreModFunSpec, ModFunSpec) + [add_boot_step_dep(G, PreModFunSpec, ModFunSpec) || {pre, PreModFunSpec} <- Attributes] end, UnsortedSteps), SortedStepsRev = [begin @@ -177,7 +177,39 @@ sort_boot_steps(UnsortedSteps) -> end || ModFunSpec <- digraph_utils:topsort(G)], SortedSteps = lists:reverse(SortedStepsRev), digraph:delete(G), - SortedSteps. + 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 -- cgit v1.2.1 From fa6b56dbba4f507dc643a6c872731aa2c9dc770b Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 14 Dec 2009 21:45:31 +0000 Subject: Move planning code out of activator and into rabbit proper. --- Makefile | 1 - src/rabbit.erl | 120 ++++++++++++++++++++++++++++++---------- src/rabbit_plugin_activator.erl | 77 ++------------------------ 3 files changed, 95 insertions(+), 103 deletions(-) diff --git a/Makefile b/Makefile index f9af1cbe..1cd48df2 100644 --- a/Makefile +++ b/Makefile @@ -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) -> -- cgit v1.2.1 From 0071c71cbd967a161a8eddcf0b4c3a517457aa76 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 14 Dec 2009 22:27:17 +0000 Subject: Switch to explicit MFA, and symbolic boot step names. Add comments to sort_boot_steps. Reject duplicate boot step names. --- src/rabbit.erl | 125 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index dd5f221a..a78806fd 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -46,21 +46,26 @@ boot_builtin_applications/0, boot_tcp_listeners/0, boot_ssl_listeners/0]). --rabbit_boot_step({boot_database/0, [{description, "database"}]}). --rabbit_boot_step({boot_core_processes/0, [{description, "core processes"}, - {post, {?MODULE, boot_database/0}}]}). --rabbit_boot_step({boot_recovery/0, [{description, "recovery"}, - {post, {?MODULE, boot_core_processes/0}}]}). --rabbit_boot_step({boot_persister/0, [{description, "persister"}, - {post, {?MODULE, boot_recovery/0}}]}). --rabbit_boot_step({boot_guid_generator/0, [{description, "guid generator"}, - {post, {?MODULE, boot_persister/0}}]}). --rabbit_boot_step({boot_builtin_applications/0, [{description, "builtin applications"}, - {post, {?MODULE, boot_guid_generator/0}}]}). --rabbit_boot_step({boot_tcp_listeners/0, [{description, "TCP listeners"}, - {post, {?MODULE, boot_builtin_applications/0}}]}). --rabbit_boot_step({boot_ssl_listeners/0, [{description, "SSL listeners"}, - {post, {?MODULE, boot_tcp_listeners/0}}]}). +-rabbit_boot_step({database, [{mfa, {?MODULE, boot_database, []}}]}). +-rabbit_boot_step({core_processes, [{description, "core processes"}, + {mfa, {?MODULE, boot_core_processes, []}}, + {post, database}]}). +-rabbit_boot_step({recovery, [{mfa, {?MODULE, boot_recovery, []}}, + {post, core_processes}]}). +-rabbit_boot_step({persister, [{mfa, {?MODULE, boot_persister, []}}, + {post, recovery}]}). +-rabbit_boot_step({guid_generator, [{description, "guid generator"}, + {mfa, {?MODULE, boot_guid_generator, []}}, + {post, persister}]}). +-rabbit_boot_step({builtin_applications, [{description, "builtin applications"}, + {mfa, {?MODULE, boot_builtin_applications, []}}, + {post, guid_generator}]}). +-rabbit_boot_step({tcp_listeners, [{description, "TCP listeners"}, + {mfa, {?MODULE, boot_tcp_listeners, []}}, + {post, builtin_applications}]}). +-rabbit_boot_step({ssl_listeners, [{description, "SSL listeners"}, + {mfa, {?MODULE, boot_ssl_listeners, []}}, + {post, tcp_listeners}]}). %%--------------------------------------------------------------------------- -import(application). @@ -160,21 +165,25 @@ stop(_State) -> %%--------------------------------------------------------------------------- boot_error(Format, Args) -> - io:format(Format, Args), + io:format("BOOT ERROR: " ++ Format, Args), error_logger:error_msg(Format, Args), timer:sleep(1000), exit({?MODULE, failure_during_boot}). -run_boot_step({{Module, {Fun, 0}}, Attributes}) -> +run_boot_step({StepName, Attributes}) -> Description = case lists:keysearch(description, 1, Attributes) of {value, {_, D}} -> D; - false -> lists:flatten(io_lib:format("~w:~w", [Module, Fun])) + false -> StepName end, - io:format("starting ~-20s ...", [Description]), - case catch Module:Fun() of - {'EXIT', Reason} -> - boot_error("FAILED~nReason: ~p~n", [Reason]); - ok -> + case [MFA || {mfa, MFA} <- Attributes] of + [] -> + io:format("progress: ~s~n", [Description]); + MFAs -> + io:format("starting: ~-20s ...", [Description]), + [case catch apply(M,F,A) of + {'EXIT', Reason} -> boot_error("FAILED~nReason: ~p~n", [Reason]); + ok -> ok + end || {M,F,A} <- MFAs], io:format("done~n"), ok end. @@ -187,62 +196,66 @@ boot_steps() -> || App <- AllApps]])), UnsortedSteps = lists:flatmap(fun (Module) -> - [{{Module, FunSpec}, Attributes} - || {rabbit_boot_step, [{FunSpec, Attributes}]} + [{StepName, Attributes} + || {rabbit_boot_step, [{StepName, 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] + + %% Add vertices, with duplicate checking. + [case digraph:vertex(G, StepName) of + false -> digraph:add_vertex(G, StepName, Step); + _ -> boot_error("Duplicate boot step name: ~w~n", [StepName]) + end || Step = {StepName, _Attrs} <- UnsortedSteps], + + %% Add edges, detecting cycles and missing vertices. + lists:foreach(fun ({StepName, Attributes}) -> + [add_boot_step_dep(G, StepName, PrecedingStepName) + || {post, PrecedingStepName} <- Attributes], + [add_boot_step_dep(G, SucceedingStepName, StepName) + || {pre, SucceedingStepName} <- Attributes] end, UnsortedSteps), + + %% Use topological sort to find a consistent ordering (if there is + %% one, otherwise fail). SortedStepsRev = [begin - {ModFunSpec, Step} = digraph:vertex(G, ModFunSpec), + {StepName, Step} = digraph:vertex(G, StepName), Step - end || ModFunSpec <- digraph_utils:topsort(G)], + end || StepName <- digraph_utils:topsort(G)], SortedSteps = lists:reverse(SortedStepsRev), + digraph:delete(G), - check_boot_steps(SortedSteps). + + %% Check that all mentioned {M,F,A} triples are exported. + case [{StepName, {M,F,A}} || {StepName, Attributes} <- SortedSteps, + {mfa, {M,F,A}} <- Attributes, + not erlang:function_exported(M, F, length(A))] of + [] -> + SortedSteps; + MissingFunctions -> + boot_error("Boot step functions not exported: ~p~n", [MissingFunctions]) + end. 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), + boot_error("Could not add boot step dependency of ~w on ~w:~n~s", + [RunsSecond, RunsFirst, case Reason of {bad_vertex, V} -> - io_lib:format("Boot step not registered: ~s~n", - [format_modfunspec(V)]); + io_lib:format("Boot step not registered: ~w~n", [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)])] + [io_lib:format("Cyclic dependency: ~w", [First]), + [io_lib:format(" depends on ~w", [Next]) || Next <- Rest], + io_lib:format(" depends on ~w~n", [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() -> -- cgit v1.2.1 From 0a3b29bf58fd14900dacf1126436b23fdd2428c3 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Mon, 14 Dec 2009 22:55:00 +0000 Subject: Split up and tweak startup order. --- src/rabbit.erl | 81 ++++++++++++++++++--------------------------- src/rabbit_error_logger.erl | 6 ++++ src/rabbit_sup.erl | 11 +++++- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index a78806fd..3665c4c1 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -41,31 +41,43 @@ %%--------------------------------------------------------------------------- %% Boot steps. --export([boot_database/0, boot_core_processes/0, boot_recovery/0, - boot_persister/0, boot_guid_generator/0, - boot_builtin_applications/0, boot_tcp_listeners/0, +-export([boot_core_processes/0, + boot_recovery/0, + boot_tcp_listeners/0, boot_ssl_listeners/0]). --rabbit_boot_step({database, [{mfa, {?MODULE, boot_database, []}}]}). +-rabbit_boot_step({database, [{mfa, {rabbit_mnesia, init, []}}]}). -rabbit_boot_step({core_processes, [{description, "core processes"}, {mfa, {?MODULE, boot_core_processes, []}}, - {post, database}]}). + {post, database}, + {pre, core_initialized}]}). +-rabbit_boot_step({core_initialized, [{description, "core initialized"}]}). + -rabbit_boot_step({recovery, [{mfa, {?MODULE, boot_recovery, []}}, - {post, core_processes}]}). --rabbit_boot_step({persister, [{mfa, {?MODULE, boot_persister, []}}, + {post, core_initialized}]}). +-rabbit_boot_step({persister, [{mfa, {rabbit_sup, start_child, [rabbit_persister]}}, {post, recovery}]}). -rabbit_boot_step({guid_generator, [{description, "guid generator"}, - {mfa, {?MODULE, boot_guid_generator, []}}, - {post, persister}]}). --rabbit_boot_step({builtin_applications, [{description, "builtin applications"}, - {mfa, {?MODULE, boot_builtin_applications, []}}, - {post, guid_generator}]}). + {mfa, {rabbit_sup, start_child, [rabbit_guid]}}, + {post, persister}, + {pre, routing_ready}]}). +-rabbit_boot_step({routing_ready, [{description, "message delivery logic ready"}]}). + +-rabbit_boot_step({log_relay, [{description, "error log relay"}, + {mfa, {rabbit_error_logger, boot, []}}, + {post, routing_ready}]}). + -rabbit_boot_step({tcp_listeners, [{description, "TCP listeners"}, {mfa, {?MODULE, boot_tcp_listeners, []}}, - {post, builtin_applications}]}). + {post, log_relay}, + {pre, networking_listening}]}). -rabbit_boot_step({ssl_listeners, [{description, "SSL listeners"}, {mfa, {?MODULE, boot_ssl_listeners, []}}, - {post, tcp_listeners}]}). + {post, tcp_listeners}, + {pre, networking_listening}]}). + +-rabbit_boot_step({networking_listening, [{description, "network listeners available"}]}). + %%--------------------------------------------------------------------------- -import(application). @@ -177,9 +189,9 @@ run_boot_step({StepName, Attributes}) -> end, case [MFA || {mfa, MFA} <- Attributes] of [] -> - io:format("progress: ~s~n", [Description]); + io:format("progress -- ~s~n", [Description]); MFAs -> - io:format("starting: ~-20s ...", [Description]), + io:format("starting ~-20s ...", [Description]), [case catch apply(M,F,A) of {'EXIT', Reason} -> boot_error("FAILED~nReason: ~p~n", [Reason]); ok -> ok @@ -258,11 +270,8 @@ add_boot_step_dep(G, RunsSecond, RunsFirst) -> %%--------------------------------------------------------------------------- -boot_database() -> - ok = rabbit_mnesia:init(). - boot_core_processes() -> - ok = start_child(rabbit_log), + ok = rabbit_sup:start_child(rabbit_log), ok = rabbit_hooks:start(), ok = rabbit_binary_generator:check_empty_content_body_frame_size(), @@ -274,30 +283,19 @@ boot_core_processes() -> true -> ok; false -> - start_child(vm_memory_monitor, [MemoryWatermark]) + rabbit_sup:start_child(vm_memory_monitor, [MemoryWatermark]) end, ok = rabbit_amqqueue:start(), - ok = start_child(rabbit_router), - ok = start_child(rabbit_node_monitor). + ok = rabbit_sup:start_child(rabbit_router), + ok = rabbit_sup:start_child(rabbit_node_monitor). boot_recovery() -> ok = maybe_insert_default_data(), ok = rabbit_exchange:recover(), ok = rabbit_amqqueue:recover(). -boot_persister() -> - ok = start_child(rabbit_persister). - -boot_guid_generator() -> - ok = start_child(rabbit_guid). - -boot_builtin_applications() -> - {ok, DefaultVHost} = application:get_env(default_vhost), - ok = error_logger:add_report_handler(rabbit_error_logger, [DefaultVHost]), - ok = start_builtin_amq_applications(). - boot_tcp_listeners() -> ok = rabbit_networking:start(), {ok, TcpListeners} = application:get_env(tcp_listeners), @@ -376,15 +374,6 @@ print_banner() -> lists:foreach(fun ({K, V}) -> io:format(Format, [K, V]) end, Settings), io:nl(). -start_child(Mod) -> - start_child(Mod, []). - -start_child(Mod, Args) -> - {ok,_} = supervisor:start_child(rabbit_sup, - {Mod, {Mod, start_link, Args}, - transient, 100, worker, [Mod]}), - ok. - ensure_working_log_handlers() -> Handlers = gen_event:which_handlers(error_logger), ok = ensure_working_log_handler(error_logger_file_h, @@ -442,12 +431,6 @@ insert_default_data() -> DefaultReadPerm), ok. -start_builtin_amq_applications() -> - %%TODO: we may want to create a separate supervisor for these so - %%they don't bring down the entire app when they die and fail to - %%restart - ok. - rotate_logs(File, Suffix, Handler) -> rotate_logs(File, Suffix, Handler, Handler). diff --git a/src/rabbit_error_logger.erl b/src/rabbit_error_logger.erl index 297ed5aa..9651ae12 100644 --- a/src/rabbit_error_logger.erl +++ b/src/rabbit_error_logger.erl @@ -37,8 +37,14 @@ -behaviour(gen_event). +-export([boot/0]). + -export([init/1, terminate/2, code_change/3, handle_call/2, handle_event/2, handle_info/2]). +boot() -> + {ok, DefaultVHost} = application:get_env(default_vhost), + ok = error_logger:add_report_handler(?MODULE, [DefaultVHost]). + init([DefaultVHost]) -> #exchange{} = rabbit_exchange:declare( rabbit_misc:r(DefaultVHost, exchange, ?LOG_EXCH_NAME), diff --git a/src/rabbit_sup.erl b/src/rabbit_sup.erl index 730d7909..ef32544c 100644 --- a/src/rabbit_sup.erl +++ b/src/rabbit_sup.erl @@ -33,7 +33,7 @@ -behaviour(supervisor). --export([start_link/0]). +-export([start_link/0, start_child/1, start_child/2]). -export([init/1]). @@ -42,5 +42,14 @@ start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). +start_child(Mod) -> + start_child(Mod, []). + +start_child(Mod, Args) -> + {ok, _} = supervisor:start_child(?SERVER, + {Mod, {Mod, start_link, Args}, + transient, 100, worker, [Mod]}), + ok. + init([]) -> {ok, {{one_for_one, 10, 10}, []}}. -- cgit v1.2.1 From 6e96d66ff58d2363a37368003f64a4c4082b91a1 Mon Sep 17 00:00:00 2001 From: Matthew Sackman Date: Wed, 16 Dec 2009 17:25:08 +0000 Subject: cosmetics (mainly line length, alignment and trailing WS) --- src/rabbit.erl | 117 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 48 deletions(-) diff --git a/src/rabbit.erl b/src/rabbit.erl index 3665c4c1..24c4622f 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -46,37 +46,54 @@ boot_tcp_listeners/0, boot_ssl_listeners/0]). --rabbit_boot_step({database, [{mfa, {rabbit_mnesia, init, []}}]}). --rabbit_boot_step({core_processes, [{description, "core processes"}, - {mfa, {?MODULE, boot_core_processes, []}}, - {post, database}, - {pre, core_initialized}]}). --rabbit_boot_step({core_initialized, [{description, "core initialized"}]}). - --rabbit_boot_step({recovery, [{mfa, {?MODULE, boot_recovery, []}}, - {post, core_initialized}]}). --rabbit_boot_step({persister, [{mfa, {rabbit_sup, start_child, [rabbit_persister]}}, - {post, recovery}]}). --rabbit_boot_step({guid_generator, [{description, "guid generator"}, - {mfa, {rabbit_sup, start_child, [rabbit_guid]}}, - {post, persister}, - {pre, routing_ready}]}). --rabbit_boot_step({routing_ready, [{description, "message delivery logic ready"}]}). - --rabbit_boot_step({log_relay, [{description, "error log relay"}, - {mfa, {rabbit_error_logger, boot, []}}, - {post, routing_ready}]}). - --rabbit_boot_step({tcp_listeners, [{description, "TCP listeners"}, - {mfa, {?MODULE, boot_tcp_listeners, []}}, - {post, log_relay}, - {pre, networking_listening}]}). --rabbit_boot_step({ssl_listeners, [{description, "SSL listeners"}, - {mfa, {?MODULE, boot_ssl_listeners, []}}, - {post, tcp_listeners}, - {pre, networking_listening}]}). - --rabbit_boot_step({networking_listening, [{description, "network listeners available"}]}). +-rabbit_boot_step({database, + [{mfa, {rabbit_mnesia, init, []}}]}). + +-rabbit_boot_step({core_processes, + [{description, "core processes"}, + {mfa, {?MODULE, boot_core_processes, []}}, + {post, database}, + {pre, core_initialized}]}). + +-rabbit_boot_step({core_initialized, + [{description, "core initialized"}]}). + +-rabbit_boot_step({recovery, + [{mfa, {?MODULE, boot_recovery, []}}, + {post, core_initialized}]}). + +-rabbit_boot_step({persister, + [{mfa, {rabbit_sup, start_child, [rabbit_persister]}}, + {post, recovery}]}). + +-rabbit_boot_step({guid_generator, + [{description, "guid generator"}, + {mfa, {rabbit_sup, start_child, [rabbit_guid]}}, + {post, persister}, + {pre, routing_ready}]}). + +-rabbit_boot_step({routing_ready, + [{description, "message delivery logic ready"}]}). + +-rabbit_boot_step({log_relay, + [{description, "error log relay"}, + {mfa, {rabbit_error_logger, boot, []}}, + {post, routing_ready}]}). + +-rabbit_boot_step({tcp_listeners, + [{description, "TCP listeners"}, + {mfa, {?MODULE, boot_tcp_listeners, []}}, + {post, log_relay}, + {pre, networking_listening}]}). + +-rabbit_boot_step({ssl_listeners, + [{description, "SSL listeners"}, + {mfa, {?MODULE, boot_ssl_listeners, []}}, + {post, tcp_listeners}, + {pre, networking_listening}]}). + +-rabbit_boot_step({networking_listening, + [{description, "network listeners available"}]}). %%--------------------------------------------------------------------------- @@ -120,7 +137,7 @@ prepare() -> start() -> try ok = prepare(), - ok = rabbit_misc:start_applications(?APPS) + ok = rabbit_misc:start_applications(?APPS) after %%give the error loggers some time to catch up timer:sleep(100) @@ -185,7 +202,7 @@ boot_error(Format, Args) -> run_boot_step({StepName, Attributes}) -> Description = case lists:keysearch(description, 1, Attributes) of {value, {_, D}} -> D; - false -> StepName + false -> StepName end, case [MFA || {mfa, MFA} <- Attributes] of [] -> @@ -193,8 +210,10 @@ run_boot_step({StepName, Attributes}) -> MFAs -> io:format("starting ~-20s ...", [Description]), [case catch apply(M,F,A) of - {'EXIT', Reason} -> boot_error("FAILED~nReason: ~p~n", [Reason]); - ok -> ok + {'EXIT', Reason} -> + boot_error("FAILED~nReason: ~p~n", [Reason]); + ok -> + ok end || {M,F,A} <- MFAs], io:format("done~n"), ok @@ -204,8 +223,9 @@ boot_steps() -> AllApps = [App || {App, _, _} <- application:loaded_applications()], Modules = lists:usort( lists:append([Modules - || {ok, Modules} <- [application:get_key(App, modules) - || App <- AllApps]])), + || {ok, Modules} <- + [application:get_key(App, modules) + || App <- AllApps]])), UnsortedSteps = lists:flatmap(fun (Module) -> [{StepName, Attributes} @@ -220,7 +240,7 @@ sort_boot_steps(UnsortedSteps) -> %% Add vertices, with duplicate checking. [case digraph:vertex(G, StepName) of false -> digraph:add_vertex(G, StepName, Step); - _ -> boot_error("Duplicate boot step name: ~w~n", [StepName]) + _ -> boot_error("Duplicate boot step name: ~w~n", [StepName]) end || Step = {StepName, _Attrs} <- UnsortedSteps], %% Add edges, detecting cycles and missing vertices. @@ -242,13 +262,13 @@ sort_boot_steps(UnsortedSteps) -> digraph:delete(G), %% Check that all mentioned {M,F,A} triples are exported. - case [{StepName, {M,F,A}} || {StepName, Attributes} <- SortedSteps, - {mfa, {M,F,A}} <- Attributes, - not erlang:function_exported(M, F, length(A))] of - [] -> - SortedSteps; - MissingFunctions -> - boot_error("Boot step functions not exported: ~p~n", [MissingFunctions]) + case [{StepName, {M,F,A}} + || {StepName, Attributes} <- SortedSteps, + {mfa, {M,F,A}} <- Attributes, + not erlang:function_exported(M, F, length(A))] of + [] -> SortedSteps; + MissingFunctions -> boot_error("Boot step functions not exported: ~p~n", + [MissingFunctions]) end. add_boot_step_dep(G, RunsSecond, RunsFirst) -> @@ -261,7 +281,8 @@ add_boot_step_dep(G, RunsSecond, RunsFirst) -> io_lib:format("Boot step not registered: ~w~n", [V]); {bad_edge, [First | Rest]} -> [io_lib:format("Cyclic dependency: ~w", [First]), - [io_lib:format(" depends on ~w", [Next]) || Next <- Rest], + [io_lib:format(" depends on ~w", [Next]) + || Next <- Rest], io_lib:format(" depends on ~w~n", [First])] end]); _ -> @@ -318,7 +339,7 @@ boot_ssl_listeners() -> %--------------------------------------------------------------------------- log_location(Type) -> - case application:get_env(Type, case Type of + case application:get_env(Type, case Type of kernel -> error_logger; sasl -> sasl_error_logger end) of @@ -399,7 +420,7 @@ ensure_working_log_handler(OldFHandler, NewFHandler, TTYHandler, throw({error, {cannot_log_to_tty, TTYHandler, not_installed}}) end; - _ -> case lists:member(NewFHandler, Handlers) of + _ -> case lists:member(NewFHandler, Handlers) of true -> ok; false -> case rotate_logs(LogLocation, "", OldFHandler, NewFHandler) of -- cgit v1.2.1