|
53 | 53 | -export([delete_crashed/1,
|
54 | 54 | delete_crashed/2,
|
55 | 55 | delete_crashed_internal/2]).
|
56 |
| - |
| 56 | +-export([delete_with/4, delete_with/6]). |
57 | 57 | -export([pid_of/1, pid_of/2]).
|
| 58 | +-export([pid_or_crashed/2]). |
58 | 59 | -export([mark_local_durable_queues_stopped/1]).
|
59 | 60 |
|
60 | 61 | -export([rebalance/3]).
|
|
70 | 71 |
|
71 | 72 | -export([prepend_extra_bcc/1]).
|
72 | 73 |
|
| 74 | +-export([kill_queue/2, kill_queue/3, kill_queue_hard/2, kill_queue_hard/3]). |
| 75 | + |
73 | 76 | %% internal
|
74 | 77 | -export([internal_declare/2, internal_delete/2, run_backing_queue/3,
|
75 | 78 | set_ram_duration_target/2, set_maximum_since_use/2,
|
|
108 | 111 | -define(CONSUMER_INFO_KEYS,
|
109 | 112 | [queue_name, channel_pid, consumer_tag, ack_required, prefetch_count,
|
110 | 113 | active, activity_status, arguments]).
|
| 114 | +-define(KILL_QUEUE_DELAY_INTERVAL, 100). |
111 | 115 |
|
112 | 116 | warn_file_limit() ->
|
113 | 117 | DurableQueues = find_recoverable_queues(),
|
@@ -1581,6 +1585,51 @@ delete_immediately_by_resource(Resources) ->
|
1581 | 1585 | delete(Q, IfUnused, IfEmpty, ActingUser) ->
|
1582 | 1586 | rabbit_queue_type:delete(Q, IfUnused, IfEmpty, ActingUser).
|
1583 | 1587 |
|
| 1588 | +-spec delete_with(amqqueue:amqqueue() | name(), boolean(), boolean(), rabbit_types:username()) -> |
| 1589 | + rabbit_types:ok(integer()) | rabbit_misc:channel_or_connection_exit(). |
| 1590 | +delete_with(QueueName, IfUnused, IfEmpty, ActingUser) -> |
| 1591 | + delete_with(QueueName, undefined, IfUnused, IfEmpty, ActingUser, false). |
| 1592 | + |
| 1593 | +-spec delete_with(amqqueue:amqqueue() | name(), pid() | undefined, boolean(), boolean(), rabbit_types:username(), boolean()) -> |
| 1594 | + rabbit_types:ok(integer()) | rabbit_misc:channel_or_connection_exit(). |
| 1595 | +delete_with(AMQQueue, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive) when ?is_amqqueue(AMQQueue) -> |
| 1596 | + QueueName = amqqueue:get_name(AMQQueue), |
| 1597 | + delete_with(QueueName, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive); |
| 1598 | +delete_with(QueueName, ConnPid, IfUnused, IfEmpty, Username, CheckExclusive) when is_record(QueueName, resource) -> |
| 1599 | + case with( |
| 1600 | + QueueName, |
| 1601 | + fun (Q) -> |
| 1602 | + if CheckExclusive -> |
| 1603 | + check_exclusive_access(Q, ConnPid); |
| 1604 | + true -> |
| 1605 | + ok |
| 1606 | + end, |
| 1607 | + rabbit_queue_type:delete(Q, IfUnused, IfEmpty, Username) |
| 1608 | + end, |
| 1609 | + fun (not_found) -> |
| 1610 | + {ok, 0}; |
| 1611 | + ({absent, Q, crashed}) -> |
| 1612 | + _ = delete_crashed(Q, Username), |
| 1613 | + {ok, 0}; |
| 1614 | + ({absent, Q, stopped}) -> |
| 1615 | + _ = delete_crashed(Q, Username), |
| 1616 | + {ok, 0}; |
| 1617 | + ({absent, Q, Reason}) -> |
| 1618 | + absent(Q, Reason) |
| 1619 | + end) of |
| 1620 | + {error, in_use} -> |
| 1621 | + rabbit_misc:precondition_failed("~ts in use", [rabbit_misc:rs(QueueName)]); |
| 1622 | + {error, not_empty} -> |
| 1623 | + rabbit_misc:precondition_failed("~ts not empty", [rabbit_misc:rs(QueueName)]); |
| 1624 | + {error, {exit, _, _}} -> |
| 1625 | + %% rabbit_amqqueue:delete()/delegate:invoke might return {error, {exit, _, _}} |
| 1626 | + {ok, 0}; |
| 1627 | + {ok, Count} -> |
| 1628 | + {ok, Count}; |
| 1629 | + {protocol_error, Type, Reason, ReasonArgs} -> |
| 1630 | + rabbit_misc:protocol_error(Type, Reason, ReasonArgs) |
| 1631 | + end. |
| 1632 | + |
1584 | 1633 | %% delete_crashed* INCLUDED FOR BACKWARDS COMPATBILITY REASONS
|
1585 | 1634 | delete_crashed(Q) when ?amqqueue_is_classic(Q) ->
|
1586 | 1635 | rabbit_classic_queue:delete_crashed(Q).
|
@@ -2039,3 +2088,61 @@ get_bcc_queue(Q, BCCName) ->
|
2039 | 2088 | #resource{virtual_host = VHost} = amqqueue:get_name(Q),
|
2040 | 2089 | BCCQueueName = rabbit_misc:r(VHost, queue, BCCName),
|
2041 | 2090 | rabbit_amqqueue:lookup(BCCQueueName).
|
| 2091 | + |
| 2092 | +-spec kill_queue_hard(node(), name()) -> ok. |
| 2093 | +kill_queue_hard(Node, QRes = #resource{kind = queue}) -> |
| 2094 | + kill_queue_hard(Node, QRes, boom). |
| 2095 | + |
| 2096 | +-spec kill_queue_hard(node(), name(), atom()) -> ok. |
| 2097 | +kill_queue_hard(Node, QRes = #resource{kind = queue}, Reason) -> |
| 2098 | + case kill_queue(Node, QRes, Reason) of |
| 2099 | + crashed -> ok; |
| 2100 | + stopped -> ok; |
| 2101 | + NewPid when is_pid(NewPid) -> |
| 2102 | + timer:sleep(?KILL_QUEUE_DELAY_INTERVAL), |
| 2103 | + kill_queue_hard(Node, QRes, Reason); |
| 2104 | + Error -> Error |
| 2105 | + end. |
| 2106 | + |
| 2107 | +-spec kill_queue(node(), name()) -> pid() | crashed | stopped | rabbit_types:error(term()). |
| 2108 | +kill_queue(Node, QRes = #resource{kind = queue}) -> |
| 2109 | + kill_queue(Node, QRes, boom). |
| 2110 | + |
| 2111 | +-spec kill_queue(node(), name(), atom()) -> pid() | crashed | stopped | rabbit_types:error(term()). |
| 2112 | +kill_queue(Node, QRes = #resource{kind = queue}, Reason = shutdown) -> |
| 2113 | + Pid1 = pid_or_crashed(Node, QRes), |
| 2114 | + exit(Pid1, Reason), |
| 2115 | + rabbit_amqqueue_control:await_state(Node, QRes, stopped), |
| 2116 | + stopped; |
| 2117 | +kill_queue(Node, QRes = #resource{kind = queue}, Reason) -> |
| 2118 | + case pid_or_crashed(Node, QRes) of |
| 2119 | + Pid1 when is_pid(Pid1) -> |
| 2120 | + exit(Pid1, Reason), |
| 2121 | + rabbit_amqqueue_control:await_new_pid(Node, QRes, Pid1); |
| 2122 | + crashed -> |
| 2123 | + crashed; |
| 2124 | + Error -> |
| 2125 | + Error |
| 2126 | + end. |
| 2127 | + |
| 2128 | +-spec pid_or_crashed(node(), name()) -> pid() | crashed | rabbit_types:error(term()). |
| 2129 | +pid_or_crashed(Node, QRes = #resource{virtual_host = VHost, kind = queue}) -> |
| 2130 | + case rpc:call(Node, rabbit_amqqueue, lookup, [QRes]) of |
| 2131 | + {ok, Q} -> |
| 2132 | + QPid = amqqueue:get_pid(Q), |
| 2133 | + State = amqqueue:get_state(Q), |
| 2134 | + case State of |
| 2135 | + crashed -> |
| 2136 | + case rabbit_amqqueue_sup_sup:find_for_vhost(VHost, Node) of |
| 2137 | + {error, {queue_supervisor_not_found, _}} -> {error, no_sup}; |
| 2138 | + {ok, SPid} -> |
| 2139 | + case rabbit_misc:remote_sup_child(Node, SPid) of |
| 2140 | + {ok, _} -> QPid; %% restarting |
| 2141 | + {error, no_child} -> crashed %% given up |
| 2142 | + end |
| 2143 | + end; |
| 2144 | + _ -> QPid |
| 2145 | + end; |
| 2146 | + Error = {error, _} -> Error; |
| 2147 | + Reason -> {error, Reason} |
| 2148 | + end. |
0 commit comments