From 55117d37db9543e089ccde5b51bc1658d0158d18 Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Fri, 18 Jan 2013 11:08:27 -0800 Subject: [PATCH] Add intersection to GroupMembership Support slower group backends by allowing a lookup of a lot of groups at once to use intersection(). This method signature allows the backend to filter the input query set and return the subset of groups that the user is a member of. Using a batch style interface can decrease latency when resolving a large number of external groups identified through the internal group system's nested includes feature. Change-Id: I6926a3373589f439c8d694d36cdbe5fa8396a040 --- .../server/account/GroupMembership.java | 14 ++++++++ .../account/IncludingGroupMembership.java | 11 ++++++ .../server/account/ListGroupMembership.java | 6 +++- .../server/account/UniversalGroupBackend.java | 36 ++++++++++++++----- 4 files changed, 58 insertions(+), 9 deletions(-) diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java index d536c09109..d7a97fb671 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GroupMembership.java @@ -39,6 +39,20 @@ public interface GroupMembership { */ boolean containsAnyOf(Iterable groupIds); + /** + * Returns a set containing an input member of {@code contains(id)} is true. + *

+ * This is batch form of contains that returns specific group information. + * Implementors may implement the method as: + * + *

+   * Set<AccountGroup.UUID> r = Sets.newHashSet();
+   * for (AccountGroup.UUID id : groupIds)
+   *   if (contains(id)) r.add(id);
+   * 
+ */ + Set intersection(Iterable groupIds); + /** * Returns the set of groups that can be determined by the implementation. * This may not return all groups the {@link #contains(AccountGroup.UUID)} diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/IncludingGroupMembership.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/IncludingGroupMembership.java index d448fff15a..75b7f32833 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/IncludingGroupMembership.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/IncludingGroupMembership.java @@ -70,6 +70,17 @@ public class IncludingGroupMembership implements GroupMembership { return findIncludedGroup(query); } + @Override + public Set intersection(Iterable groupIds) { + Set r = Sets.newHashSet(); + for (AccountGroup.UUID id : groupIds) { + if (contains(id)) { + r.add(id); + } + } + return r; + } + private boolean findIncludedGroup(Set query) { boolean found = false; while (!found && !groupQueue.isEmpty()) { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java index 346f406dc3..118940f9bf 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ListGroupMembership.java @@ -24,7 +24,6 @@ import java.util.Set; * GroupMembership over an explicit list. */ public class ListGroupMembership implements GroupMembership { - private final Set groups; public ListGroupMembership(Iterable groupIds) { @@ -46,6 +45,11 @@ public class ListGroupMembership implements GroupMembership { return false; } + @Override + public Set intersection(Iterable groupIds) { + return Sets.intersection(ImmutableSet.copyOf(groupIds), groups); + } + @Override public Set getKnownGroups() { return Sets.newHashSet(groups); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java index 1f670f6713..d9c9257296 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/UniversalGroupBackend.java @@ -156,13 +156,33 @@ public class UniversalGroupBackend implements GroupBackend { return false; } - @Override - public Set getKnownGroups() { - Set groups = Sets.newHashSet(); - for (GroupMembership m : memberships.values()) { - groups.addAll(m.getKnownGroups()); - } - return groups; - } + @Override + public Set intersection(Iterable uuids) { + Multimap lookups = + ArrayListMultimap.create(); + for (AccountGroup.UUID uuid : uuids) { + GroupMembership m = membership(uuid); + if (m == null) { + log.warn("Unknown GroupMembership for UUID: " + uuid); + continue; + } + lookups.put(m, uuid); + } + Set groups = Sets.newHashSet(); + for (Map.Entry> entry + : lookups.asMap().entrySet()) { + groups.addAll(entry.getKey().intersection(entry.getValue())); + } + return groups; + } + + @Override + public Set getKnownGroups() { + Set groups = Sets.newHashSet(); + for (GroupMembership m : memberships.values()) { + groups.addAll(m.getKnownGroups()); + } + return groups; + } } }