Savepoint for changing the routing structure
This commit is contained in:
		
							parent
							
								
									fbab5e9e49
								
							
						
					
					
						commit
						0a1d35c530
					
				|  | @ -41,11 +41,14 @@ | |||
| 
 | ||||
| -record(exchange, {name, type, durable, auto_delete, arguments}). | ||||
| 
 | ||||
| -record(amqqueue, {name, durable, auto_delete, arguments, binding_specs, pid}). | ||||
| -record(binding_spec, {exchange_name, routing_key, arguments}). | ||||
| -record(amqqueue, {name, durable, auto_delete, arguments, pid}). | ||||
| %% This constant field seems to be required because the underlying storage is | ||||
| %% ets, which stores key value pairs | ||||
| 
 | ||||
| -record(binding, {key, handlers}). | ||||
| -record(handler, {binding_spec, queue, qpid}). | ||||
| %% The spec field is made up of an {Exchange, Binding, Queue} | ||||
| -record(forwards_binding, {spec, value = const}). | ||||
| %% The spec field is made up of an {Queue, Binding, Exchange} | ||||
| -record(reverse_binding, {spec, value = const}). | ||||
| 
 | ||||
| -record(listener, {node, protocol, host, port}). | ||||
| 
 | ||||
|  | @ -76,16 +79,11 @@ | |||
|       #user{username :: username(), | ||||
|             password :: password()}). | ||||
| -type(permission() :: 'passive' | 'active' | 'write' | 'read').       | ||||
| -type(binding_spec() :: | ||||
|       #binding_spec{exchange_name :: exchange_name(), | ||||
|                     routing_key   :: routing_key(), | ||||
|                     arguments     :: amqp_table()}). | ||||
| -type(amqqueue() :: | ||||
|       #amqqueue{name          :: queue_name(), | ||||
|                 durable       :: bool(), | ||||
|                 auto_delete   :: bool(), | ||||
|                 arguments     :: amqp_table(), | ||||
|                 binding_specs :: [binding_spec()], | ||||
|                 pid           :: maybe(pid())}). | ||||
| -type(exchange() :: | ||||
|       #exchange{name        :: exchange_name(), | ||||
|  |  | |||
|  | @ -84,7 +84,7 @@ | |||
| -spec(commit/2 :: (pid(), txn()) -> 'ok'). | ||||
| -spec(rollback/2 :: (pid(), txn()) -> 'ok'). | ||||
| -spec(notify_down/2 :: (amqqueue(), pid()) -> 'ok'). | ||||
| -spec(binding_forcibly_removed/2 :: (binding_spec(), queue_name()) -> 'ok'). | ||||
| %-spec(binding_forcibly_removed/2 :: (binding_spec(), queue_name()) -> 'ok'). | ||||
| -spec(claim_queue/2 :: (amqqueue(), pid()) -> 'ok' | 'locked'). | ||||
| -spec(basic_get/3 :: (amqqueue(), pid(), bool()) -> | ||||
|              {'ok', non_neg_integer(), msg()} | 'empty'). | ||||
|  | @ -135,7 +135,6 @@ declare(Resource = #resource{}, Durable, AutoDelete, Args) -> | |||
|                                       durable = Durable, | ||||
|                                       auto_delete = AutoDelete, | ||||
|                                       arguments = Args, | ||||
|                                       binding_specs = [], | ||||
|                                       pid = none}), | ||||
|     case rabbit_misc:execute_mnesia_transaction( | ||||
|            fun () -> | ||||
|  | @ -168,48 +167,52 @@ recover_queue(Q) -> | |||
|     ok. | ||||
| 
 | ||||
| default_binding_spec(#resource{virtual_host = VHostPath, name = Name}) -> | ||||
|     #binding_spec{exchange_name = rabbit_misc:r(VHostPath,exchange,<<"">>), | ||||
|                   routing_key = Name, | ||||
|                   arguments = []}. | ||||
| 
 | ||||
| recover_bindings(Q = #amqqueue{name = QueueName, binding_specs = Specs}) -> | ||||
|     ok = rabbit_exchange:add_binding(default_binding_spec(QueueName), Q), | ||||
|     lists:foreach(fun (B) -> | ||||
|                           ok = rabbit_exchange:add_binding(B, Q) | ||||
|                   end, Specs), | ||||
|     ok. | ||||
| 
 | ||||
|     exit(default_binding_spec). | ||||
|     % #binding_spec{exchange_name = rabbit_misc:r(VHostPath,exchange,<<"">>), | ||||
|     %                   routing_key = Name, | ||||
|     %                   arguments = []}. | ||||
|      | ||||
| recover_bindings(Q = #amqqueue{name = QueueName}) -> | ||||
|     exit(recover_bindings). | ||||
|     % ok = rabbit_exchange:add_binding(default_binding_spec(QueueName), Q), | ||||
|     %     lists:foreach(fun (B) -> | ||||
|     %                           ok = rabbit_exchange:add_binding(B, Q) | ||||
|     %                   end, Specs), | ||||
|     %     ok. | ||||
|      | ||||
| modify_bindings(Queue = #resource{}, X = #resource{}, RoutingKey, Arguments, | ||||
|                 SpecPresentFun, SpecAbsentFun) -> | ||||
|     rabbit_misc:execute_mnesia_transaction( | ||||
|       fun () -> | ||||
|               case mnesia:wread({amqqueue, Queue}) of | ||||
|                   [Q = #amqqueue{binding_specs = Specs0}] -> | ||||
|                       Spec = #binding_spec{exchange_name = X, | ||||
|                                            routing_key = RoutingKey, | ||||
|                                            arguments = Arguments}, | ||||
|                       case (case lists:member(Spec, Specs0) of | ||||
|                                 true  -> SpecPresentFun; | ||||
|                                 false -> SpecAbsentFun | ||||
|                             end)(Q, Spec) of | ||||
|                           {ok, #amqqueue{binding_specs = Specs}} -> | ||||
|                               {ok, length(Specs)}; | ||||
|                           {error, not_found} -> | ||||
|                               {error, exchange_not_found}; | ||||
|                           Other -> Other | ||||
|                       end; | ||||
|                   [] -> {error, queue_not_found} | ||||
|               end | ||||
|       end). | ||||
| 
 | ||||
| update_bindings(Q = #amqqueue{binding_specs = Specs0}, Spec, | ||||
|     exit(modify_bindings). | ||||
|     % rabbit_misc:execute_mnesia_transaction( | ||||
|     %       fun () -> | ||||
|     %               case mnesia:wread({amqqueue, Queue}) of | ||||
|     %                   [Q = #amqqueue{binding_specs = Specs0}] -> | ||||
|     %                       Spec = #binding_spec{exchange_name = X, | ||||
|     %                                            routing_key = RoutingKey, | ||||
|     %                                            arguments = Arguments}, | ||||
|     %                       case (case lists:member(Spec, Specs0) of | ||||
|     %                                 true  -> SpecPresentFun; | ||||
|     %                                 false -> SpecAbsentFun | ||||
|     %                             end)(Q, Spec) of | ||||
|     %                           {ok, #amqqueue{binding_specs = Specs}} -> | ||||
|     %                               {ok, length(Specs)}; | ||||
|     %                           {error, not_found} -> | ||||
|     %                               {error, exchange_not_found}; | ||||
|     %                           Other -> Other | ||||
|     %                       end; | ||||
|     %                   [] -> {error, queue_not_found} | ||||
|     %               end | ||||
|     %       end). | ||||
|      | ||||
| update_bindings(Q = #amqqueue{}, Spec, | ||||
|                 UpdateSpecFun, UpdateExchangeFun) -> | ||||
|     Q1 = Q#amqqueue{binding_specs = UpdateSpecFun(Spec, Specs0)}, | ||||
|     case UpdateExchangeFun(Spec, Q1) of | ||||
|         ok    -> store_queue(Q1), | ||||
|                  {ok, Q1}; | ||||
|         Other -> Other | ||||
|     end. | ||||
|     exit(update_bindings). | ||||
|     % Q1 = Q#amqqueue{binding_specs = UpdateSpecFun(Spec, Specs0)}, | ||||
|     %     case UpdateExchangeFun(Spec, Q1) of | ||||
|     %         ok    -> store_queue(Q1), | ||||
|     %                  {ok, Q1}; | ||||
|     %         Other -> Other | ||||
|     %     end. | ||||
| 
 | ||||
| add_binding(QueueName, ExchangeName, RoutingKey, Arguments) -> | ||||
|     modify_bindings( | ||||
|  | @ -297,15 +300,16 @@ notify_down(#amqqueue{ pid = QPid }, ChPid) -> | |||
|     gen_server:call(QPid, {notify_down, ChPid}). | ||||
| 
 | ||||
| binding_forcibly_removed(BindingSpec, QueueName) -> | ||||
|     rabbit_misc:execute_mnesia_transaction( | ||||
|       fun () -> | ||||
|               case mnesia:wread({amqqueue, QueueName}) of | ||||
|                   [] -> ok; | ||||
|                   [Q = #amqqueue{binding_specs = Specs}] -> | ||||
|                       store_queue(Q#amqqueue{binding_specs = | ||||
|                                              lists:delete(BindingSpec, Specs)}) | ||||
|               end | ||||
|       end). | ||||
|     exit(binding_forcibly_removed). | ||||
|     % rabbit_misc:execute_mnesia_transaction( | ||||
|     %       fun () -> | ||||
|     %               case mnesia:wread({amqqueue, QueueName}) of | ||||
|     %                   [] -> ok; | ||||
|     %                   [Q = #amqqueue{binding_specs = Specs}] -> | ||||
|     %                       store_queue(Q#amqqueue{binding_specs = | ||||
|     %                                              lists:delete(BindingSpec, Specs)}) | ||||
|     %               end | ||||
|     %       end). | ||||
| 
 | ||||
| claim_queue(#amqqueue{pid = QPid}, ReaderPid) -> | ||||
|     gen_server:call(QPid, {claim_queue, ReaderPid}). | ||||
|  | @ -324,11 +328,12 @@ basic_cancel(#amqqueue{pid = QPid}, ChPid, ConsumerTag, OkMsg) -> | |||
| notify_sent(QPid, ChPid) -> | ||||
|     gen_server:cast(QPid, {notify_sent, ChPid}). | ||||
| 
 | ||||
| delete_bindings(Q = #amqqueue{binding_specs = Specs}) -> | ||||
|     lists:foreach(fun (BindingSpec) -> | ||||
|                           ok = rabbit_exchange:delete_binding( | ||||
|                                  BindingSpec, Q) | ||||
|                   end, Specs). | ||||
| delete_bindings(Q = #amqqueue{}) -> | ||||
|     exit(delete_bindings). | ||||
|     % lists:foreach(fun (BindingSpec) -> | ||||
|     %                           ok = rabbit_exchange:delete_binding( | ||||
|     %                                  BindingSpec, Q) | ||||
|     %                   end, Specs). | ||||
| 
 | ||||
| internal_delete(QueueName) -> | ||||
|     rabbit_misc:execute_mnesia_transaction( | ||||
|  | @ -368,5 +373,4 @@ pseudo_queue(NameBin, Pid) -> | |||
|               durable = false, | ||||
|               auto_delete = false, | ||||
|               arguments = [], | ||||
|               binding_specs = [], | ||||
|               pid = Pid}. | ||||
|  |  | |||
|  | @ -64,11 +64,11 @@ | |||
|              publish_res()). | ||||
| -spec(simple_publish/3 :: (bool(), bool(), message()) -> publish_res()). | ||||
| -spec(route/2 :: (exchange(), routing_key()) -> [pid()]). | ||||
| -spec(add_binding/2 :: (binding_spec(), amqqueue()) ->  | ||||
|              'ok' | not_found() | | ||||
|                  {'error', 'durability_settings_incompatible'}). | ||||
| -spec(delete_binding/2 :: (binding_spec(), amqqueue()) -> | ||||
|              'ok' | not_found()). | ||||
| % -spec(add_binding/2 :: (binding_spec(), amqqueue()) ->  | ||||
| %              'ok' | not_found() | | ||||
| %                  {'error', 'durability_settings_incompatible'}). | ||||
| % -spec(delete_binding/2 :: (binding_spec(), amqqueue()) -> | ||||
| %              'ok' | not_found()). | ||||
| -spec(topic_matches/2 :: (binary(), binary()) -> bool()). | ||||
| -spec(delete/2 :: (exchange_name(), bool()) -> | ||||
|              'ok' | not_found() | {'error', 'in_use'}). | ||||
|  | @ -144,15 +144,17 @@ list_vhost_exchanges(VHostPath) -> | |||
|       #exchange{name = rabbit_misc:r(VHostPath, exchange), _ = '_'}). | ||||
| 
 | ||||
| list_exchange_bindings(Name) -> | ||||
|     [{QueueName, RoutingKey, Arguments} || | ||||
|     #binding{handlers = Handlers} <- bindings_for_exchange(Name), | ||||
|     #handler{binding_spec = #binding_spec{routing_key = RoutingKey, | ||||
|                           arguments = Arguments}, | ||||
|          queue = QueueName} <- Handlers]. | ||||
| 
 | ||||
|     exit(list_exchange_bindings). | ||||
|     % [{QueueName, RoutingKey, Arguments} || | ||||
|     %     #binding{handlers = Handlers} <- bindings_for_exchange(Name), | ||||
|     %     #handler{binding_spec = #binding_spec{routing_key = RoutingKey, | ||||
|     %                           arguments = Arguments}, | ||||
|     %          queue = QueueName} <- Handlers]. | ||||
|      | ||||
| bindings_for_exchange(Name) -> | ||||
|     qlc:e(qlc:q([B || B = #binding{key = K} <- mnesia:table(binding), | ||||
|                       element(1, K) == Name])). | ||||
|     exit(bindings_for_exchange). | ||||
|     % qlc:e(qlc:q([B || B = #binding{key = K} <- mnesia:table(binding), | ||||
|     %                       element(1, K) == Name])). | ||||
| 
 | ||||
| empty_handlers() -> | ||||
|     []. | ||||
|  | @ -189,25 +191,27 @@ simple_publish(Mandatory, Immediate, | |||
| %% as many times as a message should be delivered to it. With the | ||||
| %% current exchange types that is at most once. | ||||
| route(#exchange{name = Name, type = topic}, RoutingKey) -> | ||||
|     sets:to_list( | ||||
|       sets:union( | ||||
|         mnesia:activity( | ||||
|           async_dirty, | ||||
|           fun () -> | ||||
|                   qlc:e(qlc:q([handler_qpids(H) ||  | ||||
|                                   #binding{key = {Name1, PatternKey}, | ||||
|                                            handlers = H} | ||||
|                                       <- mnesia:table(binding), | ||||
|                                   Name == Name1, | ||||
|                                   topic_matches(PatternKey, RoutingKey)])) | ||||
|           end))); | ||||
|     exit(route); | ||||
|     % sets:to_list( | ||||
|     %       sets:union( | ||||
|     %         mnesia:activity( | ||||
|     %           async_dirty, | ||||
|     %           fun () -> | ||||
|     %                   qlc:e(qlc:q([handler_qpids(H) ||  | ||||
|     %                                   #binding{key = {Name1, PatternKey}, | ||||
|     %                                            handlers = H} | ||||
|     %                                       <- mnesia:table(binding), | ||||
|     %                                   Name == Name1, | ||||
|     %                                   topic_matches(PatternKey, RoutingKey)])) | ||||
|     %           end))); | ||||
| 
 | ||||
| route(#exchange{name = Name, type = Type}, RoutingKey) -> | ||||
|     BindingKey = delivery_key_for_type(Type, Name, RoutingKey), | ||||
|     case rabbit_misc:dirty_read({binding, BindingKey}) of | ||||
|         {ok, #binding{handlers = H}} -> sets:to_list(handler_qpids(H)); | ||||
|         {error, not_found} -> [] | ||||
|     end. | ||||
|     exit(route). | ||||
|     % BindingKey = delivery_key_for_type(Type, Name, RoutingKey), | ||||
|     %     case rabbit_misc:dirty_read({binding, BindingKey}) of | ||||
|     %         {ok, #binding{handlers = H}} -> sets:to_list(handler_qpids(H)); | ||||
|     %         {error, not_found} -> [] | ||||
|     %     end. | ||||
| 
 | ||||
| delivery_key_for_type(fanout, Name, _RoutingKey) -> | ||||
|     {Name, fanout}; | ||||
|  | @ -221,28 +225,33 @@ call_with_exchange(Name, Fun) -> | |||
|     end. | ||||
| 
 | ||||
| make_handler(BindingSpec, #amqqueue{name = QueueName, pid = QPid}) -> | ||||
|     #handler{binding_spec = BindingSpec, queue = QueueName, qpid = QPid}. | ||||
|     exit(make_handler). | ||||
|     %#handler{binding_spec = BindingSpec, queue = QueueName, qpid = QPid}. | ||||
| 
 | ||||
| add_binding(BindingSpec = #binding_spec{exchange_name = ExchangeName, | ||||
|                                         routing_key = RoutingKey}, Q) -> | ||||
|     call_with_exchange( | ||||
|       ExchangeName, | ||||
|       fun (X) -> if Q#amqqueue.durable and not(X#exchange.durable) -> | ||||
|                          {error, durability_settings_incompatible}; | ||||
|                     true -> | ||||
|                          internal_add_binding( | ||||
|                            X, RoutingKey, make_handler(BindingSpec, Q)) | ||||
|                  end | ||||
|       end). | ||||
| add_binding(BindingSpec %= #binding_spec{exchange_name = ExchangeName, | ||||
|                         %                routing_key = RoutingKey},  | ||||
|                         ,Q) -> | ||||
|     exit(add_binding). | ||||
|     % call_with_exchange( | ||||
|     %       ExchangeName, | ||||
|     %       fun (X) -> if Q#amqqueue.durable and not(X#exchange.durable) -> | ||||
|     %                          {error, durability_settings_incompatible}; | ||||
|     %                     true -> | ||||
|     %                          internal_add_binding( | ||||
|     %                            X, RoutingKey, make_handler(BindingSpec, Q)) | ||||
|     %                  end | ||||
|     %       end). | ||||
| 
 | ||||
| delete_binding(BindingSpec = #binding_spec{exchange_name = ExchangeName, | ||||
|                                            routing_key = RoutingKey}, Q) -> | ||||
|     call_with_exchange( | ||||
|       ExchangeName, | ||||
|       fun (X) -> ok = internal_delete_binding( | ||||
|                         X, RoutingKey, make_handler(BindingSpec, Q)), | ||||
|                  maybe_auto_delete(X) | ||||
|       end). | ||||
| delete_binding(BindingSpec %= #binding_spec{exchange_name = ExchangeName, | ||||
|                            %               routing_key = RoutingKey},  | ||||
|                            ,Q) -> | ||||
|     exit(delete_binding). | ||||
|     % call_with_exchange( | ||||
|     %   ExchangeName, | ||||
|     %   fun (X) -> ok = internal_delete_binding( | ||||
|     %                     X, RoutingKey, make_handler(BindingSpec, Q)), | ||||
|     %              maybe_auto_delete(X) | ||||
|     %   end). | ||||
| 
 | ||||
| %% Must run within a transaction. | ||||
| maybe_auto_delete(#exchange{auto_delete = false}) -> | ||||
|  | @ -261,7 +270,8 @@ extend_handlers(Handlers, Handler) -> [Handler | Handlers]. | |||
| delete_handler(Handlers, Handler) -> lists:delete(Handler, Handlers). | ||||
| 
 | ||||
| handler_qpids(Handlers) -> | ||||
|     sets:from_list([QPid || #handler{qpid = QPid} <- Handlers]). | ||||
|     exit(handler_qpids). | ||||
|     %sets:from_list([QPid || #handler{qpid = QPid} <- Handlers]). | ||||
| 
 | ||||
| %% Must run within a transaction. | ||||
| internal_add_binding(#exchange{name = ExchangeName, type = Type}, | ||||
|  | @ -277,32 +287,34 @@ internal_delete_binding(#exchange{name = ExchangeName, type = Type}, RoutingKey, | |||
| 
 | ||||
| %% Must run within a transaction. | ||||
| add_handler_to_binding(BindingKey, Handler) -> | ||||
|     ok = case mnesia:wread({binding, BindingKey}) of | ||||
|              [] -> | ||||
|                  ok = mnesia:write( | ||||
|                         #binding{key = BindingKey, | ||||
|                                  handlers = extend_handlers( | ||||
|                                               empty_handlers(), Handler)}); | ||||
|              [B = #binding{handlers = H}] -> | ||||
|                  ok = mnesia:write( | ||||
|                         B#binding{handlers = extend_handlers(H, Handler)}) | ||||
|          end. | ||||
|     exit(add_handler_to_binding). | ||||
|     % ok = case mnesia:wread({binding, BindingKey}) of | ||||
|     %              [] -> | ||||
|     %                  ok = mnesia:write( | ||||
|     %                         #binding{key = BindingKey, | ||||
|     %                                  handlers = extend_handlers( | ||||
|     %                                               empty_handlers(), Handler)}); | ||||
|     %              [B = #binding{handlers = H}] -> | ||||
|     %                  ok = mnesia:write( | ||||
|     %                         B#binding{handlers = extend_handlers(H, Handler)}) | ||||
|     %          end. | ||||
|           | ||||
| %% Must run within a transaction. | ||||
| remove_handler_from_binding(BindingKey, Handler) -> | ||||
|     case mnesia:wread({binding, BindingKey}) of | ||||
|         [] -> empty; | ||||
|         [B = #binding{handlers = H}] -> | ||||
|             H1 = delete_handler(H, Handler), | ||||
|             case handlers_isempty(H1) of | ||||
|                 true -> | ||||
|                     ok = mnesia:delete({binding, BindingKey}), | ||||
|                     empty; | ||||
|                 _ -> | ||||
|                     ok = mnesia:write(B#binding{handlers = H1}), | ||||
|                     not_empty | ||||
|             end | ||||
|     end. | ||||
|     exit(remove_handler_from_binding). | ||||
|     % case mnesia:wread({binding, BindingKey}) of | ||||
|     %         [] -> empty; | ||||
|     %         [B = #binding{handlers = H}] -> | ||||
|     %             H1 = delete_handler(H, Handler), | ||||
|     %             case handlers_isempty(H1) of | ||||
|     %                 true -> | ||||
|     %                     ok = mnesia:delete({binding, BindingKey}), | ||||
|     %                     empty; | ||||
|     %                 _ -> | ||||
|     %                     ok,% = mnesia:write(B#binding{handlers = H1}), | ||||
|     %                     not_empty | ||||
|     %             end | ||||
|     %     end. | ||||
| 
 | ||||
| split_topic_key(Key) -> | ||||
|     {ok, KeySplit} = regexp:split(binary_to_list(Key), "\\."), | ||||
|  | @ -336,41 +348,44 @@ delete(ExchangeName, IfUnused) -> | |||
|       fun () -> internal_delete(ExchangeName, IfUnused) end). | ||||
| 
 | ||||
| internal_delete(ExchangeName, _IfUnused = true) -> | ||||
|     Bindings = bindings_for_exchange(ExchangeName), | ||||
|     case Bindings of | ||||
|         [] -> do_internal_delete(ExchangeName, Bindings); | ||||
|         _ -> | ||||
|             case lists:all(fun (#binding{handlers = H}) -> handlers_isempty(H) end, | ||||
|                            Bindings) of | ||||
|                 true -> | ||||
|                     %% There are no handlers anywhere in any of the | ||||
|                     %% bindings for this exchange. | ||||
|                     do_internal_delete(ExchangeName, Bindings); | ||||
|                 false -> | ||||
|                     %% There was at least one real handler | ||||
|                     %% present. It's still in use. | ||||
|                     {error, in_use} | ||||
|             end | ||||
|     end; | ||||
|     exit(internal_delete); | ||||
|     % Bindings = bindings_for_exchange(ExchangeName), | ||||
|     %     case Bindings of | ||||
|     %         [] -> do_internal_delete(ExchangeName, Bindings); | ||||
|     %         _ -> | ||||
|     %             case lists:all(fun (#binding{handlers = H}) -> handlers_isempty(H) end, | ||||
|     %                            Bindings) of | ||||
|     %                 true -> | ||||
|     %                     %% There are no handlers anywhere in any of the | ||||
|     %                     %% bindings for this exchange. | ||||
|     %                     do_internal_delete(ExchangeName, Bindings); | ||||
|     %                 false -> | ||||
|     %                     %% There was at least one real handler | ||||
|     %                     %% present. It's still in use. | ||||
|     %                     {error, in_use} | ||||
|     %             end | ||||
|     %     end; | ||||
| internal_delete(ExchangeName, false) -> | ||||
|     do_internal_delete(ExchangeName, bindings_for_exchange(ExchangeName)). | ||||
| 
 | ||||
| forcibly_remove_handlers(Handlers) -> | ||||
|     lists:foreach( | ||||
|       fun (#handler{binding_spec = BindingSpec, queue = QueueName}) -> | ||||
|               ok = rabbit_amqqueue:binding_forcibly_removed( | ||||
|                      BindingSpec, QueueName) | ||||
|       end, Handlers), | ||||
|     ok. | ||||
|     exit(forcibly_remove_handlers). | ||||
|     % lists:foreach( | ||||
|     %       fun (#handler{binding_spec = BindingSpec, queue = QueueName}) -> | ||||
|     %               ok = rabbit_amqqueue:binding_forcibly_removed( | ||||
|     %                      BindingSpec, QueueName) | ||||
|     %       end, Handlers), | ||||
|     %     ok. | ||||
| 
 | ||||
| do_internal_delete(ExchangeName, Bindings) -> | ||||
|     case mnesia:wread({exchange, ExchangeName}) of | ||||
|         [] -> {error, not_found}; | ||||
|         _ -> | ||||
|             lists:foreach(fun (#binding{key = K, handlers = H}) -> | ||||
|                                   ok = forcibly_remove_handlers(H), | ||||
|                                   ok = mnesia:delete({binding, K}) | ||||
|                           end, Bindings), | ||||
|             ok = mnesia:delete({durable_exchanges, ExchangeName}), | ||||
|             ok = mnesia:delete({exchange, ExchangeName}) | ||||
|     end. | ||||
|     exit(do_internal_delete). | ||||
|     % case mnesia:wread({exchange, ExchangeName}) of | ||||
|     %         [] -> {error, not_found}; | ||||
|     %         _ -> | ||||
|     %             lists:foreach(fun (#binding{key = K, handlers = H}) -> | ||||
|     %                                   ok = forcibly_remove_handlers(H), | ||||
|     %                                   ok = mnesia:delete({binding, K}) | ||||
|     %                           end, Bindings), | ||||
|     %             ok = mnesia:delete({durable_exchanges, ExchangeName}), | ||||
|     %             ok = mnesia:delete({exchange, ExchangeName}) | ||||
|     %     end. | ||||
|  |  | |||
|  | @ -105,7 +105,8 @@ table_definitions() -> | |||
|      {rabbit_config, [{disc_copies, [node()]}]}, | ||||
|      {listener, [{type, bag}, | ||||
|                  {attributes, record_info(fields, listener)}]}, | ||||
|      {binding, [{attributes, record_info(fields, binding)}]}, | ||||
|      {forwards_binding, [{type,ordered_set},{attributes, record_info(fields, forwards_binding)}]}, | ||||
|      {reverse_binding, [{type,ordered_set},{attributes, record_info(fields, reverse_binding)}]}, | ||||
|      {durable_exchanges, [{disc_copies, [node()]}, | ||||
|                           {record_name, exchange}, | ||||
|                           {attributes, record_info(fields, exchange)}]}, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue