opendj3-server-dev/src/server/org/opends/server/api/ExtensibleIndexer.java
@@ -27,8 +27,6 @@ package org.opends.server.api; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.forgerock.opendj.ldap.ByteSequence; @@ -86,56 +84,4 @@ throw new RuntimeException("Not implemented yet"); } /** * Generates a map of index keys and a boolean flag indicating * whether the corresponding key will be inserted or deleted. * * @param attrValue * The attribute for which keys are required. * @param modifiedKeys * A map containing the keys and a boolean. Keys * corresponding to the boolean value <code>true</code> * should be inserted and <code>false</code> should be * deleted. * @param insert * <code>true</code> if generated keys should be inserted * or <code>false</code> otherwise. */ public void getKeys(AttributeValue attrValue, Map<byte[], Boolean> modifiedKeys, Boolean insert) { final Set<byte[]> keys = new HashSet<byte[]>(); getKeys(attrValue, keys); computeModifiedKeys(modifiedKeys, insert, keys); } /** * Computes the modified keys by an indexer. * * @param modifiedKeys * A map containing the keys and a boolean. Keys * corresponding to the boolean value <code>true</code> * should be inserted and <code>false</code> should be * deleted. * @param insert * <code>true</code> if generated keys should be inserted * or <code>false</code> otherwise. * @param keys * the newly generated keys that will be added or removed from the Map */ public static void computeModifiedKeys(Map<byte[], Boolean> modifiedKeys, Boolean insert, final Set<byte[]> keys) { for (byte[] key : keys) { Boolean cInsert = modifiedKeys.get(key); if (cInsert == null) { modifiedKeys.put(key, insert); } else if (!cInsert.equals(insert)) { modifiedKeys.remove(key); } } } } opendj3-server-dev/src/server/org/opends/server/backends/jeb/ApproximateIndexer.java
@@ -26,43 +26,28 @@ */ package org.opends.server.backends.jeb; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.ldap.DecodeException; import org.opends.server.api.ApproximateMatchingRule; import org.opends.server.api.ExtensibleIndexer; import org.opends.server.types.*; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; /** * An implementation of an Indexer for attribute approximate matching. */ public class ApproximateIndexer extends Indexer public class ApproximateIndexer extends ExtensibleIndexer { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** * The comparator for index keys generated by this class. */ private static final Comparator<byte[]> comparator = new AttributeIndex.KeyComparator(); /** * The attribute type approximate matching rule. */ private ApproximateMatchingRule approximateRule; /** * The attribute type for which this instance will * generate index keys. */ private AttributeType attributeType; /** * Create a new attribute approximate indexer for the given index * configuration. * @param attributeType The attribute type for which an indexer is @@ -70,121 +55,31 @@ */ public ApproximateIndexer(AttributeType attributeType) { this.attributeType = attributeType; this.approximateRule = attributeType.getApproximateMatchingRule(); } /** * Get a string representation of this object. The returned value is * used to name an index created using this object. * @return A string representation of this object. */ /** {@inheritDoc} */ @Override public String toString() public String getIndexID() { return attributeType.getNameOrOID() + ".approximate"; // TODO Auto-generated method stub throw new RuntimeException(); } /** * Get the comparator that must be used to compare index keys * generated by this class. * * @return A byte array comparator. */ /** {@inheritDoc} */ @Override public Comparator<byte[]> getComparator() public String getExtensibleIndexID() { return comparator; return "approximate"; } /** * Generate the set of index keys for an entry. * * @param entry The entry. * @param keys The set into which the generated keys will be inserted. */ /** {@inheritDoc} */ @Override public void indexEntry(Entry entry, Set<byte[]> keys) { List<Attribute> attrList = entry.getAttribute(attributeType); if (attrList != null) { indexAttribute(attrList, keys); } } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that has been replaced. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void replaceEntry(Entry oldEntry, Entry newEntry, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that was modified. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param mods The set of modifications that were applied to the entry. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void modifyEntry(Entry oldEntry, Entry newEntry, List<Modification> mods, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param keys The set into which the keys will be inserted. */ private void indexAttribute(List<Attribute> attrList, Set<byte[]> keys) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { getKeys(value, keys); } } } } private void getKeys(AttributeValue value, Set<byte[]> keys) public void getKeys(AttributeValue value, Set<byte[]> keys) { try { byte[] keyBytes = approximateRule.normalizeAttributeValue(value.getValue()).toByteArray(); keys.add(keyBytes); keys.add(approximateRule.normalizeAttributeValue(value.getValue()).toByteArray()); } catch (DecodeException e) { @@ -192,37 +87,4 @@ } } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param modifiedKeys The map into which the modified * keys will be inserted. * @param insert <code>true</code> if generated keys should * be inserted or <code>false</code> otherwise. */ private void indexAttribute(List<Attribute> attrList, Map<byte[], Boolean> modifiedKeys, Boolean insert) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { getKeys(value, modifiedKeys, insert); } } } } private void getKeys(AttributeValue value, Map<byte[], Boolean> modifiedKeys, Boolean insert) { Set<byte[]> keys = new HashSet<byte[]>(); getKeys(value, keys); ExtensibleIndexer.computeModifiedKeys(modifiedKeys, insert, keys); } } opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -26,7 +26,9 @@ * Portions Copyright 2014 Manuel Gaupp */ package org.opends.server.backends.jeb; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.slf4j.LocalizedLogger; @@ -35,6 +37,7 @@ import org.forgerock.opendj.ldap.ResultCode; 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; import org.opends.server.admin.std.server.LocalDBIndexCfg; @@ -151,20 +154,8 @@ if (indexConfig.getIndexType().contains( LocalDBIndexCfgDefn.IndexType.EQUALITY)) { if (attrType.getEqualityMatchingRule() == null) { throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "equality")); } Indexer equalityIndexer = new EqualityIndexer(attrType); this.equalityIndex = new Index(name + ".equality", equalityIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); this.equalityIndex = buildExtIndex( name, attrType, attrType.getEqualityMatchingRule(), new EqualityIndexer()); } if (indexConfig.getIndexType().contains( @@ -184,57 +175,21 @@ if (indexConfig.getIndexType().contains( LocalDBIndexCfgDefn.IndexType.SUBSTRING)) { if (attrType.getSubstringMatchingRule() == null) { throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "substring")); } Indexer substringIndexer = new SubstringIndexer(attrType, config); this.substringIndex = new Index(name + ".substring", substringIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); this.substringIndex = buildExtIndex( name, attrType, attrType.getSubstringMatchingRule(), new SubstringIndexer(attrType, config)); } if (indexConfig.getIndexType().contains( LocalDBIndexCfgDefn.IndexType.ORDERING)) { if (attrType.getOrderingMatchingRule() == null) { throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "ordering")); } Indexer orderingIndexer = new OrderingIndexer(attrType); this.orderingIndex = new Index(name + ".ordering", orderingIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); this.orderingIndex = buildExtIndex( name, attrType, attrType.getOrderingMatchingRule(), new OrderingIndexer(attrType)); } if (indexConfig.getIndexType().contains( LocalDBIndexCfgDefn.IndexType.APPROXIMATE)) { if (attrType.getApproximateMatchingRule() == null) { throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "approximate")); } Indexer approximateIndexer = new ApproximateIndexer(attrType); this.approximateIndex = new Index(name + ".approximate", approximateIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); this.approximateIndex = buildExtIndex( name, attrType, attrType.getApproximateMatchingRule(), new ApproximateIndexer(attrType)); } if (indexConfig.getIndexType().contains( LocalDBIndexCfgDefn.IndexType.EXTENSIBLE)) @@ -294,6 +249,26 @@ } } private Index buildExtIndex(String name, AttributeType attrType, MatchingRule rule, ExtensibleIndexer extIndexer) throws ConfigException { if (rule == null) { throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get( attrType, extIndexer.getExtensibleIndexID())); } Indexer indexer = new JEExtensibleIndexer(attrType, rule, extIndexer); return new Index(name + "." + extIndexer.getExtensibleIndexID(), indexer, state, indexConfig.getIndexEntryLimit(), cursorEntryLimit, false, env, entryContainer); } /** * Open the attribute index. * @@ -302,30 +277,11 @@ */ public void open() throws DatabaseException { if (equalityIndex != null) { equalityIndex.open(); } if (presenceIndex != null) { presenceIndex.open(); } if (substringIndex != null) { substringIndex.open(); } if (orderingIndex != null) { orderingIndex.open(); } if (approximateIndex != null) { approximateIndex.open(); } open(equalityIndex); open(presenceIndex); open(substringIndex); open(orderingIndex); open(approximateIndex); if(extensibleIndexes!=null) { @@ -338,6 +294,14 @@ indexConfig.addChangeListener(this); } private void open(Index index) { if (index != null) { index.open(); } } /** * Close the attribute index. * @@ -346,37 +310,12 @@ */ public void close() throws DatabaseException { if (equalityIndex != null) { equalityIndex.close(); } if (presenceIndex != null) { presenceIndex.close(); } if (substringIndex != null) { substringIndex.close(); } if (orderingIndex != null) { orderingIndex.close(); } if (approximateIndex != null) { approximateIndex.close(); } Utils.closeSilently(equalityIndex, presenceIndex, substringIndex, orderingIndex, approximateIndex); if(extensibleIndexes!=null) { for(Index extensibleIndex:extensibleIndexes.getIndexes()) { extensibleIndex.close(); } Utils.closeSilently(extensibleIndexes.getIndexes()); } indexConfig.removeChangeListener(this); @@ -416,33 +355,13 @@ Entry entry) throws DatabaseException, DirectoryException { boolean success = false; boolean success = true; if (equalityIndex != null && !equalityIndex.addEntry(buffer, entryID, entry)) { success = false; } if (presenceIndex != null && !presenceIndex.addEntry(buffer, entryID, entry)) { success = false; } if (substringIndex != null && !substringIndex.addEntry(buffer, entryID, entry)) { success = false; } if (orderingIndex != null && !orderingIndex.addEntry(buffer, entryID, entry)) { success = false; } if (approximateIndex != null && !approximateIndex.addEntry(buffer, entryID, entry)) { success = false; } success = addEntry(equalityIndex, buffer, entryID, entry, success); success = addEntry(presenceIndex, buffer, entryID, entry, success); success = addEntry(substringIndex, buffer, entryID, entry, success); success = addEntry(orderingIndex, buffer, entryID, entry, success); success = addEntry(approximateIndex, buffer, entryID, entry, success); if(extensibleIndexes!=null) { @@ -458,6 +377,15 @@ return success; } private boolean addEntry(Index index, IndexBuffer buffer, EntryID entryID, Entry entry, boolean success) throws DirectoryException, DatabaseException { if (index != null && !index.addEntry(buffer, entryID, entry)) { return false; } return success; } /** * Update the attribute index for a new entry. @@ -475,27 +403,11 @@ { boolean success = true; if (equalityIndex != null && !equalityIndex.addEntry(txn, entryID, entry)) { success = false; } if (presenceIndex != null && !presenceIndex.addEntry(txn, entryID, entry)) { success = false; } if (substringIndex != null && !substringIndex.addEntry(txn, entryID, entry)) { success = false; } if (orderingIndex != null && !orderingIndex.addEntry(txn, entryID, entry)) { success = false; } if (approximateIndex != null && !approximateIndex.addEntry(txn, entryID, entry)) { success = false; } success = addEntry(equalityIndex, txn, entryID, entry, success); success = addEntry(presenceIndex, txn, entryID, entry, success); success = addEntry(substringIndex, txn, entryID, entry, success); success = addEntry(orderingIndex, txn, entryID, entry, success); success = addEntry(approximateIndex, txn, entryID, entry, success); if(extensibleIndexes!=null) { @@ -511,6 +423,17 @@ return success; } private boolean addEntry(Index index, Transaction txn, EntryID entryID, Entry entry, boolean success) throws DirectoryException, DatabaseException { if (index != null && !index.addEntry(txn, entryID, entry)) { return false; } return success; } /** * Update the attribute index for a deleted entry. * @@ -524,30 +447,11 @@ Entry entry) throws DatabaseException, DirectoryException { if (equalityIndex != null) { equalityIndex.removeEntry(buffer, entryID, entry); } if (presenceIndex != null) { presenceIndex.removeEntry(buffer, entryID, entry); } if (substringIndex != null) { substringIndex.removeEntry(buffer, entryID, entry); } if (orderingIndex != null) { orderingIndex.removeEntry(buffer, entryID, entry); } if(approximateIndex != null) { approximateIndex.removeEntry(buffer, entryID, entry); } removeEntry(equalityIndex, buffer, entryID, entry); removeEntry(presenceIndex, buffer, entryID, entry); removeEntry(substringIndex, buffer, entryID, entry); removeEntry(orderingIndex, buffer, entryID, entry); removeEntry(approximateIndex, buffer, entryID, entry); if(extensibleIndexes!=null) { @@ -558,6 +462,15 @@ } } private void removeEntry(Index index, IndexBuffer buffer, EntryID entryID, Entry entry) throws DirectoryException, DatabaseException { if (index != null) { index.removeEntry(buffer, entryID, entry); } } /** * Update the attribute index for a deleted entry. * @@ -570,30 +483,11 @@ public void removeEntry(Transaction txn, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException { if (equalityIndex != null) { equalityIndex.removeEntry(txn, entryID, entry); } if (presenceIndex != null) { presenceIndex.removeEntry(txn, entryID, entry); } if (substringIndex != null) { substringIndex.removeEntry(txn, entryID, entry); } if (orderingIndex != null) { orderingIndex.removeEntry(txn, entryID, entry); } if(approximateIndex != null) { approximateIndex.removeEntry(txn, entryID, entry); } removeEntry(equalityIndex, txn, entryID, entry); removeEntry(presenceIndex, txn, entryID, entry); removeEntry(substringIndex, txn, entryID, entry); removeEntry(orderingIndex, txn, entryID, entry); removeEntry(approximateIndex, txn, entryID, entry); if(extensibleIndexes!=null) { @@ -604,6 +498,15 @@ } } private void removeEntry(Index index, Transaction txn, EntryID entryID, Entry entry) throws DirectoryException, DatabaseException { if (index != null) { index.removeEntry(txn, entryID, entry); } } /** * Update the index to reflect a sequence of modifications in a Modify * operation. @@ -623,30 +526,11 @@ List<Modification> mods) throws DatabaseException { if (equalityIndex != null) { equalityIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods); } if (presenceIndex != null) { presenceIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods); } if (substringIndex != null) { substringIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods); } if (orderingIndex != null) { orderingIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods); } if (approximateIndex != null) { approximateIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods); } modifyEntry(equalityIndex, txn, entryID, oldEntry, newEntry, mods); modifyEntry(presenceIndex, txn, entryID, oldEntry, newEntry, mods); modifyEntry(substringIndex, txn, entryID, oldEntry, newEntry, mods); modifyEntry(orderingIndex, txn, entryID, oldEntry, newEntry, mods); modifyEntry(approximateIndex, txn, entryID, oldEntry, newEntry, mods); if(extensibleIndexes!=null) { @@ -657,6 +541,16 @@ } } private void modifyEntry(Index index, Transaction txn, EntryID entryID, Entry oldEntry, Entry newEntry, List<Modification> mods) throws DatabaseException { if (index != null) { index.modifyEntry(txn, entryID, oldEntry, newEntry, mods); } } /** * Update the index to reflect a sequence of modifications in a Modify * operation. @@ -676,30 +570,11 @@ List<Modification> mods) throws DatabaseException { if (equalityIndex != null) { equalityIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods); } if (presenceIndex != null) { presenceIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods); } if (substringIndex != null) { substringIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods); } if (orderingIndex != null) { orderingIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods); } if (approximateIndex != null) { approximateIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods); } modifyEntry(equalityIndex, buffer, entryID, oldEntry, newEntry, mods); modifyEntry(presenceIndex, buffer, entryID, oldEntry, newEntry, mods); modifyEntry(substringIndex, buffer, entryID, oldEntry, newEntry, mods); modifyEntry(orderingIndex, buffer, entryID, oldEntry, newEntry, mods); modifyEntry(approximateIndex, buffer, entryID, oldEntry, newEntry, mods); if(extensibleIndexes!=null) { @@ -710,6 +585,16 @@ } } private void modifyEntry(Index index, IndexBuffer buffer, EntryID entryID, Entry oldEntry, Entry newEntry, List<Modification> mods) throws DatabaseException { if (index != null) { index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods); } } /** * Makes a byte array representing a substring index key for * one substring of a value. @@ -735,8 +620,7 @@ * @return A set of index keys. */ Set<ByteString> substringKeys(byte[] value) { // FIXME replace this code with SDK's { // FIXME replace this code with SDK's // AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys() // Eliminate duplicates by putting the keys into a set. @@ -769,8 +653,7 @@ * @return The candidate entry IDs. */ private EntryIDSet matchSubstring(byte[] bytes) { // FIXME replace this code with SDK's { // FIXME replace this code with SDK's // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery() int substrLength = indexConfig.getSubstringLength(); @@ -855,8 +738,7 @@ * @return The candidate entry IDs. */ private EntryIDSet matchInitialSubstring(byte[] bytes) { // FIXME replace this code with SDK's { // FIXME replace this code with SDK's // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery() // Iterate through all the keys that have this value as the prefix. @@ -1051,73 +933,9 @@ SearchFilter filter, StringBuilder debugBuffer, DatabaseEnvironmentMonitor monitor) { if (orderingIndex == null) { if(monitor.isFilterUseEnabled()) { monitor.updateStats(filter, INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("ordering", indexConfig.getAttribute().getNameOrOID())); } return new EntryIDSet(); return evaluateOrderingFilter(filter, true, debugBuffer, monitor); } try { // Set the lower bound for a range search. // Use the ordering matching rule to normalize the value. OrderingMatchingRule orderingRule = filter.getAttributeType().getOrderingMatchingRule(); byte[] lower = orderingRule.normalizeAttributeValue( filter.getAssertionValue().getValue()).toByteArray(); // Set the upper bound to 0 to search all keys greater then the lower // bound. byte[] upper = new byte[0]; if(debugBuffer != null) { debugBuffer.append("[INDEX:"); debugBuffer.append(indexConfig.getAttribute().getNameOrOID()); debugBuffer.append("."); debugBuffer.append("ordering]"); } // Read the range: lower <= keys < upper. EntryIDSet idSet = orderingIndex.readRange(lower, upper, true, false); if(monitor.isFilterUseEnabled()) { if(idSet.isDefined()) { monitor.updateStats(filter, idSet.size()); } else if(!orderingIndex.isTrusted()) { monitor.updateStats(filter, INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get( orderingIndex.getName())); } else if(orderingIndex.isRebuildRunning()) { monitor.updateStats(filter, INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get( orderingIndex.getName())); } else { monitor.updateStats(filter, INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get( orderingIndex.getName())); } } return idSet; } catch (DecodeException e) { logger.traceException(e); return new EntryIDSet(); } } /** * Retrieve the entry IDs that might match a less-or-equal filter. @@ -1135,6 +953,14 @@ StringBuilder debugBuffer, DatabaseEnvironmentMonitor monitor) { return evaluateOrderingFilter(filter, false, debugBuffer, monitor); } private EntryIDSet evaluateOrderingFilter(SearchFilter filter, boolean greater, StringBuilder debugBuffer, DatabaseEnvironmentMonitor monitor) { if (orderingIndex == null) { if(monitor.isFilterUseEnabled()) @@ -1148,17 +974,29 @@ try { // Set the lower bound to 0 to start the range search from the smallest // key. byte[] lower = new byte[0]; // Set the upper bound for a range search. // Use the ordering matching rule to normalize the value. OrderingMatchingRule orderingRule = filter.getAttributeType().getOrderingMatchingRule(); byte[] upper = orderingRule.normalizeAttributeValue( // FIXME JNR this looks wrong, it should use normalizeAssertionValue() byte[] normalizedValue = orderingRule.normalizeAttributeValue( filter.getAssertionValue().getValue()).toByteArray(); // Set the lower and upper bounds for a range search. byte[] lower; byte[] upper; if (greater) { // Set upper bound to 0 to search all keys greater than the lower bound. lower = normalizedValue; upper = new byte[0]; } else { // Set lower bound to 0 to start the range search from the smallest key. lower = new byte[0]; upper = normalizedValue; } if(debugBuffer != null) { debugBuffer.append("[INDEX:"); @@ -1167,8 +1005,8 @@ debugBuffer.append("ordering]"); } // Read the range: lower < keys <= upper. EntryIDSet idSet = orderingIndex.readRange(lower, upper, false, true); // Read the range: lower <= keys < upper OR lower < keys <= upper EntryIDSet idSet = orderingIndex.readRange(lower, upper, greater, !greater); if(monitor.isFilterUseEnabled()) { if(idSet.isDefined()) @@ -1506,6 +1344,7 @@ ApproximateMatchingRule approximateMatchingRule = approximateFilter.getAttributeType().getApproximateMatchingRule(); // Make a key from the normalized assertion value. // FIXME JNR this looks wrong, it should use normalizeAssertionValue() byte[] keyBytes = approximateMatchingRule.normalizeAttributeValue( approximateFilter.getAssertionValue().getValue()).toByteArray(); @@ -1648,30 +1487,11 @@ */ public void listDatabases(List<DatabaseContainer> dbList) { if (equalityIndex != null) { dbList.add(equalityIndex); } if (presenceIndex != null) { dbList.add(presenceIndex); } if (substringIndex != null) { dbList.add(substringIndex); } if (orderingIndex != null) { dbList.add(orderingIndex); } if (approximateIndex != null) { dbList.add(approximateIndex); } addIfNotNull(dbList, equalityIndex); addIfNotNull(dbList, presenceIndex); addIfNotNull(dbList, substringIndex); addIfNotNull(dbList, orderingIndex); addIfNotNull(dbList, approximateIndex); if(extensibleIndexes!=null) { @@ -1682,6 +1502,14 @@ } } private void addIfNotNull(Collection<? super Index> dbList, Index index) { if (index != null) { dbList.add(index); } } /** * Get a string representation of this object. * @return return A string representation of this object. @@ -1748,7 +1576,8 @@ public synchronized ConfigChangeResult applyConfigurationChange( LocalDBIndexCfg cfg) { boolean adminActionRequired = false; // this method is not perf sensitive, using an AtomicBoolean will not hurt AtomicBoolean adminActionRequired = new AtomicBoolean(false); ArrayList<LocalizableMessage> messages = new ArrayList<LocalizableMessage>(); try { @@ -1762,32 +1591,16 @@ { if (equalityIndex == null) { // Adding equality index Indexer equalityIndexer = new EqualityIndexer(attrType); equalityIndex = new Index(name + ".equality", equalityIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); equalityIndex.open(); if(!equalityIndex.isTrusted()) { adminActionRequired = true; messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get( equalityIndex.getName())); } EqualityIndexer indexer = new EqualityIndexer(); Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getEqualityMatchingRule(), indexer); equalityIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages); } else { // already exists. Just update index entry limit. if(this.equalityIndex.setIndexEntryLimit(indexEntryLimit)) { adminActionRequired = true; adminActionRequired.set(true); LocalizableMessage message = NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get( equalityIndex.getName()); @@ -1806,13 +1619,6 @@ entryContainer.deleteDatabase(equalityIndex); equalityIndex = null; } catch(DatabaseException de) { messages.add(LocalizableMessage.raw( StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -1837,7 +1643,7 @@ if(!presenceIndex.isTrusted()) { adminActionRequired = true; adminActionRequired.set(true); messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get( presenceIndex.getName())); } @@ -1847,8 +1653,7 @@ // already exists. Just update index entry limit. if(this.presenceIndex.setIndexEntryLimit(indexEntryLimit)) { adminActionRequired = true; adminActionRequired.set(true); LocalizableMessage message = NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get( presenceIndex.getName()); @@ -1866,13 +1671,6 @@ entryContainer.deleteDatabase(presenceIndex); presenceIndex = null; } catch(DatabaseException de) { messages.add(LocalizableMessage.raw( StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -1882,43 +1680,27 @@ if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.SUBSTRING)) { SubstringIndexer indexer = new SubstringIndexer(attrType, config); Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), indexer); if(substringIndex == null) { Indexer substringIndexer = new SubstringIndexer(attrType, config); substringIndex = new Index(name + ".substring", substringIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); substringIndex.open(); if(!substringIndex.isTrusted()) { adminActionRequired = true; messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get( substringIndex.getName())); } substringIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages); } else { // already exists. Just update index entry limit. if(this.substringIndex.setIndexEntryLimit(indexEntryLimit)) { adminActionRequired = true; adminActionRequired.set(true); LocalizableMessage message = NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get( substringIndex.getName()); messages.add(message); } if(indexConfig.getSubstringLength() != cfg.getSubstringLength()) if (indexConfig.getSubstringLength() != cfg.getSubstringLength()) { Indexer substringIndexer = new SubstringIndexer(attrType, config); this.substringIndex.setIndexer(substringIndexer); this.substringIndex.setIndexer(extIndexer); } } } @@ -1932,13 +1714,6 @@ entryContainer.deleteDatabase(substringIndex); substringIndex = null; } catch(DatabaseException de) { messages.add(LocalizableMessage.raw( StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -1950,31 +1725,16 @@ { if(orderingIndex == null) { Indexer orderingIndexer = new OrderingIndexer(attrType); orderingIndex = new Index(name + ".ordering", orderingIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); orderingIndex.open(); if(!orderingIndex.isTrusted()) { adminActionRequired = true; messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get( orderingIndex.getName())); } OrderingIndexer indexer = new OrderingIndexer(attrType); Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getOrderingMatchingRule(), indexer); orderingIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages); } else { // already exists. Just update index entry limit. if(this.orderingIndex.setIndexEntryLimit(indexEntryLimit)) { adminActionRequired = true; adminActionRequired.set(true); LocalizableMessage message = NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get( orderingIndex.getName()); @@ -1992,13 +1752,6 @@ entryContainer.deleteDatabase(orderingIndex); orderingIndex = null; } catch(DatabaseException de) { messages.add(LocalizableMessage.raw( StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -2011,31 +1764,16 @@ { if(approximateIndex == null) { Indexer approximateIndexer = new ApproximateIndexer(attrType); approximateIndex = new Index(name + ".approximate", approximateIndexer, state, indexEntryLimit, cursorEntryLimit, false, env, entryContainer); approximateIndex.open(); if(!approximateIndex.isTrusted()) { adminActionRequired = true; messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get( approximateIndex.getName())); } ApproximateIndexer indexer = new ApproximateIndexer(attrType); Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getApproximateMatchingRule(), indexer); approximateIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages); } else { // already exists. Just update index entry limit. if(this.approximateIndex.setIndexEntryLimit(indexEntryLimit)) { adminActionRequired = true; adminActionRequired.set(true); LocalizableMessage message = NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get( approximateIndex.getName()); @@ -2053,13 +1791,6 @@ entryContainer.deleteDatabase(approximateIndex); approximateIndex = null; } catch(DatabaseException de) { messages.add( LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -2114,7 +1845,7 @@ if(!extensibleIndex.isTrusted()) { adminActionRequired = true; adminActionRequired.set(true); messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get( extensibleIndex.getName())); } @@ -2124,7 +1855,7 @@ Index extensibleIndex = extensibleIndexes.getIndex(indexID); if(extensibleIndex.setIndexEntryLimit(indexEntryLimit)) { adminActionRequired = true; adminActionRequired.set(true); LocalizableMessage message = NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get( extensibleIndex.getName()); @@ -2201,13 +1932,6 @@ } } } catch(DatabaseException de) { messages.add( LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -2228,13 +1952,6 @@ } extensibleIndexes.deleteAll(); } catch(DatabaseException de) { messages.add( LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), false, messages); } finally { entryContainer.exclusiveLock.unlock(); @@ -2244,17 +1961,34 @@ indexConfig = cfg; return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired, messages); return new ConfigChangeResult( ResultCode.SUCCESS, adminActionRequired.get(), messages); } catch(Exception e) { messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e))); return new ConfigChangeResult( DirectoryServer.getServerErrorResultCode(), adminActionRequired, messages); DirectoryServer.getServerErrorResultCode(), adminActionRequired.get(), messages); } } private Index openNewIndex(String name, Indexer indexer, ExtensibleIndexer extIndexer, AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages) { Index index = new Index(name + "." + extIndexer.getExtensibleIndexID(), indexer, state, indexConfig.getIndexEntryLimit(), cursorEntryLimit, false, env, entryContainer); index.open(); if (!index.isTrusted()) { adminActionRequired.set(true); messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(index .getName())); } return index; } /** * Set the index truststate. * @param txn A database transaction, or null if none is required. @@ -2265,30 +1999,11 @@ public synchronized void setTrusted(Transaction txn, boolean trusted) throws DatabaseException { if (equalityIndex != null) { equalityIndex.setTrusted(txn, trusted); } if (presenceIndex != null) { presenceIndex.setTrusted(txn, trusted); } if (substringIndex != null) { substringIndex.setTrusted(txn, trusted); } if (orderingIndex != null) { orderingIndex.setTrusted(txn, trusted); } if (approximateIndex != null) { approximateIndex.setTrusted(txn, trusted); } setTrusted(equalityIndex, txn, trusted); setTrusted(presenceIndex, txn, trusted); setTrusted(substringIndex, txn, trusted); setTrusted(orderingIndex, txn, trusted); setTrusted(approximateIndex, txn, trusted); if(extensibleIndexes!=null) { @@ -2299,33 +2014,25 @@ } } private void setTrusted(Index index, Transaction txn, boolean trusted) { if (index != null) { index.setTrusted(txn, trusted); } } /** * Return true iff this index is trusted. * @return the trusted state of this index */ public boolean isTrusted() { if (equalityIndex != null && !equalityIndex.isTrusted()) { return false; } if (presenceIndex != null && !presenceIndex.isTrusted()) { return false; } if (substringIndex != null && !substringIndex.isTrusted()) { return false; } if (orderingIndex != null && !orderingIndex.isTrusted()) { return false; } if (approximateIndex != null && !approximateIndex.isTrusted()) if ((equalityIndex != null && !equalityIndex.isTrusted()) || (presenceIndex != null && !presenceIndex.isTrusted()) || (substringIndex != null && !substringIndex.isTrusted()) || (orderingIndex != null && !orderingIndex.isTrusted()) || (approximateIndex != null && !approximateIndex.isTrusted())) { return false; } @@ -2351,30 +2058,11 @@ */ public synchronized void setRebuildStatus(boolean rebuildRunning) { if (equalityIndex != null) { equalityIndex.setRebuildStatus(rebuildRunning); } if (presenceIndex != null) { presenceIndex.setRebuildStatus(rebuildRunning); } if (substringIndex != null) { substringIndex.setRebuildStatus(rebuildRunning); } if (orderingIndex != null) { orderingIndex.setRebuildStatus(rebuildRunning); } if (approximateIndex != null) { approximateIndex.setRebuildStatus(rebuildRunning); } setRebuildStatus(rebuildRunning, equalityIndex); setRebuildStatus(rebuildRunning, presenceIndex); setRebuildStatus(rebuildRunning, substringIndex); setRebuildStatus(rebuildRunning, orderingIndex); setRebuildStatus(rebuildRunning, approximateIndex); if(extensibleIndexes!=null) { @@ -2385,6 +2073,14 @@ } } private void setRebuildStatus(boolean rebuildRunning, Index index) { if (index != null) { index.setRebuildStatus(rebuildRunning); } } /** * Get the JE database name prefix for indexes in this attribute index. * @@ -2466,30 +2162,11 @@ public Collection<Index> getAllIndexes() { LinkedHashSet<Index> indexes = new LinkedHashSet<Index>(); if (equalityIndex != null) { indexes.add(equalityIndex); } if (presenceIndex != null) { indexes.add(presenceIndex); } if (substringIndex != null) { indexes.add(substringIndex); } if (orderingIndex != null) { indexes.add(orderingIndex); } if (approximateIndex != null) { indexes.add(approximateIndex); } addIfNotNull(indexes, equalityIndex); addIfNotNull(indexes, presenceIndex); addIfNotNull(indexes, substringIndex); addIfNotNull(indexes, orderingIndex); addIfNotNull(indexes, approximateIndex); if(extensibleIndexes!=null) { opendj3-server-dev/src/server/org/opends/server/backends/jeb/DatabaseContainer.java
@@ -26,17 +26,19 @@ */ package org.opends.server.backends.jeb; import com.sleepycat.je.*; import java.io.Closeable; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.opends.server.util.ServerConstants; import org.opends.server.util.StaticUtils; import com.sleepycat.je.*; /** * This class is a wrapper around the JE database object and provides basic * read and write methods for entries. */ public abstract class DatabaseContainer public abstract class DatabaseContainer implements Closeable { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); @@ -89,7 +91,7 @@ * created and used to perform the open. * * @throws DatabaseException if a JE database error occurs while * openning the index. * opening the index. */ public void open() throws DatabaseException { @@ -131,17 +133,18 @@ * database container. * * The database container should not be closed while other processes * aquired the container. The container should not be closed * acquired the container. The container should not be closed * while cursors handles into the database remain open, or * transactions that include operations on the database have not yet * been commited or aborted. * been committed or aborted. * * The container may not be accessed again after this method is * called, regardless of the method's success or failure. * * @throws DatabaseException if an error occurs. */ synchronized void close() throws DatabaseException @Override synchronized public void close() throws DatabaseException { if(dbConfig.getDeferredWrite()) { @@ -270,7 +273,6 @@ throws DatabaseException { return database.openCursor(cursorConfig); } /** @@ -293,6 +295,7 @@ * Get a string representation of this object. * @return return A string representation of this object. */ @Override public String toString() { return name; @@ -338,7 +341,7 @@ { StringBuilder builder = new StringBuilder(); builder.append(" ("); builder.append(status.toString()); builder.append(status); builder.append(")"); builder.append(" db="); try @@ -347,7 +350,7 @@ } catch (DatabaseException de) { builder.append(de.toString()); builder.append(de); } if (txn != null) { @@ -358,7 +361,7 @@ } catch (DatabaseException de) { builder.append(de.toString()); builder.append(de); } } else @@ -387,5 +390,4 @@ return builder.toString(); } } opendj3-server-dev/src/server/org/opends/server/backends/jeb/EqualityIndexer.java
@@ -26,159 +26,38 @@ */ package org.opends.server.backends.jeb; import java.util.*; import java.util.Set; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.opends.server.api.ExtensibleIndexer; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.DirectoryException; import org.opends.server.types.Entry; import org.opends.server.types.Modification; /** * An implementation of an Indexer for attribute equality. */ public class EqualityIndexer extends Indexer public class EqualityIndexer extends ExtensibleIndexer { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** * The comparator for index keys generated by this class. */ private static final Comparator<byte[]> comparator = new AttributeIndex.KeyComparator(); /** * The attribute type for which this instance will * generate index keys. */ private AttributeType attributeType; /** * Create a new attribute equality indexer for the given attribute type. * @param attributeType The attribute type for which an indexer is * required. */ public EqualityIndexer(AttributeType attributeType) { this.attributeType = attributeType; } /** * Get a string representation of this object. The returned value is * used to name an index created using this object. * @return A string representation of this object. */ /** {@inheritDoc} */ @Override public String toString() public String getIndexID() { return attributeType.getNameOrOID() + ".equality"; // TODO Auto-generated method stub throw new RuntimeException(); } /** * Get the comparator that must be used to compare index keys * generated by this class. * * @return A byte array comparator. */ /** {@inheritDoc} */ @Override public Comparator<byte[]> getComparator() public String getExtensibleIndexID() { return comparator; return "equality"; } /** * Generate the set of index keys for an entry. * * @param entry The entry. * @param keys The set into which the generated keys will be inserted. */ /** {@inheritDoc} */ @Override public void indexEntry(Entry entry, Set<byte[]> keys) { List<Attribute> attrList = entry.getAttribute(attributeType); if (attrList != null) { indexAttribute(attrList, keys); } } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that has been replaced. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void replaceEntry(Entry oldEntry, Entry newEntry, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that was modified. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param mods The set of modifications that were applied to the entry. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void modifyEntry(Entry oldEntry, Entry newEntry, List<Modification> mods, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param keys The set into which the keys will be inserted. */ private void indexAttribute(List<Attribute> attrList, Set<byte[]> keys) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { getKeys(value, keys); } } } } private void getKeys(AttributeValue value, Set<byte[]> keys) public void getKeys(AttributeValue value, Set<byte[]> keys) { try { @@ -190,37 +69,4 @@ } } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param modifiedKeys The map into which the modified * keys will be inserted. * @param insert <code>true</code> if generated keys should * be inserted or <code>false</code> otherwise. */ private void indexAttribute(List<Attribute> attrList, Map<byte[], Boolean> modifiedKeys, Boolean insert) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { getKeys(value, modifiedKeys, insert); } } } } private void getKeys(AttributeValue value, Map<byte[], Boolean> modifiedKeys, Boolean insert) { Set<byte[]> keys = new HashSet<byte[]>(); getKeys(value, keys); ExtensibleIndexer.computeModifiedKeys(modifiedKeys, insert, keys); } } opendj3-server-dev/src/server/org/opends/server/backends/jeb/JEExtensibleIndexer.java
@@ -27,12 +27,13 @@ package org.opends.server.backends.jeb; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.opends.server.api.ExtensibleIndexer; import org.opends.server.api.ExtensibleMatchingRule; import org.opends.server.api.MatchingRule; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.Entry; @@ -77,15 +78,13 @@ * @param extensibleIndexer The extensible indexer to be used. */ public JEExtensibleIndexer(AttributeType attributeType, ExtensibleMatchingRule matchingRule, MatchingRule matchingRule, ExtensibleIndexer extensibleIndexer) { this.attributeType = attributeType; this.extensibleIndexer = extensibleIndexer; } /** * Gets a string representation of this object. The returned value is * used to name an index created using this object. @@ -202,14 +201,38 @@ { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { extensibleIndexer.getKeys(value, modifiedKeys, insert); final Set<byte[]> keys = new HashSet<byte[]>(); indexAttribute(attrList, keys); computeModifiedKeys(modifiedKeys, insert, keys); } /** * Computes a map of index keys and a boolean flag indicating whether the * corresponding key will be inserted or deleted. * * @param modifiedKeys * A map containing the keys and a boolean. Keys corresponding to the * boolean value <code>true</code> should be inserted and * <code>false</code> should be deleted. * @param insert * <code>true</code> if generated keys should be inserted or * <code>false</code> otherwise. * @param keys * The index keys to map. */ private static void computeModifiedKeys(Map<byte[], Boolean> modifiedKeys, Boolean insert, final Set<byte[]> keys) { for (byte[] key : keys) { Boolean cInsert = modifiedKeys.get(key); if (cInsert == null) { modifiedKeys.put(key, insert); } else if (!cInsert.equals(insert)) { modifiedKeys.remove(key); } } } opendj3-server-dev/src/server/org/opends/server/backends/jeb/NullIndex.java
@@ -67,9 +67,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean insertID(IndexBuffer buffer, byte[] keyBytes, EntryID entryID) { @@ -78,9 +76,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean insertID(Transaction txn, DatabaseEntry key, EntryID entryID) throws DatabaseException @@ -90,9 +86,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void insert(DatabaseEntry key, ImportIDSet importIdSet, DatabaseEntry data) throws DatabaseException @@ -102,9 +96,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void delete(DatabaseEntry key, ImportIDSet importIdSet, DatabaseEntry data) throws DatabaseException @@ -114,11 +106,9 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public synchronized boolean insert(ImportIDSet importIDSet, public boolean insert(ImportIDSet importIDSet, Set<byte[]> keySet, DatabaseEntry keyData, DatabaseEntry data) throws DatabaseException { @@ -127,9 +117,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override void updateKey(Transaction txn, DatabaseEntry key, EntryIDSet deletedIDs, EntryIDSet addedIDs) throws DatabaseException @@ -139,9 +127,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean removeID(IndexBuffer buffer, byte[] keyBytes, EntryID entryID) { @@ -150,9 +136,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void removeID(Transaction txn, DatabaseEntry key, EntryID entryID) throws DatabaseException @@ -162,9 +146,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void delete(Transaction txn, Set<byte[]> keySet, EntryID entryID) throws DatabaseException @@ -174,9 +156,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void delete(IndexBuffer buffer, byte[] keyBytes) { @@ -185,9 +165,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public ConditionResult containsID(Transaction txn, DatabaseEntry key, EntryID entryID) throws DatabaseException @@ -197,9 +175,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public EntryIDSet readKey(DatabaseEntry key, Transaction txn, LockMode lockMode) @@ -209,9 +185,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void writeKey(Transaction txn, DatabaseEntry key, EntryIDSet entryIDList) throws DatabaseException @@ -221,9 +195,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public EntryIDSet readRange(byte[] lower, byte[] upper, boolean lowerIncluded, boolean upperIncluded) @@ -233,9 +205,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public int getEntryLimitExceededCount() { @@ -244,9 +214,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void closeCursor() throws DatabaseException { @@ -255,9 +223,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException @@ -267,9 +233,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean addEntry(Transaction txn, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException @@ -279,9 +243,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException @@ -291,9 +253,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void removeEntry(Transaction txn, EntryID entryID, Entry entry) throws DatabaseException, DirectoryException @@ -303,9 +263,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void modifyEntry(Transaction txn, EntryID entryID, Entry oldEntry, Entry newEntry, List<Modification> mods) throws DatabaseException @@ -315,9 +273,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void modifyEntry(IndexBuffer buffer, EntryID entryID, Entry oldEntry, Entry newEntry, List<Modification> mods) throws DatabaseException @@ -327,9 +283,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean setIndexEntryLimit(int indexEntryLimit) { @@ -338,9 +292,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public int getIndexEntryLimit() { @@ -349,11 +301,9 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public synchronized void setTrusted(Transaction txn, boolean trusted) public void setTrusted(Transaction txn, boolean trusted) throws DatabaseException { // Do nothing. @@ -361,42 +311,34 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public synchronized boolean isTrusted() public boolean isTrusted() { return true; } /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public synchronized boolean isRebuildRunning() public boolean isRebuildRunning() { return false; } /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public synchronized void setRebuildStatus(boolean rebuildRunning) public void setRebuildStatus(boolean rebuildRunning) { // Do nothing. } /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public boolean getMaintainCount() { @@ -405,9 +347,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public void open() throws DatabaseException { @@ -416,20 +356,16 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override synchronized void close() throws DatabaseException public void close() throws DatabaseException { // Do nothing. } /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override protected OperationStatus put(Transaction txn, DatabaseEntry key, DatabaseEntry data) throws DatabaseException @@ -439,9 +375,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override protected OperationStatus read(Transaction txn, DatabaseEntry key, DatabaseEntry data, LockMode lockMode) throws DatabaseException @@ -451,9 +385,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override protected OperationStatus insert(Transaction txn, DatabaseEntry key, DatabaseEntry data) throws DatabaseException @@ -463,9 +395,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override protected OperationStatus delete(Transaction txn, DatabaseEntry key) throws DatabaseException @@ -475,9 +405,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public Cursor openCursor(Transaction txn, CursorConfig cursorConfig) throws DatabaseException @@ -487,9 +415,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public long getRecordCount() throws DatabaseException { @@ -498,9 +424,7 @@ /** * {@inheritDoc} */ /** {@inheritDoc} */ @Override public PreloadStats preload(PreloadConfig config) throws DatabaseException { opendj3-server-dev/src/server/org/opends/server/backends/jeb/OrderingIndexer.java
@@ -26,37 +26,22 @@ */ package org.opends.server.backends.jeb; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.ldap.DecodeException; import org.opends.server.api.ExtensibleIndexer; import org.opends.server.api.OrderingMatchingRule; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.Entry; import org.opends.server.types.Modification; /** * An implementation of an Indexer for attribute ordering. */ public class OrderingIndexer extends Indexer public class OrderingIndexer extends ExtensibleIndexer { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** * The attribute type for which this instance will * generate index keys. */ private AttributeType attributeType; /** * The attribute type ordering matching rule which is also the * comparator for the index keys generated by this class. @@ -71,115 +56,27 @@ */ public OrderingIndexer(AttributeType attributeType) { this.attributeType = attributeType; this.orderingRule = attributeType.getOrderingMatchingRule(); } /** * Get a string representation of this object. The returned value is * used to name an index created using this object. * @return A string representation of this object. */ /** {@inheritDoc} */ @Override public String toString() public String getIndexID() { return attributeType.getNameOrOID() + ".ordering"; // TODO Auto-generated method stub throw new RuntimeException(); } /** * Get the comparator that must be used to compare index keys * generated by this class. * * @return A byte array comparator. */ /** {@inheritDoc} */ @Override public Comparator<byte[]> getComparator() public String getExtensibleIndexID() { return orderingRule; return "ordering"; } /** * Generate the set of index keys for an entry. * * @param entry The entry. * @param keys The set into which the generated keys will be inserted. */ /** {@inheritDoc} */ @Override public void indexEntry(Entry entry, Set<byte[]> keys) { List<Attribute> attrList = entry.getAttribute(attributeType); if (attrList != null) { indexAttribute(attrList, keys); } } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that has been replaced. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void replaceEntry(Entry oldEntry, Entry newEntry, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that was modified. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param mods The set of modifications that were applied to the entry. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void modifyEntry(Entry oldEntry, Entry newEntry, List<Modification> mods, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param keys The set into which the keys will be inserted. */ private void indexAttribute(List<Attribute> attrList, Set<byte[]> keys) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { getKeys(value, keys); } } } } private void getKeys(AttributeValue value, Set<byte[]> keys) public void getKeys(AttributeValue value, Set<byte[]> keys) { try { @@ -191,38 +88,4 @@ } } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param modifiedKeys The map into which the modified * keys will be inserted. * @param insert <code>true</code> if generated keys should * be inserted or <code>false</code> otherwise. */ private void indexAttribute(List<Attribute> attrList, Map<byte[], Boolean> modifiedKeys, Boolean insert) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { for (AttributeValue value : attr) { getKeys(value, modifiedKeys, insert); } } } } private void getKeys(AttributeValue value, Map<byte[], Boolean> modifiedKeys, Boolean insert) { Set<byte[]> keys = new HashSet<byte[]>(); getKeys(value, keys); ExtensibleIndexer.computeModifiedKeys(modifiedKeys, insert, keys); } } opendj3-server-dev/src/server/org/opends/server/backends/jeb/SubstringIndexer.java
@@ -26,10 +26,6 @@ */ package org.opends.server.backends.jeb; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.forgerock.i18n.slf4j.LocalizedLogger; @@ -37,28 +33,17 @@ import org.forgerock.opendj.ldap.spi.IndexingOptions; import org.opends.server.api.ExtensibleIndexer; import org.opends.server.api.SubstringMatchingRule; import org.opends.server.types.*; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; /** * An implementation of an Indexer for attribute substrings. */ public class SubstringIndexer extends Indexer public class SubstringIndexer extends ExtensibleIndexer { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** * The comparator for index keys generated by this class. */ private static final Comparator<byte[]> comparator = new AttributeIndex.KeyComparator(); /** * The attribute type for which this instance will * generate index keys. */ private AttributeType attributeType; private SubstringMatchingRule substringRule; private IndexingOptions indexingOptions; /** @@ -72,115 +57,23 @@ public SubstringIndexer(AttributeType attributeType, IndexingOptions indexingOptions) { this.attributeType = attributeType; this.substringRule = attributeType.getSubstringMatchingRule(); this.indexingOptions = indexingOptions; } /** * Get a string representation of this object. The returned value is * used to name an index created using this object. * @return A string representation of this object. */ /** {@inheritDoc} */ @Override public String toString() public String getIndexID() { return attributeType.getNameOrOID() + ".substring"; // TODO Auto-generated method stub throw new RuntimeException(); } /** * Get the comparator that must be used to compare index keys * generated by this class. * * @return A byte array comparator. */ /** {@inheritDoc} */ @Override public Comparator<byte[]> getComparator() public String getExtensibleIndexID() { return comparator; } /** * Generate the set of index keys for an entry. * * @param entry The entry. * @param keys The set into which the generated keys will be inserted. */ @Override public void indexEntry(Entry entry, Set<byte[]> keys) { List<Attribute> attrList = entry.getAttribute(attributeType); if (attrList != null) { indexAttribute(attrList, keys); } } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that has been replaced. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void replaceEntry(Entry oldEntry, Entry newEntry, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of index keys to be added and the set of index keys * to be deleted for an entry that was modified. * * @param oldEntry The original entry contents. * @param newEntry The new entry contents. * @param mods The set of modifications that were applied to the entry. * @param modifiedKeys The map into which the modified keys will be inserted. */ @Override public void modifyEntry(Entry oldEntry, Entry newEntry, List<Modification> mods, Map<byte[], Boolean> modifiedKeys) { List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); indexAttribute(oldAttributes, modifiedKeys, false); indexAttribute(newAttributes, modifiedKeys, true); } /** * Generate the set of substring index keys for an attribute. * @param attrList The attribute for which substring keys are required. * @param keys The set into which the generated keys will be inserted. */ private void indexAttribute(List<Attribute> attrList, Set<byte[]> keys) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { SubstringMatchingRule rule = attr.getAttributeType().getSubstringMatchingRule(); for (AttributeValue value : attr) { getKeys(rule, value, keys); } } } return "substring"; } /** @@ -191,12 +84,12 @@ * @param attrValue A byte array containing the normalized attribute value * @param keys A set into which the keys will be inserted. */ private void getKeys(SubstringMatchingRule rule, AttributeValue attrValue, Set<byte[]> keys) @Override public void getKeys(AttributeValue attrValue, Set<byte[]> keys) { // TODO merge with ExtensibleIndexer.getKeys(attrValue, keys); try { byte[] value = rule.normalizeAttributeValue(attrValue.getValue()).toByteArray(); byte[] value = substringRule.normalizeAttributeValue(attrValue.getValue()).toByteArray(); // Example: The value is ABCDE and the substring length is 3. // We produce the keys ABC BCD CDE DE E @@ -233,51 +126,4 @@ return keyBytes; } /** * Generate the set of index keys for an attribute. * @param attrList The attribute to be indexed. * @param modifiedKeys The map into which the modified * keys will be inserted. * @param insert <code>true</code> if generated keys should * be inserted or <code>false</code> otherwise. */ private void indexAttribute(List<Attribute> attrList, Map<byte[], Boolean> modifiedKeys, Boolean insert) { if (attrList == null) return; for (Attribute attr : attrList) { if (!attr.isVirtual()) { SubstringMatchingRule rule = attr.getAttributeType().getSubstringMatchingRule(); for (AttributeValue value : attr) { getKeys(rule, value, modifiedKeys, insert); } } } } /** * Decompose an attribute value into a set of substring index keys. * The ID of the entry containing this value should be inserted * into the list of each of these keys. * * @param value A byte array containing the normalized attribute value * @param modifiedKeys The map into which the modified * keys will be inserted. * @param insert <code>true</code> if generated keys should * be inserted or <code>false</code> otherwise. */ private void getKeys(SubstringMatchingRule rule, AttributeValue value, Map<byte[], Boolean> modifiedKeys, Boolean insert) { // TODO merge with ExtensibleIndexer.getKeys(attrValue, modifiedKeys, insert); Set<byte[]> keys = new HashSet<byte[]>(); getKeys(rule, value, keys); ExtensibleIndexer.computeModifiedKeys(modifiedKeys, insert, keys); } } opendj3-server-dev/src/server/org/opends/server/schema/CollationMatchingRuleFactory.java
@@ -1350,7 +1350,6 @@ // initialLength, initial, numberofany, anyLength1, any1, // anyLength2, any2, ..., anyLengthn, anyn, finalLength, // final CollationKey key; List<Integer> normalizedList = new ArrayList<Integer>(); if (subInitial == null) @@ -1359,16 +1358,7 @@ } else { key = collator.getCollationKey(subInitial); byte[] initialBytes = key.toByteArray(); // Last 4 bytes are 0s with PRIMARY strength. int length = initialBytes.length - 4; normalizedList.add(length); for (int i = 0; i < length; i++) { normalizedList.add((int) initialBytes[i]); } addLengthAndBytes(subInitial, normalizedList); } List<String> subAny = assertion.getAny(); @@ -1381,14 +1371,7 @@ normalizedList.add(subAny.size()); for (String any : subAny) { key = collator.getCollationKey(any); byte[] anyBytes = key.toByteArray(); int length = anyBytes.length - 4; normalizedList.add(length); for (int i = 0; i < length; i++) { normalizedList.add((int) anyBytes[i]); } addLengthAndBytes(any, normalizedList); } } @@ -1399,14 +1382,7 @@ } else { key = collator.getCollationKey(subFinal); byte[] subFinalBytes = key.toByteArray(); int length = subFinalBytes.length - 4; normalizedList.add(length); for (int i = 0; i < length; i++) { normalizedList.add((int) subFinalBytes[i]); } addLengthAndBytes(subFinal, normalizedList); } byte[] normalizedBytes = new byte[normalizedList.size()]; @@ -1420,6 +1396,23 @@ private void addLengthAndBytes(String substring, List<Integer> normalizedList) { CollationKey key = collator.getCollationKey(substring); byte[] substrBytes = key.toByteArray(); // Last 4 bytes are 0s with PRIMARY strength. int length = substrBytes.length - 4; normalizedList.add(length); for (int i = 0; i < length; i++) { normalizedList.add((int) substrBytes[i]); } } /** * {@inheritDoc} */ @@ -1566,50 +1559,6 @@ } /** * Decomposes an attribute value into a set of substring index keys. * * @param attValue * The normalized attribute value * @param set * A set into which the keys will be inserted. */ private void substringKeys(ByteString attValue, Set<byte[]> keys) { // TODO merge with ExtensibleIndexer.getKeys(attrValue, keys); // TODO and with AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys(); String value = attValue.toString(); int keyLength = subIndexer.getSubstringLength(); for (int i = 0, remain = value.length(); remain > 0; i++, remain--) { int len = Math.min(keyLength, remain); keys.add(makeSubstringKey(value, i, len)); } } /** * Decomposes an attribute value into a set of substring index keys. * * @param value * The normalized attribute value * @param modifiedKeys * The map into which the modified keys will be inserted. * @param insert * <code>true</code> if generated keys should be inserted * or <code>false</code> otherwise. */ private void substringKeys(ByteString attValue, Map<byte[], Boolean> modifiedKeys, Boolean insert) { // TODO merge with ExtensibleIndexer.getKeys(attrValue, modifiedKeys, insert); Set<byte[]> keys = new TreeSet<byte[]>(); substringKeys(attValue, keys); ExtensibleIndexer.computeModifiedKeys(modifiedKeys, insert, keys); } /** * Makes a byte array representing a substring index key for one * substring of a value. @@ -2199,21 +2148,16 @@ * {@inheritDoc} */ @Override public void getKeys(AttributeValue value, Set<byte[]> keys) public void getKeys(AttributeValue attValue, Set<byte[]> keys) { // TODO merge with ExtensibleIndexer.getKeys(attrValue, keys); // TODO and with AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys(); String value = attValue.toString(); int keyLength = substringLen; for (int i = 0, remain = value.length(); remain > 0; i++, remain--) { matchingRule.substringKeys(value.getValue(), keys); int len = Math.min(keyLength, remain); keys.add(matchingRule.makeSubstringKey(value, i, len)); } /** * {@inheritDoc} */ @Override public void getKeys(AttributeValue attValue, Map<byte[], Boolean> modifiedKeys, Boolean insert) { matchingRule.substringKeys(attValue.getValue(), modifiedKeys, insert); } /** {@inheritDoc} */ opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -30,7 +30,6 @@ import org.forgerock.opendj.ldap.ConditionResult; import org.forgerock.opendj.ldap.DereferenceAliasesPolicy; import org.forgerock.opendj.ldap.ModificationType; import org.forgerock.opendj.ldap.ResultCode; import org.forgerock.opendj.ldap.SearchScope; import org.forgerock.opendj.ldap.spi.IndexingOptions; @@ -38,6 +37,7 @@ import org.opends.server.admin.server.AdminTestCaseUtils; import org.opends.server.admin.std.meta.LocalDBBackendCfgDefn; import org.opends.server.admin.std.server.LocalDBBackendCfg; import org.opends.server.api.ExtensibleIndexer; import org.opends.server.controls.SubtreeDeleteControl; import org.opends.server.core.DeleteOperationBasis; import org.opends.server.core.DirectoryServer; @@ -47,12 +47,6 @@ import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.protocols.ldap.LDAPFilter; import org.opends.server.types.*; import org.opends.server.types.Attribute; import org.opends.server.types.Attributes; import org.opends.server.types.DN; import org.opends.server.types.Entry; import org.opends.server.types.Modification; import org.opends.server.types.RDN; import org.opends.server.util.Base64; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -64,7 +58,9 @@ import static org.assertj.core.api.Assertions.*; import static org.forgerock.opendj.ldap.ConditionResult.*; import static org.forgerock.opendj.ldap.ModificationType.*; import static org.mockito.Mockito.*; import static org.opends.server.types.Attributes.*; import static org.testng.Assert.*; /** @@ -846,7 +842,7 @@ assertIndexContainsID(presenceIndexer, entry, index.presenceIndex, entryID, FALSE); Indexer equalityIndexer = new EqualityIndexer(index.getAttributeType()); Indexer equalityIndexer = newEqualityIndexer(index); assertIndexContainsID(equalityIndexer, entry, index.equalityIndex, entryID, FALSE); @@ -854,7 +850,7 @@ assertIndexContainsID(substringIndexer, entry, index.substringIndex, entryID, FALSE); Indexer orderingIndexer = new OrderingIndexer(index.getAttributeType()); Indexer orderingIndexer = newOrderingIndexer(index); assertIndexContainsID(orderingIndexer, entry, index.orderingIndex, entryID, FALSE); } @@ -864,12 +860,28 @@ } } private SubstringIndexer newSubstringIndexer(AttributeIndex index) private Indexer newOrderingIndexer(AttributeIndex index) { AttributeType attrType = index.getAttributeType(); ExtensibleIndexer extIndexer = new OrderingIndexer(index.getAttributeType()); return new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), extIndexer); } private Indexer newEqualityIndexer(AttributeIndex index) { AttributeType attrType = index.getAttributeType(); ExtensibleIndexer extIndexer = new EqualityIndexer(); return new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), extIndexer); } private Indexer newSubstringIndexer(AttributeIndex index) { final IndexingOptions options = mock(IndexingOptions.class); when(options.substringKeySize()).thenReturn( index.getConfiguration().getSubstringLength()); return new SubstringIndexer(index.getAttributeType(), options); AttributeType attrType = index.getAttributeType(); ExtensibleIndexer extIndexer = new SubstringIndexer(attrType, options); return new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), extIndexer); } private void assertIndexContainsID(Indexer indexer, Entry entry, Index index, @@ -940,7 +952,7 @@ entry.getAttribute("cn").get(0).getAttributeType(); AttributeIndex index = ec.getAttributeIndex(attribute); Indexer orderingIndexer = new OrderingIndexer(index.getAttributeType()); Indexer orderingIndexer = newOrderingIndexer(index); assertIndexContainsID(orderingIndexer, entry, index.orderingIndex, entryID, TRUE); assertIndexContainsID(orderingIndexer, oldEntry, index.orderingIndex, @@ -952,7 +964,7 @@ assertIndexContainsID(substringIndexer, oldEntry, index.substringIndex, entryID, FALSE); Indexer equalityIndexer = new EqualityIndexer(index.getAttributeType()); Indexer equalityIndexer = newEqualityIndexer(index); assertIndexContainsID(equalityIndexer, entry, index.equalityIndex, entryID, TRUE); assertIndexContainsID(equalityIndexer, oldEntry, index.equalityIndex, @@ -976,10 +988,10 @@ AttributeIndex titleIndex; AttributeIndex nameIndex; Set<byte[]> addKeys; PresenceIndexer presenceIndexer; EqualityIndexer equalityIndexer; SubstringIndexer substringIndexer; OrderingIndexer orderingIndexer; Indexer presenceIndexer; Indexer equalityIndexer; Indexer substringIndexer; Indexer orderingIndexer; EntryContainer ec = backend.getRootContainer().getEntryContainer( DN.valueOf("dc=test,dc=com")); @@ -987,42 +999,32 @@ try { List<Modification> modifications = new ArrayList<Modification>(); modifications.add(new Modification(ModificationType.ADD, Attributes .create("title", "debugger"))); modifications.add(new Modification(ADD, create("title", "debugger"))); AttributeBuilder builder = new AttributeBuilder("title"); builder.setOption("lang-en"); builder.add("debugger2"); modifications.add(new Modification(ModificationType.ADD, builder .toAttribute())); modifications.add(new Modification(ModificationType.DELETE, Attributes.create("cn", "Aaren Atp"))); modifications.add(new Modification(ModificationType.ADD, Attributes .create("cn", "Aaren Rigor"))); modifications.add(new Modification(ModificationType.ADD, Attributes .create("cn", "Aarenister Rigor"))); modifications.add(new Modification(ADD, builder.toAttribute())); modifications.add(new Modification(DELETE, create("cn", "Aaren Atp"))); modifications.add(new Modification(ADD, create("cn", "Aaren Rigor"))); modifications.add(new Modification(ADD, create("cn", "Aarenister Rigor"))); builder = new AttributeBuilder("givenname"); builder.add("test"); builder.setOption("lang-de"); modifications.add(new Modification(ModificationType.ADD, builder .toAttribute())); modifications.add(new Modification(ADD, builder.toAttribute())); builder = new AttributeBuilder("givenname"); builder.add("test2"); builder.setOption("lang-cn"); modifications.add(new Modification(ModificationType.DELETE, builder .toAttribute())); modifications.add(new Modification(DELETE, builder.toAttribute())); builder = new AttributeBuilder("givenname"); builder.add("newtest3"); builder.setOption("lang-es"); modifications.add(new Modification(ModificationType.REPLACE, builder .toAttribute())); modifications.add(new Modification(ModificationType.REPLACE, Attributes.create("employeenumber", "222"))); modifications.add(new Modification(REPLACE, builder.toAttribute())); modifications.add(new Modification(REPLACE, create("employeenumber", "222"))); newEntry = entries.get(1); newEntry.applyModifications(modifications); @@ -1097,16 +1099,16 @@ presenceIndexer = new PresenceIndexer(nameIndex.getAttributeType()); assertIndexContainsID(presenceIndexer, entry, nameIndex.presenceIndex, entryID); orderingIndexer = new OrderingIndexer(titleIndex.getAttributeType()); orderingIndexer = newOrderingIndexer(titleIndex); assertIndexContainsID(orderingIndexer, entry, titleIndex.orderingIndex, entryID); orderingIndexer = new OrderingIndexer(nameIndex.getAttributeType()); orderingIndexer = newOrderingIndexer(nameIndex); assertIndexContainsID(orderingIndexer, entry, nameIndex.orderingIndex, entryID); equalityIndexer = new EqualityIndexer(titleIndex.getAttributeType()); equalityIndexer = newEqualityIndexer(titleIndex); assertIndexContainsID(equalityIndexer, entry, titleIndex.equalityIndex, entryID); equalityIndexer = new EqualityIndexer(nameIndex.getAttributeType()); equalityIndexer = newEqualityIndexer(nameIndex); assertIndexContainsID(equalityIndexer, entry, nameIndex.equalityIndex, entryID); substringIndexer = newSubstringIndexer(titleIndex);