@@ -284,20 +284,15 @@ terminating(Reason, State = #ch{channel = Channel, reader_pid = Reader}) ->
284284 Reader ! {channel_exit , Channel , Reason },
285285 State # ch {state = terminating }.
286286
287- return_queue_declare_ok (State , NoWait , Q ) ->
288- NewState = State # ch { most_recently_declared_queue =
289- ( Q # amqqueue . name ) # resource . name },
287+ return_queue_declare_ok (# resource { name = ActualName },
288+ NoWait , MessageCount , ConsumerCount , State ) ->
289+ NewState = State # ch { most_recently_declared_queue = ActualName },
290290 case NoWait of
291291 true -> {noreply , NewState };
292- false ->
293- {ok , ActualName , MessageCount , ConsumerCount } =
294- rabbit_misc :with_exit_handler (
295- fun () -> {ok , Q # amqqueue .name , 0 , 0 } end ,
296- fun () -> rabbit_amqqueue :stat (Q ) end ),
297- Reply = # 'queue.declare_ok' {queue = ActualName # resource .name ,
298- message_count = MessageCount ,
299- consumer_count = ConsumerCount },
300- {reply , Reply , NewState }
292+ false -> Reply = # 'queue.declare_ok' {queue = ActualName ,
293+ message_count = MessageCount ,
294+ consumer_count = ConsumerCount },
295+ {reply , Reply , NewState }
301296 end .
302297
303298check_resource_access (Username , Resource , Perm ) ->
@@ -329,19 +324,6 @@ check_write_permitted(Resource, #ch{ username = Username}) ->
329324check_read_permitted (Resource , # ch { username = Username }) ->
330325 check_resource_access (Username , Resource , read ).
331326
332- check_exclusive_access (# amqqueue {exclusive_owner = Owner }, Owner , _MatchType ) ->
333- ok ;
334- check_exclusive_access (# amqqueue {exclusive_owner = none }, _ReaderPid , lax ) ->
335- ok ;
336- check_exclusive_access (# amqqueue {name = QName }, _ReaderPid , _MatchType ) ->
337- rabbit_misc :protocol_error (
338- resource_locked ,
339- " cannot obtain exclusive access to locked ~s " , [rabbit_misc :rs (QName )]).
340-
341- with_exclusive_access_or_die (QName , ReaderPid , F ) ->
342- rabbit_amqqueue :with_or_die (
343- QName , fun (Q ) -> check_exclusive_access (Q , ReaderPid , lax ), F (Q ) end ).
344-
345327expand_queue_name_shortcut (<<>>, # ch { most_recently_declared_queue = <<>> }) ->
346328 rabbit_misc :protocol_error (
347329 not_found , " no previously declared queue" , []);
@@ -444,12 +426,9 @@ handle_method(#'basic.publish'{exchange = ExchangeNameBin,
444426 Exchange ,
445427 rabbit_basic :delivery (Mandatory , Immediate , TxnKey , Message )),
446428 case RoutingRes of
447- routed ->
448- ok ;
449- unroutable ->
450- ok = basic_return (Message , WriterPid , no_route );
451- not_delivered ->
452- ok = basic_return (Message , WriterPid , no_consumers )
429+ routed -> ok ;
430+ unroutable -> ok = basic_return (Message , WriterPid , no_route );
431+ not_delivered -> ok = basic_return (Message , WriterPid , no_consumers )
453432 end ,
454433 {noreply , case TxnKey of
455434 none -> State ;
@@ -480,7 +459,7 @@ handle_method(#'basic.get'{queue = QueueNameBin,
480459 next_tag = DeliveryTag }) ->
481460 QueueName = expand_queue_name_shortcut (QueueNameBin , State ),
482461 check_read_permitted (QueueName , State ),
483- case with_exclusive_access_or_die (
462+ case rabbit_amqqueue : with_exclusive_access_or_die (
484463 QueueName , ReaderPid ,
485464 fun (Q ) -> rabbit_amqqueue :basic_get (Q , self (), NoAck ) end ) of
486465 {ok , MessageCount ,
@@ -499,7 +478,7 @@ handle_method(#'basic.get'{queue = QueueNameBin,
499478 Content ),
500479 {noreply , State1 # ch {next_tag = DeliveryTag + 1 }};
501480 empty ->
502- {reply , # 'basic.get_empty' {cluster_id = <<>> }, State }
481+ {reply , # 'basic.get_empty' {}, State }
503482 end ;
504483
505484handle_method (# 'basic.consume' {queue = QueueNameBin ,
@@ -524,7 +503,7 @@ handle_method(#'basic.consume'{queue = QueueNameBin,
524503 % % We get the queue process to send the consume_ok on our
525504 % % behalf. This is for symmetry with basic.cancel - see
526505 % % the comment in that method for why.
527- case with_exclusive_access_or_die (
506+ case rabbit_amqqueue : with_exclusive_access_or_die (
528507 QueueName , ReaderPid ,
529508 fun (Q ) ->
530509 rabbit_amqqueue :basic_consume (
@@ -716,45 +695,48 @@ handle_method(#'queue.declare'{queue = QueueNameBin,
716695 exclusive = ExclusiveDeclare ,
717696 auto_delete = AutoDelete ,
718697 nowait = NoWait ,
719- arguments = Args },
698+ arguments = Args } = Declare ,
720699 _ , State = # ch {virtual_host = VHostPath ,
721700 reader_pid = ReaderPid ,
722701 queue_collector_pid = CollectorPid }) ->
723702 Owner = case ExclusiveDeclare of
724703 true -> ReaderPid ;
725704 false -> none
726705 end ,
727- % % We use this in both branches, because queue_declare may yet return an
728- % % existing queue.
729706 ActualNameBin = case QueueNameBin of
730707 <<>> -> rabbit_guid :binstring_guid (" amq.gen" );
731708 Other -> check_name ('queue' , Other )
732709 end ,
733710 QueueName = rabbit_misc :r (VHostPath , queue , ActualNameBin ),
734- Q = case rabbit_amqqueue :declare (QueueName , Durable , AutoDelete ,
735- Args , Owner ) of
736- # amqqueue {name = QueueName ,
737- durable = Durable1 ,
738- auto_delete = AutoDelete1 } = Q1
739- when Durable =:= Durable1 , AutoDelete =:= AutoDelete1 ->
740- check_exclusive_access (Q1 , Owner , strict ),
741- check_configure_permitted (QueueName , State ),
742- % % We need to notify the reader within the channel
743- % % process so that we can be sure there are no
744- % % outstanding exclusive queues being declared as the
745- % % connection shuts down.
746- case Owner of
747- none -> ok ;
748- _ -> ok = rabbit_reader_queue_collector :register_exclusive_queue (CollectorPid , Q1 )
749- end ,
750- Q1 ;
751- % % non-equivalence trumps exclusivity arbitrarily
752- # amqqueue {name = QueueName } ->
753- rabbit_misc :protocol_error (
754- not_allowed , " parameters for ~s not equivalent" ,
755- [rabbit_misc :rs (QueueName )])
756- end ,
757- return_queue_declare_ok (State , NoWait , Q );
711+ check_configure_permitted (QueueName , State ),
712+ case rabbit_amqqueue :with (
713+ QueueName ,
714+ fun (Q ) -> ok = rabbit_amqqueue :assert_equivalence (
715+ Q , Durable , AutoDelete , Args , Owner ),
716+ rabbit_amqqueue :stat (Q )
717+ end ) of
718+ {ok , MessageCount , ConsumerCount } ->
719+ return_queue_declare_ok (QueueName , NoWait , MessageCount ,
720+ ConsumerCount , State );
721+ {error , not_found } ->
722+ case rabbit_amqqueue :declare (QueueName , Durable , AutoDelete ,
723+ Args , Owner ) of
724+ {new , Q = # amqqueue {}} ->
725+ % % We need to notify the reader within the channel
726+ % % process so that we can be sure there are no
727+ % % outstanding exclusive queues being declared as
728+ % % the connection shuts down.
729+ ok = case Owner of
730+ none -> ok ;
731+ _ -> rabbit_reader_queue_collector :register_exclusive_queue (CollectorPid , Q )
732+ end ,
733+ return_queue_declare_ok (QueueName , NoWait , 0 , 0 , State );
734+ {existing , _Q } ->
735+ % % must have been created between the stat and the
736+ % % declare. Loop around again.
737+ handle_method (Declare , none , State )
738+ end
739+ end ;
758740
759741handle_method (# 'queue.declare' {queue = QueueNameBin ,
760742 passive = true ,
@@ -763,8 +745,12 @@ handle_method(#'queue.declare'{queue = QueueNameBin,
763745 reader_pid = ReaderPid }) ->
764746 QueueName = rabbit_misc :r (VHostPath , queue , QueueNameBin ),
765747 check_configure_permitted (QueueName , State ),
766- Q = with_exclusive_access_or_die (QueueName , ReaderPid , fun (Q ) -> Q end ),
767- return_queue_declare_ok (State , NoWait , Q );
748+ {{ok , MessageCount , ConsumerCount }, # amqqueue {} = Q } =
749+ rabbit_amqqueue :with_or_die (
750+ QueueName , fun (Q ) -> {rabbit_amqqueue :stat (Q ), Q } end ),
751+ ok = rabbit_amqqueue :check_exclusive_access (Q , ReaderPid ),
752+ return_queue_declare_ok (QueueName , NoWait , MessageCount , ConsumerCount ,
753+ State );
768754
769755handle_method (# 'queue.delete' {queue = QueueNameBin ,
770756 if_unused = IfUnused ,
@@ -773,7 +759,7 @@ handle_method(#'queue.delete'{queue = QueueNameBin,
773759 _ , State = # ch {reader_pid = ReaderPid }) ->
774760 QueueName = expand_queue_name_shortcut (QueueNameBin , State ),
775761 check_configure_permitted (QueueName , State ),
776- case with_exclusive_access_or_die (
762+ case rabbit_amqqueue : with_exclusive_access_or_die (
777763 QueueName , ReaderPid ,
778764 fun (Q ) -> rabbit_amqqueue :delete (Q , IfUnused , IfEmpty ) end ) of
779765 {error , in_use } ->
@@ -809,7 +795,7 @@ handle_method(#'queue.purge'{queue = QueueNameBin,
809795 _ , State = # ch {reader_pid = ReaderPid }) ->
810796 QueueName = expand_queue_name_shortcut (QueueNameBin , State ),
811797 check_read_permitted (QueueName , State ),
812- {ok , PurgedMessageCount } = with_exclusive_access_or_die (
798+ {ok , PurgedMessageCount } = rabbit_amqqueue : with_exclusive_access_or_die (
813799 QueueName , ReaderPid ,
814800 fun (Q ) -> rabbit_amqqueue :purge (Q ) end ),
815801 return_ok (State , NoWait ,
@@ -917,7 +903,9 @@ binding_action(Fun, ExchangeNameBin, QueueNameBin, RoutingKey, Arguments,
917903 ExchangeName = rabbit_misc :r (VHostPath , exchange , ExchangeNameBin ),
918904 check_read_permitted (ExchangeName , State ),
919905 case Fun (ExchangeName , QueueName , ActualRoutingKey , Arguments ,
920- fun (_X , Q ) -> check_exclusive_access (Q , ReaderPid , lax ) end ) of
906+ fun (_X , Q ) ->
907+ rabbit_amqqueue :check_exclusive_access (Q , ReaderPid )
908+ end ) of
921909 {error , exchange_not_found } ->
922910 rabbit_misc :not_found (ExchangeName );
923911 {error , queue_not_found } ->
0 commit comments