diff options
| author | Matthew Sackman <matthew@lshift.net> | 2009-05-27 13:33:24 +0100 |
|---|---|---|
| committer | Matthew Sackman <matthew@lshift.net> | 2009-05-27 13:33:24 +0100 |
| commit | 6246085d1566ef701379006b2ed5ce1b45b4f434 (patch) | |
| tree | 2937eade747010bfa7ebddc174edc83686544ff1 | |
| parent | 07a45e744d24384e3b2a1667d4b98650e83f671d (diff) | |
| parent | 3120cdcb7b8f903c7236c636578ddabeb50068fd (diff) | |
| download | rabbitmq-server-git-6246085d1566ef701379006b2ed5ce1b45b4f434.tar.gz | |
just merging in default branch
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | docs/rabbitmqctl.1.pod | 2 | ||||
| -rw-r--r-- | packaging/RPMS/Fedora/init.d | 2 | ||||
| -rw-r--r-- | packaging/RPMS/Fedora/rabbitmq-server.spec | 34 | ||||
| -rw-r--r-- | packaging/debs/Debian/debian/changelog | 6 | ||||
| -rw-r--r-- | packaging/windows/rabbitmq-service.pod | 6 | ||||
| -rwxr-xr-x | scripts/rabbitmq-multi.bat | 4 | ||||
| -rwxr-xr-x | scripts/rabbitmq-server | 2 | ||||
| -rwxr-xr-x | scripts/rabbitmq-server.bat | 1 | ||||
| -rw-r--r-- | src/priority_queue.erl | 2 | ||||
| -rw-r--r-- | src/rabbit.erl | 12 | ||||
| -rw-r--r-- | src/rabbit_amqqueue.erl | 29 | ||||
| -rw-r--r-- | src/rabbit_channel.erl | 13 | ||||
| -rw-r--r-- | src/rabbit_control.erl | 13 | ||||
| -rw-r--r-- | src/rabbit_exchange.erl | 63 | ||||
| -rw-r--r-- | src/rabbit_misc.erl | 22 | ||||
| -rw-r--r-- | src/rabbit_mnesia.erl | 13 | ||||
| -rw-r--r-- | src/rabbit_multi.erl | 11 | ||||
| -rw-r--r-- | src/rabbit_persister.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_tests.erl | 6 |
20 files changed, 166 insertions, 84 deletions
@@ -94,11 +94,10 @@ run-node: all run-tests: all echo "rabbit_tests:all_tests()." | $(ERL_CALL) -start-background-node: stop-node +start-background-node: $(BASIC_SCRIPT_ENVIRONMENT_SETTINGS) \ RABBITMQ_NODE_ONLY=true \ - RABBITMQ_SERVER_START_ARGS="$(RABBITMQ_SERVER_START_ARGS) -detached" \ - ./scripts/rabbitmq-server ; sleep 1 + ./scripts/rabbitmq-server -detached; sleep 1 start-rabbit-on-node: all echo "rabbit:start()." | $(ERL_CALL) @@ -130,7 +129,7 @@ srcdist: distclean cp README.in $(TARGET_SRC_DIR)/README elinks -dump -no-references -no-numbering $(WEB_URL)build-server.html \ >> $(TARGET_SRC_DIR)/BUILD - sed -i 's/%%VERSION%%/$(VERSION)/' $(TARGET_SRC_DIR)/ebin/rabbit_app.in + sed -i.save 's/%%VERSION%%/$(VERSION)/' $(TARGET_SRC_DIR)/ebin/rabbit_app.in && rm -f $(TARGET_SRC_DIR)/ebin/rabbit_app.in.save cp -r $(AMQP_CODEGEN_DIR)/* $(TARGET_SRC_DIR)/codegen/ cp codegen.py Makefile generate_app $(TARGET_SRC_DIR) diff --git a/docs/rabbitmqctl.1.pod b/docs/rabbitmqctl.1.pod index a0232a40f2..421568960e 100644 --- a/docs/rabbitmqctl.1.pod +++ b/docs/rabbitmqctl.1.pod @@ -201,7 +201,7 @@ name URL-encoded name of the exchange type - exchange type (B<direct>, B<topic> or B<fanout>) + exchange type (B<direct>, B<topic>, B<fanout>, or B<headers>) durable whether the exchange survives server restarts diff --git a/packaging/RPMS/Fedora/init.d b/packaging/RPMS/Fedora/init.d index a9155f3b03..77a6a89af1 100644 --- a/packaging/RPMS/Fedora/init.d +++ b/packaging/RPMS/Fedora/init.d @@ -8,6 +8,8 @@ ### BEGIN INIT INFO # Provides: rabbitmq-server +# Default-Start: +# Default-Stop: # Required-Start: $remote_fs $network # Required-Stop: $remote_fs $network # Description: RabbitMQ broker diff --git a/packaging/RPMS/Fedora/rabbitmq-server.spec b/packaging/RPMS/Fedora/rabbitmq-server.spec index 9a67a3410d..bed1611ab8 100644 --- a/packaging/RPMS/Fedora/rabbitmq-server.spec +++ b/packaging/RPMS/Fedora/rabbitmq-server.spec @@ -28,20 +28,17 @@ scalable implementation of an AMQP broker. %define _maindir %{buildroot}%{_rabbit_erllibdir} -%pre -if [ $1 -gt 1 ]; then - #Upgrade - stop and remove previous instance of rabbitmq-server init.d script - /sbin/service rabbitmq-server stop - /sbin/chkconfig --del rabbitmq-server -fi - %prep %setup -q %build cp %{S:2} %{_rabbit_wrapper} -sed 's|/usr/lib/|%{_libdir}/|' %{_rabbit_wrapper} -make %{?_smp_mflags} +sed -i 's|/usr/lib/|%{_libdir}/|' %{_rabbit_wrapper} + +# The rabbitmq build needs escript, which is missing from /usr/bin in +# some versions of the erlang RPM. See +# <https://bugzilla.redhat.com/show_bug.cgi?id=481302> +PATH=%{_libdir}/erlang/bin:$PATH make %{?_smp_mflags} %install rm -rf %{buildroot} @@ -73,7 +70,14 @@ echo '%defattr(-,root,root, -)' >> %{_builddir}/filelist.%{name}.rpm ! -regex '\.\(%{_rabbit_erllibdir}\|%{_rabbit_libdir}\).*' \ | sed -e 's/^\.//' >> %{_builddir}/filelist.%{name}.rpm) -%post +%pre + +if [ $1 -gt 1 ]; then + #Upgrade - stop and remove previous instance of rabbitmq-server init.d script + /sbin/service rabbitmq-server stop + /sbin/chkconfig --del rabbitmq-server +fi + # create rabbitmq group if ! getent group rabbitmq >/dev/null; then groupadd -r rabbitmq @@ -81,10 +85,11 @@ fi # create rabbitmq user if ! getent passwd rabbitmq >/dev/null; then - useradd -r -g rabbitmq -d %{_localstatedir}/lib/rabbitmq rabbitmq \ - -c "RabbitMQ messaging server" rabbitmq + useradd -r -g rabbitmq -d %{_localstatedir}/lib/rabbitmq rabbitmq \ + -c "RabbitMQ messaging server" fi +%post /sbin/chkconfig --add %{name} %preun @@ -106,12 +111,15 @@ fi %{_rabbit_libdir} %{_initrddir}/rabbitmq-server %config(noreplace) %{_sysconfdir}/logrotate.d/rabbitmq-server -%doc LICENSE LICENSE-MPL-RabbitMQ INSTALL +%doc LICENSE LICENSE-MPL-RabbitMQ %clean rm -rf %{buildroot} %changelog +* Mon Apr 6 2009 Matthias Radestock <matthias@lshift.net> 1.5.4-1 +- Maintenance release for the 1.5.x series + * Tue Feb 24 2009 Tony Garnock-Jones <tonyg@lshift.net> 1.5.3-1 - Maintenance release for the 1.5.x series diff --git a/packaging/debs/Debian/debian/changelog b/packaging/debs/Debian/debian/changelog index 3be25f4836..d1ccd3a0c2 100644 --- a/packaging/debs/Debian/debian/changelog +++ b/packaging/debs/Debian/debian/changelog @@ -1,3 +1,9 @@ +rabbitmq-server (1.5.4-1) hardy; urgency=low + + * New Upstream Release + + -- Matthias Radestock <matthias@lshift.net> Mon, 06 Apr 2009 09:19:32 +0100 + rabbitmq-server (1.5.3-1) hardy; urgency=low * New Upstream Release diff --git a/packaging/windows/rabbitmq-service.pod b/packaging/windows/rabbitmq-service.pod index 7c4d3ef210..8a2d2e5b22 100644 --- a/packaging/windows/rabbitmq-service.pod +++ b/packaging/windows/rabbitmq-service.pod @@ -92,8 +92,10 @@ Defaults to 5672. =head2 ERLANG_SERVICE_MANAGER_PATH -Defaults to F<C:\Program Files\erl5.5.5\erts-5.5.5\bin>. This is -the installation location of the Erlang service manager. +Defaults to F<C:\Program Files\erl5.5.5\erts-5.5.5\bin> +(or F<C:\Program Files (x86)\erl5.5.5\erts-5.5.5\bin> for 64-bit +environments). This is the installation location of the Erlang service +manager. =head2 CLUSTER_CONFIG_FILE diff --git a/scripts/rabbitmq-multi.bat b/scripts/rabbitmq-multi.bat index 30f33a5a26..a30c0889ab 100755 --- a/scripts/rabbitmq-multi.bat +++ b/scripts/rabbitmq-multi.bat @@ -47,7 +47,7 @@ if "%RABBITMQ_NODE_PORT%"=="" ( )
set RABBITMQ_PIDS_FILE=%RABBITMQ_BASE%\rabbitmq.pids
-set RABBITMQ_SCRIPT_HOME=%~dp0%
+set RABBITMQ_SCRIPT_HOME=%~sdp0%
if "%ERLANG_HOME%"=="" (
set ERLANG_HOME=%~dp0%..\..\..
@@ -65,5 +65,5 @@ if not exist "%ERLANG_HOME%\bin\erl.exe" ( exit /B
)
-"%ERLANG_HOME%\bin\erl.exe" -pa "%~dp0..\ebin" -noinput -hidden -sname rabbitmq_multi -s rabbit_multi %START_ARGS% -extra %*
+"%ERLANG_HOME%\bin\erl.exe" -pa "%~dp0..\ebin" -noinput -hidden %RABBITMQ_MULTI_ERL_ARGS% -sname rabbitmq_multi -s rabbit_multi %RABBITMQ_MULTI_START_ARGS% -extra %*
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server index d5be944a27..8502d60abc 100755 --- a/scripts/rabbitmq-server +++ b/scripts/rabbitmq-server @@ -36,7 +36,7 @@ NODE_PORT=5672 SERVER_ERL_ARGS="+K true +A30 \ -kernel inet_default_listen_options [{nodelay,true},{sndbuf,16384},{recbuf,4096}] \ -kernel inet_default_connect_options [{nodelay,true}]" -CLUSTER_CONFIG_FILE=/etc/rabbitmq/cluster.config +CLUSTER_CONFIG_FILE=/etc/rabbitmq/rabbitmq_cluster.config LOG_BASE=/var/log/rabbitmq MNESIA_BASE=/var/lib/rabbitmq/mnesia SERVER_START_ARGS= diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat index 5b20ef2010..9915727bd9 100755 --- a/scripts/rabbitmq-server.bat +++ b/scripts/rabbitmq-server.bat @@ -117,6 +117,7 @@ if "%RABBITMQ_MNESIA_DIR%"=="" ( -kernel inet_default_connect_options "[{nodelay, true}]" ^
-rabbit tcp_listeners "[{\"%RABBITMQ_NODE_IP_ADDRESS%\", %RABBITMQ_NODE_PORT%}]" ^
-kernel error_logger {file,\""%RABBITMQ_LOG_BASE%/%RABBITMQ_NODENAME%.log"\"} ^
+%RABBITMQ_SERVER_ERL_ARGS% ^
-sasl errlog_type error ^
-sasl sasl_error_logger {file,\""%RABBITMQ_LOG_BASE%/%RABBITMQ_NODENAME%-sasl.log"\"} ^
-os_mon start_cpu_sup true ^
diff --git a/src/priority_queue.erl b/src/priority_queue.erl index 88ad0c182d..732757c41c 100644 --- a/src/priority_queue.erl +++ b/src/priority_queue.erl @@ -111,7 +111,7 @@ in(X, 0, {queue, [_] = In, []}) -> {queue, [X], In}; in(X, 0, {queue, In, Out}) when is_list(In), is_list(Out) -> {queue, [X|In], Out}; -in(X, Priority, Q = {queue, [], []}) -> +in(X, Priority, _Q = {queue, [], []}) -> in(X, Priority, {pqueue, []}); in(X, Priority, Q = {queue, _, _}) -> in(X, Priority, {pqueue, [{0, Q}]}); diff --git a/src/rabbit.erl b/src/rabbit.erl index 3a15e6b07c..c0d09547c5 100644 --- a/src/rabbit.erl +++ b/src/rabbit.erl @@ -216,10 +216,14 @@ print_banner() -> [Product, Version, ?PROTOCOL_VERSION_MAJOR, ?PROTOCOL_VERSION_MINOR, ?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE]), - io:format("Logging to ~p~nSASL logging to ~p~n~n", - [log_location(kernel), log_location(sasl)]). - - + Settings = [{"node", node()}, + {"log", log_location(kernel)}, + {"sasl log", log_location(sasl)}, + {"database dir", rabbit_mnesia:dir()}], + DescrLen = lists:max([length(K) || {K, _V} <- Settings]), + Format = "~-" ++ integer_to_list(DescrLen) ++ "s: ~s~n", + lists:foreach(fun ({K, V}) -> io:format(Format, [K, V]) end, Settings), + io:nl(). start_child(Mod) -> {ok,_} = supervisor:start_child(rabbit_sup, diff --git a/src/rabbit_amqqueue.erl b/src/rabbit_amqqueue.erl index 06bb18f5d3..0316788fe1 100644 --- a/src/rabbit_amqqueue.erl +++ b/src/rabbit_amqqueue.erl @@ -201,9 +201,7 @@ with(Name, F, E) -> with(Name, F) -> with(Name, F, fun () -> {error, not_found} end). with_or_die(Name, F) -> - with(Name, F, fun () -> rabbit_misc:protocol_error( - not_found, "no ~s", [rabbit_misc:rs(Name)]) - end). + with(Name, F, fun () -> rabbit_misc:not_found(Name) end). list(VHostPath) -> mnesia:dirty_match_object( @@ -305,28 +303,29 @@ internal_delete(QueueName) -> rabbit_misc:execute_mnesia_transaction( fun () -> case mnesia:wread({rabbit_queue, QueueName}) of - [] -> {error, not_found}; - [Q] -> - ok = delete_queue(Q), + [] -> {error, not_found}; + [_] -> + ok = rabbit_exchange:delete_queue_bindings(QueueName), + ok = mnesia:delete({rabbit_queue, QueueName}), ok = mnesia:delete({rabbit_durable_queue, QueueName}), ok end end). -delete_queue(#amqqueue{name = QueueName}) -> - ok = rabbit_exchange:delete_bindings_for_queue(QueueName), - ok = mnesia:delete({rabbit_queue, QueueName}), - ok. - on_node_down(Node) -> rabbit_misc:execute_mnesia_transaction( fun () -> qlc:fold( - fun (Q, Acc) -> ok = delete_queue(Q), Acc end, + fun (QueueName, Acc) -> + ok = rabbit_exchange:delete_transient_queue_bindings( + QueueName), + ok = mnesia:delete({rabbit_queue, QueueName}), + Acc + end, ok, - qlc:q([Q || Q = #amqqueue{pid = Pid} - <- mnesia:table(rabbit_queue), - node(Pid) == Node])) + qlc:q([QueueName || #amqqueue{name = QueueName, pid = Pid} + <- mnesia:table(rabbit_queue), + node(Pid) == Node])) end). pseudo_queue(QueueName, Pid) -> diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl index aeb15bd1b9..d14a01bee9 100644 --- a/src/rabbit_channel.erl +++ b/src/rabbit_channel.erl @@ -576,8 +576,7 @@ handle_method(#'exchange.delete'{exchange = ExchangeNameBin, check_configure_permitted(ExchangeName, State), case rabbit_exchange:delete(ExchangeName, IfUnused) of {error, not_found} -> - rabbit_misc:protocol_error( - not_found, "no ~s", [rabbit_misc:rs(ExchangeName)]); + rabbit_misc:not_found(ExchangeName); {error, in_use} -> die_precondition_failed( "~s in use", [rabbit_misc:rs(ExchangeName)]); @@ -742,12 +741,14 @@ binding_action(Fun, ExchangeNameBin, QueueNameBin, RoutingKey, Arguments, ExchangeName = rabbit_misc:r(VHostPath, exchange, ExchangeNameBin), check_read_permitted(ExchangeName, State), case Fun(ExchangeName, QueueName, ActualRoutingKey, Arguments) of - {error, queue_not_found} -> - rabbit_misc:protocol_error( - not_found, "no ~s", [rabbit_misc:rs(QueueName)]); {error, exchange_not_found} -> + rabbit_misc:not_found(ExchangeName); + {error, queue_not_found} -> + rabbit_misc:not_found(QueueName); + {error, exchange_and_queue_not_found} -> rabbit_misc:protocol_error( - not_found, "no ~s", [rabbit_misc:rs(ExchangeName)]); + not_found, "no ~s and no ~s", [rabbit_misc:rs(ExchangeName), + rabbit_misc:rs(QueueName)]); {error, binding_not_found} -> rabbit_misc:protocol_error( not_found, "no binding ~s between ~s and ~s", diff --git a/src/rabbit_control.erl b/src/rabbit_control.erl index e6717d689f..6649899ade 100644 --- a/src/rabbit_control.erl +++ b/src/rabbit_control.erl @@ -38,6 +38,19 @@ -define(RPC_TIMEOUT, 30000). +%%---------------------------------------------------------------------------- + +-ifdef(use_specs). + +-spec(start/0 :: () -> no_return()). +-spec(stop/0 :: () -> 'ok'). +-spec(action/4 :: (atom(), erlang_node(), [string()], + fun ((string(), [any()]) -> 'ok')) -> 'ok'). + +-endif. + +%%---------------------------------------------------------------------------- + start() -> FullCommand = init:get_plain_arguments(), #params{quiet = Quiet, node = Node, command = Command, args = Args} = diff --git a/src/rabbit_exchange.erl b/src/rabbit_exchange.erl index 9b3bbb1851..e0f76d895c 100644 --- a/src/rabbit_exchange.erl +++ b/src/rabbit_exchange.erl @@ -40,7 +40,7 @@ route/3]). -export([add_binding/4, delete_binding/4, list_bindings/1]). -export([delete/2]). --export([delete_bindings_for_queue/1]). +-export([delete_queue_bindings/1, delete_transient_queue_bindings/1]). -export([check_type/1, assert_type/2, topic_matches/2, headers_match/2]). %% EXTENDED API @@ -59,8 +59,10 @@ -type(publish_res() :: {'ok', [pid()]} | not_found() | {'error', 'unroutable' | 'not_delivered'}). --type(bind_res() :: 'ok' | - {'error', 'queue_not_found' | 'exchange_not_found'}). +-type(bind_res() :: 'ok' | {'error', + 'queue_not_found' | + 'exchange_not_found' | + 'exchange_and_queue_not_found'}). -spec(recover/0 :: () -> 'ok'). -spec(declare/5 :: (exchange_name(), exchange_type(), bool(), bool(), amqp_table()) -> exchange()). @@ -86,7 +88,8 @@ bind_res() | {'error', 'binding_not_found'}). -spec(list_bindings/1 :: (vhost()) -> [{exchange_name(), queue_name(), routing_key(), amqp_table()}]). --spec(delete_bindings_for_queue/1 :: (queue_name()) -> 'ok'). +-spec(delete_queue_bindings/1 :: (queue_name()) -> 'ok'). +-spec(delete_transient_queue_bindings/1 :: (queue_name()) -> 'ok'). -spec(topic_matches/2 :: (binary(), binary()) -> bool()). -spec(headers_match/2 :: (amqp_table(), amqp_table()) -> bool()). -spec(delete/2 :: (exchange_name(), bool()) -> @@ -161,9 +164,7 @@ lookup(Name) -> lookup_or_die(Name) -> case lookup(Name) of {ok, X} -> X; - {error, not_found} -> - rabbit_misc:protocol_error( - not_found, "no ~s", [rabbit_misc:rs(Name)]) + {error, not_found} -> rabbit_misc:not_found(Name) end. list(VHostPath) -> @@ -295,7 +296,7 @@ lookup_qpids(Queues) -> %% refactored to its own module, especially seeing as unbind will have %% to be implemented for 0.91 ? -delete_bindings_for_exchange(ExchangeName) -> +delete_exchange_bindings(ExchangeName) -> [begin ok = mnesia:delete_object(rabbit_reverse_route, reverse_route(Route), write), @@ -307,10 +308,16 @@ delete_bindings_for_exchange(ExchangeName) -> write)], ok. -delete_bindings_for_queue(QueueName) -> +delete_queue_bindings(QueueName) -> + delete_queue_bindings(QueueName, fun delete_forward_routes/1). + +delete_transient_queue_bindings(QueueName) -> + delete_queue_bindings(QueueName, fun delete_transient_forward_routes/1). + +delete_queue_bindings(QueueName, FwdDeleteFun) -> Exchanges = exchanges_for_queue(QueueName), [begin - ok = delete_forward_routes(reverse_route(Route)), + ok = FwdDeleteFun(reverse_route(Route)), ok = mnesia:delete_object(rabbit_reverse_route, Route, write) end || Route <- mnesia:match_object( rabbit_reverse_route, @@ -328,6 +335,9 @@ delete_forward_routes(Route) -> ok = mnesia:delete_object(rabbit_route, Route, write), ok = mnesia:delete_object(rabbit_durable_route, Route, write). +delete_transient_forward_routes(Route) -> + ok = mnesia:delete_object(rabbit_route, Route, write). + exchanges_for_queue(QueueName) -> MatchHead = reverse_route( #route{binding = #binding{exchange_name = '$1', @@ -337,16 +347,13 @@ exchanges_for_queue(QueueName) -> sets:from_list( mnesia:select(rabbit_reverse_route, [{MatchHead, [], ['$1']}]))). -has_bindings(ExchangeName) -> - MatchHead = #route{binding = #binding{exchange_name = ExchangeName, - _ = '_'}}, +contains(Table, MatchHead) -> try - continue(mnesia:select(rabbit_route, [{MatchHead, [], ['$_']}], - 1, read)) + continue(mnesia:select(Table, [{MatchHead, [], ['$_']}], 1, read)) catch exit:{aborted, {badarg, _}} -> %% work around OTP-7025, which was fixed in R12B-1, by %% falling back on a less efficient method - case mnesia:match_object(rabbit_route, MatchHead, read) of + case mnesia:match_object(Table, MatchHead, read) of [] -> false; [_|_] -> true end @@ -359,18 +366,20 @@ continue({[], Continuation}) -> continue(mnesia:select(Continuation)). call_with_exchange(Exchange, Fun) -> rabbit_misc:execute_mnesia_transaction( fun() -> case mnesia:read({rabbit_exchange, Exchange}) of - [] -> {error, exchange_not_found}; + [] -> {error, not_found}; [X] -> Fun(X) end end). call_with_exchange_and_queue(Exchange, Queue, Fun) -> - call_with_exchange( - Exchange, - fun(X) -> case mnesia:read({rabbit_queue, Queue}) of - [] -> {error, queue_not_found}; - [Q] -> Fun(X, Q) - end + rabbit_misc:execute_mnesia_transaction( + fun() -> case {mnesia:read({rabbit_exchange, Exchange}), + mnesia:read({rabbit_queue, Queue})} of + {[X], [Q]} -> Fun(X, Q); + {[ ], [_]} -> {error, exchange_not_found}; + {[_], [ ]} -> {error, queue_not_found}; + {[ ], [ ]} -> {error, exchange_and_queue_not_found} + end end). add_binding(ExchangeName, QueueName, RoutingKey, Arguments) -> @@ -554,13 +563,17 @@ maybe_auto_delete(Exchange = #exchange{auto_delete = true}) -> ok. conditional_delete(Exchange = #exchange{name = ExchangeName}) -> - case has_bindings(ExchangeName) of + Match = #route{binding = #binding{exchange_name = ExchangeName, _ = '_'}}, + %% we need to check for durable routes here too in case a bunch of + %% routes to durable queues have been removed temporarily as a + %% result of a node failure + case contains(rabbit_route, Match) orelse contains(rabbit_durable_route, Match) of false -> unconditional_delete(Exchange); true -> {error, in_use} end. unconditional_delete(#exchange{name = ExchangeName}) -> - ok = delete_bindings_for_exchange(ExchangeName), + ok = delete_exchange_bindings(ExchangeName), ok = mnesia:delete({rabbit_durable_exchange, ExchangeName}), ok = mnesia:delete({rabbit_exchange, ExchangeName}). diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index 2f329aa91c..49faba293b 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -36,6 +36,7 @@ -export([method_record_type/1, polite_pause/0, polite_pause/1]). -export([die/1, frame_error/2, protocol_error/3, protocol_error/4]). +-export([not_found/1]). -export([get_config/1, get_config/2, set_config/2]). -export([dirty_read/1]). -export([r/3, r/2, rs/1]). @@ -73,6 +74,7 @@ (atom() | amqp_error(), string(), [any()]) -> no_return()). -spec(protocol_error/4 :: (atom() | amqp_error(), string(), [any()], atom()) -> no_return()). +-spec(not_found/1 :: (r(atom())) -> no_return()). -spec(get_config/1 :: (atom()) -> {'ok', any()} | not_found()). -spec(get_config/2 :: (atom(), A) -> A). -spec(set_config/2 :: (atom(), any()) -> 'ok'). @@ -107,7 +109,7 @@ -spec(dirty_dump_log/1 :: (string()) -> 'ok' | {'error', any()}). -spec(append_file/2 :: (string(), string()) -> 'ok' | {'error', any()}). -spec(ensure_parent_dirs_exist/1 :: (string()) -> 'ok'). --spec(format_stderr/2 :: (string(), [any()]) -> 'true'). +-spec(format_stderr/2 :: (string(), [any()]) -> 'ok'). -spec(start_applications/1 :: ([atom()]) -> 'ok'). -spec(stop_applications/1 :: ([atom()]) -> 'ok'). -spec(unfold/2 :: (fun ((A) -> ({'true', B, A} | 'false')), A) -> [B]). @@ -141,6 +143,8 @@ protocol_error(Error, Explanation, Params, Method) -> CompleteExplanation = lists:flatten(io_lib:format(Explanation, Params)), exit({amqp, Error, CompleteExplanation, Method}). +not_found(R) -> protocol_error(not_found, "no ~s", [rs(R)]). + get_config(Key) -> case dirty_read({rabbit_config, Key}) of {ok, {rabbit_config, Key, V}} -> {ok, V}; @@ -377,9 +381,19 @@ ensure_parent_dirs_exist(Filename) -> end. format_stderr(Fmt, Args) -> - Port = open_port({fd, 0, 2}, [out]), - port_command(Port, io_lib:format(Fmt, Args)), - port_close(Port). + case os:type() of + {unix, _} -> + Port = open_port({fd, 0, 2}, [out]), + port_command(Port, io_lib:format(Fmt, Args)), + port_close(Port); + {win32, _} -> + %% stderr on Windows is buffered and I can't figure out a + %% way to trigger a fflush(stderr) in Erlang. So rather + %% than risk losing output we write to stdout instead, + %% which appears to be unbuffered. + io:format(Fmt, Args) + end, + ok. manage_applications(Iterate, Do, Undo, SkipError, ErrorTag, Apps) -> Iterate(fun (App, Acc) -> diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl index d2b2b15c8a..cddcab643e 100644 --- a/src/rabbit_mnesia.erl +++ b/src/rabbit_mnesia.erl @@ -31,7 +31,7 @@ -module(rabbit_mnesia). --export([ensure_mnesia_dir/0, status/0, init/0, is_db_empty/0, +-export([ensure_mnesia_dir/0, dir/0, status/0, init/0, is_db_empty/0, cluster/1, reset/0, force_reset/0]). -export([table_names/0]). @@ -47,6 +47,7 @@ -ifdef(use_specs). -spec(status/0 :: () -> [{'nodes' | 'running_nodes', [erlang_node()]}]). +-spec(dir/0 :: () -> string()). -spec(ensure_mnesia_dir/0 :: () -> 'ok'). -spec(init/0 :: () -> 'ok'). -spec(is_db_empty/0 :: () -> bool()). @@ -155,8 +156,10 @@ table_definitions() -> table_names() -> [Tab || {Tab, _} <- table_definitions()]. +dir() -> mnesia:system_info(directory). + ensure_mnesia_dir() -> - MnesiaDir = mnesia:system_info(directory) ++ "/", + MnesiaDir = dir() ++ "/", case filelib:ensure_dir(MnesiaDir) of {error, Reason} -> throw({error, {cannot_create_mnesia_dir, MnesiaDir, Reason}}); @@ -192,7 +195,7 @@ check_schema_integrity() -> %% it doesn't. cluster_nodes_config_filename() -> - mnesia:system_info(directory) ++ "/cluster_nodes.config". + dir() ++ "/cluster_nodes.config". create_cluster_nodes_config(ClusterNodes) -> FileName = cluster_nodes_config_filename(), @@ -308,7 +311,7 @@ create_schema() -> move_db() -> mnesia:stop(), - MnesiaDir = filename:dirname(mnesia:system_info(directory) ++ "/"), + MnesiaDir = filename:dirname(dir() ++ "/"), {{Year, Month, Day}, {Hour, Minute, Second}} = erlang:universaltime(), BackupDir = lists:flatten( io_lib:format("~s_~w~2..0w~2..0w~2..0w~2..0w~2..0w", @@ -425,7 +428,7 @@ reset(Force) -> ok = delete_cluster_nodes_config(), %% remove persistet messages and any other garbage we find lists:foreach(fun file:delete/1, - filelib:wildcard(mnesia:system_info(directory) ++ "/*")), + filelib:wildcard(dir() ++ "/*")), ok. leave_cluster([], _) -> ok; diff --git a/src/rabbit_multi.erl b/src/rabbit_multi.erl index 5e8edd53a1..d91975359a 100644 --- a/src/rabbit_multi.erl +++ b/src/rabbit_multi.erl @@ -36,6 +36,17 @@ -define(RPC_SLEEP, 500). +%%---------------------------------------------------------------------------- + +-ifdef(use_specs). + +-spec(start/0 :: () -> no_return()). +-spec(stop/0 :: () -> 'ok'). + +-endif. + +%%---------------------------------------------------------------------------- + start() -> RpcTimeout = case init:get_argument(maxwait) of diff --git a/src/rabbit_persister.erl b/src/rabbit_persister.erl index f4fa45993a..d0d60ddf3d 100644 --- a/src/rabbit_persister.erl +++ b/src/rabbit_persister.erl @@ -259,7 +259,7 @@ log(State = #pstate{deadline = ExistingDeadline, pending_logs = Logs}, pending_logs = [Message | Logs]}. base_filename() -> - mnesia:system_info(directory) ++ "/rabbit_persister.LOG". + rabbit_mnesia:dir() ++ "/rabbit_persister.LOG". take_snapshot(LogHandle, OldFileName, Snapshot) -> ok = disk_log:sync(LogHandle), diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl index 552e4ed959..597b0a76e6 100644 --- a/src/rabbit_tests.erl +++ b/src/rabbit_tests.erl @@ -490,7 +490,13 @@ test_cluster_management2(SecondaryNode) -> ok = control_action(stop_app, []), {error, {no_running_cluster_nodes, _, _}} = control_action(reset, []), + + %% leave system clustered, with the secondary node as a ram node ok = control_action(force_reset, []), + ok = control_action(start_app, []), + ok = control_action(force_reset, SecondaryNode, []), + ok = control_action(cluster, SecondaryNode, [NodeS]), + ok = control_action(start_app, SecondaryNode, []), passed. |
