OPENDJ-1591 (CR-5206) Switch to SDK matching rules
After r11260 some code cleanup can be performed.
ApproximateIndexer.java, EqualityIndexer.java, OrderingIndexer.java, SubstringIndexer.java: REMOVED
Replaced with calling MatchingRule.getIndexers().
AttributeIndex.java:
Consequence of removing the indexer types.
Changed buildExtIndex() into buildIndexes() + getMatchingRule().
Factorized code by extracting IndexFilterType enum: Inlined several evaluate*Filter() methods and replaced them with the newly extracted methods evaluateFilter() + getIndexQuery().
Simplified evaluateBoundedRange() with the help of the newly extracted methods evaluateFilter() + getIndexQuery().
Extracted method isIndexAcceptable().
Changed buildExtIndex() into buildIndexes().
Extracted methods applyChangeToPresenceIndex() and applyChangeToExtensibleIndexes() from applyConfigurationChange().
In applyChangeToIndex(), reworked the code.
Removed openNewIndex().
IndexFilter.java:
Consequence of the changes to AttributeIndex.evaluate*Filter().
Removed several evaluate*Filter() methods and replaced them with a single extracted evaluateFilter() method.
TestBackendImpl.java:
Consequence of removing the indexer types.
3 files deleted
4 files modified
| | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.schema.MatchingRule; |
| | | import org.forgerock.opendj.ldap.spi.IndexQueryFactory; |
| | | import org.forgerock.opendj.ldap.spi.IndexingOptions; |
| | | import org.forgerock.util.Utils; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType; |
| | | import org.opends.server.admin.std.server.LocalDBIndexCfg; |
| | | import org.forgerock.opendj.ldap.schema.MatchingRule; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.monitors.DatabaseEnvironmentMonitor; |
| | | import org.opends.server.types.*; |
| | |
| | | { |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** Type of the index filter. */ |
| | | static enum IndexFilterType |
| | | { |
| | | /** Equality. */ |
| | | EQUALITY(IndexType.EQUALITY), |
| | | /** Presence. */ |
| | | PRESENCE(IndexType.PRESENCE), |
| | | /** Ordering. */ |
| | | GREATER_OR_EQUAL(IndexType.ORDERING), |
| | | /** Ordering. */ |
| | | LESS_OR_EQUAL(IndexType.ORDERING), |
| | | /** Substring. */ |
| | | SUBSTRING(IndexType.SUBSTRING), |
| | | /** Approximate. */ |
| | | APPROXIMATE(IndexType.APPROXIMATE); |
| | | |
| | | private final IndexType indexType; |
| | | |
| | | private IndexFilterType(IndexType indexType) |
| | | { |
| | | this.indexType = indexType; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | return indexType.toString(); |
| | | } |
| | | } |
| | | |
| | | /* |
| | | * FIXME Matthew Swift: Once the matching rules have been migrated we should |
| | | * revisit this class. IMO the core indexes (equality, etc) should all be |
| | | * treated in the same way as extensible indexes. In other words, there should |
| | | * be one table mapping index ID to index and one IndexQueryFactory. Matching |
| | | * rules should then be able to select which indexes they need to use when |
| | | * evaluating searches, and all index queries should be processed using the |
| | | * IndexQueryFactory implementation. Moreover, all of the evaluateXXX methods |
| | | * should go (the Matcher class in the SDK could implement the logic, I hope). |
| | | * That's the theory at least... |
| | | * revisit this class. All of the evaluateXXX methods should go (the Matcher |
| | | * class in the SDK could implement the logic, I hope). |
| | | */ |
| | | |
| | | /** |
| | |
| | | final int indexEntryLimit = indexConfig.getIndexEntryLimit(); |
| | | final JEIndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength()); |
| | | |
| | | if (indexConfig.getIndexType().contains(IndexType.EQUALITY)) |
| | | { |
| | | Index equalityIndex = buildExtIndex(name, attrType, indexEntryLimit, |
| | | attrType.getEqualityMatchingRule(), new EqualityIndexer(attrType)); |
| | | nameToIndexes.put(IndexType.EQUALITY.toString(), equalityIndex); |
| | | } |
| | | |
| | | if (indexConfig.getIndexType().contains(IndexType.PRESENCE)) |
| | | { |
| | | Index presenceIndex = newIndex(name + "." + IndexType.PRESENCE.toString(), |
| | | indexEntryLimit, new PresenceIndexer(attrType)); |
| | | nameToIndexes.put(IndexType.PRESENCE.toString(), presenceIndex); |
| | | String indexID = IndexType.PRESENCE.toString(); |
| | | String indexName = name + "." + indexID; |
| | | Index presenceIndex = newIndex(indexName, indexEntryLimit, new PresenceIndexer(attrType)); |
| | | nameToIndexes.put(indexID, presenceIndex); |
| | | } |
| | | |
| | | if (indexConfig.getIndexType().contains(IndexType.SUBSTRING)) |
| | | { |
| | | Index substringIndex = buildExtIndex(name, attrType, indexEntryLimit, |
| | | attrType.getSubstringMatchingRule(), new SubstringIndexer(attrType)); |
| | | nameToIndexes.put(IndexType.SUBSTRING.toString(), substringIndex); |
| | | } |
| | | |
| | | if (indexConfig.getIndexType().contains(IndexType.ORDERING)) |
| | | { |
| | | Index orderingIndex = buildExtIndex(name, attrType, indexEntryLimit, |
| | | attrType.getOrderingMatchingRule(), new OrderingIndexer(attrType)); |
| | | nameToIndexes.put(IndexType.ORDERING.toString(), orderingIndex); |
| | | } |
| | | |
| | | if (indexConfig.getIndexType().contains(IndexType.APPROXIMATE)) |
| | | { |
| | | Index approximateIndex = buildExtIndex(name, attrType, indexEntryLimit, |
| | | attrType.getApproximateMatchingRule(), new ApproximateIndexer(attrType)); |
| | | nameToIndexes.put(IndexType.APPROXIMATE.toString(), approximateIndex); |
| | | } |
| | | |
| | | buildIndexes(indexConfig, attrType, name, IndexType.EQUALITY); |
| | | buildIndexes(indexConfig, attrType, name, IndexType.SUBSTRING); |
| | | buildIndexes(indexConfig, attrType, name, IndexType.ORDERING); |
| | | buildIndexes(indexConfig, attrType, name, IndexType.APPROXIMATE); |
| | | |
| | | if (indexConfig.getIndexType().contains(IndexType.EXTENSIBLE)) |
| | | { |
| | |
| | | if (!nameToIndexes.containsKey(indexId)) |
| | | { |
| | | //There is no index available for this index id. Create a new index. |
| | | final String indexName = name + "." + indexId; |
| | | final Index extIndex = newExtensibleIndex(indexName, attrType, indexEntryLimit, indexer); |
| | | final Index extIndex = newExtensibleIndex(attrType, name, indexEntryLimit, indexer); |
| | | nameToIndexes.put(indexId, extIndex); |
| | | } |
| | | } |
| | |
| | | |
| | | private Index newIndex(String indexName, int indexEntryLimit, Indexer indexer) |
| | | { |
| | | return new Index(indexName, indexer, state, indexEntryLimit, |
| | | cursorEntryLimit, false, env, entryContainer); |
| | | return new Index(indexName, indexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); |
| | | } |
| | | |
| | | private Index buildExtIndex(String name, AttributeType attrType, |
| | | int indexEntryLimit, MatchingRule rule, org.forgerock.opendj.ldap.spi.Indexer extIndexer) throws ConfigException |
| | | private void buildIndexes(LocalDBIndexCfg cfg, AttributeType attrType, String name, IndexType indexType) |
| | | throws ConfigException |
| | | { |
| | | if (cfg.getIndexType().contains(indexType)) |
| | | { |
| | | final String indexID = indexType.toString(); |
| | | final MatchingRule rule = getMatchingRule(indexType, attrType); |
| | | if (rule == null) |
| | | { |
| | | throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get( |
| | | attrType, extIndexer.getIndexID())); |
| | | throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexID)); |
| | | } |
| | | |
| | | final String indexName = name + "." + extIndexer.getIndexID(); |
| | | return newExtensibleIndex(indexName, attrType, indexEntryLimit, extIndexer); |
| | | } |
| | | |
| | | private Index newExtensibleIndex(String indexName, AttributeType attrType, |
| | | int indexEntryLimit, org.forgerock.opendj.ldap.spi.Indexer extIndexer) |
| | | for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers()) |
| | | { |
| | | JEExtensibleIndexer indexer = new JEExtensibleIndexer(attrType, extIndexer); |
| | | return newIndex(indexName, indexEntryLimit, indexer); |
| | | final Index index = newExtensibleIndex(attrType, name, cfg.getIndexEntryLimit(), indexer); |
| | | nameToIndexes.put(indexID, index); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private MatchingRule getMatchingRule(IndexType indexType, AttributeType attrType) |
| | | { |
| | | switch (indexType) |
| | | { |
| | | case APPROXIMATE: |
| | | return attrType.getApproximateMatchingRule(); |
| | | case EQUALITY: |
| | | return attrType.getEqualityMatchingRule(); |
| | | case ORDERING: |
| | | return attrType.getOrderingMatchingRule(); |
| | | case SUBSTRING: |
| | | return attrType.getSubstringMatchingRule(); |
| | | default: |
| | | throw new IllegalArgumentException("Not implemented for index type " + indexType); |
| | | } |
| | | } |
| | | |
| | | private Index newExtensibleIndex(AttributeType attrType, String name, final int indexEntryLimit, |
| | | org.forgerock.opendj.ldap.spi.Indexer indexer) |
| | | { |
| | | final String indexName = name + "." + indexer.getIndexID(); |
| | | final JEExtensibleIndexer extIndexer = new JEExtensibleIndexer(attrType, indexer); |
| | | return newIndex(indexName, indexEntryLimit, extIndexer); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match an equality filter. |
| | | * |
| | | * @param equalityFilter The equality filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain the filter |
| | | * assertion value. |
| | | */ |
| | | public EntryIDSet evaluateEqualityFilter(SearchFilter equalityFilter, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | try { |
| | | final MatchingRule matchRule = equalityFilter.getAttributeType().getEqualityMatchingRule(); |
| | | final IndexQuery indexQuery = matchRule.getAssertion(equalityFilter.getAssertionValue()) |
| | | .createIndexQuery(indexQueryFactory); |
| | | return evaluateIndexQuery(indexQuery, "equality", equalityFilter, debugBuffer, monitor); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | | logger.traceException(e); |
| | | return new EntryIDSet(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match a presence filter. |
| | | * |
| | | * @param filter The presence filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain one or more |
| | | * values of the attribute type in the filter. |
| | | */ |
| | | public EntryIDSet evaluatePresenceFilter(SearchFilter filter, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | final IndexQuery indexQuery = indexQueryFactory.createMatchAllQuery(); |
| | | return evaluateIndexQuery(indexQuery, "presence", filter, debugBuffer, monitor); |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match a greater-or-equal filter. |
| | | * |
| | | * @param filter The greater-or-equal filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain a value |
| | | * greater than or equal to the filter assertion value. |
| | | */ |
| | | public EntryIDSet evaluateGreaterOrEqualFilter(SearchFilter filter, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | return evaluateOrderingFilter(filter, true, debugBuffer, monitor); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match a less-or-equal filter. |
| | | * |
| | | * @param filter The less-or-equal filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain a value |
| | | * less than or equal to the filter assertion value. |
| | | */ |
| | | public EntryIDSet evaluateLessOrEqualFilter(SearchFilter filter, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | return evaluateOrderingFilter(filter, false, debugBuffer, monitor); |
| | | } |
| | | |
| | | private EntryIDSet evaluateOrderingFilter(SearchFilter filter, boolean greater, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | try { |
| | | final MatchingRule matchRule = filter.getAttributeType().getOrderingMatchingRule(); |
| | | final Assertion assertion = greater ? |
| | | matchRule.getGreaterOrEqualAssertion(filter.getAssertionValue()) : |
| | | matchRule.getLessOrEqualAssertion(filter.getAssertionValue()); |
| | | final IndexQuery indexQuery = assertion.createIndexQuery(indexQueryFactory); |
| | | return evaluateIndexQuery(indexQuery, "ordering", filter, debugBuffer, monitor); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | | logger.traceException(e); |
| | | return new EntryIDSet(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match a substring filter. |
| | | * |
| | | * @param filter The substring filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain a value |
| | | * that matches the filter substrings. |
| | | */ |
| | | public EntryIDSet evaluateSubstringFilter(SearchFilter filter, |
| | | StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | try { |
| | | final MatchingRule matchRule = filter.getAttributeType().getSubstringMatchingRule(); |
| | | final IndexQuery indexQuery = matchRule.getSubstringAssertion( |
| | | filter.getSubInitialElement(), filter.getSubAnyElements(), filter.getSubFinalElement()) |
| | | .createIndexQuery(indexQueryFactory); |
| | | return evaluateIndexQuery(indexQuery, "substring", filter, debugBuffer, monitor); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | | logger.traceException(e); |
| | | return new EntryIDSet(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match two filters that restrict a value |
| | | * to both a lower bound and an upper bound. |
| | | * |
| | |
| | | { |
| | | // TODO : this implementation is not optimal |
| | | // as it implies two separate evaluations instead of a single one, |
| | | // thus defeating the purpose of the optimisation done |
| | | // thus defeating the purpose of the optimization done |
| | | // in IndexFilter#evaluateLogicalAndFilter method. |
| | | // One solution could be to implement a boundedRangeAssertion that combine |
| | | // the two operations in one. |
| | | EntryIDSet results = filter1.getFilterType() == FilterType.LESS_OR_EQUAL ? |
| | | evaluateLessOrEqualFilter(filter1, debugBuffer, monitor) : |
| | | evaluateGreaterOrEqualFilter(filter1, debugBuffer, monitor); |
| | | EntryIDSet results2 = filter2.getFilterType() == FilterType.LESS_OR_EQUAL ? |
| | | evaluateLessOrEqualFilter(filter2, debugBuffer, monitor) : |
| | | evaluateGreaterOrEqualFilter(filter2, debugBuffer, monitor); |
| | | EntryIDSet results = evaluate(filter1, debugBuffer, monitor); |
| | | EntryIDSet results2 = evaluate(filter2, debugBuffer, monitor); |
| | | results.retainAll(results2); |
| | | return results; |
| | | } |
| | | |
| | | private EntryIDSet evaluate(SearchFilter filter, StringBuilder debugBuffer, DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | boolean isLessOrEqual = filter.getFilterType() == FilterType.LESS_OR_EQUAL; |
| | | IndexFilterType indexFilterType = isLessOrEqual ? IndexFilterType.LESS_OR_EQUAL : IndexFilterType.GREATER_OR_EQUAL; |
| | | return evaluateFilter(indexFilterType, filter, debugBuffer, monitor); |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match a filter. |
| | | * |
| | | * @param indexFilterType the index type filter |
| | | * @param filter The filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain a value |
| | | * that matches the filter type. |
| | | */ |
| | | public EntryIDSet evaluateFilter(IndexFilterType indexFilterType, SearchFilter filter, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | try |
| | | { |
| | | final IndexQuery indexQuery = getIndexQuery(indexFilterType, filter); |
| | | return evaluateIndexQuery(indexQuery, indexFilterType.toString(), filter, debugBuffer, monitor); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | | logger.traceException(e); |
| | | return new EntryIDSet(); |
| | | } |
| | | } |
| | | |
| | | private IndexQuery getIndexQuery(IndexFilterType indexFilterType, SearchFilter filter) throws DecodeException |
| | | { |
| | | MatchingRule rule; |
| | | Assertion assertion; |
| | | switch (indexFilterType) |
| | | { |
| | | case EQUALITY: |
| | | rule = filter.getAttributeType().getEqualityMatchingRule(); |
| | | assertion = rule.getAssertion(filter.getAssertionValue()); |
| | | return assertion.createIndexQuery(indexQueryFactory); |
| | | |
| | | case PRESENCE: |
| | | return indexQueryFactory.createMatchAllQuery(); |
| | | |
| | | case GREATER_OR_EQUAL: |
| | | rule = filter.getAttributeType().getOrderingMatchingRule(); |
| | | assertion = rule.getGreaterOrEqualAssertion(filter.getAssertionValue()); |
| | | return assertion.createIndexQuery(indexQueryFactory); |
| | | |
| | | case LESS_OR_EQUAL: |
| | | rule = filter.getAttributeType().getOrderingMatchingRule(); |
| | | assertion = rule.getLessOrEqualAssertion(filter.getAssertionValue()); |
| | | return assertion.createIndexQuery(indexQueryFactory); |
| | | |
| | | case SUBSTRING: |
| | | rule = filter.getAttributeType().getSubstringMatchingRule(); |
| | | assertion = rule.getSubstringAssertion( |
| | | filter.getSubInitialElement(), filter.getSubAnyElements(), filter.getSubFinalElement()); |
| | | return assertion.createIndexQuery(indexQueryFactory); |
| | | |
| | | case APPROXIMATE: |
| | | rule = filter.getAttributeType().getApproximateMatchingRule(); |
| | | assertion = rule.getAssertion(filter.getAssertionValue()); |
| | | return assertion.createIndexQuery(indexQueryFactory); |
| | | |
| | | default: |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * The default lexicographic byte array comparator. |
| | | * Is there one available in the Java platform? |
| | |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match an approximate filter. |
| | | * |
| | | * @param approximateFilter The approximate filter. |
| | | * @param debugBuffer If not null, a diagnostic string will be written |
| | | * which will help determine how the indexes contributed |
| | | * to this search. |
| | | * @param monitor The database environment monitor provider that will keep |
| | | * index filter usage statistics. |
| | | * @return The candidate entry IDs that might contain the filter |
| | | * assertion value. |
| | | */ |
| | | public EntryIDSet evaluateApproximateFilter(SearchFilter approximateFilter, StringBuilder debugBuffer, |
| | | DatabaseEnvironmentMonitor monitor) |
| | | { |
| | | try { |
| | | MatchingRule matchRule = approximateFilter.getAttributeType().getApproximateMatchingRule(); |
| | | IndexQuery indexQuery = matchRule.getAssertion(approximateFilter.getAssertionValue()) |
| | | .createIndexQuery(indexQueryFactory); |
| | | return evaluateIndexQuery(indexQuery, "approximate", approximateFilter, debugBuffer, monitor); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | | logger.traceException(e); |
| | | return new EntryIDSet(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Close cursors related to the attribute indexes. |
| | | * |
| | | * @throws DatabaseException If a database error occurs. |
| | |
| | | public synchronized boolean isConfigurationChangeAcceptable( |
| | | LocalDBIndexCfg cfg, List<LocalizableMessage> unacceptableReasons) |
| | | { |
| | | AttributeType attrType = cfg.getAttribute(); |
| | | if (!isIndexAcceptable(cfg, IndexType.EQUALITY, unacceptableReasons) |
| | | || !isIndexAcceptable(cfg, IndexType.SUBSTRING, unacceptableReasons) |
| | | || !isIndexAcceptable(cfg, IndexType.ORDERING, unacceptableReasons) |
| | | || !isIndexAcceptable(cfg, IndexType.APPROXIMATE, unacceptableReasons)) |
| | | { |
| | | return false; |
| | | } |
| | | |
| | | if (cfg.getIndexType().contains(IndexType.EQUALITY) |
| | | && nameToIndexes.get(IndexType.EQUALITY.toString()) == null |
| | | && attrType.getEqualityMatchingRule() == null) |
| | | { |
| | | unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "equality")); |
| | | return false; |
| | | } |
| | | if (cfg.getIndexType().contains(IndexType.SUBSTRING) |
| | | && nameToIndexes.get(IndexType.SUBSTRING.toString()) == null |
| | | && attrType.getSubstringMatchingRule() == null) |
| | | { |
| | | unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "substring")); |
| | | return false; |
| | | } |
| | | if (cfg.getIndexType().contains(IndexType.ORDERING) |
| | | && nameToIndexes.get(IndexType.ORDERING.toString()) == null |
| | | && attrType.getOrderingMatchingRule() == null) |
| | | { |
| | | unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "ordering")); |
| | | return false; |
| | | } |
| | | if (cfg.getIndexType().contains(IndexType.APPROXIMATE) |
| | | && nameToIndexes.get(IndexType.APPROXIMATE.toString()) == null |
| | | && attrType.getApproximateMatchingRule() == null) |
| | | { |
| | | unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "approximate")); |
| | | return false; |
| | | } |
| | | AttributeType attrType = cfg.getAttribute(); |
| | | if (cfg.getIndexType().contains(IndexType.EXTENSIBLE)) |
| | | { |
| | | Set<String> newRules = cfg.getIndexExtensibleMatchingRule(); |
| | |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | private boolean isIndexAcceptable(LocalDBIndexCfg cfg, IndexType indexType, |
| | | List<LocalizableMessage> unacceptableReasons) |
| | | { |
| | | final String indexId = indexType.toString(); |
| | | final AttributeType attrType = cfg.getAttribute(); |
| | | if (cfg.getIndexType().contains(indexType) |
| | | && nameToIndexes.get(indexId) == null |
| | | && getMatchingRule(indexType, attrType) == null) |
| | | { |
| | | unacceptableReasons.add(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, indexId)); |
| | | return false; |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public synchronized ConfigChangeResult applyConfigurationChange( |
| | | LocalDBIndexCfg cfg) |
| | | public synchronized ConfigChangeResult applyConfigurationChange(LocalDBIndexCfg cfg) |
| | | { |
| | | // this method is not perf sensitive, using an AtomicBoolean will not hurt |
| | | AtomicBoolean adminActionRequired = new AtomicBoolean(false); |
| | |
| | | { |
| | | AttributeType attrType = cfg.getAttribute(); |
| | | String name = entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID(); |
| | | final int indexEntryLimit = cfg.getIndexEntryLimit(); |
| | | |
| | | Index presenceIndex = nameToIndexes.get(IndexType.PRESENCE.toString()); |
| | | if (cfg.getIndexType().contains(IndexType.PRESENCE)) |
| | | { |
| | | if (presenceIndex == null) |
| | | { |
| | | Indexer presenceIndexer = new PresenceIndexer(attrType); |
| | | presenceIndex = newIndex(name + ".presence", indexEntryLimit, presenceIndexer); |
| | | openIndex(presenceIndex, adminActionRequired, messages); |
| | | nameToIndexes.put(IndexType.PRESENCE.toString(), presenceIndex); |
| | | applyChangeToPresenceIndex(cfg, attrType, name, adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.EQUALITY, adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.SUBSTRING, adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.ORDERING, adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.APPROXIMATE, adminActionRequired, messages); |
| | | applyChangeToExtensibleIndexes(cfg, attrType, name, adminActionRequired, messages); |
| | | |
| | | extensibleIndexesMapping = computeExtensibleIndexesMapping(); |
| | | indexConfig = cfg; |
| | | |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired.get(), messages); |
| | | } |
| | | else |
| | | catch(Exception e) |
| | | { |
| | | // already exists. Just update index entry limit. |
| | | if (presenceIndex.setIndexEntryLimit(indexEntryLimit)) |
| | | { |
| | | adminActionRequired.set(true); |
| | | messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(presenceIndex.getName())); |
| | | messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e))); |
| | | return new ConfigChangeResult( |
| | | DirectoryServer.getServerErrorResultCode(), adminActionRequired.get(), messages); |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | removeIndex(presenceIndex, IndexType.PRESENCE); |
| | | } |
| | | |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.EQUALITY, |
| | | new EqualityIndexer(attrType), adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.SUBSTRING, |
| | | new SubstringIndexer(attrType), adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.ORDERING, |
| | | new OrderingIndexer(attrType), adminActionRequired, messages); |
| | | applyChangeToIndex(cfg, attrType, name, IndexType.APPROXIMATE, |
| | | new ApproximateIndexer(attrType), adminActionRequired, messages); |
| | | |
| | | if (cfg.getIndexType().contains(IndexType.EXTENSIBLE)) |
| | | private void applyChangeToExtensibleIndexes(LocalDBIndexCfg cfg, AttributeType attrType, |
| | | String name, AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages) |
| | | { |
| | | if (!cfg.getIndexType().contains(IndexType.EXTENSIBLE)) |
| | | { |
| | | final Set<MatchingRule> validRules = Collections.emptySet(); |
| | | final Set<String> validIndexIds = Collections.emptySet(); |
| | | removeIndexesForExtensibleMatchingRules(validRules, validIndexIds); |
| | | return; |
| | | } |
| | | |
| | | final Set<String> extensibleRules = cfg.getIndexExtensibleMatchingRule(); |
| | | final Set<MatchingRule> validRules = new HashSet<MatchingRule>(); |
| | | final Set<String> validIndexIds = new HashSet<String>(); |
| | | final int indexEntryLimit = cfg.getIndexEntryLimit(); |
| | | |
| | | for (String ruleName: extensibleRules) |
| | | { |
| | |
| | | validIndexIds.add(indexId); |
| | | if (!nameToIndexes.containsKey(indexId)) |
| | | { |
| | | String indexName = name + "." + indexId; |
| | | Index extIndex = newExtensibleIndex(indexName, attrType, indexEntryLimit, indexer); |
| | | nameToIndexes.put(indexId, extIndex); |
| | | Index extIndex = newExtensibleIndex(attrType, name, indexEntryLimit, indexer); |
| | | openIndex(extIndex, adminActionRequired, messages); |
| | | nameToIndexes.put(indexId, extIndex); |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | removeIndexesForExtensibleMatchingRules(validRules, validIndexIds); |
| | | } |
| | | else |
| | | { |
| | | final Set<MatchingRule> validRules = Collections.emptySet(); |
| | | final Set<String> validIndexIds = Collections.emptySet(); |
| | | removeIndexesForExtensibleMatchingRules(validRules, validIndexIds); |
| | | } |
| | | |
| | | extensibleIndexesMapping = computeExtensibleIndexesMapping(); |
| | | indexConfig = cfg; |
| | | |
| | | return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired.get(), messages); |
| | | } |
| | | catch(Exception e) |
| | | { |
| | | messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e))); |
| | | return new ConfigChangeResult( |
| | | DirectoryServer.getServerErrorResultCode(), adminActionRequired.get(), messages); |
| | | } |
| | | } |
| | | |
| | | /** Remove indexes which do not correspond to valid rules. */ |
| | | private void removeIndexesForExtensibleMatchingRules(Set<MatchingRule> validRules, Set<String> validIndexIds) |
| | |
| | | return rules; |
| | | } |
| | | |
| | | private void applyChangeToIndex(LocalDBIndexCfg cfg, AttributeType attrType, |
| | | String name, IndexType indexType, org.forgerock.opendj.ldap.spi.Indexer indexer, |
| | | private void applyChangeToIndex(LocalDBIndexCfg cfg, AttributeType attrType, String name, IndexType indexType, |
| | | AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages) |
| | | { |
| | | final int indexEntryLimit = cfg.getIndexEntryLimit(); |
| | | |
| | | Index index = nameToIndexes.get(indexType.toString()); |
| | | if (cfg.getIndexType().contains(indexType)) |
| | | String indexId = indexType.toString(); |
| | | Index index = nameToIndexes.get(indexId); |
| | | if (!cfg.getIndexType().contains(indexType)) |
| | | { |
| | | removeIndex(index, indexType); |
| | | return; |
| | | } |
| | | |
| | | final int indexEntryLimit = cfg.getIndexEntryLimit(); |
| | | if (index == null) |
| | | { |
| | | index = openNewIndex(name, attrType, indexEntryLimit, |
| | | indexer, adminActionRequired, messages); |
| | | nameToIndexes.put(indexType.toString(), index); |
| | | final MatchingRule matchingRule = getMatchingRule(indexType, attrType); |
| | | for (org.forgerock.opendj.ldap.spi.Indexer indexer : matchingRule.getIndexers()) |
| | | { |
| | | index = newExtensibleIndex(attrType, name, indexEntryLimit, indexer); |
| | | openIndex(index, adminActionRequired, messages); |
| | | nameToIndexes.put(indexId, index); |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | else |
| | | |
| | | private void applyChangeToPresenceIndex(LocalDBIndexCfg cfg, AttributeType attrType, String name, |
| | | AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages) |
| | | { |
| | | IndexType indexType = IndexType.PRESENCE; |
| | | String indexId = indexType.toString(); |
| | | Index index = nameToIndexes.get(indexId); |
| | | if (!cfg.getIndexType().contains(indexType)) |
| | | { |
| | | removeIndex(index, indexType); |
| | | return; |
| | | } |
| | | |
| | | final int indexEntryLimit = cfg.getIndexEntryLimit(); |
| | | if (index == null) |
| | | { |
| | | Indexer presenceIndexer = new PresenceIndexer(attrType); |
| | | index = newIndex(name + ".presence", indexEntryLimit, presenceIndexer); |
| | | openIndex(index, adminActionRequired, messages); |
| | | nameToIndexes.put(indexId, index); |
| | | } |
| | | else |
| | | { |
| | | // already exists. Just update index entry limit. |
| | | if (index.setIndexEntryLimit(indexEntryLimit)) |
| | | { |
| | | adminActionRequired.set(true); |
| | | messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(index.getName())); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | private Index openNewIndex(String name, AttributeType attrType, |
| | | int indexEntryLimit, org.forgerock.opendj.ldap.spi.Indexer indexer, |
| | | AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages) |
| | | { |
| | | final String indexName = name + "." + indexer.getIndexID(); |
| | | Index index = newExtensibleIndex(indexName, attrType, indexEntryLimit, indexer); |
| | | return openIndex(index, adminActionRequired, messages); |
| | | } |
| | | |
| | | private Index openIndex(Index index, AtomicBoolean adminActionRequired, |
| | | ArrayList<LocalizableMessage> messages) |
| | | private void openIndex(Index index, AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages) |
| | | { |
| | | index.open(); |
| | | |
| | |
| | | adminActionRequired.set(true); |
| | | messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(index.getName())); |
| | | } |
| | | return index; |
| | | } |
| | | |
| | | /** |
| | |
| | | || matchRuleOID.equalsIgnoreCase(eqRule.getNameOrOID())) |
| | | { |
| | | //No matching rule is defined; use the default equality matching rule. |
| | | return evaluateEqualityFilter(filter, debugBuffer, monitor); |
| | | return evaluateFilter(IndexFilterType.EQUALITY, filter, debugBuffer, monitor); |
| | | } |
| | | |
| | | MatchingRule rule = DirectoryServer.getMatchingRule(matchRuleOID); |
| | |
| | | |
| | | private boolean ruleHasAtLeasOneIndex(MatchingRule rule) |
| | | { |
| | | boolean ruleHasAtLeastOneIndex = false; |
| | | for (org.forgerock.opendj.ldap.spi.Indexer indexer : rule.getIndexers()) |
| | | { |
| | | if (nameToIndexes.containsKey(indexer.getIndexID())) |
| | | { |
| | | ruleHasAtLeastOneIndex = true; |
| | | break; |
| | | return true; |
| | | } |
| | | } |
| | | return ruleHasAtLeastOneIndex; |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | import org.opends.server.backends.jeb.AttributeIndex.IndexFilterType; |
| | | import org.opends.server.core.SearchOperation; |
| | | import org.opends.server.monitors.DatabaseEnvironmentMonitor; |
| | | import org.opends.server.types.AttributeType; |
| | |
| | | |
| | | import static org.opends.messages.JebMessages.*; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * An index filter is used to apply a search operation to a set of indexes |
| | | * to generate a set of candidate entries. |
| | |
| | | */ |
| | | private EntryIDSet evaluateFilter(SearchFilter filter) |
| | | { |
| | | EntryIDSet candidates; |
| | | EntryIDSet candidates = pp(filter); |
| | | if (buffer != null) |
| | | { |
| | | candidates.toString(buffer); |
| | | } |
| | | return candidates; |
| | | } |
| | | |
| | | /** |
| | | * @param filter |
| | | * @return |
| | | */ |
| | | private EntryIDSet pp(SearchFilter filter) |
| | | { |
| | | switch (filter.getFilterType()) |
| | | { |
| | | case AND: |
| | |
| | | { |
| | | buffer.append("(&"); |
| | | } |
| | | candidates = evaluateLogicalAndFilter(filter); |
| | | final EntryIDSet res1 = evaluateLogicalAndFilter(filter); |
| | | if (buffer != null) |
| | | { |
| | | buffer.append(")"); |
| | | } |
| | | break; |
| | | return res1; |
| | | |
| | | case OR: |
| | | if (buffer != null) |
| | | { |
| | | buffer.append("(|"); |
| | | } |
| | | candidates = evaluateLogicalOrFilter(filter); |
| | | final EntryIDSet res2 = evaluateLogicalOrFilter(filter); |
| | | if (buffer != null) |
| | | { |
| | | buffer.append(")"); |
| | | } |
| | | break; |
| | | return res2; |
| | | |
| | | case EQUALITY: |
| | | if (buffer != null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluateEqualityFilter(filter); |
| | | break; |
| | | return evaluateFilterWithDiagnostic(IndexFilterType.EQUALITY, filter); |
| | | |
| | | case GREATER_OR_EQUAL: |
| | | if (buffer != null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluateGreaterOrEqualFilter(filter); |
| | | break; |
| | | return evaluateFilterWithDiagnostic(IndexFilterType.GREATER_OR_EQUAL, filter); |
| | | |
| | | case SUBSTRING: |
| | | if (buffer != null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluateSubstringFilter(filter); |
| | | break; |
| | | return evaluateFilterWithDiagnostic(IndexFilterType.SUBSTRING, filter); |
| | | |
| | | case LESS_OR_EQUAL: |
| | | if (buffer != null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluateLessOrEqualFilter(filter); |
| | | break; |
| | | return evaluateFilterWithDiagnostic(IndexFilterType.LESS_OR_EQUAL, filter); |
| | | |
| | | case PRESENT: |
| | | if (buffer != null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluatePresenceFilter(filter); |
| | | break; |
| | | return evaluateFilterWithDiagnostic(IndexFilterType.PRESENCE, filter); |
| | | |
| | | case APPROXIMATE_MATCH: |
| | | if (buffer != null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluateApproximateFilter(filter); |
| | | break; |
| | | return evaluateFilterWithDiagnostic(IndexFilterType.APPROXIMATE, filter); |
| | | |
| | | case EXTENSIBLE_MATCH: |
| | | if (buffer!= null) |
| | | { |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = evaluateExtensibleFilter(filter); |
| | | break; |
| | | return evaluateExtensibleFilter(filter); |
| | | |
| | | case NOT: |
| | | default: |
| | |
| | | filter.toString(buffer); |
| | | } |
| | | //NYI |
| | | candidates = new EntryIDSet(); |
| | | break; |
| | | return new EntryIDSet(); |
| | | } |
| | | |
| | | if (buffer != null) |
| | | { |
| | | candidates.toString(buffer); |
| | | } |
| | | return candidates; |
| | | } |
| | | |
| | | /** |
| | |
| | | for (SearchFilter filter : fastComps) |
| | | { |
| | | EntryIDSet set = evaluateFilter(filter); |
| | | |
| | | if (retainAll(results, set)) |
| | | { |
| | | return results; |
| | |
| | | for (SearchFilter filter : otherComps) |
| | | { |
| | | EntryIDSet set = evaluateFilter(filter); |
| | | |
| | | if (retainAll(results, set)) |
| | | { |
| | | return results; |
| | |
| | | } |
| | | |
| | | ArrayList<SearchFilter> remainComps = new ArrayList<SearchFilter>(); |
| | | for (Map.Entry<AttributeType, ArrayList<SearchFilter>> rangeEntry : |
| | | rangeComps.entrySet()) |
| | | for (Map.Entry<AttributeType, ArrayList<SearchFilter>> rangeEntry : rangeComps.entrySet()) |
| | | { |
| | | ArrayList<SearchFilter> rangeList = rangeEntry.getValue(); |
| | | if (rangeList.size() == 2) |
| | |
| | | a.retainAll(b); |
| | | |
| | | // We may have reached the point of diminishing returns where |
| | | // it is quicker to stop now and process the current small number of |
| | | // candidates. |
| | | // it is quicker to stop now and process the current small number of candidates. |
| | | return a.isDefined() && a.size() <= FILTER_CANDIDATE_THRESHOLD; |
| | | |
| | | } |
| | |
| | | return EntryIDSet.unionOfSets(candidateSets, false); |
| | | } |
| | | |
| | | /** |
| | | * Evaluate an equality filter against the indexes. |
| | | * |
| | | * @param equalityFilter The equality filter to be evaluated. |
| | | * @return A set of entry IDs representing candidate entries. |
| | | */ |
| | | private EntryIDSet evaluateEqualityFilter(SearchFilter equalityFilter) |
| | | private EntryIDSet evaluateFilterWithDiagnostic(IndexFilterType indexFilterType, SearchFilter filter) |
| | | { |
| | | EntryIDSet candidates; |
| | | AttributeIndex attributeIndex = |
| | | entryContainer.getAttributeIndex(equalityFilter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | if (buffer != null) |
| | | { |
| | | if(monitor.isFilterUseEnabled()) |
| | | { |
| | | monitor.updateStats(equalityFilter, |
| | | INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("equality", |
| | | equalityFilter.getAttributeType().getNameOrOID())); |
| | | filter.toString(buffer); |
| | | } |
| | | candidates = new EntryIDSet(); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluateEqualityFilter(equalityFilter, |
| | | buffer, monitor); |
| | | } |
| | | return candidates; |
| | | return evaluateFilter(indexFilterType, filter); |
| | | } |
| | | |
| | | /** |
| | | * Evaluate a presence filter against the indexes. |
| | | * |
| | | * @param filter The presence filter to be evaluated. |
| | | * @return A set of entry IDs representing candidate entries. |
| | | */ |
| | | private EntryIDSet evaluatePresenceFilter(SearchFilter filter) |
| | | private EntryIDSet evaluateFilter(IndexFilterType indexFilterType, SearchFilter filter) |
| | | { |
| | | EntryIDSet candidates; |
| | | AttributeIndex attributeIndex = |
| | | entryContainer.getAttributeIndex(filter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | AttributeIndex attributeIndex = entryContainer.getAttributeIndex(filter.getAttributeType()); |
| | | if (attributeIndex != null) |
| | | { |
| | | if(monitor.isFilterUseEnabled()) |
| | | { |
| | | monitor.updateStats(filter, |
| | | INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("presence", |
| | | filter.getAttributeType().getNameOrOID())); |
| | | } |
| | | candidates = new EntryIDSet(); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluatePresenceFilter(filter, buffer, |
| | | monitor); |
| | | } |
| | | return candidates; |
| | | return attributeIndex.evaluateFilter(indexFilterType, filter, buffer, monitor); |
| | | } |
| | | |
| | | /** |
| | | * Evaluate a greater-or-equal filter against the indexes. |
| | | * |
| | | * @param filter The greater-or-equal filter to be evaluated. |
| | | * @return A set of entry IDs representing candidate entries. |
| | | */ |
| | | private EntryIDSet evaluateGreaterOrEqualFilter(SearchFilter filter) |
| | | { |
| | | EntryIDSet candidates; |
| | | AttributeIndex attributeIndex = |
| | | entryContainer.getAttributeIndex(filter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | { |
| | | if(monitor.isFilterUseEnabled()) |
| | | { |
| | | monitor.updateStats(filter, |
| | | INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("ordering", |
| | | filter.getAttributeType().getNameOrOID())); |
| | | monitor.updateStats(filter, INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get( |
| | | indexFilterType.toString(), filter.getAttributeType().getNameOrOID())); |
| | | } |
| | | candidates = new EntryIDSet(); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluateGreaterOrEqualFilter(filter, |
| | | buffer, monitor); |
| | | } |
| | | return candidates; |
| | | } |
| | | |
| | | /** |
| | | * Evaluate a less-or-equal filter against the indexes. |
| | | * |
| | | * @param filter The less-or-equal filter to be evaluated. |
| | | * @return A set of entry IDs representing candidate entries. |
| | | */ |
| | | private EntryIDSet evaluateLessOrEqualFilter(SearchFilter filter) |
| | | { |
| | | EntryIDSet candidates; |
| | | AttributeIndex attributeIndex = |
| | | entryContainer.getAttributeIndex(filter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | { |
| | | if(monitor.isFilterUseEnabled()) |
| | | { |
| | | monitor.updateStats(filter, |
| | | INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("ordering", |
| | | filter.getAttributeType().getNameOrOID())); |
| | | } |
| | | candidates = new EntryIDSet(); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluateLessOrEqualFilter(filter, buffer, |
| | | monitor); |
| | | } |
| | | return candidates; |
| | | } |
| | | |
| | | /** |
| | | * Evaluate a substring filter against the indexes. |
| | | * |
| | | * @param filter The substring filter to be evaluated. |
| | | * @return A set of entry IDs representing candidate entries. |
| | | */ |
| | | private EntryIDSet evaluateSubstringFilter(SearchFilter filter) |
| | | { |
| | | EntryIDSet candidates; |
| | | AttributeIndex attributeIndex = |
| | | entryContainer.getAttributeIndex(filter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | { |
| | | if(monitor.isFilterUseEnabled()) |
| | | { |
| | | monitor.updateStats(filter, |
| | | INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get( |
| | | "substring or equality", |
| | | filter.getAttributeType().getNameOrOID())); |
| | | } |
| | | candidates = new EntryIDSet(); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluateSubstringFilter(filter, |
| | | buffer, monitor); |
| | | } |
| | | return candidates; |
| | | } |
| | | |
| | | /** |
| | | * Evaluate an approximate filter against the indexes. |
| | | * |
| | | * @param approximateFilter The approximate filter to be evaluated. |
| | | * @return A set of entry IDs representing candidate entries. |
| | | */ |
| | | private EntryIDSet evaluateApproximateFilter(SearchFilter approximateFilter) |
| | | { |
| | | EntryIDSet candidates; |
| | | AttributeIndex attributeIndex = |
| | | entryContainer.getAttributeIndex(approximateFilter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | { |
| | | if(monitor.isFilterUseEnabled()) |
| | | { |
| | | monitor.updateStats(approximateFilter, |
| | | INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("approximate", |
| | | approximateFilter.getAttributeType().getNameOrOID())); |
| | | } |
| | | candidates = new EntryIDSet(); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluateApproximateFilter(approximateFilter, |
| | | buffer, monitor); |
| | | } |
| | | return candidates; |
| | | return new EntryIDSet(); |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | private EntryIDSet evaluateExtensibleFilter(SearchFilter extensibleFilter) |
| | | { |
| | | EntryIDSet candidates; |
| | | |
| | | 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. |
| | | candidates = IndexQuery.createNullIndexQuery().evaluate(null); |
| | | return IndexQuery.createNullIndexQuery().evaluate(null); |
| | | } |
| | | else |
| | | |
| | | AttributeIndex attributeIndex = entryContainer.getAttributeIndex(extensibleFilter.getAttributeType()); |
| | | if (attributeIndex != null) |
| | | { |
| | | AttributeIndex attributeIndex = entryContainer |
| | | .getAttributeIndex(extensibleFilter.getAttributeType()); |
| | | if (attributeIndex == null) |
| | | { |
| | | candidates = IndexQuery.createNullIndexQuery().evaluate(null); |
| | | return attributeIndex.evaluateExtensibleFilter(extensibleFilter, buffer, monitor); |
| | | } |
| | | else |
| | | { |
| | | candidates = attributeIndex.evaluateExtensibleFilter(extensibleFilter, |
| | | buffer, monitor); |
| | | } |
| | | } |
| | | return candidates; |
| | | return IndexQuery.createNullIndexQuery().evaluate(null); |
| | | } |
| | | } |
| | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.schema.Schema; |
| | | import org.forgerock.opendj.ldap.spi.IndexingOptions; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | |
| | | { |
| | | try |
| | | { |
| | | indexer.createKeys(null, value, options, keys); |
| | | indexer.createKeys(Schema.getDefaultSchema(), value, options, keys); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.util.*; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedHashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.opendj.ldap.*; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.forgerock.opendj.ldap.schema.MatchingRule; |
| | | import org.forgerock.opendj.ldap.spi.IndexingOptions; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.server.AdminTestCaseUtils; |
| | |
| | | import org.opends.server.protocols.internal.InternalClientConnection; |
| | | import org.opends.server.protocols.internal.InternalSearchOperation; |
| | | import org.opends.server.protocols.internal.SearchRequest; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeBuilder; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.Attributes; |
| | | import org.opends.server.types.Control; |
| | | import org.opends.server.types.DN; |
| | | import org.opends.server.types.DirectoryException; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.RDN; |
| | | import org.opends.server.types.SearchResultEntry; |
| | | import org.opends.server.util.Base64; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | |
| | | import com.sleepycat.je.DatabaseEntry; |
| | | import com.sleepycat.je.LockMode; |
| | | |
| | | import static java.util.Collections.*; |
| | | |
| | | import static org.assertj.core.api.Assertions.*; |
| | | import static org.forgerock.opendj.ldap.ConditionResult.*; |
| | | import static org.forgerock.opendj.ldap.ModificationType.*; |
| | |
| | | |
| | | @Test(dependsOnMethods = "testAdd") |
| | | public void testSearchIndex() throws Exception { |
| | | InternalClientConnection conn = InternalClientConnection.getRootConnection(); |
| | | Set<String> attribs = new LinkedHashSet<String>(); |
| | | String debugString; |
| | | List<SearchResultEntry> result; |
| | | |
| | | // search 1 |
| | | result = doSubtreeSearch(conn, "(&(cn=Aaccf Amar)(cn=Ardyth Bainton))", attribs); |
| | | result = doSubtreeSearch("(&(cn=Aaccf Amar)(cn=Ardyth Bainton))", attribs); |
| | | assertEquals(result.size(), 0); |
| | | |
| | | // Adding a debug search attribute for next searches |
| | | attribs.add(ATTR_DEBUG_SEARCH_INDEX); |
| | | |
| | | // search 2 |
| | | result = doSubtreeSearch(conn, "(&(cn=Aaccf Amar)(employeeNumber=222))", attribs); |
| | | result = doSubtreeSearch("(&(cn=Aaccf Amar)(employeeNumber=222))", attribs); |
| | | |
| | | // Only one index should be used because it is below the FILTER_CANDIDATE |
| | | debugString = getDebugString(result); |
| | |
| | | assertResultsCountIs(1, debugString); |
| | | |
| | | // search 3 |
| | | result = doSubtreeSearch(conn, "(|(cn=Aaccf Amar)(cn=Ardyth Bainton))", attribs); |
| | | result = doSubtreeSearch("(|(cn=Aaccf Amar)(cn=Ardyth Bainton))", attribs); |
| | | |
| | | debugString = getDebugString(result); |
| | | assertFalse(debugString.contains("NOT-INDEXED")); |
| | | assertThat(debugString).doesNotContain("NOT-INDEXED"); |
| | | assertResultsCountIs(2, debugString); |
| | | |
| | | // search 4 |
| | | result = doSubtreeSearch(conn, "(&(employeeNumber=*)(cn=A*)(employeeNumber>=0)(employeeNumber<=z))", attribs); |
| | | result = doSubtreeSearch("(&(employeeNumber=*)(cn=A*)(employeeNumber>=0)(employeeNumber<=z))", attribs); |
| | | |
| | | debugString = getDebugString(result); |
| | | assertFalse(debugString.contains("NOT-INDEXED")); |
| | | assertThat(debugString).doesNotContain("NOT-INDEXED"); |
| | | assertResultsCountIs(12, debugString); |
| | | |
| | | // search 5 |
| | | result = doSubtreeSearch(conn, |
| | | "(&(employeeNumber<=z)(cn<=Abbey Abbie)(cn>=0)(|(cn>=Abahri Abazari)(employeeNumber<=9)))", attribs); |
| | | |
| | | result = doSubtreeSearch("(&(employeeNumber<=z)(cn<=Abbey Abbie)(cn>=0)(|(cn>=Abahri Abazari)(employeeNumber<=9)))", |
| | | attribs); |
| | | |
| | | debugString = getDebugString(result); |
| | | assertFalse(debugString.contains("NOT-INDEXED")); |
| | | assertThat(debugString).doesNotContain("NOT-INDEXED"); |
| | | assertResultsCountIs(11, debugString); |
| | | |
| | | // search 6 |
| | | result = doSubtreeSearch(conn, "(cn~=Aartjan)", attribs); |
| | | result = doSubtreeSearch("(cn~=Aartjan)", attribs); |
| | | |
| | | debugString = getDebugString(result); |
| | | assertFalse(debugString.contains("NOT-INDEXED")); |
| | | assertThat(debugString).doesNotContain("NOT-INDEXED"); |
| | | assertResultsCountIs(1, debugString); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** Returns the results of subtree search on provided connection with provided filter. */ |
| | | private List<SearchResultEntry> doSubtreeSearch(InternalClientConnection conn, String filter, |
| | | Set<String> attribs) throws Exception |
| | | private List<SearchResultEntry> doSubtreeSearch(String filter, Set<String> attribs) throws Exception |
| | | { |
| | | final SearchRequest request = |
| | | newSearchRequest("dc=test,dc=com", SearchScope.WHOLE_SUBTREE, filter).addAttribute(attribs); |
| | | InternalSearchOperation search = conn.processSearch(request); |
| | | InternalSearchOperation search = getRootConnection().processSearch(request); |
| | | return search.getSearchEntries(); |
| | | } |
| | | |
| | |
| | | "testNumSubordinatesIndexEntryLimitExceeded"}) |
| | | public void testDeleteSubtree() throws Exception { |
| | | Control control = new SubtreeDeleteControl(false); |
| | | List<Control> deleteSubTreeControl = new ArrayList<Control>(); |
| | | deleteSubTreeControl.add(control); |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | List<Control> deleteSubTreeControl = Collections.singletonList(control); |
| | | |
| | | DeleteOperationBasis delete = new DeleteOperationBasis(conn, |
| | | InternalClientConnection.nextOperationID(), |
| | | InternalClientConnection.nextMessageID(), |
| | | DeleteOperationBasis delete = new DeleteOperationBasis( |
| | | getRootConnection(), nextOperationID(), nextMessageID(), |
| | | deleteSubTreeControl, |
| | | DN.valueOf("dc=test1,dc=com")); |
| | | |
| | |
| | | "testSearchScope", "testMatchedDN"}) |
| | | public void testDeleteEntry() throws Exception { |
| | | List<Control> noControls = new ArrayList<Control>(0); |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | |
| | | EntryContainer ec = |
| | | backend.getRootContainer().getEntryContainer(DN.valueOf("ou=People,dc=test,dc=com")); |
| | | |
| | |
| | | EntryID entryID = ec.getDN2ID().get(null, |
| | | DN.valueOf("uid=user.539,ou=People,dc=test,dc=com"), LockMode.DEFAULT); |
| | | |
| | | DeleteOperationBasis delete = new DeleteOperationBasis(conn, |
| | | InternalClientConnection.nextOperationID(), |
| | | InternalClientConnection.nextMessageID(), |
| | | DeleteOperationBasis delete = new DeleteOperationBasis( |
| | | getRootConnection(), nextOperationID(), nextMessageID(), |
| | | noControls, |
| | | |
| | | DN.valueOf("uid=user.539,ou=People,dc=test,dc=com")); |
| | | |
| | | |
| | | backend.deleteEntry(DN.valueOf("uid=user.539,ou=People,dc=test,dc=com"), |
| | | delete); |
| | | backend.deleteEntry(DN.valueOf("uid=user.539,ou=People,dc=test,dc=com"), delete); |
| | | |
| | | |
| | | assertFalse(ec.entryExists(DN.valueOf("uid=user.539,ou=People,dc=test,dc=com"))); |
| | |
| | | assertFalse(ec.getDN2URI().delete(null, |
| | | DN.valueOf("uid=user.539,ou=People,dc=test,dc=com"))); |
| | | |
| | | AttributeType attribute = |
| | | entries.get(0).getAttribute("cn").get(0).getAttributeType(); |
| | | AttributeType attribute = entries.get(0).getAttribute("cn").get(0).getAttributeType(); |
| | | AttributeIndex index = ec.getAttributeIndex(attribute); |
| | | AttributeType attrType = index.getAttributeType(); |
| | | |
| | | Indexer presenceIndexer = new PresenceIndexer(index.getAttributeType()); |
| | | assertIndexContainsID(presenceIndexer, entry, index.getPresenceIndex(), entryID, FALSE); |
| | | List<? extends Indexer> indexers; |
| | | indexers = singletonList(new PresenceIndexer(index.getAttributeType())); |
| | | assertIndexContainsID(indexers, entry, index.getPresenceIndex(), entryID, FALSE); |
| | | |
| | | Indexer equalityIndexer = newEqualityIndexer(index); |
| | | assertIndexContainsID(equalityIndexer, entry, index.getEqualityIndex(), entryID, FALSE); |
| | | indexers = newJEExtensibleIndexers(attrType, attrType.getEqualityMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, index.getEqualityIndex(), entryID, FALSE); |
| | | |
| | | Indexer substringIndexer = newSubstringIndexer(index); |
| | | assertIndexContainsID(substringIndexer, entry, index.getSubstringIndex(), entryID, FALSE); |
| | | indexers = newJEExtensibleIndexers(attrType, attrType.getSubstringMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, index.getSubstringIndex(), entryID, FALSE); |
| | | |
| | | Indexer orderingIndexer = newOrderingIndexer(index); |
| | | assertIndexContainsID(orderingIndexer, entry, index.getOrderingIndex(), entryID, FALSE); |
| | | indexers = newJEExtensibleIndexers(attrType, attrType.getOrderingMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, index.getOrderingIndex(), entryID, FALSE); |
| | | } |
| | | finally |
| | | { |
| | |
| | | } |
| | | } |
| | | |
| | | private Indexer newOrderingIndexer(AttributeIndex index) |
| | | private List<JEExtensibleIndexer> newJEExtensibleIndexers(AttributeType attrType, MatchingRule matchingRule) |
| | | { |
| | | AttributeType attrType = index.getAttributeType(); |
| | | return new JEExtensibleIndexer(attrType, new OrderingIndexer(attrType)); |
| | | List<JEExtensibleIndexer> extIndexers = new ArrayList<JEExtensibleIndexer>(); |
| | | for (org.forgerock.opendj.ldap.spi.Indexer indexer : matchingRule.getIndexers()) |
| | | { |
| | | extIndexers.add(new JEExtensibleIndexer(attrType, indexer)); |
| | | } |
| | | |
| | | private Indexer newEqualityIndexer(AttributeIndex index) |
| | | { |
| | | AttributeType attrType = index.getAttributeType(); |
| | | return new JEExtensibleIndexer(attrType, new EqualityIndexer(attrType)); |
| | | } |
| | | |
| | | private Indexer newSubstringIndexer(AttributeIndex index) |
| | | { |
| | | AttributeType attrType = index.getAttributeType(); |
| | | return new JEExtensibleIndexer(attrType, new SubstringIndexer(attrType)); |
| | | } |
| | | |
| | | private IndexingOptions getOptions(AttributeIndex index) |
| | | { |
| | | final IndexingOptions options = mock(IndexingOptions.class); |
| | | when(options.substringKeySize()).thenReturn( |
| | | index.getConfiguration().getSubstringLength()); |
| | | return options; |
| | | return extIndexers; |
| | | } |
| | | |
| | | private IndexingOptions getOptions() |
| | |
| | | return options; |
| | | } |
| | | |
| | | private void assertIndexContainsID(Indexer indexer, Entry entry, Index index, |
| | | EntryID entryID) |
| | | private void assertIndexContainsID(List<? extends Indexer> indexers, Entry entry, Index index, EntryID entryID) |
| | | { |
| | | for (Indexer indexer : indexers) |
| | | { |
| | | Set<ByteString> addKeys = new HashSet<ByteString>(); |
| | | indexer.indexEntry(entry, addKeys, getOptions()); |
| | |
| | | assertEquals(index.containsID(null, key, entryID), TRUE); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void assertIndexContainsID(Indexer indexer, Entry entry, |
| | | private void assertIndexContainsID(List<? extends Indexer> indexers, Entry entry, |
| | | Index index, EntryID entryID, ConditionResult expected) |
| | | { |
| | | for (Indexer indexer : indexers) |
| | | { |
| | | Set<ByteString> addKeys = new HashSet<ByteString>(); |
| | | indexer.indexEntry(entry, addKeys, getOptions()); |
| | | |
| | | assertIndexContainsID(addKeys, index, entryID, expected); |
| | | } |
| | | } |
| | | |
| | | private void assertIndexContainsID(Set<ByteString> addKeys, Index index, |
| | | EntryID entryID, ConditionResult expected) |
| | |
| | | assertEquals(value.toString(), "777"); |
| | | } |
| | | |
| | | AttributeType attribute = |
| | | entry.getAttribute("cn").get(0).getAttributeType(); |
| | | AttributeType attribute = entry.getAttribute("cn").get(0).getAttributeType(); |
| | | AttributeIndex index = ec.getAttributeIndex(attribute); |
| | | AttributeType attrType = index.getAttributeType(); |
| | | |
| | | Indexer orderingIndexer = newOrderingIndexer(index); |
| | | assertIndexContainsID(orderingIndexer, entry, index.getOrderingIndex(), entryID, TRUE); |
| | | assertIndexContainsID(orderingIndexer, oldEntry, index.getOrderingIndex(), entryID, FALSE); |
| | | List<? extends Indexer> indexers; |
| | | indexers = newJEExtensibleIndexers(attrType, attrType.getOrderingMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, index.getOrderingIndex(), entryID, TRUE); |
| | | assertIndexContainsID(indexers, oldEntry, index.getOrderingIndex(), entryID, FALSE); |
| | | |
| | | Indexer substringIndexer = newSubstringIndexer(index); |
| | | assertIndexContainsID(substringIndexer, entry, index.getSubstringIndex(), entryID, TRUE); |
| | | assertIndexContainsID(substringIndexer, oldEntry, index.getSubstringIndex(), entryID, FALSE); |
| | | indexers = newJEExtensibleIndexers(attrType, attrType.getSubstringMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, index.getSubstringIndex(), entryID, TRUE); |
| | | assertIndexContainsID(indexers, oldEntry, index.getSubstringIndex(), entryID, FALSE); |
| | | |
| | | Indexer equalityIndexer = newEqualityIndexer(index); |
| | | assertIndexContainsID(equalityIndexer, entry, index.getEqualityIndex(), entryID, TRUE); |
| | | assertIndexContainsID(equalityIndexer, oldEntry, index.getEqualityIndex(), entryID, FALSE); |
| | | indexers = newJEExtensibleIndexers(attrType, attrType.getEqualityMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, index.getEqualityIndex(), entryID, TRUE); |
| | | assertIndexContainsID(indexers, oldEntry, index.getEqualityIndex(), entryID, FALSE); |
| | | } |
| | | finally |
| | | { |
| | |
| | | AttributeIndex titleIndex; |
| | | AttributeIndex nameIndex; |
| | | Set<ByteString> addKeys; |
| | | Indexer presenceIndexer; |
| | | Indexer equalityIndexer; |
| | | Indexer substringIndexer; |
| | | Indexer orderingIndexer; |
| | | List<? extends Indexer> indexers; |
| | | |
| | | EntryContainer ec = backend.getRootContainer().getEntryContainer( |
| | | DN.valueOf("dc=test,dc=com")); |
| | |
| | | assertIndexContainsID(addKeys, nameIndex.getPresenceIndex(), entryID, TRUE); |
| | | |
| | | List<Control> noControls = new ArrayList<Control>(0); |
| | | InternalClientConnection conn = InternalClientConnection.getRootConnection(); |
| | | |
| | | ModifyOperationBasis modifyOp = new ModifyOperationBasis(conn, InternalClientConnection |
| | | .nextOperationID(), InternalClientConnection.nextMessageID(), noControls, DN |
| | | .valueOf("uid=user.1,ou=People,dc=test,dc=com"), modifications); |
| | | ModifyOperationBasis modifyOp = new ModifyOperationBasis(getRootConnection(), nextOperationID(), nextMessageID(), |
| | | noControls, DN.valueOf("uid=user.1,ou=People,dc=test,dc=com"), modifications); |
| | | |
| | | backend.replaceEntry(entry, newEntry, modifyOp); |
| | | |
| | |
| | | assertFalse(entry.getAttribute("employeenumber").contains( |
| | | Attributes.create("employeenumber", "1"))); |
| | | |
| | | presenceIndexer = new PresenceIndexer(titleIndex.getAttributeType()); |
| | | assertIndexContainsID(presenceIndexer, entry, titleIndex.getPresenceIndex(), entryID); |
| | | AttributeType titleIndexAttrType = titleIndex.getAttributeType(); |
| | | AttributeType nameIndexAttrType = nameIndex.getAttributeType(); |
| | | |
| | | presenceIndexer = new PresenceIndexer(nameIndex.getAttributeType()); |
| | | assertIndexContainsID(presenceIndexer, entry, nameIndex.getPresenceIndex(), entryID); |
| | | indexers = singletonList(new PresenceIndexer(titleIndexAttrType)); |
| | | assertIndexContainsID(indexers, entry, titleIndex.getPresenceIndex(), entryID); |
| | | indexers = singletonList(new PresenceIndexer(nameIndexAttrType)); |
| | | assertIndexContainsID(indexers, entry, nameIndex.getPresenceIndex(), entryID); |
| | | |
| | | orderingIndexer = newOrderingIndexer(titleIndex); |
| | | assertIndexContainsID(orderingIndexer, entry, titleIndex.getOrderingIndex(), entryID); |
| | | indexers = newJEExtensibleIndexers(titleIndexAttrType, titleIndexAttrType.getOrderingMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, titleIndex.getOrderingIndex(), entryID); |
| | | indexers = newJEExtensibleIndexers(nameIndexAttrType, nameIndexAttrType.getOrderingMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, nameIndex.getOrderingIndex(), entryID); |
| | | |
| | | orderingIndexer = newOrderingIndexer(nameIndex); |
| | | assertIndexContainsID(orderingIndexer, entry, nameIndex.getOrderingIndex(), entryID); |
| | | indexers = newJEExtensibleIndexers(titleIndexAttrType, titleIndexAttrType.getEqualityMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, titleIndex.getEqualityIndex(), entryID); |
| | | indexers = newJEExtensibleIndexers(nameIndexAttrType, nameIndexAttrType.getEqualityMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, nameIndex.getEqualityIndex(), entryID); |
| | | |
| | | equalityIndexer = newEqualityIndexer(titleIndex); |
| | | assertIndexContainsID(equalityIndexer, entry, titleIndex.getEqualityIndex(), entryID); |
| | | |
| | | equalityIndexer = newEqualityIndexer(nameIndex); |
| | | assertIndexContainsID(equalityIndexer, entry, nameIndex.getEqualityIndex(), entryID); |
| | | |
| | | substringIndexer = newSubstringIndexer(titleIndex); |
| | | assertIndexContainsID(substringIndexer, entry, titleIndex.getSubstringIndex(), entryID); |
| | | |
| | | substringIndexer = newSubstringIndexer(nameIndex); |
| | | assertIndexContainsID(substringIndexer, entry, nameIndex.getSubstringIndex(), entryID); |
| | | indexers = newJEExtensibleIndexers(titleIndexAttrType, titleIndexAttrType.getSubstringMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, titleIndex.getSubstringIndex(), entryID); |
| | | indexers = newJEExtensibleIndexers(nameIndexAttrType, nameIndexAttrType.getSubstringMatchingRule()); |
| | | assertIndexContainsID(indexers, entry, nameIndex.getSubstringIndex(), entryID); |
| | | } |
| | | finally |
| | | { |
| | |
| | | ec.sharedLock.lock(); |
| | | try |
| | | { |
| | | Entry entry = |
| | | ec.getEntry(DN.valueOf("uid=user.2,ou=People,dc=test,dc=com")); |
| | | entry.setDN(DN.valueOf("cn=Abbey Abbie,ou=People,dc=test,dc=com")); |
| | | DN user2Dn = DN.valueOf("uid=user.2,ou=People,dc=test,dc=com"); |
| | | DN abbieDn = DN.valueOf("cn=Abbey Abbie,ou=People,dc=test,dc=com"); |
| | | Entry entry = ec.getEntry(user2Dn); |
| | | entry.setDN(abbieDn); |
| | | |
| | | backend.renameEntry(user2Dn, entry, null); |
| | | |
| | | backend.renameEntry(DN.valueOf("uid=user.2,ou=People,dc=test,dc=com"), |
| | | entry, null); |
| | | assertNotNull(backend.getEntry(abbieDn)); |
| | | assertNotNull(ec.getDN2ID().get(null, abbieDn, LockMode.DEFAULT)); |
| | | |
| | | assertNotNull(backend.getEntry(DN.valueOf("cn=Abbey Abbie,ou=People,dc=test,dc=com"))); |
| | | assertNotNull(ec.getDN2ID().get(null, DN.valueOf("cn=Abbey Abbie,ou=People,dc=test,dc=com"), LockMode.DEFAULT)); |
| | | |
| | | |
| | | assertNull(backend.getEntry(DN.valueOf("uid=user.2,ou=People,dc=test,dc=com"))); |
| | | assertNull(ec.getDN2ID().get(null, |
| | | DN.valueOf("uid=user.2,ou=People,dc=test,dc=com"), LockMode.DEFAULT)); |
| | | assertNull(backend.getEntry(user2Dn)); |
| | | assertNull(ec.getDN2ID().get(null, user2Dn, LockMode.DEFAULT)); |
| | | } |
| | | finally |
| | | { |
| | |
| | | assertTrue(newSuperiorID.compareTo(oldID) > 0); |
| | | |
| | | List<Control> noControls = new ArrayList<Control>(0); |
| | | InternalClientConnection conn = |
| | | InternalClientConnection.getRootConnection(); |
| | | |
| | | ModifyDNOperationBasis modifyDN = new ModifyDNOperationBasis(conn, |
| | | InternalClientConnection.nextOperationID(), |
| | | InternalClientConnection.nextMessageID(), |
| | | ModifyDNOperationBasis modifyDN = new ModifyDNOperationBasis( |
| | | getRootConnection(), nextOperationID(), nextMessageID(), |
| | | noControls, |
| | | DN.valueOf("ou=People,dc=test,dc=com"), |
| | | RDN.decode("ou=Good People"), |
| | |
| | | RootContainer rootContainer = backend.getRootContainer(); |
| | | EntryContainer ec = rootContainer.getEntryContainer(DN.valueOf("dc=test,dc=com")); |
| | | |
| | | AttributeIndex attributeIndex = |
| | | ec.getAttributeIndex(DirectoryServer.getAttributeType("givenname")); |
| | | AttributeType givennameAttr = DirectoryServer.getAttributeType("givenname"); |
| | | AttributeIndex attributeIndex = ec.getAttributeIndex(givennameAttr); |
| | | assertNull(attributeIndex.getEqualityIndex()); |
| | | assertNull(attributeIndex.getPresenceIndex()); |
| | | assertNull(attributeIndex.getSubstringIndex()); |
| | |
| | | assertNotNull(attributeIndex.getApproximateIndex()); |
| | | List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>(); |
| | | ec.listDatabases(databases); |
| | | boolean eqfound = false; |
| | | boolean prfound = false; |
| | | boolean subfound = false; |
| | | boolean orfound = false; |
| | | boolean apfound = false; |
| | | for(DatabaseContainer dc : databases) |
| | | { |
| | | if(dc.getName().toLowerCase().contains("givenname.approximate")) |
| | | { |
| | | apfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.presence")) |
| | | { |
| | | prfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.substring")) |
| | | { |
| | | subfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.ordering")) |
| | | { |
| | | orfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.equality")) |
| | | { |
| | | eqfound = true; |
| | | } |
| | | } |
| | | assertFalse(eqfound); |
| | | assertFalse(prfound); |
| | | assertFalse(subfound); |
| | | assertFalse(orfound); |
| | | assertTrue(apfound); |
| | | assertFalse(findContainer(databases, "givenname.equality")); |
| | | assertFalse(findContainer(databases, "givenname.presence")); |
| | | assertFalse(findContainer(databases, "givenname.substring")); |
| | | assertFalse(findContainer(databases, "givenname.ordering")); |
| | | assertTrue(findContainer(databases, "givenname.approximate")); |
| | | |
| | | final SearchRequest request = newSearchRequest("dc=test,dc=com", SearchScope.SUBORDINATES, "(givenName~=Aaccf)") |
| | | .addAttribute(ATTR_DEBUG_SEARCH_INDEX); |
| | | InternalSearchOperation search = getRootConnection().processSearch(request); |
| | | |
| | | List<SearchResultEntry> result = search.getSearchEntries(); |
| | | |
| | | //No indexes should be used. |
| | |
| | | assertNull(attributeIndex.getApproximateIndex()); |
| | | databases = new ArrayList<DatabaseContainer>(); |
| | | ec.listDatabases(databases); |
| | | eqfound = false; |
| | | prfound = false; |
| | | subfound = false; |
| | | orfound = false; |
| | | apfound = false; |
| | | for(DatabaseContainer dc : databases) |
| | | { |
| | | if(dc.getName().toLowerCase().contains("givenname.approximate")) |
| | | { |
| | | apfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.presence")) |
| | | { |
| | | prfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.substring")) |
| | | { |
| | | subfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.ordering")) |
| | | { |
| | | orfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.equality")) |
| | | { |
| | | eqfound = true; |
| | | } |
| | | } |
| | | assertTrue(eqfound); |
| | | assertTrue(prfound); |
| | | assertTrue(subfound); |
| | | assertTrue(orfound); |
| | | assertFalse(apfound); |
| | | assertTrue(findContainer(databases, "givenname.equality")); |
| | | assertTrue(findContainer(databases, "givenname.presence")); |
| | | assertTrue(findContainer(databases, "givenname.substring")); |
| | | assertTrue(findContainer(databases, "givenname.ordering")); |
| | | assertFalse(findContainer(databases, "givenname.approximate")); |
| | | |
| | | // Delete the entries attribute index. |
| | | resultCode = TestCaseUtils.applyModifications(true, |
| | |
| | | |
| | | assertEquals(resultCode, 0); |
| | | |
| | | assertNull(ec.getAttributeIndex( |
| | | DirectoryServer.getAttributeType("givenname"))); |
| | | assertNull(ec.getAttributeIndex(givennameAttr)); |
| | | databases = new ArrayList<DatabaseContainer>(); |
| | | ec.listDatabases(databases); |
| | | for(DatabaseContainer dc : databases) |
| | |
| | | |
| | | assertEquals(resultCode, 0); |
| | | |
| | | assertNotNull(ec.getAttributeIndex( |
| | | DirectoryServer.getAttributeType("givenname"))); |
| | | assertNotNull(ec.getAttributeIndex(givennameAttr)); |
| | | databases = new ArrayList<DatabaseContainer>(); |
| | | ec.listDatabases(databases); |
| | | eqfound = false; |
| | | prfound = false; |
| | | subfound = false; |
| | | orfound = false; |
| | | apfound = false; |
| | | for(DatabaseContainer dc : databases) |
| | | { |
| | | if(dc.getName().toLowerCase().contains("givenname.approximate")) |
| | | { |
| | | apfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.presence")) |
| | | { |
| | | prfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.substring")) |
| | | { |
| | | subfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.ordering")) |
| | | { |
| | | orfound = true; |
| | | } |
| | | if(dc.getName().toLowerCase().contains("givenname.equality")) |
| | | { |
| | | eqfound = true; |
| | | } |
| | | } |
| | | assertTrue(eqfound); |
| | | assertTrue(prfound); |
| | | assertTrue(subfound); |
| | | assertTrue(orfound); |
| | | assertFalse(apfound); |
| | | assertTrue(findContainer(databases, "givenname.equality")); |
| | | assertTrue(findContainer(databases, "givenname.presence")); |
| | | assertTrue(findContainer(databases, "givenname.substring")); |
| | | assertTrue(findContainer(databases, "givenname.ordering")); |
| | | assertFalse(findContainer(databases, "givenname.approximate")); |
| | | |
| | | // Make sure changing the index entry limit on an index where the limit |
| | | // is already exceeded causes warnings. |
| | |
| | | assertEquals(resultCode, 0); |
| | | } |
| | | |
| | | private boolean findContainer(List<DatabaseContainer> databases, String lowercaseName) |
| | | { |
| | | for (DatabaseContainer dc : databases) |
| | | { |
| | | if (dc.getName().toLowerCase().contains(lowercaseName)) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | @Test(dependsOnMethods = {"testDeleteEntry", "testSearchScope", |
| | | "testSearchIndex", "testMatchedDN"}) |
| | | public void testSearchNotIndexed() throws Exception { |
| | |
| | | ResultCode expectedResultCode |
| | | ) throws Exception |
| | | { |
| | | InternalClientConnection conn = getRootConnection(); |
| | | SearchFilter filter = SearchFilter.objectClassPresent(); |
| | | |
| | | // Test is performed with each and every scope |
| | | for (SearchScope scope: SearchScope.values()) |
| | | { |
| | | final SearchRequest request = newSearchRequest(searchBaseDN, scope, filter); |
| | | InternalSearchOperation searchOperation = conn.processSearch(request); |
| | | final SearchRequest request = newSearchRequest(searchBaseDN, scope); |
| | | InternalSearchOperation searchOperation = getRootConnection().processSearch(request); |
| | | |
| | | assertEquals(searchOperation.getResultCode(), expectedResultCode); |
| | | assertEquals(searchOperation.getMatchedDN(), expectedMatchedDN); |