summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Radestock <matthias@rabbitmq.com>2012-10-24 00:07:12 +0100
committerMatthias Radestock <matthias@rabbitmq.com>2012-10-24 00:07:12 +0100
commit7a5c2bba14e02c1801ed30e16a5cce889b24d9c7 (patch)
treeed6c0903a566163232fca21d24ec4eebb1616904
parenta1681fe2227d2074b3e26fc9dfb1ba2f41219371 (diff)
downloadrabbitmq-server-7a5c2bba14e02c1801ed30e16a5cce889b24d9c7.tar.gz
better error messages for 'absent' queues on declaration
- change amqqueue:internal_declare to return {absent, Q} instead of 'not_found' - let this ripple through amqqueue_process:declare, stopping with {absent, Q} instead - that in in turn will end up in in amqqueue:declare/5. Instead of inovking misc:not_found(QName), which was EXITing, we make {absent, Q} part of the API. - at the call site in the channel we handle the new {absent, Q} case and produce a nice error message.
-rw-r--r--src/rabbit_amqqueue.erl22
-rw-r--r--src/rabbit_amqqueue_process.erl10
-rw-r--r--src/rabbit_channel.erl13
3 files changed, 27 insertions, 18 deletions
diff --git a/src/rabbit_amqqueue.erl b/src/rabbit_amqqueue.erl
index 6ad85b24..8ab9bc87 100644
--- a/src/rabbit_amqqueue.erl
+++ b/src/rabbit_amqqueue.erl
@@ -61,18 +61,19 @@
-type(ok_or_errors() ::
'ok' | {'error', [{'error' | 'exit' | 'throw', any()}]}).
-type(routing_result() :: 'routed' | 'unroutable').
--type(queue_or_not_found() :: rabbit_types:amqqueue() | 'not_found').
+-type(queue_or_absent() :: rabbit_types:amqqueue() |
+ {'absent', rabbit_types:amqqueue()}).
-spec(start/0 :: () -> [name()]).
-spec(stop/0 :: () -> 'ok').
-spec(declare/5 ::
(name(), boolean(), boolean(),
rabbit_framing:amqp_table(), rabbit_types:maybe(pid()))
- -> {'new' | 'existing', rabbit_types:amqqueue()} |
+ -> {'new' | 'existing' | 'absent', rabbit_types:amqqueue()} |
rabbit_types:channel_exit()).
-spec(internal_declare/2 ::
(rabbit_types:amqqueue(), boolean())
- -> queue_or_not_found() | rabbit_misc:thunk(queue_or_not_found())).
+ -> queue_or_absent() | rabbit_misc:thunk(queue_or_absent())).
-spec(update/2 ::
(name(),
fun((rabbit_types:amqqueue()) -> rabbit_types:amqqueue())) -> 'ok').
@@ -223,10 +224,7 @@ declare(QueueName, Durable, AutoDelete, Args, Owner) ->
gm_pids = []}),
{Node, _MNodes} = rabbit_mirror_queue_misc:suggested_queue_nodes(Q0),
Q1 = start_queue_process(Node, Q0),
- case gen_server2:call(Q1#amqqueue.pid, {init, false}, infinity) of
- not_found -> rabbit_misc:not_found(QueueName);
- Q2 -> Q2
- end.
+ gen_server2:call(Q1#amqqueue.pid, {init, false}, infinity).
internal_declare(Q, true) ->
rabbit_misc:execute_mnesia_tx_with_tail(
@@ -237,12 +235,12 @@ internal_declare(Q = #amqqueue{name = QueueName}, false) ->
case mnesia:wread({rabbit_queue, QueueName}) of
[] ->
case mnesia:read({rabbit_durable_queue, QueueName}) of
- [] -> Q1 = rabbit_policy:set(Q),
- ok = store_queue(Q1),
- B = add_default_binding(Q1),
- fun () -> B(), Q1 end;
+ [] -> Q1 = rabbit_policy:set(Q),
+ ok = store_queue(Q1),
+ B = add_default_binding(Q1),
+ fun () -> B(), Q1 end;
%% Q exists on stopped node
- [_] -> rabbit_misc:const(not_found)
+ [Q1] -> rabbit_misc:const({absent, Q1})
end;
[ExistingQ = #amqqueue{pid = QPid}] ->
case rabbit_misc:is_process_alive(QPid) of
diff --git a/src/rabbit_amqqueue_process.erl b/src/rabbit_amqqueue_process.erl
index 68f95778..40240cb1 100644
--- a/src/rabbit_amqqueue_process.erl
+++ b/src/rabbit_amqqueue_process.erl
@@ -196,9 +196,7 @@ declare(Recover, From, State = #q{q = Q,
backing_queue = BQ,
backing_queue_state = undefined}) ->
case rabbit_amqqueue:internal_declare(Q, Recover) of
- not_found ->
- {stop, normal, not_found, State};
- Q1 ->
+ #amqqueue{} = Q1 ->
case matches(Recover, Q, Q1) of
true ->
gen_server2:reply(From, {new, Q}),
@@ -216,8 +214,10 @@ declare(Recover, From, State = #q{q = Q,
noreply(State1);
false ->
{stop, normal, {existing, Q1}, State}
- end
- end.
+ end;
+ Err ->
+ {stop, normal, Err, State}
+ end.
matches(true, Q, Q) -> true;
matches(true, _Q, _Q1) -> false;
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index 0d13312b..276ad38f 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -423,6 +423,15 @@ 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,
@@ -960,7 +969,9 @@ handle_method(#'queue.declare'{queue = QueueNameBin,
{existing, _Q} ->
%% must have been created between the stat and the
%% declare. Loop around again.
- handle_method(Declare, none, State)
+ handle_method(Declare, none, State);
+ {absent, Q} ->
+ absent(Q)
end
end;