IndexFilter.java revision 24ef7c741bf20dabe8a5be3978187f8f1eb5dd41
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions copyright 2011-2015 ForgeRock AS
*/
/**
* An index filter is used to apply a search operation to a set of indexes
* to generate a set of candidate entries.
*/
class IndexFilter
{
/**
* Stop processing the filter against the indexes when the
* number of candidates is smaller than this value.
*/
private static final int FILTER_CANDIDATE_THRESHOLD = 10;
/**
* Limit on the number of entry IDs that may be retrieved by cursoring through an index.
*/
static final int CURSOR_ENTRY_LIMIT = 100000;
/** The entry container holding the attribute indexes. */
private final EntryContainer entryContainer;
private final ReadableTransaction txn;
/**
* The search operation provides the search base, scope and filter.
* It can also be checked periodically for cancellation.
*/
private final SearchOperation searchOp;
/**
* A string builder to hold a diagnostic string which helps determine
* how the indexed contributed to the search operation.
*/
private final StringBuilder buffer;
private final DatabaseEnvironmentMonitor monitor;
/**
* Construct an index filter for a search operation.
*
* @param entryContainer The entry entryContainer.
* @param txn a non null database transaction
* @param searchOp The search operation to be evaluated.
* @param monitor The monitor to gather filter usage stats.
* @param debugBuilder If not null, a diagnostic string will be written
* which will help determine how the indexes contributed
* to this search.
*/
{
this.entryContainer = entryContainer;
this.buffer = debugBuilder;
}
/**
* Evaluate the search operation against the indexes.
*
* @return A set of entry IDs representing candidate entries.
*/
{
appendToDebugBuffer("filter=");
}
/**
* Evaluate a search filter against the indexes.
*
* @param filter The search filter to be evaluated.
* @return A set of entry IDs representing candidate entries.
*/
{
{
}
return candidates;
}
{
switch (filter.getFilterType())
{
case AND:
appendToDebugBuffer("(&");
appendToDebugBuffer(")");
return res1;
case OR:
appendToDebugBuffer("(|");
appendToDebugBuffer(")");
return res2;
case EQUALITY:
case GREATER_OR_EQUAL:
case SUBSTRING:
case LESS_OR_EQUAL:
case PRESENT:
case APPROXIMATE_MATCH:
case EXTENSIBLE_MATCH:
{
}
return evaluateExtensibleFilter(filter);
case NOT:
default:
{
}
//NYI
return newUndefinedSet();
}
}
/**
* Evaluate a logical AND search filter against the indexes.
*
* @param andFilter The AND search filter to be evaluated.
* @return A set of entry IDs representing candidate entries.
*/
{
// Put the slow range filters (greater-or-equal, less-or-equal)
// into a hash map, the faster components (equality, presence, approx)
// into one list and the remainder into another list.
{
{
{
}
}
{
}
else
{
}
}
// First, process the fast components.
// Next, process the other (non-range) components.
return results;
}
// Next, process range component pairs like (cn>=A)(cn<=B).
{
{
if (attributeIndex == null)
{
if(monitor.isFilterUseEnabled())
{
}
continue;
}
EntryIDSet set = attributeIndex.evaluateBoundedRange(indexQueryFactory, filter1, filter2, buffer, monitor);
{
}
{
return results;
}
}
else
{
// Add to the remaining range components to be processed.
}
}
// Finally, process the remaining slow range components.
}
{
if (isBelowFilterThreshold(results)) {
return results;
}
}
return results;
}
{
}
/**
* Evaluate a logical OR search filter against the indexes.
*
* @param orFilter The OR search filter to be evaluated.
* @return A set of entry IDs representing candidate entries.
*/
{
{
{
// There is no point continuing.
return set;
}
}
return newSetFromUnion(candidateSets);
}
private EntryIDSet evaluateFilterWithDiagnostic(IndexFilterType indexFilterType, SearchFilter filter)
{
{
}
}
{
if (attributeIndex != null)
{
}
if (monitor.isFilterUseEnabled())
{
}
return newUndefinedSet();
}
/**
* Evaluate an extensible filter against the indexes.
*
* @param extensibleFilter The extensible filter to be evaluated.
* @return A set of entry IDs representing candidate entries.
*/
{
if (extensibleFilter.getDNAttributes())
{
// This will always be unindexed since the filter potentially matches
// entries containing the specified attribute type as well as any entry
// containing the attribute in its DN as part of a superior RDN.
}
AttributeIndex attributeIndex = entryContainer.getAttributeIndex(extensibleFilter.getAttributeType());
if (attributeIndex != null)
{
return attributeIndex.evaluateExtensibleFilter(indexQueryFactory, extensibleFilter, buffer, monitor);
}
}
{
{
}
}
}