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_exclusive/1, | ||||||
|          is_classic/1, |          is_classic/1, | ||||||
|          is_quorum/1, |          is_quorum/1, | ||||||
|  |          is_internal/1, | ||||||
|  |          internal_owner/1, | ||||||
|  |          make_internal/1, | ||||||
|  |          make_internal/2, | ||||||
|          pattern_match_all/0, |          pattern_match_all/0, | ||||||
|          pattern_match_on_name/1, |          pattern_match_on_name/1, | ||||||
|          pattern_match_on_type/1, |          pattern_match_on_type/1, | ||||||
|  | @ -76,6 +80,8 @@ | ||||||
| -define(is_backwards_compat_classic(T), | -define(is_backwards_compat_classic(T), | ||||||
|         (T =:= classic orelse T =:= ?amqqueue_v1_type)). |         (T =:= classic orelse T =:= ?amqqueue_v1_type)). | ||||||
| 
 | 
 | ||||||
|  | -type amqqueue_options() ::  map() | ets:match_pattern(). | ||||||
|  | 
 | ||||||
| -record(amqqueue, { | -record(amqqueue, { | ||||||
|           %% immutable |           %% immutable | ||||||
|           name :: rabbit_amqqueue:name() | ets:match_pattern(), |           name :: rabbit_amqqueue:name() | ets:match_pattern(), | ||||||
|  | @ -106,7 +112,7 @@ | ||||||
|           slave_pids_pending_shutdown = [], %% reserved |           slave_pids_pending_shutdown = [], %% reserved | ||||||
|           %% secondary index |           %% secondary index | ||||||
|           vhost :: rabbit_types:vhost() | undefined | ets:match_pattern(), |           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 = ?amqqueue_v1_type :: module() | ets:match_pattern(), | ||||||
|           type_state = #{} :: map() | ets:match_pattern() |           type_state = #{} :: map() | ets:match_pattern() | ||||||
|          }). |          }). | ||||||
|  | @ -349,6 +355,19 @@ get_arguments(#amqqueue{arguments = Args}) -> | ||||||
| set_arguments(#amqqueue{} = Queue, Args) -> | set_arguments(#amqqueue{} = Queue, Args) -> | ||||||
|     Queue#amqqueue{arguments = 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 | % decorators | ||||||
| 
 | 
 | ||||||
| -spec get_decorators(amqqueue()) -> [atom()] | none | undefined. | -spec get_decorators(amqqueue()) -> [atom()] | none | undefined. | ||||||
|  | @ -394,15 +413,6 @@ get_name(#amqqueue{name = Name}) -> Name. | ||||||
| set_name(#amqqueue{} = Queue, Name) -> | set_name(#amqqueue{} = Queue, Name) -> | ||||||
|     Queue#amqqueue{name = 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 | % pid | ||||||
| 
 | 
 | ||||||
| -spec get_pid(amqqueue_v2()) -> pid() | ra_server_id() | none. | -spec get_pid(amqqueue_v2()) -> pid() | ra_server_id() | none. | ||||||
|  | @ -496,6 +506,27 @@ is_classic(Queue) -> | ||||||
| is_quorum(Queue) -> | is_quorum(Queue) -> | ||||||
|     get_type(Queue) =:= rabbit_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() -> | ||||||
|     fields(?record_version). |     fields(?record_version). | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -820,6 +820,35 @@ check_exclusive_access(Q, _ReaderPid, _MatchType) -> | ||||||
|       "match that of the original declaration.", |       "match that of the original declaration.", | ||||||
|       [rabbit_misc:rs(QueueName)]). |       [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)) -> | -spec with_exclusive_access_or_die(name(), pid(), qfun(A)) -> | ||||||
|     A | rabbit_types:channel_exit(). |     A | rabbit_types:channel_exit(). | ||||||
| with_exclusive_access_or_die(Name, ReaderPid, F) -> | with_exclusive_access_or_die(Name, ReaderPid, F) -> | ||||||
|  | @ -1689,6 +1718,7 @@ delete_with(QueueName, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive) whe | ||||||
|     case with( |     case with( | ||||||
|            QueueName, |            QueueName, | ||||||
|            fun (Q) -> |            fun (Q) -> | ||||||
|  |                 ok = check_internal(Q, Username), | ||||||
|                 if CheckExclusive -> |                 if CheckExclusive -> | ||||||
|                     check_exclusive_access(Q, ConnPid); |                     check_exclusive_access(Q, ConnPid); | ||||||
|                 true -> |                 true -> | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue