Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 112 additions & 1 deletion opendj-server-legacy/src/main/java/org/opends/server/types/Entry.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
* Portions Copyright 2023-2024 3A Systems, LLC.
* Portions Copyright 2023-2026 3A Systems, LLC.
*/
package org.opends.server.types;

Expand All @@ -34,6 +34,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -663,9 +664,87 @@ public List<Attribute> getAllAttributes(AttributeType attributeType,
return Collections.emptyList();
}

/**
* The set of attribute types having at least one subordinate type in a
* schema, cached per schema instance. Subtype-inclusive attribute lookups
* run for every entry read (compare assertions, search filters, password
* policy attributes, ...): when the requested type has no subordinates,
* walking every attribute of the entry degenerates to an exact map lookup,
* so cache which types actually need the walk. The schema and the set
* computed for it are held in one immutable holder swapped atomically, so
* a reader can never pair a set with the wrong schema.
*/
private static final class TypesWithSubordinates
{
private final Schema schema;
private final Set<AttributeType> types;

private TypesWithSubordinates(Schema schema, Set<AttributeType> types)
{
this.schema = schema;
this.types = types;
}
}

private static volatile TypesWithSubordinates typesWithSubordinates =
new TypesWithSubordinates(null, Collections.<AttributeType> emptySet());

private static boolean mayHaveSubordinateTypes(AttributeType attrType)
{
if (attrType.isPlaceHolder())
{
// isSuperTypeOf() matches place-holder types against schema-defined
// types by name, which an exact map lookup cannot honor: keep the walk.
return true;
}
Schema schema;
try
{
schema = DirectoryServer.getInstance().getServerContext().getSchema();
}
catch (Exception e)
{
// No server schema available (offline tools, early startup):
// conservatively assume subtypes may exist.
return true;
}
if (schema == null)
{
return true;
}
TypesWithSubordinates cached = typesWithSubordinates;
if (cached.schema != schema)
{
Set<AttributeType> withSubordinates = new HashSet<>();
for (AttributeType type : schema.getAttributeTypes())
{
for (AttributeType superior = type.getSuperiorType(); superior != null;
superior = superior.getSuperiorType())
{
withSubordinates.add(superior);
}
}
cached = new TypesWithSubordinates(schema, withSubordinates);
typesWithSubordinates = cached;
}
return cached.types.contains(attrType);
}

private void addAttributeTypeOrSubTypeValue(Collection<Attribute> results, AttributeType attrType,
Map<AttributeType, List<Attribute>> attrsMap)
{
if (!mayHaveSubordinateTypes(attrType))
{
// No type in the schema extends attrType: isSuperTypeOf() can only
// match the type itself, so use an exact lookup instead of walking
// every attribute of the entry.
List<Attribute> attributes = attrsMap.get(attrType);
if (attributes != null)
{
results.addAll(attributes);
}
return;
}
for (Map.Entry<AttributeType, List<Attribute>> mapEntry : attrsMap.entrySet())
{
if (attrType.isSuperTypeOf(mapEntry.getKey()))
Expand All @@ -678,6 +757,21 @@ private void addAttributeTypeOrSubTypeValue(Collection<Attribute> results, Attri
private void addAttributeTypeOrSubTypeValue(Collection<Attribute> results, AttributeDescription attrDesc,
Map<AttributeType, List<Attribute>> attrsMap)
{
if (!mayHaveSubordinateTypes(attrDesc.getAttributeType()))
{
List<Attribute> attributes = attrsMap.get(attrDesc.getAttributeType());
if (attributes != null)
{
for (Attribute attribute : attributes)
{
if (attrDesc.isSuperTypeOf(attribute.getAttributeDescription()))
{
results.add(attribute);
}
}
}
return;
}
for (Map.Entry<AttributeType, List<Attribute>> mapEntry : attrsMap.entrySet())
{
if (!attrDesc.getAttributeType().isSuperTypeOf(mapEntry.getKey()))
Expand All @@ -697,6 +791,23 @@ private void addAttributeTypeOrSubTypeValue(Collection<Attribute> results, Attri

private boolean hasAttributeOrSubType(AttributeDescription attrDesc, Map<AttributeType, List<Attribute>> attrsMap)
{
if (!mayHaveSubordinateTypes(attrDesc.getAttributeType()))
{
List<Attribute> attributes = attrsMap.get(attrDesc.getAttributeType());
if (attributes != null)
{
for (Attribute attribute : attributes)
{
// It's possible that there could be an attribute without any values,
// which we should treat as not having the requested attribute.
if (!attribute.isEmpty() && attrDesc.isSuperTypeOf(attribute.getAttributeDescription()))
{
return true;
}
}
}
return false;
}
for (Map.Entry<AttributeType, List<Attribute>> mapEntry : attrsMap.entrySet())
{
if (!attrDesc.getAttributeType().isSuperTypeOf(mapEntry.getKey()))
Expand Down
Loading