diff options
| author | Tony Garnock-Jones <tonyg@lshift.net> | 2008-07-14 15:36:53 +0100 |
|---|---|---|
| committer | Tony Garnock-Jones <tonyg@lshift.net> | 2008-07-14 15:36:53 +0100 |
| commit | 2f76073a7976385c1b6b3deb9ed93eaa5dfc8331 (patch) | |
| tree | 151a8ff9acbb7bf85a41ec985cd4f4ef18b5d8ef | |
| parent | 0cf76f887a34afa6ec9f04a33fb254fea580b6b5 (diff) | |
| parent | 13340f0d67088fb75b136a038561585f2db9d681 (diff) | |
| download | rabbitmq-server-git-2f76073a7976385c1b6b3deb9ed93eaa5dfc8331.tar.gz | |
Merger
| -rw-r--r-- | include/rabbit.hrl | 4 | ||||
| -rw-r--r-- | src/rabbit_mnesia.erl | 6 | ||||
| -rw-r--r-- | src/rabbit_realm.erl | 138 | ||||
| -rw-r--r-- | src/rabbit_ticket.erl | 26 |
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}, |
