From 54bce9308b67ebfeb77c4090a2ed79aef31ae19b Mon Sep 17 00:00:00 2001 From: Simon MacMullen Date: Wed, 10 Sep 2014 17:35:53 +0100 Subject: Sensible errors on queue durable / auto_delete inequivalence. --- src/rabbit_amqqueue.erl | 18 ++++++++---------- src/rabbit_misc.erl | 32 +++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/rabbit_amqqueue.erl b/src/rabbit_amqqueue.erl index 692179fc..5bd93ea2 100644 --- a/src/rabbit_amqqueue.erl +++ b/src/rabbit_amqqueue.erl @@ -405,16 +405,14 @@ with_or_die(Name, F) -> ({absent, Q}) -> rabbit_misc:absent(Q) end). -assert_equivalence(#amqqueue{durable = Durable, - auto_delete = AutoDelete} = Q, - Durable, AutoDelete, RequiredArgs, Owner) -> - assert_args_equivalence(Q, RequiredArgs), - check_exclusive_access(Q, Owner, strict); -assert_equivalence(#amqqueue{name = QueueName}, - _Durable, _AutoDelete, _RequiredArgs, _Owner) -> - rabbit_misc:protocol_error( - precondition_failed, "parameters for ~s not equivalent", - [rabbit_misc:rs(QueueName)]). +assert_equivalence(#amqqueue{name = QName, + durable = Durable, + auto_delete = AD} = Q, + Durable1, AD1, Args1, Owner) -> + rabbit_misc:assert_field_equivalence(Durable, Durable1, QName, durable), + rabbit_misc:assert_field_equivalence(AD, AD1, QName, auto_delete), + assert_args_equivalence(Q, Args1), + check_exclusive_access(Q, Owner, strict). check_exclusive_access(Q, Owner) -> check_exclusive_access(Q, Owner, lax). diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index c4148bbf..bd8ba42e 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -22,7 +22,7 @@ -export([die/1, frame_error/2, amqp_error/4, quit/1, protocol_error/3, protocol_error/4, protocol_error/1]). -export([not_found/1, absent/1]). --export([type_class/1, assert_args_equivalence/4]). +-export([type_class/1, assert_args_equivalence/4, assert_field_equivalence/4]). -export([dirty_read/1]). -export([table_lookup/2, set_table_value/4]). -export([r/3, r/2, r_arg/4, rs/1]). @@ -125,6 +125,9 @@ rabbit_framing:amqp_table(), rabbit_types:r(any()), [binary()]) -> 'ok' | rabbit_types:connection_exit()). +-spec(assert_field_equivalence/4 :: + (any(), any(), rabbit_types:r(any()), atom()) -> + 'ok' | rabbit_types:connection_exit()). -spec(dirty_read/1 :: ({atom(), any()}) -> rabbit_types:ok_or_error2(any(), 'not_found')). -spec(table_lookup/2 :: @@ -316,11 +319,6 @@ assert_args_equivalence(Orig, New, Name, Keys) -> assert_args_equivalence1(Orig, New, Name, Key) -> {Orig1, New1} = {table_lookup(Orig, Key), table_lookup(New, Key)}, - FailureFun = fun () -> - protocol_error(precondition_failed, "inequivalent arg '~s'" - "for ~s: received ~s but current is ~s", - [Key, rs(Name), val(New1), val(Orig1)]) - end, case {Orig1, New1} of {Same, Same} -> ok; @@ -328,12 +326,22 @@ assert_args_equivalence1(Orig, New, Name, Key) -> case type_class(OrigType) == type_class(NewType) andalso OrigVal == NewVal of true -> ok; - false -> FailureFun() + false -> assert_field_equivalence(OrigVal, NewVal, Name, Key) end; {_, _} -> - FailureFun() + assert_field_equivalence(Orig, New, Name, Key) end. +assert_field_equivalence(_Orig, _Orig, _Name, _Key) -> + ok; +assert_field_equivalence(Orig, New, Name, Key) -> + equivalence_fail(Orig, New, Name, Key). + +equivalence_fail(Orig, New, Name, Key) -> + protocol_error(precondition_failed, "inequivalent arg '~s' " + "for ~s: received ~s but current is ~s", + [Key, rs(Name), val(New), val(Orig)]). + val(undefined) -> "none"; val({Type, Value}) -> @@ -341,7 +349,13 @@ val({Type, Value}) -> true -> "~s"; false -> "~w" end, - format("the value '" ++ ValFmt ++ "' of type '~s'", [Value, Type]). + format("the value '" ++ ValFmt ++ "' of type '~s'", [Value, Type]); +val(Value) -> + ValFmt = case is_binary(Value) of + true -> "~s"; + false -> "~w" + end, + format(ValFmt, [Value]). %% Normally we'd call mnesia:dirty_read/1 here, but that is quite %% expensive due to general mnesia overheads (figuring out table types -- cgit v1.2.1 From 965dad72f59a767d9d6b1343eaea810a5f13c39e Mon Sep 17 00:00:00 2001 From: Simon MacMullen Date: Wed, 10 Sep 2014 17:45:49 +0100 Subject: ...and the same for exchanges. --- src/rabbit_exchange.erl | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/rabbit_exchange.erl b/src/rabbit_exchange.erl index f184174c..5448cb01 100644 --- a/src/rabbit_exchange.erl +++ b/src/rabbit_exchange.erl @@ -214,19 +214,18 @@ check_type(TypeBin) -> end end. -assert_equivalence(X = #exchange{ durable = Durable, +assert_equivalence(X = #exchange{ name = XName, + durable = Durable, auto_delete = AutoDelete, internal = Internal, type = Type}, - Type, Durable, AutoDelete, Internal, RequiredArgs) -> - (type_to_module(Type)):assert_args_equivalence(X, RequiredArgs); -assert_equivalence(#exchange{ name = Name }, - _Type, _Durable, _Internal, _AutoDelete, _Args) -> - rabbit_misc:protocol_error( - precondition_failed, - "cannot redeclare ~s with different type, durable, " - "internal or autodelete value", - [rabbit_misc:rs(Name)]). + ReqType, ReqDurable, ReqAutoDelete, ReqInternal, ReqArgs) -> + AFE = fun rabbit_misc:assert_field_equivalence/4, + AFE(Type, ReqType, XName, type), + AFE(Durable, ReqDurable, XName, durable), + AFE(AutoDelete, ReqAutoDelete, XName, auto_delete), + AFE(Internal, ReqInternal, XName, internal), + (type_to_module(Type)):assert_args_equivalence(X, ReqArgs). assert_args_equivalence(#exchange{ name = Name, arguments = Args }, RequiredArgs) -> -- cgit v1.2.1 From 1642d52183224568471c1210a1ee2b550b44dd6b Mon Sep 17 00:00:00 2001 From: Simon MacMullen Date: Wed, 10 Sep 2014 17:47:19 +0100 Subject: Quotes. --- src/rabbit_misc.erl | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl index bd8ba42e..58d53611 100644 --- a/src/rabbit_misc.erl +++ b/src/rabbit_misc.erl @@ -351,11 +351,10 @@ val({Type, Value}) -> end, format("the value '" ++ ValFmt ++ "' of type '~s'", [Value, Type]); val(Value) -> - ValFmt = case is_binary(Value) of - true -> "~s"; - false -> "~w" - end, - format(ValFmt, [Value]). + format(case is_binary(Value) of + true -> "'~s'"; + false -> "'~w'" + end, [Value]). %% Normally we'd call mnesia:dirty_read/1 here, but that is quite %% expensive due to general mnesia overheads (figuring out table types -- cgit v1.2.1