summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/rabbit.erl80
-rw-r--r--src/rabbit_boot.erl86
2 files changed, 111 insertions, 55 deletions
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 562497b326..74efbf22d7 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -305,59 +305,40 @@ ensure_application_loaded() ->
end.
start() ->
- start_it(fun() ->
- %% We do not want to HiPE compile or upgrade
- %% mnesia after just restarting the app
- ok = ensure_application_loaded(),
- ok = ensure_working_log_handlers(),
- rabbit_node_monitor:prepare_cluster_status_files(),
- rabbit_mnesia:check_cluster_consistency(),
- ok = rabbit_boot:start(app_startup_order()),
- ok = log_broker_started(rabbit_plugins:active())
- end).
+ rabbit_boot:boot_with(
+ fun() ->
+ %% We do not want to HiPE compile or upgrade
+ %% mnesia after just restarting the app
+ ok = ensure_application_loaded(),
+ ok = ensure_working_log_handlers(),
+ rabbit_node_monitor:prepare_cluster_status_files(),
+ rabbit_mnesia:check_cluster_consistency(),
+ ok = rabbit_boot:start(app_startup_order()),
+ ok = log_broker_started(rabbit_plugins:active())
+ end).
boot() ->
- start_it(fun() ->
- ok = ensure_application_loaded(),
- Success = maybe_hipe_compile(),
- ok = ensure_working_log_handlers(),
- warn_if_hipe_compilation_failed(Success),
- rabbit_node_monitor:prepare_cluster_status_files(),
- ok = rabbit_upgrade:maybe_upgrade_mnesia(),
- %% It's important that the consistency check happens after
- %% the upgrade, since if we are a secondary node the
- %% primary node will have forgotten us
- rabbit_mnesia:check_cluster_consistency(),
- Plugins = rabbit_plugins:setup(),
- ToBeLoaded = Plugins ++ ?APPS,
- ok = rabbit_boot:start(ToBeLoaded),
- ok = log_broker_started(Plugins)
- end).
-
-start_it(StartFun) ->
- Marker = spawn_link(fun() -> receive stop -> ok end end),
- register(rabbit_boot, Marker),
- try
- StartFun()
- catch
- throw:{could_not_start, _App, _Reason}=Err ->
- rabbit_boot:boot_error(Err, not_available);
- _:Reason ->
- rabbit_boot:boot_error(Reason, erlang:get_stacktrace())
- after
- unlink(Marker),
- Marker ! stop,
- %% give the error loggers some time to catch up
- timer:sleep(100)
- end.
+ rabbit_boot:boot_with(
+ fun() ->
+ ok = ensure_application_loaded(),
+ Success = maybe_hipe_compile(),
+ ok = ensure_working_log_handlers(),
+ warn_if_hipe_compilation_failed(Success),
+ rabbit_node_monitor:prepare_cluster_status_files(),
+ ok = rabbit_upgrade:maybe_upgrade_mnesia(),
+ %% It's important that the consistency check happens after
+ %% the upgrade, since if we are a secondary node the
+ %% primary node will have forgotten us
+ rabbit_mnesia:check_cluster_consistency(),
+ Plugins = rabbit_plugins:setup(),
+ ToBeLoaded = Plugins ++ ?APPS,
+ ok = rabbit_boot:start(ToBeLoaded),
+ ok = log_broker_started(Plugins)
+ end).
stop() ->
- case whereis(rabbit_boot) of
- undefined -> ok;
- _ -> await_startup()
- end,
- rabbit_log:info("Stopping RabbitMQ~n"), %% TODO: move this to boot:stop/1
- ok = app_utils:stop_applications(app_shutdown_order()).
+ rabbit_log:info("Stopping RabbitMQ~n"),
+ rabbit_boot:shutdown(app_shutdown_order()).
stop_and_halt() ->
try
@@ -441,6 +422,7 @@ stop(_State) ->
true -> rabbit_amqqueue:on_node_down(node());
false -> rabbit_table:clear_ram_only_tables()
end,
+ ok = rabbit_boot:shutdown(),
ok.
%%---------------------------------------------------------------------------
diff --git a/src/rabbit_boot.erl b/src/rabbit_boot.erl
index ffc74ca03b..7de74b14d4 100644
--- a/src/rabbit_boot.erl
+++ b/src/rabbit_boot.erl
@@ -16,38 +16,73 @@
-module(rabbit_boot).
+-export([boot_with/1, shutdown/1]).
-export([start/1, stop/1]).
-export([run_boot_steps/1]).
-export([boot_error/2, boot_error/4]).
-ifdef(use_specs).
+-spec(boot_with/1 :: (fun(() -> 'ok')) -> 'ok').
+-spec(shutdown/1 :: ([atom()]) -> 'ok').
-spec(start/1 :: ([atom()]) -> 'ok').
-spec(stop/1 :: ([atom()]) -> 'ok').
-spec(run_boot_steps/1 :: (atom()) -> 'ok').
-spec(boot_error/2 :: (term(), not_available | [tuple()]) -> no_return()).
-spec(boot_error/4 :: (term(), string(), [any()], not_available | [tuple()])
- -> no_return()).
+ -> no_return()).
-endif.
+-define(BOOT_FILE, "boot.info").
+
%%---------------------------------------------------------------------------
%% Public API
+boot_with(StartFun) ->
+ %% TODO: this should be done with monitors, not links, I think
+ Marker = spawn_link(fun() -> receive stop -> ok end end),
+ register(rabbit_boot, Marker),
+ try
+ StartFun()
+ catch
+ throw:{could_not_start, _App, _Reason}=Err ->
+ boot_error(Err, not_available);
+ _:Reason ->
+ boot_error(Reason, erlang:get_stacktrace())
+ after
+ unlink(Marker),
+ Marker ! stop,
+ %% give the error loggers some time to catch up
+ timer:sleep(100)
+ end.
+
+shutdown(Apps) ->
+ try
+ case whereis(rabbit_boot) of
+ undefined -> ok;
+ _ -> await_startup(Apps)
+ end,
+ rabbit_log:info("Stopping RabbitMQ~n"),
+ ok = app_utils:stop_applications(Apps)
+ after
+ delete_boot_table()
+ end.
+
start(Apps) ->
try
- ets:new(boot_steps, [named_table, public, ordered_set]),
+ ensure_boot_table(),
ok = app_utils:load_applications(Apps),
StartupApps = app_utils:app_dependency_order(Apps, false),
ok = app_utils:start_applications(StartupApps,
handle_app_error(could_not_start))
after
- ets:delete(boot_steps)
+ save_boot_table()
end.
stop(Apps) ->
+ %% ensure_boot_table(),
ShutdownApps = app_utils:app_dependency_order(Apps, true),
- io:format("Stopping ~p~n", [ShutdownApps]),
try
ok = app_utils:stop_applications(
ShutdownApps, handle_app_error(error_during_shutdown))
@@ -99,6 +134,45 @@ boot_error(Reason, Fmt, Args, Stacktrace) ->
%%---------------------------------------------------------------------------
%% Private API
+await_startup(Apps) ->
+ app_utils:wait_for_applications(Apps).
+
+delete_boot_table() ->
+ case filelib:is_file(boot_file()) of
+ true -> file:delete(boot_file());
+ false -> ok
+ end.
+
+ensure_boot_table() ->
+ case whereis(?MODULE) of
+ undefined ->
+ case filelib:is_file(boot_file()) of
+ true -> load_table();
+ false -> clean_table()
+ end;
+ _Pid ->
+ clean_table()
+ end.
+
+clean_table() ->
+ ets:new(?MODULE, [named_table, public, ordered_set]).
+
+load_table() ->
+ {ok, _Tab} = ets:file2tab(boot_file(), [{verify, true}]),
+ ok.
+
+save_boot_table() ->
+ delete_boot_table(),
+ case ets:info(?MODULE) of
+ undefined -> ok;
+ _ -> ets:tab2file(?MODULE, boot_file(),
+ [{extended_info, [object_count]}]),
+ ets:delete(?MODULE)
+ end.
+
+boot_file() ->
+ filename:join(rabbit_mnesia:dir(), ?BOOT_FILE).
+
handle_app_error(Term) ->
fun(App, {bad_return, {_MFA, {'EXIT', {ExitReason, _}}}}) ->
throw({Term, App, ExitReason});
@@ -129,10 +203,10 @@ run_it(StepName, Attributes) ->
end.
already_run(StepName) ->
- ets:member(boot_steps, StepName).
+ ets:member(?MODULE, StepName).
mark_complete(StepName) ->
- ets:insert(boot_steps, {StepName}).
+ ets:insert(?MODULE, {StepName}).
basic_boot_error(Reason, Format, Args) ->
io:format("~n~nBOOT FAILED~n===========~n~n" ++ Format, Args),