|  | @@ -383,21 +383,45 @@ public final class IndicesPermission {
 | 
	
		
			
				|  |  |                      if (actionCheck || bwcMappingActionCheck) {
 | 
	
		
			
				|  |  |                          // propagate DLS and FLS permissions over the concrete indices
 | 
	
		
			
				|  |  |                          for (String index : concreteIndices) {
 | 
	
		
			
				|  |  | -                            Set<FieldPermissions> fieldPermissions = fieldPermissionsByIndex.computeIfAbsent(index, (k) -> new HashSet<>());
 | 
	
		
			
				|  |  | -                            fieldPermissionsByIndex.put(resource.name, fieldPermissions);
 | 
	
		
			
				|  |  | -                            fieldPermissions.add(group.getFieldPermissions());
 | 
	
		
			
				|  |  | +                            final Set<FieldPermissions> fieldPermissions = fieldPermissionsByIndex.compute(index, (k, existingSet) -> {
 | 
	
		
			
				|  |  | +                                if (existingSet == null) {
 | 
	
		
			
				|  |  | +                                    // Most indices rely on the default (empty) field permissions object, so we optimize for that case
 | 
	
		
			
				|  |  | +                                    // Using an immutable single item set is significantly faster because it avoids any of the hashing
 | 
	
		
			
				|  |  | +                                    // and backing set creation.
 | 
	
		
			
				|  |  | +                                    return Set.of(group.getFieldPermissions());
 | 
	
		
			
				|  |  | +                                } else if (existingSet.size() == 1) {
 | 
	
		
			
				|  |  | +                                    FieldPermissions fp = group.getFieldPermissions();
 | 
	
		
			
				|  |  | +                                    if (existingSet.contains(fp)) {
 | 
	
		
			
				|  |  | +                                        return existingSet;
 | 
	
		
			
				|  |  | +                                    }
 | 
	
		
			
				|  |  | +                                    // This index doesn't have a single field permissions object, replace the singleton with a real Set
 | 
	
		
			
				|  |  | +                                    final Set<FieldPermissions> hashSet = new HashSet<>(existingSet);
 | 
	
		
			
				|  |  | +                                    hashSet.add(fp);
 | 
	
		
			
				|  |  | +                                    return hashSet;
 | 
	
		
			
				|  |  | +                                } else {
 | 
	
		
			
				|  |  | +                                    existingSet.add(group.getFieldPermissions());
 | 
	
		
			
				|  |  | +                                    return existingSet;
 | 
	
		
			
				|  |  | +                                }
 | 
	
		
			
				|  |  | +                            });
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                            DocumentLevelPermissions permissions =
 | 
	
		
			
				|  |  | -                                    roleQueriesByIndex.computeIfAbsent(index, (k) -> new DocumentLevelPermissions());
 | 
	
		
			
				|  |  | -                            roleQueriesByIndex.putIfAbsent(resource.name, permissions);
 | 
	
		
			
				|  |  | +                            DocumentLevelPermissions docPermissions;
 | 
	
		
			
				|  |  |                              if (group.hasQuery()) {
 | 
	
		
			
				|  |  | -                                permissions.addAll(group.getQuery());
 | 
	
		
			
				|  |  | +                                docPermissions = roleQueriesByIndex.computeIfAbsent(index, (k) -> new DocumentLevelPermissions());
 | 
	
		
			
				|  |  | +                                docPermissions.addAll(group.getQuery());
 | 
	
		
			
				|  |  |                              } else {
 | 
	
		
			
				|  |  |                                  // if more than one permission matches for a concrete index here and if
 | 
	
		
			
				|  |  |                                  // a single permission doesn't have a role query then DLS will not be
 | 
	
		
			
				|  |  |                                  // applied even when other permissions do have a role query
 | 
	
		
			
				|  |  | -                                permissions.setAllowAll();
 | 
	
		
			
				|  |  | +                                docPermissions = DocumentLevelPermissions.ALLOW_ALL;
 | 
	
		
			
				|  |  | +                                // don't worry about what's already there - just overwrite it, it avoids doing a 2nd hash lookup.
 | 
	
		
			
				|  |  | +                                roleQueriesByIndex.put(index, docPermissions);
 | 
	
		
			
				|  |  | +                            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                            if (index.equals(resource.name) == false) {
 | 
	
		
			
				|  |  | +                                fieldPermissionsByIndex.put(resource.name, fieldPermissions);
 | 
	
		
			
				|  |  | +                                roleQueriesByIndex.put(resource.name, docPermissions);
 | 
	
		
			
				|  |  |                              }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |                          }
 | 
	
		
			
				|  |  |                          if (false == actionCheck) {
 | 
	
		
			
				|  |  |                              for (String privilegeName : group.privilege.name()) {
 | 
	
	
		
			
				|  | @@ -547,6 +571,11 @@ public final class IndicesPermission {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private static class DocumentLevelPermissions {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        public static final DocumentLevelPermissions ALLOW_ALL = new DocumentLevelPermissions();
 | 
	
		
			
				|  |  | +        static {
 | 
	
		
			
				|  |  | +            ALLOW_ALL.allowAll = true;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          private Set<BytesReference> queries = null;
 | 
	
		
			
				|  |  |          private boolean allowAll = false;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -562,9 +591,5 @@ public final class IndicesPermission {
 | 
	
		
			
				|  |  |          private boolean isAllowAll() {
 | 
	
		
			
				|  |  |              return allowAll;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        private void setAllowAll() {
 | 
	
		
			
				|  |  | -            this.allowAll = true;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |