Skip to content

Commit 72b5343

Browse files
ikavgodeadtrickster
authored andcommitted
Check if queue protected from deleted inside rabbit_amqqueue:with_delete
If queue is indeed protected its removal can be forced by calling with .
1 parent 3c938aa commit 72b5343

File tree

2 files changed

+71
-10
lines changed

2 files changed

+71
-10
lines changed

deps/rabbit/src/amqqueue.erl

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
is_exclusive/1,
6262
is_classic/1,
6363
is_quorum/1,
64+
is_internal/1,
65+
internal_owner/1,
66+
make_internal/1,
67+
make_internal/2,
6468
pattern_match_all/0,
6569
pattern_match_on_name/1,
6670
pattern_match_on_type/1,
@@ -76,6 +80,8 @@
7680
-define(is_backwards_compat_classic(T),
7781
(T =:= classic orelse T =:= ?amqqueue_v1_type)).
7882

83+
-type amqqueue_options() :: map() | ets:match_pattern().
84+
7985
-record(amqqueue, {
8086
%% immutable
8187
name :: rabbit_amqqueue:name() | ets:match_pattern(),
@@ -106,7 +112,7 @@
106112
slave_pids_pending_shutdown = [], %% reserved
107113
%% secondary index
108114
vhost :: rabbit_types:vhost() | undefined | ets:match_pattern(),
109-
options = #{} :: map() | ets:match_pattern(),
115+
options = #{} :: amqqueue_options(),
110116
type = ?amqqueue_v1_type :: module() | ets:match_pattern(),
111117
type_state = #{} :: map() | ets:match_pattern()
112118
}).
@@ -349,6 +355,19 @@ get_arguments(#amqqueue{arguments = Args}) ->
349355
set_arguments(#amqqueue{} = Queue, Args) ->
350356
Queue#amqqueue{arguments = Args}.
351357

358+
% options
359+
360+
-spec get_options(amqqueue()) -> amqqueue_options().
361+
362+
get_options(#amqqueue{options = Options}) ->
363+
Options.
364+
365+
-spec set_options(amqqueue(), amqqueue_options()) -> amqqueue().
366+
367+
set_options(#amqqueue{} = Queue, Options) ->
368+
Queue#amqqueue{options = Options}.
369+
370+
352371
% decorators
353372

354373
-spec get_decorators(amqqueue()) -> [atom()] | none | undefined.
@@ -394,15 +413,6 @@ get_name(#amqqueue{name = Name}) -> Name.
394413
set_name(#amqqueue{} = Queue, Name) ->
395414
Queue#amqqueue{name = Name}.
396415

397-
-spec get_options(amqqueue()) -> map().
398-
399-
get_options(#amqqueue{options = Options}) -> Options.
400-
401-
-spec set_options(amqqueue(), map()) -> amqqueue().
402-
403-
set_options(#amqqueue{} = Queue, Options) ->
404-
Queue#amqqueue{options = Options}.
405-
406416
% pid
407417

408418
-spec get_pid(amqqueue_v2()) -> pid() | ra_server_id() | none.
@@ -496,6 +506,27 @@ is_classic(Queue) ->
496506
is_quorum(Queue) ->
497507
get_type(Queue) =:= rabbit_quorum_queue.
498508

509+
-spec is_internal(amqqueue()) -> boolean().
510+
511+
is_internal(#amqqueue{options = #{internal := true}}) -> true;
512+
is_internal(#amqqueue{}) -> false.
513+
514+
-spec internal_owner(amqqueue()) -> #resource{}.
515+
516+
internal_owner(#amqqueue{options = #{internal := true,
517+
internal_owner := IOwner}}) ->
518+
IOwner;
519+
internal_owner(#amqqueue{}) ->
520+
undefined.
521+
522+
make_internal(Q = #amqqueue{options = Options}) when is_map(Options) ->
523+
Q#amqqueue{options = maps:merge(Options, #{internal => true,
524+
internal_owner => undefined})}.
525+
make_internal(Q = #amqqueue{options = Options}, Owner)
526+
when is_map(Options) andalso is_record(Owner, resource) ->
527+
Q#amqqueue{options = maps:merge(Options, #{internal => true,
528+
interna_owner => Owner})}.
529+
499530
fields() ->
500531
fields(?record_version).
501532

deps/rabbit/src/rabbit_amqqueue.erl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,35 @@ check_exclusive_access(Q, _ReaderPid, _MatchType) ->
820820
"match that of the original declaration.",
821821
[rabbit_misc:rs(QueueName)]).
822822

823+
-spec check_internal(amqqueue:amqqueue(), rabbit_types:username()) ->
824+
'ok' | rabbit_types:channel_exit().
825+
check_internal(Q, Username) ->
826+
case amqqueue:is_internal(Q) of
827+
true ->
828+
case Username of
829+
%% note cli delete command uses "cli_user"
830+
?INTERNAL_USER ->
831+
ok;
832+
_ ->
833+
QueueName = amqqueue:get_name(Q),
834+
case amqqueue:internal_owner(Q) of
835+
undefined ->
836+
rabbit_misc:protocol_error(
837+
resource_locked,
838+
"Cannot delete protected ~ts.",
839+
[rabbit_misc:rs(QueueName)]);
840+
IOwner ->
841+
rabbit_misc:protocol_error(
842+
resource_locked,
843+
"Cannot delete protected ~ts. It was "
844+
"declared as an protected and can be deleted only by deleting the owner entity: ~ts",
845+
[rabbit_misc:rs(QueueName), rabbit_misc:rs(IOwner)])
846+
end
847+
end;
848+
false ->
849+
ok
850+
end.
851+
823852
-spec with_exclusive_access_or_die(name(), pid(), qfun(A)) ->
824853
A | rabbit_types:channel_exit().
825854
with_exclusive_access_or_die(Name, ReaderPid, F) ->
@@ -1689,6 +1718,7 @@ delete_with(QueueName, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive) whe
16891718
case with(
16901719
QueueName,
16911720
fun (Q) ->
1721+
ok = check_internal(Q, Username),
16921722
if CheckExclusive ->
16931723
check_exclusive_access(Q, ConnPid);
16941724
true ->

0 commit comments

Comments
 (0)