Check if queue protected from deleted inside rabbit_amqqueue:with_delete
If queue is indeed protected its removal can be forced by calling with .
This commit is contained in:
		
							parent
							
								
									3c938aa3d5
								
							
						
					
					
						commit
						72b53437f2
					
				|  | @ -61,6 +61,10 @@ | |||
|          is_exclusive/1, | ||||
|          is_classic/1, | ||||
|          is_quorum/1, | ||||
|          is_internal/1, | ||||
|          internal_owner/1, | ||||
|          make_internal/1, | ||||
|          make_internal/2, | ||||
|          pattern_match_all/0, | ||||
|          pattern_match_on_name/1, | ||||
|          pattern_match_on_type/1, | ||||
|  | @ -76,6 +80,8 @@ | |||
| -define(is_backwards_compat_classic(T), | ||||
|         (T =:= classic orelse T =:= ?amqqueue_v1_type)). | ||||
| 
 | ||||
| -type amqqueue_options() ::  map() | ets:match_pattern(). | ||||
| 
 | ||||
| -record(amqqueue, { | ||||
|           %% immutable | ||||
|           name :: rabbit_amqqueue:name() | ets:match_pattern(), | ||||
|  | @ -106,7 +112,7 @@ | |||
|           slave_pids_pending_shutdown = [], %% reserved | ||||
|           %% secondary index | ||||
|           vhost :: rabbit_types:vhost() | undefined | ets:match_pattern(), | ||||
|           options = #{} :: map() | ets:match_pattern(), | ||||
|           options = #{} :: amqqueue_options(), | ||||
|           type = ?amqqueue_v1_type :: module() | ets:match_pattern(), | ||||
|           type_state = #{} :: map() | ets:match_pattern() | ||||
|          }). | ||||
|  | @ -349,6 +355,19 @@ get_arguments(#amqqueue{arguments = Args}) -> | |||
| set_arguments(#amqqueue{} = Queue, Args) -> | ||||
|     Queue#amqqueue{arguments = Args}. | ||||
| 
 | ||||
| % options | ||||
| 
 | ||||
| -spec get_options(amqqueue()) -> amqqueue_options(). | ||||
| 
 | ||||
| get_options(#amqqueue{options = Options}) -> | ||||
|     Options. | ||||
| 
 | ||||
| -spec set_options(amqqueue(), amqqueue_options()) -> amqqueue(). | ||||
| 
 | ||||
| set_options(#amqqueue{} = Queue, Options) -> | ||||
|     Queue#amqqueue{options = Options}. | ||||
| 
 | ||||
| 
 | ||||
| % decorators | ||||
| 
 | ||||
| -spec get_decorators(amqqueue()) -> [atom()] | none | undefined. | ||||
|  | @ -394,15 +413,6 @@ get_name(#amqqueue{name = Name}) -> Name. | |||
| set_name(#amqqueue{} = Queue, Name) -> | ||||
|     Queue#amqqueue{name = Name}. | ||||
| 
 | ||||
| -spec get_options(amqqueue()) -> map(). | ||||
| 
 | ||||
| get_options(#amqqueue{options = Options}) -> Options. | ||||
| 
 | ||||
| -spec set_options(amqqueue(), map()) -> amqqueue(). | ||||
| 
 | ||||
| set_options(#amqqueue{} = Queue, Options) -> | ||||
|     Queue#amqqueue{options = Options}. | ||||
| 
 | ||||
| % pid | ||||
| 
 | ||||
| -spec get_pid(amqqueue_v2()) -> pid() | ra_server_id() | none. | ||||
|  | @ -496,6 +506,27 @@ is_classic(Queue) -> | |||
| is_quorum(Queue) -> | ||||
|     get_type(Queue) =:= rabbit_quorum_queue. | ||||
| 
 | ||||
| -spec is_internal(amqqueue()) -> boolean(). | ||||
| 
 | ||||
| is_internal(#amqqueue{options = #{internal := true}}) -> true; | ||||
| is_internal(#amqqueue{}) -> false. | ||||
| 
 | ||||
| -spec internal_owner(amqqueue()) -> #resource{}. | ||||
| 
 | ||||
| internal_owner(#amqqueue{options = #{internal := true, | ||||
|                                      internal_owner := IOwner}}) -> | ||||
|     IOwner; | ||||
| internal_owner(#amqqueue{}) -> | ||||
|     undefined. | ||||
| 
 | ||||
| make_internal(Q = #amqqueue{options = Options}) when is_map(Options) -> | ||||
|     Q#amqqueue{options = maps:merge(Options, #{internal => true, | ||||
|                                                internal_owner => undefined})}. | ||||
| make_internal(Q = #amqqueue{options = Options}, Owner) | ||||
|   when is_map(Options) andalso is_record(Owner, resource) -> | ||||
|     Q#amqqueue{options = maps:merge(Options, #{internal => true, | ||||
|                                               interna_owner => Owner})}. | ||||
| 
 | ||||
| fields() -> | ||||
|     fields(?record_version). | ||||
| 
 | ||||
|  |  | |||
|  | @ -820,6 +820,35 @@ check_exclusive_access(Q, _ReaderPid, _MatchType) -> | |||
|       "match that of the original declaration.", | ||||
|       [rabbit_misc:rs(QueueName)]). | ||||
| 
 | ||||
| -spec check_internal(amqqueue:amqqueue(), rabbit_types:username()) -> | ||||
|           'ok' | rabbit_types:channel_exit(). | ||||
| check_internal(Q, Username) -> | ||||
|     case amqqueue:is_internal(Q) of | ||||
|         true -> | ||||
|             case Username of | ||||
|                 %% note cli delete command uses "cli_user" | ||||
|                 ?INTERNAL_USER -> | ||||
|                     ok; | ||||
|                 _ -> | ||||
|                     QueueName = amqqueue:get_name(Q), | ||||
|                     case amqqueue:internal_owner(Q) of | ||||
|                         undefined -> | ||||
|                             rabbit_misc:protocol_error( | ||||
|                               resource_locked, | ||||
|                               "Cannot delete protected ~ts.", | ||||
|                               [rabbit_misc:rs(QueueName)]); | ||||
|                         IOwner -> | ||||
|                             rabbit_misc:protocol_error( | ||||
|                               resource_locked, | ||||
|                               "Cannot delete protected ~ts. It was " | ||||
|                               "declared as an protected and can be deleted only by deleting the owner entity: ~ts", | ||||
|                               [rabbit_misc:rs(QueueName), rabbit_misc:rs(IOwner)]) | ||||
|                     end | ||||
|             end; | ||||
|         false -> | ||||
|             ok | ||||
|     end. | ||||
| 
 | ||||
| -spec with_exclusive_access_or_die(name(), pid(), qfun(A)) -> | ||||
|     A | rabbit_types:channel_exit(). | ||||
| with_exclusive_access_or_die(Name, ReaderPid, F) -> | ||||
|  | @ -1689,6 +1718,7 @@ delete_with(QueueName, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive) whe | |||
|     case with( | ||||
|            QueueName, | ||||
|            fun (Q) -> | ||||
|                 ok = check_internal(Q, Username), | ||||
|                 if CheckExclusive -> | ||||
|                     check_exclusive_access(Q, ConnPid); | ||||
|                 true -> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue