summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Radestock <matthias@lshift.net>2008-07-14 11:16:07 +0100
committerMatthias Radestock <matthias@lshift.net>2008-07-14 11:16:07 +0100
commit13340f0d67088fb75b136a038561585f2db9d681 (patch)
tree4305d14c8d30e16d2dae2e8114552d1cbf3b9873
parentbb63114ae61e50aec7ce8f888ad5b2b673016b9d (diff)
parent59af33d7f86fa9903ec859e9fc7739eab95a032f (diff)
downloadrabbitmq-server-git-13340f0d67088fb75b136a038561585f2db9d681.tar.gz
merge bug18752 into default
-rw-r--r--include/rabbit.hrl4
-rw-r--r--src/rabbit_mnesia.erl6
-rw-r--r--src/rabbit_realm.erl138
-rw-r--r--src/rabbit_ticket.erl26
4 files changed, 84 insertions, 90 deletions
diff --git a/include/rabbit.hrl b/include/rabbit.hrl
index d8af670a04..21900294c3 100644
--- a/include/rabbit.hrl
+++ b/include/rabbit.hrl
@@ -29,7 +29,9 @@
-record(vhost, {virtual_host, dummy}).
-record(vhost_realm, {virtual_host, realm}).
--record(realm, {name, exchanges, queues}).
+-record(realm, {name, ignore}).
+-record(realm_resource, {realm, resource}).
+
-record(user_realm, {username, realm, ticket_pattern}).
-record(realm_visitor, {realm, pid}).
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index 82b80cb491..18df11fee1 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -108,6 +108,12 @@ table_definitions() ->
{index, [realm]}]},
{realm, [{disc_copies, [node()]},
{attributes, record_info(fields, realm)}]},
+ {realm_exchange, [{disc_copies, [node()]},
+ {record_name, realm_resource},
+ {attributes, record_info(fields, realm_resource)}]},
+ {realm_queue, [{disc_copies, [node()]},
+ {record_name, realm_resource},
+ {attributes, record_info(fields, realm_resource)}]},
{user_realm, [{type, bag},
{disc_copies, [node()]},
{attributes, record_info(fields, user_realm)},
diff --git a/src/rabbit_realm.erl b/src/rabbit_realm.erl
index 4463954d7e..4bd6db842c 100644
--- a/src/rabbit_realm.erl
+++ b/src/rabbit_realm.erl
@@ -63,12 +63,7 @@
recover() ->
%% preens resource lists, limiting them to currently-extant resources
- rabbit_misc:execute_mnesia_transaction(
- fun () ->
- Realms = mnesia:foldl(fun preen_realm/2, [], realm),
- lists:foreach(fun mnesia:write/1, Realms),
- ok
- end).
+ rabbit_misc:execute_mnesia_transaction(fun preen_realms/0).
add_realm(Name = #resource{virtual_host = VHostPath, kind = realm}) ->
rabbit_misc:execute_mnesia_transaction(
@@ -77,9 +72,7 @@ add_realm(Name = #resource{virtual_host = VHostPath, kind = realm}) ->
fun () ->
case mnesia:read({realm, Name}) of
[] ->
- NewRealm = #realm{name = Name,
- exchanges = ordsets:new(),
- queues = ordsets:new()},
+ NewRealm = #realm{name = Name},
ok = mnesia:write(NewRealm),
ok = mnesia:write(
#vhost_realm{virtual_host = VHostPath,
@@ -116,45 +109,45 @@ list_vhost_realms(VHostPath) ->
VHostPath,
fun () -> mnesia:read({vhost_realm, VHostPath}) end))].
-add(Name = #resource{kind = realm}, Resource) ->
- internal_update_realm_byname(Name, Resource, fun ordsets:add_element/2).
+add(Realm = #resource{kind = realm}, Resource = #resource{}) ->
+ manage_link(fun mnesia:write/3, Realm, Resource).
+
+delete(Realm = #resource{kind = realm}, Resource = #resource{}) ->
+ manage_link(fun mnesia:delete_object/3, Realm, Resource).
+
+% This links or unlinks a resource to a realm
+manage_link(Action, Realm = #resource{kind = realm, name = RealmName},
+ R = #resource{name = Name}) ->
+ rabbit_misc:execute_mnesia_transaction(
+ fun () ->
+ case mnesia:read({realm, Realm}) of
+ [] -> mnesia:abort(not_found);
+ [_] -> Action(realm_table_for_resource(R),
+ #realm_resource{realm = RealmName,
+ resource = Name},
+ write)
+ end
+ end).
+
+realm_table_for_resource(#resource{kind = exchange}) -> realm_exchange;
+realm_table_for_resource(#resource{kind = queue}) -> realm_queue.
+parent_table_for_resource(#resource{kind = exchange}) -> exchange;
+parent_table_for_resource(#resource{kind = queue}) -> amqqueue.
-delete(Name = #resource{kind = realm}, Resource) ->
- internal_update_realm_byname(Name, Resource, fun ordsets:del_element/2).
-check(Name = #resource{kind = realm}, Resource = #resource{kind = Kind}) ->
- case rabbit_misc:dirty_read({realm, Name}) of
- {ok, R} ->
- case Kind of
- exchange -> ordsets:is_element(Resource, R#realm.exchanges);
- queue -> ordsets:is_element(Resource, R#realm.queues)
- end;
- Other -> Other
+check(#resource{kind = realm, name = Realm}, R = #resource{name = Name}) ->
+ case mnesia:dirty_match_object(realm_table_for_resource(R),
+ #realm_resource{realm = Realm,
+ resource = Name}) of
+ [] -> false;
+ _ -> true
end.
% Requires a mnesia transaction.
-delete_from_all(Resource = #resource{kind = Kind}) ->
- Realms = mnesia:foldl
- (fun (Realm = #realm{exchanges = E0,
- queues = Q0},
- Acc) ->
- IsMember = lists:member(Resource,
- case Kind of
- exchange -> E0;
- queue -> Q0
- end),
- if
- IsMember ->
- [internal_update_realm_record(
- Realm, Resource,
- fun ordsets:del_element/2)
- | Acc];
- true ->
- Acc
- end
- end, [], realm),
- lists:foreach(fun mnesia:write/1, Realms),
- ok.
+delete_from_all(R = #resource{name = Name}) ->
+ mnesia:delete_object(realm_table_for_resource(R),
+ #realm_resource{realm = '_', resource = Name},
+ write).
access_request(Username, Exclusive, Ticket = #ticket{realm_name = RealmName})
when is_binary(Username) ->
@@ -237,41 +230,34 @@ on_node_down(Node) ->
%%--------------------------------------------------------------------
-preen_realm(Realm = #realm{name = #resource{kind = realm},
- exchanges = E0,
- queues = Q0},
- Realms) ->
- [Realm#realm{exchanges = filter_out_missing(E0, exchange),
- queues = filter_out_missing(Q0, amqqueue)}
- | Realms].
+%% This iterates through the realm_exchange and realm_queue link tables
+%% and deletes rows that have no underlying exchange or queue record.
+preen_realms() ->
+ lists:foreach(fun preen_realm/1, [exchange, queue]),
+ ok.
-filter_out_missing(Items, TableName) ->
- ordsets:filter(fun (Item) ->
- case mnesia:read({TableName, Item}) of
- [] -> false;
- _ -> true
- end
- end, Items).
+preen_realm(Kind) ->
+ R = #resource{kind = Kind},
+ Table = realm_table_for_resource(R),
+ Cursor = qlc:cursor(
+ qlc:q([L#realm_resource.resource ||
+ L <- mnesia:table(Table)])),
+ preen_next(Cursor, Table, parent_table_for_resource(R)),
+ qlc:delete_cursor(Cursor).
-internal_update_realm_byname(Name, Resource, SetUpdater) ->
- rabbit_misc:execute_mnesia_transaction(
- fun () ->
- case mnesia:read({realm, Name}) of
- [] ->
- mnesia:abort(not_found);
- [R] ->
- ok = mnesia:write(internal_update_realm_record
- (R, Resource, SetUpdater))
- end
- end).
-
-internal_update_realm_record(R = #realm{exchanges = E0, queues = Q0},
- Resource = #resource{kind = Kind},
- SetUpdater) ->
- case Kind of
- exchange -> R#realm{exchanges = SetUpdater(Resource, E0)};
- queue -> R#realm{queues = SetUpdater(Resource, Q0)}
- end.
+preen_next(Cursor, Table, ParentTable) ->
+ case qlc:next_answers(Cursor, 1) of
+ [] -> ok;
+ [Name] ->
+ case mnesia:read({ParentTable, Name}) of
+ [] -> mnesia:delete_object(
+ Table,
+ #realm_resource{realm = '_', resource = Name},
+ write);
+ _ -> ok
+ end,
+ preen_next(Cursor, Table, ParentTable)
+ end.
check_and_lookup(RealmName = #resource{kind = realm,
name = <<"/data", _/binary>>}) ->
diff --git a/src/rabbit_ticket.erl b/src/rabbit_ticket.erl
index 3a608faa91..16475a9843 100644
--- a/src/rabbit_ticket.erl
+++ b/src/rabbit_ticket.erl
@@ -99,21 +99,21 @@ check_ticket(TicketNumber, FieldIndex,
#ticket{realm_name = RealmName} =
lookup_ticket(TicketNumber, FieldIndex, Username, VHostPath),
case resource_in_realm(RealmName, Name) of
- false ->
- case rabbit_misc:strict_ticket_checking() of
- true ->
- rabbit_misc:protocol_error(
- access_refused,
- "insufficient permissions in ticket ~w to access ~s in ~s",
- [TicketNumber, rabbit_misc:rs(Name),
- rabbit_misc:rs(RealmName)]);
false ->
- rabbit_log:warning("Lax ticket check mode: ignoring cross-realm access for ticket ~p~n", [TicketNumber]),
+ case rabbit_misc:strict_ticket_checking() of
+ true ->
+ rabbit_misc:protocol_error(
+ access_refused,
+ "insufficient permissions in ticket ~w to access ~s in ~s",
+ [TicketNumber, rabbit_misc:rs(Name),
+ rabbit_misc:rs(RealmName)]);
+ false ->
+ rabbit_log:warning("Lax ticket check mode: ignoring cross-realm access for ticket ~p~n", [TicketNumber]),
+ ok
+ end;
+ true ->
ok
- end;
- true ->
- ok
- end.
+ end.
resource_in_realm(RealmName, ResourceName = #resource{kind = Kind}) ->
CacheKey = {resource_cache, RealmName, Kind},