summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Klishin <michael@novemberain.com>2018-10-03 02:24:36 +0300
committerGitHub <noreply@github.com>2018-10-03 02:24:36 +0300
commitda4a6c0d31f8abd812b7f47384f32c816d31ceb1 (patch)
tree0a7ea7c79ed0ee775d716dec6187cdc363ab945f
parentc1fb658ce13ae7f14919bd784eddd3dc77ab5144 (diff)
parenta9dc1f82e4e19519685c869cbb0772b2614f4d98 (diff)
downloadrabbitmq-server-git-da4a6c0d31f8abd812b7f47384f32c816d31ceb1.tar.gz
Merge pull request #1715 from rabbitmq/bindings-optimisation
Bindings optimisation
-rw-r--r--src/rabbit_binding.erl44
-rw-r--r--src/rabbit_exchange.erl12
2 files changed, 37 insertions, 19 deletions
diff --git a/src/rabbit_binding.erl b/src/rabbit_binding.erl
index f2bcd93b74..e96dfd7673 100644
--- a/src/rabbit_binding.erl
+++ b/src/rabbit_binding.erl
@@ -145,7 +145,7 @@ recover_semi_durable_route(Gatherer, R = #route{binding = B}, ToRecover) ->
recover_semi_durable_route_txn(R = #route{binding = B}, X) ->
rabbit_misc:execute_mnesia_transaction(
fun () ->
- case mnesia:match_object(rabbit_semi_durable_route, R, read) of
+ case mnesia:read(rabbit_semi_durable_route, B, read) of
[] -> no_recover;
_ -> ok = sync_transient_route(R, fun mnesia:write/3),
rabbit_exchange:serial(X)
@@ -232,7 +232,7 @@ remove(Src, Dst, B, ActingUser) ->
lock_resource(Src),
lock_resource(Dst),
ok = sync_route(#route{binding = B}, durable(Src), durable(Dst),
- fun mnesia:delete_object/3),
+ fun delete/3),
Deletions = maybe_auto_delete(
B#binding.source, [B], new_deletions(), false),
process_deletions(Deletions, ActingUser).
@@ -319,8 +319,8 @@ remove_for_source(SrcName) ->
Match = #route{binding = #binding{source = SrcName, _ = '_'}},
remove_routes(
lists:usort(
- mnesia:match_object(rabbit_route, Match, read) ++
- mnesia:match_object(rabbit_semi_durable_route, Match, read))).
+ mnesia:dirty_match_object(rabbit_route, Match) ++
+ mnesia:dirty_match_object(rabbit_semi_durable_route, Match))).
remove_for_destination(DstName, OnlyDurable) ->
remove_for_destination(DstName, OnlyDurable, fun remove_routes/1).
@@ -406,21 +406,33 @@ remove_routes(Routes) ->
%% This partitioning allows us to suppress unnecessary delete
%% operations on disk tables, which require an fsync.
{RamRoutes, DiskRoutes} =
- lists:partition(fun (R) -> mnesia:match_object(
- rabbit_durable_route, R, read) == [] end,
+ lists:partition(fun (R) -> mnesia:read(
+ rabbit_durable_route, R#route.binding, read) == [] end,
Routes),
+ {RamOnlyRoutes, SemiDurableRoutes} =
+ lists:partition(fun (R) -> mnesia:read(
+ rabbit_semi_durable_route, R#route.binding, read) == [] end,
+ RamRoutes),
%% Of course the destination might not really be durable but it's
%% just as easy to try to delete it from the semi-durable table
%% than check first
- [ok = sync_route(R, false, true, fun mnesia:delete_object/3) ||
- R <- RamRoutes],
- [ok = sync_route(R, true, true, fun mnesia:delete_object/3) ||
+ [ok = sync_route(R, true, true, fun delete/3) ||
R <- DiskRoutes],
+ [ok = sync_route(R, false, true, fun delete/3) ||
+ R <- SemiDurableRoutes],
+ [ok = sync_route(R, false, false, fun delete/3) ||
+ R <- RamOnlyRoutes],
[R#route.binding || R <- Routes].
+
+delete(Tab, #route{binding = B}, LockKind) ->
+ mnesia:delete(Tab, B, LockKind);
+delete(Tab, #reverse_route{reverse_binding = B}, LockKind) ->
+ mnesia:delete(Tab, B, LockKind).
+
remove_transient_routes(Routes) ->
[begin
- ok = sync_transient_route(R, fun mnesia:delete_object/3),
+ ok = sync_transient_route(R, fun delete/3),
R#route.binding
end || R <- Routes].
@@ -431,13 +443,13 @@ remove_for_destination(DstName, OnlyDurable, Fun) ->
Routes = case OnlyDurable of
false ->
[reverse_route(R) ||
- R <- mnesia:match_object(
- rabbit_reverse_route, MatchRev, read)];
+ R <- mnesia:dirty_match_object(
+ rabbit_reverse_route, MatchRev)];
true -> lists:usort(
- mnesia:match_object(
- rabbit_durable_route, MatchFwd, read) ++
- mnesia:match_object(
- rabbit_semi_durable_route, MatchFwd, read))
+ mnesia:dirty_match_object(
+ rabbit_durable_route, MatchFwd) ++
+ mnesia:dirty_match_object(
+ rabbit_semi_durable_route, MatchFwd))
end,
Bindings = Fun(Routes),
group_bindings_fold(fun maybe_auto_delete/4, new_deletions(),
diff --git a/src/rabbit_exchange.erl b/src/rabbit_exchange.erl
index c7a849ce2e..92e3f9acbd 100644
--- a/src/rabbit_exchange.erl
+++ b/src/rabbit_exchange.erl
@@ -492,15 +492,21 @@ maybe_auto_delete(#exchange{auto_delete = true} = X, OnlyDurable) ->
conditional_delete(X = #exchange{name = XName}, OnlyDurable) ->
case rabbit_binding:has_for_source(XName) of
- false -> unconditional_delete(X, OnlyDurable);
+ false -> internal_delete(X, OnlyDurable, false);
true -> {error, in_use}
end.
-unconditional_delete(X = #exchange{name = XName}, OnlyDurable) ->
+unconditional_delete(X, OnlyDurable) ->
+ internal_delete(X, OnlyDurable, true).
+
+internal_delete(X = #exchange{name = XName}, OnlyDurable, RemoveBindingsForSource) ->
ok = mnesia:delete({rabbit_exchange, XName}),
ok = mnesia:delete({rabbit_exchange_serial, XName}),
mnesia:delete({rabbit_durable_exchange, XName}),
- Bindings = rabbit_binding:remove_for_source(XName),
+ Bindings = case RemoveBindingsForSource of
+ true -> rabbit_binding:remove_for_source(XName);
+ false -> []
+ end,
{deleted, X, Bindings, rabbit_binding:remove_for_destination(
XName, OnlyDurable)}.