| | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.spi.IndexQueryFactory; |
| | | import org.forgerock.opendj.ldap.spi.IndexingOptions; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | | import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn; |
| | | import org.opends.server.admin.std.server.LocalDBIndexCfg; |
| | |
| | | String name = |
| | | entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID(); |
| | | int indexEntryLimit = indexConfig.getIndexEntryLimit(); |
| | | JEIndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength()); |
| | | |
| | | if (indexConfig.getIndexType().contains( |
| | | LocalDBIndexCfgDefn.IndexType.EQUALITY)) |
| | |
| | | throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "substring")); |
| | | } |
| | | |
| | | Indexer substringIndexer = new SubstringIndexer(attrType, |
| | | indexConfig.getSubstringLength()); |
| | | Indexer substringIndexer = new SubstringIndexer(attrType, config); |
| | | this.substringIndex = new Index(name + ".substring", |
| | | substringIndexer, |
| | | state, |
| | |
| | | //Collation equality and Ordering matching rules share the same |
| | | //indexer and index. A Collation substring matching rule is treated |
| | | // differently as it uses a separate indexer and index. |
| | | IndexConfig config = new JEIndexConfig(indexConfig.getSubstringLength()); |
| | | for(String ruleName:extensibleRules) |
| | | { |
| | | ExtensibleMatchingRule rule = |
| | |
| | | Map<String,Index> indexMap = new HashMap<String,Index>(); |
| | | for(ExtensibleIndexer indexer : rule.getIndexers(config)) |
| | | { |
| | | String indexerId = indexer.getExtensibleIndexID(); |
| | | String indexID = |
| | | attrType.getNameOrOID() + "." |
| | | + indexer.getPreferredIndexName() |
| | | + "." + indexerId; |
| | | String indexID = attrType.getNameOrOID() + "." + indexer.getIndexID(); |
| | | if(!extensibleIndexes.isIndexPresent(indexID)) |
| | | { |
| | | //There is no index available for this index id. Create a new index. |
| | |
| | | indexMap.put(indexer.getExtensibleIndexID(), |
| | | extensibleIndexes.getIndex(indexID)); |
| | | } |
| | | IndexQueryFactory<IndexQuery> factory = |
| | | new IndexQueryFactoryImpl(indexMap); |
| | | extensibleIndexes.addQueryFactory(rule, factory); |
| | | IndexQueryFactory<IndexQuery> factory = |
| | | new IndexQueryFactoryImpl(indexMap, config); |
| | | extensibleIndexes.addQueryFactory(rule, factory); |
| | | } |
| | | } |
| | | } |
| | |
| | | */ |
| | | Set<ByteString> substringKeys(byte[] value) |
| | | { |
| | | // FIXME replace this code with SDK's |
| | | // AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys() |
| | | |
| | | // Eliminate duplicates by putting the keys into a set. |
| | | // Sorting the keys will ensure database record locks are acquired |
| | | // in a consistent order and help prevent transaction deadlocks between |
| | |
| | | Set<ByteString> set = new HashSet<ByteString>(); |
| | | |
| | | int substrLength = indexConfig.getSubstringLength(); |
| | | byte[] keyBytes; |
| | | |
| | | // Example: The value is ABCDE and the substring length is 3. |
| | | // We produce the keys ABC BCD CDE DE E |
| | |
| | | for (int i = 0, remain = value.length; remain > 0; i++, remain--) |
| | | { |
| | | int len = Math.min(substrLength, remain); |
| | | keyBytes = makeSubstringKey(value, i, len); |
| | | byte[] keyBytes = makeSubstringKey(value, i, len); |
| | | set.add(ByteString.wrap(keyBytes)); |
| | | } |
| | | |
| | |
| | | */ |
| | | private EntryIDSet matchSubstring(byte[] bytes) |
| | | { |
| | | // FIXME replace this code with SDK's |
| | | // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery() |
| | | |
| | | int substrLength = indexConfig.getSubstringLength(); |
| | | |
| | | // There are two cases, depending on whether the user-provided |
| | |
| | | for (int first = 0, last = substrLength; |
| | | last <= bytes.length; first++, last++) |
| | | { |
| | | byte[] keyBytes; |
| | | keyBytes = makeSubstringKey(bytes, first, substrLength); |
| | | set.add(keyBytes); |
| | | set.add(makeSubstringKey(bytes, first, substrLength)); |
| | | } |
| | | |
| | | EntryIDSet results = new EntryIDSet(); |
| | |
| | | */ |
| | | private EntryIDSet matchInitialSubstring(byte[] bytes) |
| | | { |
| | | // FIXME replace this code with SDK's |
| | | // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery() |
| | | |
| | | // Iterate through all the keys that have this value as the prefix. |
| | | |
| | | // Set the lower bound for a range search. |
| | |
| | | String name = |
| | | entryContainer.getDatabasePrefix() + "_" + attrType.getNameOrOID(); |
| | | int indexEntryLimit = cfg.getIndexEntryLimit(); |
| | | JEIndexConfig config = new JEIndexConfig(cfg.getSubstringLength()); |
| | | |
| | | if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.EQUALITY)) |
| | | { |
| | |
| | | { |
| | | if(substringIndex == null) |
| | | { |
| | | Indexer substringIndexer = new SubstringIndexer( |
| | | attrType, cfg.getSubstringLength()); |
| | | Indexer substringIndexer = new SubstringIndexer(attrType, config); |
| | | substringIndex = new Index(name + ".substring", |
| | | substringIndexer, |
| | | state, |
| | |
| | | if(indexConfig.getSubstringLength() != |
| | | cfg.getSubstringLength()) |
| | | { |
| | | Indexer substringIndexer = new SubstringIndexer( |
| | | attrType, cfg.getSubstringLength()); |
| | | Indexer substringIndexer = new SubstringIndexer(attrType, config); |
| | | this.substringIndex.setIndexer(substringIndexer); |
| | | } |
| | | } |
| | |
| | | { |
| | | extensibleIndexes = new ExtensibleMatchingRuleIndex(); |
| | | } |
| | | IndexConfig config = new JEIndexConfig(cfg.getSubstringLength()); |
| | | for(String ruleName:extensibleRules) |
| | | { |
| | | ExtensibleMatchingRule rule = |
| | |
| | | Map<String,Index> indexMap = new HashMap<String,Index>(); |
| | | for(ExtensibleIndexer indexer: rule.getIndexers(config)) |
| | | { |
| | | String indexerId = indexer.getExtensibleIndexID(); |
| | | String indexID = |
| | | attrType.getNameOrOID() + "." |
| | | + indexer.getPreferredIndexName() |
| | | + "." + indexerId; |
| | | String indexID = attrType.getNameOrOID() + "." + indexer.getIndexID(); |
| | | if(!extensibleIndexes.isIndexPresent(indexID)) |
| | | { |
| | | Indexer extensibleIndexer = |
| | |
| | | } |
| | | } |
| | | extensibleIndexes.addRule(indexID, rule); |
| | | indexMap.put(indexerId,extensibleIndexes.getIndex(indexID)); |
| | | indexMap.put(indexer.getExtensibleIndexID(), extensibleIndexes.getIndex(indexID)); |
| | | } |
| | | IndexQueryFactory<IndexQuery> factory = |
| | | new IndexQueryFactoryImpl(indexMap); |
| | | new IndexQueryFactoryImpl(indexMap, config); |
| | | extensibleIndexes.addQueryFactory(rule, factory); |
| | | } |
| | | //Some rules might have been removed from the configuration. |
| | |
| | | List<String> ids = new ArrayList<String>(); |
| | | for(ExtensibleIndexer indexer: rule.getIndexers(config)) |
| | | { |
| | | String id = attrType.getNameOrOID() + "." |
| | | + indexer.getPreferredIndexName() |
| | | + "." + indexer.getExtensibleIndexID(); |
| | | String id = attrType.getNameOrOID() + "." + indexer.getIndexID(); |
| | | rules.addAll(extensibleIndexes.getRules(id)); |
| | | ids.add(id); |
| | | } |
| | |
| | | if(debugBuffer != null) |
| | | { |
| | | debugBuffer.append("[INDEX:"); |
| | | IndexConfig config = |
| | | JEIndexConfig config = |
| | | new JEIndexConfig(indexConfig.getSubstringLength()); |
| | | for(ExtensibleIndexer indexer : rule.getIndexers(config)) |
| | | { |
| | | debugBuffer.append(" ") |
| | | .append(extensibleFilter.getAttributeType().getNameOrOID()) |
| | | .append(".") |
| | | .append(indexer.getPreferredIndexName()) |
| | | .append(".") |
| | | .append(indexer.getExtensibleIndexID()); |
| | | .append(indexer.getIndexID()); |
| | | } |
| | | debugBuffer.append("]"); |
| | | } |
| | |
| | | /** |
| | | * This class extends the IndexConfig for JE Backend. |
| | | */ |
| | | private class JEIndexConfig extends IndexConfig |
| | | private class JEIndexConfig implements IndexingOptions |
| | | { |
| | | /** The length of the substring index. */ |
| | | private int substringLength; |
| | |
| | | this.substringLength = substringLength; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the length of the substring. |
| | | * @return the length of the substring. |
| | | */ |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public int getSubstringLength() |
| | | public int substringKeySize() |
| | | { |
| | | return substringLength; |
| | | } |