diff options
| author | Tim Watson <watson.timothy@gmail.com> | 2013-11-20 12:13:05 +0000 |
|---|---|---|
| committer | Tim Watson <watson.timothy@gmail.com> | 2013-11-20 12:13:05 +0000 |
| commit | bc371b7de17216b213ac3ef3638b42d31fcc7b79 (patch) | |
| tree | c8ccb6a04efc835a5d59467449ca4b87be2598d6 /src | |
| parent | 3f557dc14fc766f50e371a469aa092767acb98e3 (diff) | |
| download | rabbitmq-server-git-bc371b7de17216b213ac3ef3638b42d31fcc7b79.tar.gz | |
Various boot procedure improvements
We ensure that all dependent applications are stopped, but also that
dependencies shared by multiple applications (e.g., amqp_client) are
not.
Diffstat (limited to 'src')
| -rw-r--r-- | src/app_utils.erl | 36 | ||||
| -rw-r--r-- | src/rabbit.erl | 10 | ||||
| -rw-r--r-- | src/rabbit_boot.erl | 47 | ||||
| -rw-r--r-- | src/rabbit_misc.erl | 35 |
4 files changed, 91 insertions, 37 deletions
diff --git a/src/app_utils.erl b/src/app_utils.erl index 1231ea586a..d08dfe6a5a 100644 --- a/src/app_utils.erl +++ b/src/app_utils.erl @@ -18,6 +18,7 @@ -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([direct_dependencies/1]). -ifdef(use_specs). @@ -31,6 +32,7 @@ -spec wait_for_applications([atom()]) -> 'ok'. -spec app_dependency_order([atom()], boolean()) -> [digraph:vertex()]. -spec app_dependencies(atom()) -> [atom()]. +-spec direct_dependencies(atom()) -> [atom()]. -endif. @@ -75,6 +77,40 @@ stop_applications(Apps, ErrorHandler) -> wait_for_applications(Apps) -> [wait_for_application(App) || App <- Apps], ok. +direct_dependencies(Root) -> + G = digraph:new(), + Loaded = application:loaded_applications(), + try + [begin + case digraph:vertex(G, App) of + false -> digraph:add_vertex(G, App, App); + _ -> ok = throw({graph_error, {vertex, duplicate, App}}) + end + end || {App, _, _} <- Loaded], + [digraph:add_edge(G, App, Dep) || + {App, Deps} <- [{App, app_dependencies(App)} || + {App, _Desc, _Vsn} <- Loaded], + Dep <- Deps], + 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(sets:del_element(rabbit, Deps)) + catch {graph_error, Reason} -> + {error, Reason} + 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, diff --git a/src/rabbit.erl b/src/rabbit.erl index 74efbf22d7..44cd275d3b 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -457,12 +457,12 @@ maybe_insert_default_data() -> end. insert_default_data() -> - {ok, DefaultUser} = application:get_env(default_user), - {ok, DefaultPass} = application:get_env(default_pass), - {ok, DefaultTags} = application:get_env(default_user_tags), - {ok, DefaultVHost} = application:get_env(default_vhost), + {ok, DefaultUser} = application:get_env(rabbit, default_user), + {ok, DefaultPass} = application:get_env(rabbit, default_pass), + {ok, DefaultTags} = application:get_env(rabbit, default_user_tags), + {ok, DefaultVHost} = application:get_env(rabbit, default_vhost), {ok, [DefaultConfigurePerm, DefaultWritePerm, DefaultReadPerm]} = - application:get_env(default_permissions), + application:get_env(rabbit, default_permissions), ok = rabbit_vhost:add(DefaultVHost), ok = rabbit_auth_backend_internal:add_user(DefaultUser, DefaultPass), ok = rabbit_auth_backend_internal:set_tags(DefaultUser, DefaultTags), diff --git a/src/rabbit_boot.erl b/src/rabbit_boot.erl index 58361e2641..af2bc9c406 100644 --- a/src/rabbit_boot.erl +++ b/src/rabbit_boot.erl @@ -63,7 +63,8 @@ shutdown(Apps) -> undefined -> ok; _ -> await_startup(Apps) end, - rabbit_log:info("Stopping RabbitMQ~n"), + %% TODO: put this back in somewhere sensible... + %% rabbit_log:info("Stopping RabbitMQ~n"), ok = app_utils:stop_applications(Apps) after delete_boot_table() @@ -82,35 +83,32 @@ start(Apps) -> stop(Apps) -> ensure_boot_table(), - TargetApps = lists:usort([app_utils:app_dependency_order(App, true) || - InitApp <- Apps, - App <- app_utils:app_dependencies(InitApp)]), - Ineligible = lists:usort( - app_utils:app_dependency_order( - [App || App <- app_utils:running_applications(), - not lists:member(App, Apps)], - true) ++ [rabbit]), - ShutdownApps = TargetApps -- Ineligible, - io:format("Shutdown apps = ~p~n", [ShutdownApps]), + TargetApps = + lists:usort( + lists:append([app_utils:direct_dependencies(App) || App <- Apps])), try ok = app_utils:stop_applications( - ShutdownApps, handle_app_error(error_during_shutdown)) + TargetApps, handle_app_error(error_during_shutdown)) after - [run_steps(App, rabbit_cleanup_step) || App <- ShutdownApps] + try + [run_steps(App, rabbit_cleanup_step) || App <- TargetApps] + after + save_boot_table() + end end. run_boot_steps(App) -> run_steps(App, rabbit_boot_step). run_steps(App, StepType) -> - RootApps = app_utils:app_dependencies(App), - Steps = + RootApps = [App|app_utils:direct_dependencies(App)], + StepAttrs = rabbit_misc:all_app_module_attributes(StepType), + BootSteps = sort_boot_steps( - lists:usort( - lists:append( - [rabbit_misc:all_module_attributes(A, StepType) || - A <- [App|RootApps]]))), - [ok = run_boot_step(Step, StepType) || Step <- Steps], + lists:usort( + [{Mod, Steps} || {AppName, Mod, Steps} <- StepAttrs, + lists:member(AppName, RootApps)])), + [ok = run_boot_step(Step, StepType) || Step <- BootSteps], ok. boot_error(Term={error, {timeout_waiting_for_tables, _}}, _Stacktrace) -> @@ -165,8 +163,13 @@ clean_table() -> ets:new(?MODULE, [named_table, public, ordered_set]). load_table() -> - {ok, _Tab} = ets:file2tab(boot_file(), [{verify, true}]), - ok. + case ets:file2tab(boot_file(), [{verify, true}]) of + {error, _} -> error(fuck); + {ok, _Tab} -> ok, + io:format("Starting with pre-loaded boot table:~n~p~n" + "----------------~n", + [ets:tab2list(?MODULE)]) + end. save_boot_table() -> delete_boot_table(), diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 0fa3190a69..3f5bee55d7 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -51,8 +51,8 @@ -export([dict_cons/3, orddict_cons/3, gb_trees_cons/3]). -export([gb_trees_fold/3, gb_trees_foreach/2]). -export([parse_arguments/3]). --export([all_module_attributes/1, all_module_attributes/2]). --export([build_acyclic_graph/3]). +-export([all_app_module_attributes/1]). +-export([all_module_attributes/1, build_acyclic_graph/3]). -export([now_ms/0]). -export([const_ok/0, const/1]). -export([ntoa/1, ntoab/1]). @@ -210,7 +210,6 @@ -> {'ok', {atom(), [{string(), string()}], [string()]}} | 'no_command'). -spec(all_module_attributes/1 :: (atom()) -> [{atom(), [term()]}]). --spec(all_module_attributes/2 :: (atom(), atom()) -> [{atom(), [term()]}]). -spec(build_acyclic_graph/3 :: (graph_vertex_fun(), graph_edge_fun(), [{atom(), [term()]}]) -> rabbit_types:ok_or_error2(digraph(), @@ -852,21 +851,37 @@ module_attributes(Module) -> V end. -all_module_attributes(App, Name) -> - {ok, Modules} = application:get_key(App, modules), +all_app_module_attributes(Name) -> + Modules = + lists:usort( + lists:flatten( + [{App, Module} || + {App, _, _} <- application:loaded_applications(), + {ok, Modules} <- [application:get_key(App, modules)], + Module <- Modules])), lists:foldl( - fun (Module, Acc) -> + fun ({App, Module}, Acc) -> case lists:append([Atts || {N, Atts} <- module_attributes(Module), N =:= Name]) of [] -> Acc; - Atts -> [{Module, Atts} | Acc] + Atts -> [{App, Module, Atts} | Acc] end end, [], Modules). all_module_attributes(Name) -> - lists:usort(lists:append( - [all_module_attributes(App, Name) || - {App, _, _} <- application:loaded_applications()])). + Modules = + lists:usort( + lists:append( + [Modules || {App, _, _} <- application:loaded_applications(), + {ok, Modules} <- [application:get_key(App, modules)]])), + lists:foldl( + fun (Module, Acc) -> + case lists:append([Atts || {N, Atts} <- module_attributes(Module), + N =:= Name]) of + [] -> Acc; + Atts -> [{Module, Atts} | Acc] + end + end, [], Modules). build_acyclic_graph(VertexFun, EdgeFun, Graph) -> G = digraph:new([acyclic]), |
