diff options
author | Tim Watson <tim.watson@gmail.com> | 2012-05-03 18:51:57 +0100 |
---|---|---|
committer | Tim Watson <tim.watson@gmail.com> | 2012-05-03 18:51:57 +0100 |
commit | d1bd4cff93ca8aa7642f2d44f68e8c2c38fb1fb5 (patch) | |
tree | 3e9111eb5121ff9b64ac95615939aef18086756c | |
parent | 110d85f300c697d5bb12455f3298bb8b3fbd46c8 (diff) | |
download | rabbitmq-server-d1bd4cff93ca8aa7642f2d44f68e8c2c38fb1fb5.tar.gz |
add rabbit:start_cold/0 without relying on release/boot-script
-rwxr-xr-x | scripts/rabbitmq-server | 3 | ||||
-rw-r--r-- | src/rabbit.erl | 71 | ||||
-rw-r--r-- | src/rabbit_misc.erl | 22 | ||||
-rw-r--r-- | src/rabbit_plugins.erl | 54 |
4 files changed, 127 insertions, 23 deletions
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server index 0a5a4640..3b31e83b 100755 --- a/scripts/rabbitmq-server +++ b/scripts/rabbitmq-server @@ -112,6 +112,9 @@ exec erl \ -sasl sasl_error_logger false \ -rabbit error_logger '{file,"'${RABBITMQ_LOGS}'"}' \ -rabbit sasl_error_logger '{file,"'${RABBITMQ_SASL_LOGS}'"}' \ + -rabbit enabled_plugins_file "$RABBITMQ_ENABLED_PLUGINS_FILE" \ + -rabbit plugins_dir "$RABBITMQ_PLUGINS_DIR" \ + -rabbit plugins_expand_dir "$RABBITMQ_PLUGINS_EXPAND_DIR" \ -os_mon start_cpu_sup false \ -os_mon start_disksup false \ -os_mon start_memsup false \ diff --git a/src/rabbit.erl b/src/rabbit.erl index b1f786a0..7f2845b6 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -18,8 +18,8 @@ -behaviour(application). --export([maybe_hipe_compile/0, prepare/0, start/0, stop/0, stop_and_halt/0, - status/0, is_running/0, is_running/1, environment/0, +-export([maybe_hipe_compile/0, prepare/0, start/0, start_cold/0, stop/0, + stop_and_halt/0, status/0, is_running/0, is_running/1, environment/0, rotate_logs/1, force_event_refresh/0]). -export([start/2, stop/1]). @@ -217,6 +217,7 @@ -spec(maybe_hipe_compile/0 :: () -> 'ok'). -spec(prepare/0 :: () -> 'ok'). -spec(start/0 :: () -> 'ok'). +-spec(start_cold/0 :: () -> 'ok'). -spec(stop/0 :: () -> 'ok'). -spec(stop_and_halt/0 :: () -> no_return()). -spec(status/0 :: @@ -284,22 +285,35 @@ split0([], Ls) -> Ls; split0([I | Is], [L | Ls]) -> split0(Is, Ls ++ [[I | L]]). prepare() -> + %% this ends up looking at the rabbit app's env, so it + %% needs to be loaded, but during the tests, it may end up + %% getting loaded twice, so guard against that + case application:load(rabbit) of + ok -> ok; + {error, {already_loaded, rabbit}} -> ok + end, ok = ensure_working_log_handlers(), ok = rabbit_upgrade:maybe_upgrade_mnesia(). start() -> + start_it(fun() -> + ok = prepare(), + ok = rabbit_misc:start_applications(application_load_order()) + end). + +start_cold() -> + start_it(fun() -> + ok = prepare(), + Plugins = determine_required_plugins(), + ToBeLoaded = ?APPS ++ Plugins, + StartupApps = application_load_order(ToBeLoaded, ToBeLoaded), + ok = rabbit_misc:start_applications(StartupApps) + end). + +start_it(StartFun) -> try - %% prepare/1 ends up looking at the rabbit app's env, so it - %% needs to be loaded, but during the tests, it may end up - %% getting loaded twice, so guard against that - case application:load(rabbit) of - ok -> ok; - {error, {already_loaded, rabbit}} -> ok - end, - ok = prepare(), - ok = rabbit_misc:start_applications(application_load_order()) + StartFun() after - %%give the error loggers some time to catch up timer:sleep(100) end. @@ -394,13 +408,17 @@ stop(_State) -> application_load_order() -> ok = load_applications(), + LoadedApps = application:loaded_applications(), + application_load_order(LoadedApps, ?APPS). + +application_load_order(LoadedApps, RootApps) -> {ok, G} = rabbit_misc:build_acyclic_graph( fun (App, _Deps) -> [{App, App}] end, fun (App, Deps) -> [{Dep, App} || Dep <- Deps] end, - [{App, app_dependencies(App)} || - {App, _Desc, _Vsn} <- application:loaded_applications()]), + [{App, app_dependencies(App)} || App <- LoadedApps]), true = digraph:del_vertices( - G, digraph:vertices(G) -- digraph_utils:reachable(?APPS, G)), + G, digraph:vertices(G) -- + digraph_utils:reachable(RootApps, G)), Result = digraph_utils:topsort(G), true = digraph:delete(G), Result. @@ -408,6 +426,7 @@ application_load_order() -> load_applications() -> load_applications(queue:from_list(?APPS), sets:new()). +%% FIXME: should we move this into rabbit_misc? load_applications(Worklist, Loaded) -> case queue:out(Worklist) of {empty, _WorkList} -> @@ -568,6 +587,28 @@ insert_default_data() -> %%--------------------------------------------------------------------------- %% logging +determine_required_plugins() -> + {ok, PluginDir} = application:get_env(rabbit, plugins_dir), + {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir), + {ok, EnabledPluginsFile} = application:get_env(rabbit, + enabled_plugins_file), + rabbit_plugins:prepare_plugins(EnabledPluginsFile, PluginDir, ExpandDir), + find_plugins(ExpandDir). + +find_plugins(PluginDir) -> + [prepare_dir_plugin(PluginName) || + PluginName <- filelib:wildcard(PluginDir ++ "/*/ebin/*.app")]. + +prepare_dir_plugin(PluginAppDescFn) -> + %% Add the plugin ebin directory to the load path + PluginEBinDirN = filename:dirname(PluginAppDescFn), + code:add_path(PluginEBinDirN), + + %% We want the second-last token + NameTokens = string:tokens(PluginAppDescFn,"/."), + PluginNameString = lists:nth(length(NameTokens) - 1, NameTokens), + list_to_atom(PluginNameString). + ensure_working_log_handlers() -> Handlers = gen_event:which_handlers(error_logger), ok = ensure_working_log_handler(error_logger_tty_h, diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 706de835..28c61a2e 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -19,7 +19,7 @@ -include("rabbit_framing.hrl"). -export([method_record_type/1, polite_pause/0, polite_pause/1]). --export([die/1, frame_error/2, amqp_error/4, +-export([die/1, frame_error/2, amqp_error/4, terminate/1, terminate/2, protocol_error/3, protocol_error/4, protocol_error/1]). -export([not_found/1, assert_args_equivalence/4]). -export([dirty_read/1]). @@ -87,6 +87,11 @@ -spec(polite_pause/1 :: (non_neg_integer()) -> 'done'). -spec(die/1 :: (rabbit_framing:amqp_exception()) -> channel_or_connection_exit()). + +%% TODO: figure out what the return types should actually be for these... +-spec(terminate/1 :: (integer()) -> any()). +-spec(terminate/2 :: (string(), integer()) -> any()). + -spec(frame_error/2 :: (rabbit_framing:amqp_method_name(), binary()) -> rabbit_types:connection_exit()). -spec(amqp_error/4 :: @@ -212,6 +217,8 @@ -endif. +-define(ERROR_CODE, 1). + %%---------------------------------------------------------------------------- method_record_type(Record) -> @@ -387,6 +394,19 @@ report_coverage_percentage(File, Cov, NotCov, Mod) -> confirm_to_sender(Pid, MsgSeqNos) -> gen_server2:cast(Pid, {confirm, MsgSeqNos, self()}). +terminate(Fmt, Args) -> + io:format("ERROR: " ++ Fmt ++ "~n", Args), + terminate(?ERROR_CODE). + +terminate(Status) -> + case os:type() of + {unix, _} -> halt(Status); + {win32, _} -> init:stop(Status), + receive + after infinity -> ok + end + end. + throw_on_error(E, Thunk) -> case Thunk() of {error, Reason} -> throw({E, Reason}); diff --git a/src/rabbit_plugins.erl b/src/rabbit_plugins.erl index 2a93c8f2..3ce0d3b1 100644 --- a/src/rabbit_plugins.erl +++ b/src/rabbit_plugins.erl @@ -17,8 +17,7 @@ -module(rabbit_plugins). -include("rabbit.hrl"). --export([start/0, stop/0, find_plugins/1, read_enabled_plugins/1, - lookup_plugins/2, calculate_required_plugins/2, plugin_names/1]). +-export([start/0, stop/0, prepare_plugins/3]). -define(VERBOSE_OPT, "-v"). -define(MINIMAL_OPT, "-m"). @@ -84,12 +83,32 @@ start() -> stop() -> ok. -print_error(Format, Args) -> - rabbit_misc:format_stderr("Error: " ++ Format ++ "~n", Args). +prepare_plugins(EnabledPluginsFile, PluginsDistDir, DestDir) -> + AllPlugins = rabbit_plugins:find_plugins(PluginsDistDir), + Enabled = rabbit_plugins:read_enabled_plugins(EnabledPluginsFile), + ToUnpack = rabbit_plugins:calculate_required_plugins(Enabled, AllPlugins), + ToUnpackPlugins = lookup_plugins(ToUnpack, AllPlugins), -usage() -> - io:format("~s", [rabbit_plugins_usage:usage()]), - rabbit_misc:quit(1). + Missing = Enabled -- rabbit_plugins:plugin_names(ToUnpackPlugins), + case Missing of + [] -> ok; + _ -> io:format("Warning: the following enabled plugins were " + "not found: ~p~n", [Missing]) + end, + + %% Eliminate the contents of the destination directory + case delete_recursively(DestDir) of + ok -> ok; + {error, E} -> rabbit_misc:terminate("Could not delete dir ~s (~p)", + [DestDir, E]) + end, + case filelib:ensure_dir(DestDir ++ "/") of + ok -> ok; + {error, E2} -> rabbit_misc:terminate("Could not create dir ~s (~p)", + [DestDir, E2]) + end, + + [prepare_plugin(Plugin, DestDir) || Plugin <- ToUnpackPlugins]. %%---------------------------------------------------------------------------- @@ -155,6 +174,27 @@ action(disable, ToDisable0, _Opts, PluginsFile, PluginsDir) -> %%---------------------------------------------------------------------------- +print_error(Format, Args) -> + rabbit_misc:format_stderr("Error: " ++ Format ++ "~n", Args). + +usage() -> + io:format("~s", [rabbit_plugins_usage:usage()]), + rabbit_misc:quit(1). + +delete_recursively(Fn) -> + case rabbit_file:recursive_delete([Fn]) of + ok -> ok; + {error, {Path, E}} -> {error, {cannot_delete, Path, E}}; + Error -> Error + end. + +prepare_plugin(#plugin{type = ez, location = Location}, PluginDestDir) -> + zip:unzip(Location, [{cwd, PluginDestDir}]); +prepare_plugin(#plugin{type = dir, name = Name, location = Location}, + PluginsDestDir) -> + rabbit_file:recursive_copy(Location, + filename:join([PluginsDestDir, Name])). + %% Get the #plugin{}s ready to be enabled. find_plugins(PluginsDir) -> EZs = [{ez, EZ} || EZ <- filelib:wildcard("*.ez", PluginsDir)], |