summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Radestock <matthias@rabbitmq.com>2012-10-24 09:37:04 +0100
committerMatthias Radestock <matthias@rabbitmq.com>2012-10-24 09:37:04 +0100
commit0fa431b83108b046869f4c534ed42b4911e85af8 (patch)
tree0bc1826477ff0fa96d39895e6e8ebde73aea57c4
parent7a5c2bba14e02c1801ed30e16a5cce889b24d9c7 (diff)
downloadrabbitmq-server-0fa431b83108b046869f4c534ed42b4911e85af8.tar.gz
better error messages for 'absent' queues in various commands
- move channel:absent/1 to misc, since we need it in multiple modules - change amqqueue:with/3 s.t. the error fun is invoked with not_found|{'absent', Q}. - let this change ripple through to with/2, making it return either error. This in turn has just two call sites - in 'queue.declare' in the channel, which we expand to handle the 'absent' case (producing a descriptive not_found error, as per above) - in mq_misc:if_mirrored_queue, whose callers currently do not handle errors at all - see bug 25236 - let the change also ripple through to with_or_die, handling the new 'absent' case as above. This takes care of passive queue.declare. - with_or_die is called by with_exclusive_access_or_die. This takes care of basic.get, basic.consume, queue.delete and queue.purge
-rw-r--r--src/rabbit_amqqueue.erl39
-rw-r--r--src/rabbit_channel.erl15
-rw-r--r--src/rabbit_misc.erl12
3 files changed, 41 insertions, 25 deletions
diff --git a/src/rabbit_amqqueue.erl b/src/rabbit_amqqueue.erl
index 8ab9bc87..0a544713 100644
--- a/src/rabbit_amqqueue.erl
+++ b/src/rabbit_amqqueue.erl
@@ -81,7 +81,9 @@
(name()) -> rabbit_types:ok(rabbit_types:amqqueue()) |
rabbit_types:error('not_found');
([name()]) -> [rabbit_types:amqqueue()]).
--spec(with/2 :: (name(), qfun(A)) -> A | rabbit_types:error('not_found')).
+-spec(with/2 :: (name(), qfun(A)) ->
+ A | rabbit_types:error(
+ 'not_found' | {'absent', rabbit_types:amqqueue()})).
-spec(with_or_die/2 ::
(name(), qfun(A)) -> A | rabbit_types:channel_exit()).
-spec(assert_equivalence/5 ::
@@ -300,22 +302,33 @@ with(Name, F, E) ->
%% We check is_process_alive(QPid) in case we receive a
%% nodedown (for example) in F() that has nothing to do
%% with the QPid.
- E1 = fun () ->
- case rabbit_misc:is_process_alive(QPid) of
- true -> E();
- false -> timer:sleep(25),
- with(Name, F, E)
- end
- end,
- rabbit_misc:with_exit_handler(E1, fun () -> F(Q) end);
+ rabbit_misc:with_exit_handler(
+ fun () ->
+ case rabbit_misc:is_process_alive(QPid) of
+ true -> E(not_found_or_absent(Name));
+ false -> timer:sleep(25),
+ with(Name, F, E)
+ end
+ end, fun () -> F(Q) end);
{error, not_found} ->
- E()
+ E(not_found_or_absent(Name))
end.
-with(Name, F) ->
- with(Name, F, fun () -> {error, not_found} end).
+not_found_or_absent(Name) ->
+ %% We should read from both tables inside a tx, to get a
+ %% consistent view. But the chances of an inconsistency are small,
+ %% and only affect the error kind.
+ case rabbit_misc:dirty_read({rabbit_durable_queue, Name}) of
+ {error, not_found} -> not_found;
+ {ok, Q} -> {absent, Q}
+ end.
+
+with(Name, F) -> with(Name, F, fun (E) -> {error, E} end).
+
with_or_die(Name, F) ->
- with(Name, F, fun () -> rabbit_misc:not_found(Name) end).
+ with(Name, F, fun (not_found) -> rabbit_misc:not_found(Name);
+ ({absent, Q}) -> rabbit_misc:absent(Q)
+ end).
assert_equivalence(#amqqueue{durable = Durable,
auto_delete = AutoDelete} = Q,
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index 276ad38f..91abcf1e 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -423,15 +423,6 @@ precondition_failed(Format) -> precondition_failed(Format, []).
precondition_failed(Format, Params) ->
rabbit_misc:protocol_error(precondition_failed, Format, Params).
-absent(#amqqueue{name = QueueName, pid = QPid, durable = true}) ->
- %% The assertion of durability is mainly there because we mention
- %% durability in the error message. That way we will hopefully
- %% notice if at some future point our logic changes s.t. we get
- %% here with non-durable queues.
- rabbit_misc:protocol_error(
- not_found, "home node '~s' of durable ~s is down or inaccessible",
- [node(QPid), rabbit_misc:rs(QueueName)]).
-
return_queue_declare_ok(#resource{name = ActualName},
NoWait, MessageCount, ConsumerCount, State) ->
return_ok(State#ch{most_recently_declared_queue = ActualName}, NoWait,
@@ -971,8 +962,10 @@ handle_method(#'queue.declare'{queue = QueueNameBin,
%% declare. Loop around again.
handle_method(Declare, none, State);
{absent, Q} ->
- absent(Q)
- end
+ rabbit_misc:absent(Q)
+ end;
+ {error, {absent, Q}} ->
+ rabbit_misc:absent(Q)
end;
handle_method(#'queue.declare'{queue = QueueNameBin,
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl
index ab9a9ceb..78f25175 100644
--- a/src/rabbit_misc.erl
+++ b/src/rabbit_misc.erl
@@ -21,7 +21,7 @@
-export([method_record_type/1, polite_pause/0, polite_pause/1]).
-export([die/1, frame_error/2, amqp_error/4, quit/1,
protocol_error/3, protocol_error/4, protocol_error/1]).
--export([not_found/1, assert_args_equivalence/4]).
+-export([not_found/1, absent/1, assert_args_equivalence/4]).
-export([dirty_read/1]).
-export([table_lookup/2, set_table_value/4]).
-export([r/3, r/2, r_arg/4, rs/1]).
@@ -111,6 +111,7 @@
-spec(protocol_error/1 ::
(rabbit_types:amqp_error()) -> channel_or_connection_exit()).
-spec(not_found/1 :: (rabbit_types:r(atom())) -> rabbit_types:channel_exit()).
+-spec(absent/1 :: (rabbit_types:amqqueue()) -> rabbit_types:channel_exit()).
-spec(assert_args_equivalence/4 :: (rabbit_framing:amqp_table(),
rabbit_framing:amqp_table(),
rabbit_types:r(any()), [binary()]) ->
@@ -266,6 +267,15 @@ protocol_error(#amqp_error{} = Error) ->
not_found(R) -> protocol_error(not_found, "no ~s", [rs(R)]).
+absent(#amqqueue{name = QueueName, pid = QPid, durable = true}) ->
+ %% The assertion of durability is mainly there because we mention
+ %% durability in the error message. That way we will hopefully
+ %% notice if at some future point our logic changes s.t. we get
+ %% here with non-durable queues.
+ protocol_error(not_found,
+ "home node '~s' of durable ~s is down or inaccessible",
+ [node(QPid), rs(QueueName)]).
+
type_class(byte) -> int;
type_class(short) -> int;
type_class(signedint) -> int;