diff options
author | Francesco Mazzoli <francesco@rabbitmq.com> | 2012-04-23 11:43:29 +0100 |
---|---|---|
committer | Francesco Mazzoli <francesco@rabbitmq.com> | 2012-04-23 11:43:29 +0100 |
commit | 66bd59a1f14d30b8d1a5aae6cc0077fd14889268 (patch) | |
tree | a8c050910adee7fb2e678c4d056f1d3ddcc9d6b9 | |
parent | b6d851b0638e8e0f6262ddecb2566c4ec1892d08 (diff) | |
download | rabbitmq-server-66bd59a1f14d30b8d1a5aae6cc0077fd14889268.tar.gz |
Move node waiting to rabbit_control.
That functionality doesn't have much to do with rabbit itself (we should leave
it undocumented).
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/rabbit.erl | 2 | ||||
-rw-r--r-- | src/rabbit_control.erl | 85 | ||||
-rw-r--r-- | src/rabbit_misc.erl | 83 | ||||
-rw-r--r-- | src/rabbit_nodes.erl | 9 | ||||
-rwxr-xr-x | wait_node | 22 |
6 files changed, 87 insertions, 116 deletions
@@ -207,7 +207,7 @@ start-background-node: all -rm -f $(RABBITMQ_MNESIA_DIR).pid mkdir -p $(RABBITMQ_MNESIA_DIR) setsid sh -c "$(MAKE) run-background-node > $(RABBITMQ_MNESIA_DIR)/startup_log 2> $(RABBITMQ_MNESIA_DIR)/startup_err" & - ./wait_node $(RABBITMQ_NODENAME) $(RABBITMQ_MNESIA_DIR).pid + ./scripts/rabbitmqctl -n $(RABBITMQ_NODENAME) wait $(RABBITMQ_MNESIA_DIR).pid kernel start-rabbit-on-node: all echo "rabbit:start()." | $(ERL_CALL) diff --git a/src/rabbit.erl b/src/rabbit.erl index bee2634d..b1f786a0 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -347,7 +347,7 @@ status() -> is_running() -> is_running(node()). is_running(Node) -> - rabbit_misc:is_running(Node, rabbit). + rabbit_nodes:is_running(Node, rabbit). environment() -> lists:keysort( diff --git a/src/rabbit_control.erl b/src/rabbit_control.erl index 17a69725..40663f67 100644 --- a/src/rabbit_control.erl +++ b/src/rabbit_control.erl @@ -20,6 +20,7 @@ -export([start/0, stop/0, action/5]). -define(RPC_TIMEOUT, infinity). +-define(EXTERNAL_CHECK_INTERVAL, 1000). -define(QUIET_OPT, "-q"). -define(NODE_OPT, "-n"). @@ -156,8 +157,8 @@ action(stop, Node, Args, _Opts, Inform) -> Inform("Stopping and halting node ~p", [Node]), Res = call(Node, {rabbit, stop_and_halt, []}), case {Res, Args} of - {ok, [PidFile]} -> rabbit_misc:wait_for_process_death( - rabbit_misc:read_pid_file(PidFile, false)); + {ok, [PidFile]} -> wait_for_process_death( + read_pid_file(PidFile, false)); {ok, [_, _| _]} -> exit({badarg, Args}); _ -> ok end, @@ -191,9 +192,16 @@ action(force_cluster, Node, ClusterNodeSs, _Opts, Inform) -> [Node, ClusterNodes]), rpc_call(Node, rabbit_mnesia, force_cluster, [ClusterNodes]); -action(wait, Node, [PidFile], _Opts, Inform) -> +action(wait, Node, Args, _Opts, Inform) -> + {PidFile, Application} = + case Args of + [PidFile0] -> {PidFile0, rabbit}; + [PidFile0, AppString] -> {PidFile0, list_to_atom(AppString)} + end, Inform("Waiting for ~p", [Node]), - wait_for_application(Node, PidFile, Inform); + Pid = read_pid_file(PidFile, true), + Inform("pid is ~s", [Pid]), + wait_for_application(Node, Pid, Application); action(status, Node, [], _Opts, Inform) -> Inform("Status of node ~p", [Node]), @@ -378,10 +386,71 @@ action(eval, Node, [Expr], _Opts, _Inform) -> %%---------------------------------------------------------------------------- -wait_for_application(Node, PidFile, Inform) -> - Pid = rabbit_misc:read_pid_file(PidFile, true), - Inform("pid is ~s", [Pid]), - rabbit_misc:wait_for_application(Node, Pid, rabbit). +wait_for_application(Node, Pid, Application) -> + case process_up(Pid) of + true -> case rabbit_nodes:is_running(Node, Application) of + true -> ok; + false -> timer:sleep(?EXTERNAL_CHECK_INTERVAL), + wait_for_application(Node, Pid, Application) + end; + false -> {error, process_not_running} + end. + +wait_for_process_death(Pid) -> + case process_up(Pid) of + true -> timer:sleep(?EXTERNAL_CHECK_INTERVAL), + wait_for_process_death(Pid); + false -> ok + end. + +read_pid_file(PidFile, Wait) -> + case {file:read_file(PidFile), Wait} of + {{ok, Bin}, _} -> + S = string:strip(binary_to_list(Bin), right, $\n), + try list_to_integer(S) + catch error:badarg -> + exit({error, {garbage_in_pid_file, PidFile}}) + end, + S; + {{error, enoent}, true} -> + timer:sleep(?EXTERNAL_CHECK_INTERVAL), + read_pid_file(PidFile, Wait); + {{error, _} = E, _} -> + exit({error, {could_not_read_pid, E}}) + end. + +% Test using some OS clunkiness since we shouldn't trust +% rpc:call(os, getpid, []) at this point +process_up(Pid) -> + with_os([{unix, fun () -> + system("ps -p " ++ Pid + ++ " >/dev/null 2>&1") =:= 0 + end}, + {win32, fun () -> + Res = os:cmd("tasklist /nh /fi \"pid eq " ++ + Pid ++ "\" 2>&1"), + case re:run(Res, "erl\\.exe", [{capture, none}]) of + match -> true; + _ -> false + end + end}]). + +with_os(Handlers) -> + {OsFamily, _} = os:type(), + case proplists:get_value(OsFamily, Handlers) of + undefined -> throw({unsupported_os, OsFamily}); + Handler -> Handler() + end. + +% Like system(3) +system(Cmd) -> + ShCmd = "sh -c '" ++ escape_quotes(Cmd) ++ "'", + Port = erlang:open_port({spawn, ShCmd}, [exit_status,nouse_stdio]), + receive {Port, {exit_status, Status}} -> Status end. + +% Escape the quotes in a shell command so that it can be used in "sh -c 'cmd'" +escape_quotes(Cmd) -> + lists:flatten(lists:map(fun ($') -> "'\\''"; (Ch) -> Ch end, Cmd)). format_parse_error({_Line, Mod, Err}) -> lists:flatten(Mod:format_error(Err)). diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 9456e3c1..0aacd654 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -61,10 +61,6 @@ -export([quit/1]). -export([os_cmd/1]). -export([gb_sets_difference/2]). --export([is_running/2, wait_for_application/3, wait_for_process_death/1, - read_pid_file/2]). - --define(EXTERNAL_CHECK_INTERVAL, 1000). %%---------------------------------------------------------------------------- @@ -210,11 +206,6 @@ -spec(quit/1 :: (integer() | string()) -> no_return()). -spec(os_cmd/1 :: (string()) -> string()). -spec(gb_sets_difference/2 :: (gb_set(), gb_set()) -> gb_set()). --spec(is_running/2 :: (node(), atom()) -> boolean()). --spec(wait_for_application/3 :: (node(), string(), atom()) - -> ok | {error, process_not_running}). --spec(wait_for_process_death/1 :: (string()) -> ok). --spec(read_pid_file/2 :: (file:name(), boolean()) -> string() | no_return()). -endif. @@ -926,77 +917,3 @@ os_cmd(Command) -> gb_sets_difference(S1, S2) -> gb_sets:fold(fun gb_sets:delete_any/2, S1, S2). - -%%---------------------------------------------------------------------------- - -is_running(Node, Application) -> - case rpc:call(Node, application, which_applications, [infinity]) of - {badrpc, _} -> false; - Apps -> proplists:is_defined(Application, Apps) - end. - -wait_for_application(Node, Pid, Application) -> - case process_up(Pid) of - true -> case is_running(Node, Application) of - true -> ok; - false -> timer:sleep(?EXTERNAL_CHECK_INTERVAL), - wait_for_application(Node, Pid, Application) - end; - false -> {error, process_not_running} - end. - -wait_for_process_death(Pid) -> - case process_up(Pid) of - true -> timer:sleep(?EXTERNAL_CHECK_INTERVAL), - wait_for_process_death(Pid); - false -> ok - end. - -read_pid_file(PidFile, Wait) -> - case {file:read_file(PidFile), Wait} of - {{ok, Bin}, _} -> - S = string:strip(binary_to_list(Bin), right, $\n), - try list_to_integer(S) - catch error:badarg -> - exit({error, {garbage_in_pid_file, PidFile}}) - end, - S; - {{error, enoent}, true} -> - timer:sleep(?EXTERNAL_CHECK_INTERVAL), - read_pid_file(PidFile, Wait); - {{error, _} = E, _} -> - exit({error, {could_not_read_pid, E}}) - end. - -% Test using some OS clunkiness since we shouldn't trust -% rpc:call(os, getpid, []) at this point -process_up(Pid) -> - with_os([{unix, fun () -> - system("ps -p " ++ Pid - ++ " >/dev/null 2>&1") =:= 0 - end}, - {win32, fun () -> - Res = os:cmd("tasklist /nh /fi \"pid eq " ++ - Pid ++ "\" 2>&1"), - case re:run(Res, "erl\\.exe", [{capture, none}]) of - match -> true; - _ -> false - end - end}]). - -with_os(Handlers) -> - {OsFamily, _} = os:type(), - case proplists:get_value(OsFamily, Handlers) of - undefined -> throw({unsupported_os, OsFamily}); - Handler -> Handler() - end. - -% Like system(3) -system(Cmd) -> - ShCmd = "sh -c '" ++ escape_quotes(Cmd) ++ "'", - Port = erlang:open_port({spawn, ShCmd}, [exit_status,nouse_stdio]), - receive {Port, {exit_status, Status}} -> Status end. - -% Escape the quotes in a shell command so that it can be used in "sh -c 'cmd'" -escape_quotes(Cmd) -> - lists:flatten(lists:map(fun ($') -> "'\\''"; (Ch) -> Ch end, Cmd)). diff --git a/src/rabbit_nodes.erl b/src/rabbit_nodes.erl index 9a972d9e..b6a9e263 100644 --- a/src/rabbit_nodes.erl +++ b/src/rabbit_nodes.erl @@ -16,7 +16,7 @@ -module(rabbit_nodes). --export([names/1, diagnostics/1, make/1, parts/1, cookie_hash/0]). +-export([names/1, diagnostics/1, make/1, parts/1, cookie_hash/0, is_running/2]). -define(EPMD_TIMEOUT, 30000). @@ -32,6 +32,7 @@ -spec(make/1 :: ({string(), string()} | string()) -> node()). -spec(parts/1 :: (node() | string()) -> {string(), string()}). -spec(cookie_hash/0 :: () -> string()). +-spec(is_running/2 :: (node(), atom()) -> boolean()). -endif. @@ -92,3 +93,9 @@ parts(NodeStr) -> cookie_hash() -> base64:encode_to_string(erlang:md5(atom_to_list(erlang:get_cookie()))). + +is_running(Node, Application) -> + case rpc:call(Node, application, which_applications, [infinity]) of + {badrpc, _} -> false; + Apps -> proplists:is_defined(Application, Apps) + end. diff --git a/wait_node b/wait_node deleted file mode 100755 index ee7dfeab..00000000 --- a/wait_node +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env escript -%% -*- erlang -*- -%%! -sname wait_node -pa ./ebin - -main([NodeStr, PidFile]) -> - case {code:load_file(rabbit_misc), code:load_file(rabbit_nodes)} of - {{module, _}, {module, _}} -> - ok; - _ -> - io:format("Compile with 'make' before running this script~n"), - halt(1) - end, - Node = rabbit_nodes:make(NodeStr), - Pid = rabbit_misc:read_pid_file(PidFile, true), - io:format("pid is ~s~n", [Pid]), - rabbit_misc:wait_for_application(Node, Pid, kernel); -main(_) -> - usage(). - -usage() -> - io:format("Usage: ./wait_node node pidfile~n"), - halt(1). |