summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Watson <tim.watson@gmail.com>2012-05-03 18:51:57 +0100
committerTim Watson <tim.watson@gmail.com>2012-05-03 18:51:57 +0100
commitd1bd4cff93ca8aa7642f2d44f68e8c2c38fb1fb5 (patch)
tree3e9111eb5121ff9b64ac95615939aef18086756c
parent110d85f300c697d5bb12455f3298bb8b3fbd46c8 (diff)
downloadrabbitmq-server-d1bd4cff93ca8aa7642f2d44f68e8c2c38fb1fb5.tar.gz
add rabbit:start_cold/0 without relying on release/boot-script
-rwxr-xr-xscripts/rabbitmq-server3
-rw-r--r--src/rabbit.erl71
-rw-r--r--src/rabbit_misc.erl22
-rw-r--r--src/rabbit_plugins.erl54
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)],