| | |
| | | import java.util.*; |
| | | |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import org.opends.server.api.ApproximateMatchingRule; |
| | |
| | | * @param keys The set into which the generated keys will be inserted. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | */ |
| | | public void replaceEntry(Transaction txn, |
| | | Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | { |
| | | List<Attribute> attrList; |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | |
| | | attrList = oldEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> oldSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, oldSet); |
| | | |
| | | attrList = newEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> newSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, newSet); |
| | | |
| | | HashSet<ASN1OctetString> removeSet = new HashSet<ASN1OctetString>(oldSet); |
| | | removeSet.removeAll(newSet); |
| | | for (ASN1OctetString k : removeSet) |
| | | if(newAttributes == null) |
| | | { |
| | | delKeys.add(k); |
| | | indexAttribute(oldAttributes, delKeys); |
| | | } |
| | | |
| | | HashSet<ASN1OctetString> addSet = new HashSet<ASN1OctetString>(newSet); |
| | | addSet.removeAll(oldSet); |
| | | for (ASN1OctetString k : addSet) |
| | | else |
| | | { |
| | | addKeys.add(k); |
| | | if(oldAttributes == null) |
| | | { |
| | | indexAttribute(newAttributes, addKeys); |
| | | } |
| | | else |
| | | { |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | | addKeys.addAll(newKeys); |
| | | addKeys.removeAll(oldKeys); |
| | | |
| | | delKeys.addAll(oldKeys); |
| | | delKeys.removeAll(newKeys); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | HashSet<AttributeValue> newValues; |
| | | HashSet<AttributeValue> oldValues; |
| | | |
| | | if(newAttributes == null) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | HashSet<ASN1OctetString> newKeys = |
| | | new HashSet<ASN1OctetString>(); |
| | | HashSet<ASN1OctetString> oldKeys = |
| | | new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexAttribute(List<Attribute> attrList, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (attrList == null) return; |
| | | |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexValues(Set<AttributeValue> values, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (values == null) return; |
| | | |
| | |
| | | byte[] keyBytes = |
| | | approximateRule.normalizeValue(value.getValue()).value(); |
| | | |
| | | keys.add(new ASN1OctetString(keyBytes)); |
| | | keys.add(keyBytes); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | |
| | | package org.opends.server.backends.jeb; |
| | | import org.opends.messages.Message; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Comparator; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | |
| | | import com.sleepycat.je.*; |
| | | |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | } |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | } |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | } |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | } |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | } |
| | |
| | | // index substring length, and read those keys. |
| | | |
| | | // Eliminate duplicates by putting the keys into a set. |
| | | Set<byte[]> set = new HashSet<byte[]>(); |
| | | Set<byte[]> set = |
| | | new TreeSet<byte[]>(substringIndex.indexer.getComparator()); |
| | | |
| | | // Example: The value is ABCDE and the substring length is 3. |
| | | // We produce the keys ABC BCD CDE. |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | equalityIndex.open(); |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | presenceIndex.open(); |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | substringIndex.open(); |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | orderingIndex.open(); |
| | |
| | | state, |
| | | indexEntryLimit, |
| | | cursorEntryLimit, |
| | | false, |
| | | env, |
| | | entryContainer); |
| | | approximateIndex.open(); |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Entry; |
| | | import static org.opends.server.util.StaticUtils.getFileForPath; |
| | | |
| | | import com.sleepycat.je.DatabaseException; |
| | | import com.sleepycat.je.Transaction; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.BufferedOutputStream; |
| | | import java.io.DataOutputStream; |
| | |
| | | if (oldEntry != null) |
| | | { |
| | | // This is an entry being replaced. |
| | | Set<ASN1OctetString> addKeys = new HashSet<ASN1OctetString>(); |
| | | Set<ASN1OctetString> delKeys = new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> addKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | TreeSet<byte[]> delKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | |
| | | indexer.replaceEntry(txn, oldEntry, newEntry, addKeys, delKeys); |
| | | |
| | | for (ASN1OctetString k : delKeys) |
| | | for (byte[] k : delKeys) |
| | | { |
| | | removeID(k.value(), entryID); |
| | | removeID(k, entryID); |
| | | } |
| | | |
| | | for (ASN1OctetString k : addKeys) |
| | | for (byte[] k : addKeys) |
| | | { |
| | | insertID(k.value(), entryID); |
| | | insertID(k, entryID); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // This is a new entry. |
| | | Set<ASN1OctetString> addKeys = new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> addKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | indexer.indexEntry(txn, newEntry, addKeys); |
| | | for (ASN1OctetString k : addKeys) |
| | | for (byte[] k : addKeys) |
| | | { |
| | | insertID(k.value(), entryID); |
| | | insertID(k, entryID); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | id2children = new Index(databasePrefix + "_" + ID2CHILDREN_DATABASE_NAME, |
| | | new ID2CIndexer(), state, |
| | | indexEntryLimit, 0, |
| | | indexEntryLimit, 0, true, |
| | | env,this); |
| | | id2children.open(); |
| | | id2subtree = new Index(databasePrefix + "_" + ID2SUBTREE_DATABASE_NAME, |
| | | new ID2SIndexer(), state, |
| | | indexEntryLimit, 0, |
| | | indexEntryLimit, 0, true, |
| | | env, this); |
| | | id2subtree.open(); |
| | | |
| | |
| | | */ |
| | | public Transaction beginOperationTransaction() throws DatabaseException |
| | | { |
| | | return beginTransaction(); |
| | | Transaction txn = beginTransaction(); |
| | | // Multiple adds should never encounter a deadlock. |
| | | txn.setLockTimeout(0); |
| | | return txn; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public Transaction beginOperationTransaction() throws DatabaseException |
| | | { |
| | | return beginTransaction(); |
| | | Transaction txn = beginTransaction(); |
| | | // Multiple deletes should never encounter a deadlock. |
| | | txn.setLockTimeout(0); |
| | | return txn; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public Transaction beginOperationTransaction() throws DatabaseException |
| | | { |
| | | return beginTransaction(); |
| | | Transaction txn = beginTransaction(); |
| | | // Multiple replace operations should never encounter a deadlock. |
| | | txn.setLockTimeout(0); |
| | | return txn; |
| | | } |
| | | |
| | | /** |
| | |
| | | */ |
| | | public Transaction beginOperationTransaction() throws DatabaseException |
| | | { |
| | | return beginTransaction(); |
| | | Transaction txn = beginTransaction(); |
| | | return txn; |
| | | } |
| | | |
| | | /** |
| | |
| | | import com.sleepycat.je.Transaction; |
| | | import com.sleepycat.je.DatabaseException; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | 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; |
| | | |
| | | import java.util.Comparator; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * An implementation of an Indexer for attribute equality. |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> keys) throws DatabaseException |
| | | Set<byte[]> keys) throws DatabaseException |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void replaceEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | throws DatabaseException |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | List<Attribute> attrList; |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | |
| | | attrList = oldEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> oldSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, oldSet); |
| | | |
| | | attrList = newEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> newSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, newSet); |
| | | |
| | | HashSet<ASN1OctetString> removeSet = new HashSet<ASN1OctetString>(oldSet); |
| | | removeSet.removeAll(newSet); |
| | | for (ASN1OctetString k : removeSet) |
| | | if(newAttributes == null) |
| | | { |
| | | delKeys.add(k); |
| | | indexAttribute(oldAttributes, delKeys); |
| | | } |
| | | |
| | | HashSet<ASN1OctetString> addSet = new HashSet<ASN1OctetString>(newSet); |
| | | addSet.removeAll(oldSet); |
| | | for (ASN1OctetString k : addSet) |
| | | else |
| | | { |
| | | addKeys.add(k); |
| | | if(oldAttributes == null) |
| | | { |
| | | indexAttribute(newAttributes, addKeys); |
| | | } |
| | | else |
| | | { |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | | addKeys.addAll(newKeys); |
| | | addKeys.removeAll(oldKeys); |
| | | |
| | | delKeys.addAll(oldKeys); |
| | | delKeys.removeAll(newKeys); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | throws DatabaseException |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | HashSet<AttributeValue> newValues; |
| | | HashSet<AttributeValue> oldValues; |
| | | |
| | | if(newAttributes == null) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | newValues = new HashSet<AttributeValue>(); |
| | | oldValues = new HashSet<AttributeValue>(); |
| | | for(Attribute a : newAttributes) |
| | | { |
| | | newValues.addAll(a.getValues()); |
| | | } |
| | | for(Attribute a : oldAttributes) |
| | | { |
| | | oldValues.addAll(a.getValues()); |
| | | } |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | | HashSet<AttributeValue> valuesToAdd = |
| | | new HashSet<AttributeValue>(newValues); |
| | | HashSet<AttributeValue> valuesToDel = |
| | | new HashSet<AttributeValue>(oldValues); |
| | | valuesToAdd.removeAll(oldValues); |
| | | valuesToDel.removeAll(newValues); |
| | | addKeys.addAll(newKeys); |
| | | addKeys.removeAll(oldKeys); |
| | | |
| | | indexValues(valuesToDel, delKeys); |
| | | indexValues(valuesToAdd, addKeys); |
| | | delKeys.addAll(oldKeys); |
| | | delKeys.removeAll(newKeys); |
| | | } |
| | | } |
| | | } |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexValues(Set<AttributeValue> values, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (values == null) return; |
| | | |
| | |
| | | { |
| | | byte[] keyBytes = value.getNormalizedValue().value(); |
| | | |
| | | keys.add(new ASN1OctetString(keyBytes)); |
| | | keys.add(keyBytes); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexAttribute(List<Attribute> attrList, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (attrList == null) return; |
| | | |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> addKeys) |
| | | Set<byte[]> addKeys) |
| | | throws DatabaseException |
| | | { |
| | | // The superior entry IDs are in the entry attachment. |
| | |
| | | if (iter.hasNext()) |
| | | { |
| | | DatabaseEntry nodeIDData = ((EntryID)iter.next()).getDatabaseEntry(); |
| | | addKeys.add(new ASN1OctetString(nodeIDData.getData())); |
| | | addKeys.add(nodeIDData.getData()); |
| | | } |
| | | } |
| | | |
| | |
| | | * @param delKeys The set into which the keys to be deleted will be inserted. |
| | | */ |
| | | public void replaceEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | { |
| | | // Nothing to do. |
| | | } |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | // Nothing to do. |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> addKeys) |
| | | Set<byte[]> addKeys) |
| | | throws DatabaseException |
| | | { |
| | | // The superior entry IDs are in the entry attachment. |
| | |
| | | while (iter.hasNext()) |
| | | { |
| | | DatabaseEntry nodeIDData = ((EntryID)iter.next()).getDatabaseEntry(); |
| | | addKeys.add(new ASN1OctetString(nodeIDData.getData())); |
| | | addKeys.add(nodeIDData.getData()); |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public void replaceEntry(Transaction txn, |
| | | Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | // Nothing to do. |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | // Nothing to do. |
| | |
| | | |
| | | import com.sleepycat.je.*; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.StaticUtils; |
| | | import static org.opends.messages.JebMessages.*; |
| | |
| | | */ |
| | | private int entryLimitExceededCount; |
| | | |
| | | /** |
| | | * The max number of tries to rewrite phantom records. |
| | | */ |
| | | final int phantomWriteRetires = 3; |
| | | |
| | | /** |
| | | * Whether to maintain a count of IDs for a key once the entry limit |
| | | * has exceeded. |
| | | */ |
| | | boolean maintainCount; |
| | | |
| | | private State state; |
| | | |
| | | /** |
| | |
| | | * @param indexEntryLimit The configured limit on the number of entry IDs |
| | | * that may be indexed by one key. |
| | | * @param cursorEntryLimit The configured limit on the number of entry IDs |
| | | * @param maintainCount Whether to maintain a count of IDs for a key once |
| | | * the entry limit has exceeded. |
| | | * @param env The JE Environemnt |
| | | * @param entryContainer The database entryContainer holding this index. |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public Index(String name, Indexer indexer, State state, |
| | | int indexEntryLimit, int cursorEntryLimit, Environment env, |
| | | EntryContainer entryContainer) |
| | | int indexEntryLimit, int cursorEntryLimit, boolean maintainCount, |
| | | Environment env, EntryContainer entryContainer) |
| | | throws DatabaseException |
| | | { |
| | | super(name, env, entryContainer); |
| | |
| | | this.comparator = indexer.getComparator(); |
| | | this.indexEntryLimit = indexEntryLimit; |
| | | this.cursorEntryLimit = cursorEntryLimit; |
| | | this.maintainCount = maintainCount; |
| | | |
| | | DatabaseConfig dbNodupsConfig = new DatabaseConfig(); |
| | | |
| | |
| | | throws DatabaseException |
| | | { |
| | | OperationStatus status; |
| | | LockMode lockMode = LockMode.RMW; |
| | | DatabaseEntry entryIDData = entryID.getDatabaseEntry(); |
| | | DatabaseEntry data = new DatabaseEntry(); |
| | | boolean success = true; |
| | | boolean done = false; |
| | | boolean success = false; |
| | | |
| | | while(!done) |
| | | if(maintainCount) |
| | | { |
| | | status = read(txn, key, data, lockMode); |
| | | |
| | | if (status == OperationStatus.SUCCESS) |
| | | for(int i = 0; i < phantomWriteRetires; i++) |
| | | { |
| | | if(insertIDWithRMW(txn, key, data, entryIDData, entryID) == |
| | | OperationStatus.SUCCESS) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | status = read(txn, key, data, LockMode.READ_COMMITTED); |
| | | if(status == OperationStatus.SUCCESS) |
| | | { |
| | | EntryIDSet entryIDList = |
| | | new EntryIDSet(key.getData(), data.getData()); |
| | | |
| | | if (entryIDList.isDefined()) |
| | | { |
| | | if (indexEntryLimit > 0 && entryIDList.size() >= indexEntryLimit) |
| | | for(int i = 0; i < phantomWriteRetires; i++) |
| | | { |
| | | entryIDList = new EntryIDSet(entryIDList.size()); |
| | | entryLimitExceededCount++; |
| | | |
| | | if(debugEnabled()) |
| | | if(insertIDWithRMW(txn, key, data, entryIDData, entryID) == |
| | | OperationStatus.SUCCESS) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | StaticUtils.byteArrayToHexPlusAscii(builder, key.getData(), 4); |
| | | TRACER.debugInfo("Index entry exceeded in index %s. " + |
| | | "Limit: %d. ID list size: %d.\nKey:", |
| | | name, indexEntryLimit, entryIDList.size(), |
| | | builder); |
| | | |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | |
| | | success = entryIDList.add(entryID); |
| | | |
| | | byte[] after = entryIDList.toDatabase(); |
| | | data.setData(after); |
| | | put(txn, key, data); |
| | | done = true; |
| | | } |
| | | else |
| | | { |
| | | if(rebuildRunning || trusted) |
| | | { |
| | | status = insert(txn, key, entryIDData); |
| | | if(status == OperationStatus.SUCCESS) |
| | | if(status == OperationStatus.KEYEXIST) |
| | | { |
| | | done = true; |
| | | for(int i = 1; i < phantomWriteRetires; i++) |
| | | { |
| | | if(insertIDWithRMW(txn, key, data, entryIDData, entryID) == |
| | | OperationStatus.SUCCESS) |
| | | { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | else |
| | | { |
| | | done = true; |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | |
| | | return success; |
| | | } |
| | | |
| | | private OperationStatus insertIDWithRMW(Transaction txn, DatabaseEntry key, |
| | | DatabaseEntry data, |
| | | DatabaseEntry entryIDData, |
| | | EntryID entryID) |
| | | throws DatabaseException |
| | | { |
| | | OperationStatus status; |
| | | |
| | | status = read(txn, key, data, LockMode.RMW); |
| | | if(status == OperationStatus.SUCCESS) |
| | | { |
| | | EntryIDSet entryIDList = |
| | | new EntryIDSet(key.getData(), data.getData()); |
| | | if (entryIDList.isDefined() && indexEntryLimit > 0 && |
| | | entryIDList.size() >= indexEntryLimit) |
| | | { |
| | | if(maintainCount) |
| | | { |
| | | entryIDList = new EntryIDSet(entryIDList.size()); |
| | | } |
| | | else |
| | | { |
| | | entryIDList = new EntryIDSet(); |
| | | } |
| | | entryLimitExceededCount++; |
| | | |
| | | if(debugEnabled()) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | StaticUtils.byteArrayToHexPlusAscii(builder, key.getData(), 4); |
| | | TRACER.debugInfo("Index entry exceeded in index %s. " + |
| | | "Limit: %d. ID list size: %d.\nKey:", |
| | | name, indexEntryLimit, entryIDList.size(), |
| | | builder); |
| | | |
| | | } |
| | | } |
| | | |
| | | entryIDList.add(entryID); |
| | | |
| | | byte[] after = entryIDList.toDatabase(); |
| | | data.setData(after); |
| | | return put(txn, key, data); |
| | | } |
| | | else |
| | | { |
| | | if(rebuildRunning || trusted) |
| | | { |
| | | return insert(txn, key, entryIDData); |
| | | } |
| | | else |
| | | { |
| | | return OperationStatus.SUCCESS; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Remove an entry ID from the set of IDs indexed by a given key. |
| | | * |
| | |
| | | throws DatabaseException |
| | | { |
| | | OperationStatus status; |
| | | LockMode lockMode = LockMode.RMW; |
| | | DatabaseEntry data = new DatabaseEntry(); |
| | | |
| | | status = read(txn, key, data, lockMode); |
| | | if(maintainCount) |
| | | { |
| | | removeIDWithRMW(txn, key, data, entryID); |
| | | } |
| | | else |
| | | { |
| | | status = read(txn, key, data, LockMode.READ_COMMITTED); |
| | | if(status == OperationStatus.SUCCESS) |
| | | { |
| | | EntryIDSet entryIDList = new EntryIDSet(key.getData(), data.getData()); |
| | | if(entryIDList.isDefined()) |
| | | { |
| | | removeIDWithRMW(txn, key, data, entryID); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | // Ignore failures if rebuild is running since a empty entryIDset |
| | | // will probably not be rebuilt. |
| | | if(trusted && !rebuildRunning) |
| | | { |
| | | setTrusted(txn, false); |
| | | |
| | | if(debugEnabled()) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | StaticUtils.byteArrayToHexPlusAscii(builder, key.getData(), 4); |
| | | TRACER.debugError("The expected key does not exist in the " + |
| | | "index %s.\nKey:%s", name, builder.toString()); |
| | | } |
| | | |
| | | logError(ERR_JEB_INDEX_CORRUPT_REQUIRES_REBUILD.get(name)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void removeIDWithRMW(Transaction txn, DatabaseEntry key, |
| | | DatabaseEntry data, EntryID entryID) |
| | | throws DatabaseException |
| | | { |
| | | OperationStatus status; |
| | | status = read(txn, key, data, LockMode.RMW); |
| | | |
| | | if (status == OperationStatus.SUCCESS) |
| | | { |
| | |
| | | { |
| | | setTrusted(txn, false); |
| | | |
| | | |
| | | |
| | | if(debugEnabled()) |
| | | { |
| | | StringBuilder builder = new StringBuilder(); |
| | | StaticUtils.byteArrayToHexPlusAscii(builder, key.getData(), 4); |
| | | TRACER.debugError("The expected entry ID does not exist in " + |
| | | "the entry ID list for index %s.\nKey:%s", |
| | | name, builder.toString()); |
| | | name, builder.toString()); |
| | | } |
| | | |
| | | logError(ERR_JEB_INDEX_CORRUPT_REQUIRES_REBUILD.get(name)); |
| | |
| | | public boolean addEntry(Transaction txn, EntryID entryID, Entry entry) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | HashSet<ASN1OctetString> addKeys = new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> addKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | boolean success = true; |
| | | |
| | | indexer.indexEntry(txn, entry, addKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) |
| | | for (byte[] keyBytes : addKeys) |
| | | { |
| | | key.setData(keyBytes.value()); |
| | | key.setData(keyBytes); |
| | | if(!insertID(txn, key, entryID)) |
| | | { |
| | | success = false; |
| | |
| | | public void removeEntry(Transaction txn, EntryID entryID, Entry entry) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | HashSet<ASN1OctetString> delKeys = new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> delKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | |
| | | indexer.indexEntry(txn, entry, delKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : delKeys) |
| | | for (byte[] keyBytes : delKeys) |
| | | { |
| | | key.setData(keyBytes.value()); |
| | | key.setData(keyBytes); |
| | | removeID(txn, key, entryID); |
| | | } |
| | | } |
| | |
| | | List<Modification> mods) |
| | | throws DatabaseException |
| | | { |
| | | HashSet<ASN1OctetString> addKeys = new HashSet<ASN1OctetString>(); |
| | | HashSet<ASN1OctetString> delKeys = new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> addKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | TreeSet<byte[]> delKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | |
| | | indexer.modifyEntry(txn, oldEntry, newEntry, mods, addKeys, delKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : delKeys) |
| | | for (byte[] keyBytes : delKeys) |
| | | { |
| | | key.setData(keyBytes.value()); |
| | | key.setData(keyBytes); |
| | | removeID(txn, key, entryID); |
| | | } |
| | | |
| | | for (ASN1OctetString keyBytes : addKeys) |
| | | for (byte[] keyBytes : addKeys) |
| | | { |
| | | key.setData(keyBytes.value()); |
| | | key.setData(keyBytes); |
| | | insertID(txn, key, entryID); |
| | | } |
| | | } |
| | |
| | | { |
| | | this.rebuildRunning = rebuildRunning; |
| | | } |
| | | |
| | | /** |
| | | * Whether this index maintains a count of IDs for keys once the |
| | | * entry limit has exceeded. |
| | | * @return <code>true</code> if this index maintains court of IDs |
| | | * or <code>false</code> otherwise |
| | | */ |
| | | public boolean getMaintainCount() |
| | | { |
| | | return maintainCount; |
| | | } |
| | | } |
| | |
| | | if (merged.size() > entryLimit) |
| | | { |
| | | index.incEntryLimitExceededCount(); |
| | | byte[] undefinedSizeBytes = |
| | | JebFormat.entryIDUndefinedSizeToDatabase(merged.size()); |
| | | dbData.setData(undefinedSizeBytes); |
| | | index.put(txn, dbKey, dbData); |
| | | if(index.getMaintainCount()) |
| | | { |
| | | byte[] undefinedSizeBytes = |
| | | JebFormat.entryIDUndefinedSizeToDatabase(merged.size()); |
| | | dbData.setData(undefinedSizeBytes); |
| | | index.put(txn, dbKey, dbData); |
| | | } |
| | | else |
| | | { |
| | | index.writeKey(txn, dbKey, new EntryIDSet()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | import com.sleepycat.je.DatabaseException; |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public abstract void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | throws DatabaseException; |
| | | |
| | | /** |
| | |
| | | */ |
| | | public abstract void replaceEntry(Transaction txn, |
| | | Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException; |
| | | |
| | | /** |
| | |
| | | public abstract void modifyEntry(Transaction txn, |
| | | Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException; |
| | | } |
| | |
| | | import org.opends.server.types.DebugLogLevel; |
| | | |
| | | import org.opends.server.api.OrderingMatchingRule; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.AttributeValue; |
| | |
| | | * @param keys The set into which the generated keys will be inserted. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | */ |
| | | public void replaceEntry(Transaction txn, |
| | | Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | { |
| | | List<Attribute> attrList; |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | |
| | | attrList = oldEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> oldSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, oldSet); |
| | | |
| | | attrList = newEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> newSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, newSet); |
| | | |
| | | HashSet<ASN1OctetString> removeSet = new HashSet<ASN1OctetString>(oldSet); |
| | | removeSet.removeAll(newSet); |
| | | for (ASN1OctetString k : removeSet) |
| | | if(newAttributes == null) |
| | | { |
| | | delKeys.add(k); |
| | | indexAttribute(oldAttributes, delKeys); |
| | | } |
| | | |
| | | HashSet<ASN1OctetString> addSet = new HashSet<ASN1OctetString>(newSet); |
| | | addSet.removeAll(oldSet); |
| | | for (ASN1OctetString k : addSet) |
| | | else |
| | | { |
| | | addKeys.add(k); |
| | | if(oldAttributes == null) |
| | | { |
| | | indexAttribute(newAttributes, addKeys); |
| | | } |
| | | else |
| | | { |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(orderingRule); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(orderingRule); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | | addKeys.addAll(newKeys); |
| | | addKeys.removeAll(oldKeys); |
| | | |
| | | delKeys.addAll(oldKeys); |
| | | delKeys.removeAll(newKeys); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | throws DatabaseException |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | HashSet<AttributeValue> newValues; |
| | | HashSet<AttributeValue> oldValues; |
| | | |
| | | if(newAttributes == null) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | newValues = new HashSet<AttributeValue>(); |
| | | oldValues = new HashSet<AttributeValue>(); |
| | | for(Attribute a : newAttributes) |
| | | { |
| | | newValues.addAll(a.getValues()); |
| | | } |
| | | for(Attribute a : oldAttributes) |
| | | { |
| | | oldValues.addAll(a.getValues()); |
| | | } |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(orderingRule); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(orderingRule); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | | HashSet<AttributeValue> valuesToAdd = |
| | | new HashSet<AttributeValue>(newValues); |
| | | HashSet<AttributeValue> valuesToDel = |
| | | new HashSet<AttributeValue>(oldValues); |
| | | valuesToAdd.removeAll(oldValues); |
| | | valuesToDel.removeAll(newValues); |
| | | addKeys.addAll(newKeys); |
| | | addKeys.removeAll(oldKeys); |
| | | |
| | | indexValues(valuesToDel, delKeys); |
| | | indexValues(valuesToAdd, addKeys); |
| | | delKeys.addAll(oldKeys); |
| | | delKeys.removeAll(newKeys); |
| | | } |
| | | } |
| | | } |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexValues(Set<AttributeValue> values, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (values == null) return; |
| | | |
| | |
| | | byte[] keyBytes = |
| | | orderingRule.normalizeValue(value.getValue()).value(); |
| | | |
| | | keys.add(new ASN1OctetString(keyBytes)); |
| | | keys.add(keyBytes); |
| | | } |
| | | catch (DirectoryException e) |
| | | { |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexAttribute(List<Attribute> attrList, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (attrList == null) return; |
| | | |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> keys) throws DatabaseException |
| | | Set<byte[]> keys) throws DatabaseException |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | { |
| | | if (!attrList.isEmpty()) |
| | | { |
| | | keys.add(new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | keys.add(AttributeIndex.presenceKey.getData()); |
| | | } |
| | | } |
| | | } |
| | |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | | public void replaceEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | throws DatabaseException |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | List<Attribute> beforeList, afterList; |
| | | |
| | | beforeList = oldEntry.getAttribute(attributeType); |
| | | afterList = newEntry.getAttribute(attributeType); |
| | | |
| | | if (beforeList == null || beforeList.isEmpty()) |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | if(oldAttributes == null) |
| | | { |
| | | if (afterList != null && !afterList.isEmpty()) |
| | | if(newAttributes != null) |
| | | { |
| | | addKeys.add(new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | addKeys.add(AttributeIndex.presenceKey.getData()); |
| | | } |
| | | } |
| | | else if (afterList == null || afterList.isEmpty()) |
| | | else |
| | | { |
| | | delKeys.add(new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | if(newAttributes == null) |
| | | { |
| | | delKeys.add(AttributeIndex.presenceKey.getData()); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | throws DatabaseException |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | |
| | | { |
| | | if(newAttributes != null) |
| | | { |
| | | addKeys.add( |
| | | new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | addKeys.add(AttributeIndex.presenceKey.getData()); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if(newAttributes == null) |
| | | { |
| | | delKeys.add( |
| | | new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | delKeys.add(AttributeIndex.presenceKey.getData()); |
| | | } |
| | | } |
| | | } |
| | |
| | | import static org.opends.server.loggers.debug.DebugLogger.*; |
| | | import org.opends.server.loggers.debug.DebugTracer; |
| | | import com.sleepycat.je.Transaction; |
| | | import org.opends.server.protocols.asn1.ASN1OctetString; |
| | | import org.opends.server.types.*; |
| | | |
| | | import java.util.Comparator; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * An implementation of an Indexer for attribute substrings. |
| | |
| | | * @param keys The set into which the generated keys will be inserted. |
| | | */ |
| | | public void indexEntry(Transaction txn, Entry entry, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | */ |
| | | public void replaceEntry(Transaction txn, |
| | | Entry oldEntry, Entry newEntry, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | { |
| | | List<Attribute> attrList; |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | |
| | | attrList = oldEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> oldSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, oldSet); |
| | | |
| | | attrList = newEntry.getAttribute(attributeType); |
| | | Set<ASN1OctetString> newSet = new HashSet<ASN1OctetString>(); |
| | | indexAttribute(attrList, newSet); |
| | | |
| | | HashSet<ASN1OctetString> removeSet = new HashSet<ASN1OctetString>(oldSet); |
| | | removeSet.removeAll(newSet); |
| | | for (ASN1OctetString k : removeSet) |
| | | if(newAttributes == null) |
| | | { |
| | | delKeys.add(k); |
| | | indexAttribute(oldAttributes, delKeys); |
| | | } |
| | | |
| | | HashSet<ASN1OctetString> addSet = new HashSet<ASN1OctetString>(newSet); |
| | | addSet.removeAll(oldSet); |
| | | for (ASN1OctetString k : addSet) |
| | | else |
| | | { |
| | | addKeys.add(k); |
| | | if(oldAttributes == null) |
| | | { |
| | | indexAttribute(newAttributes, addKeys); |
| | | } |
| | | else |
| | | { |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | | addKeys.addAll(newKeys); |
| | | addKeys.removeAll(oldKeys); |
| | | |
| | | delKeys.addAll(oldKeys); |
| | | delKeys.removeAll(newKeys); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | */ |
| | | public void modifyEntry(Transaction txn, Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Set<ASN1OctetString> addKeys, |
| | | Set<ASN1OctetString> delKeys) |
| | | Set<byte[]> addKeys, |
| | | Set<byte[]> delKeys) |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | | HashSet<AttributeValue> newValues; |
| | | HashSet<AttributeValue> oldValues; |
| | | |
| | | if(newAttributes == null) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | HashSet<ASN1OctetString> newKeys = |
| | | new HashSet<ASN1OctetString>(); |
| | | HashSet<ASN1OctetString> oldKeys = |
| | | new HashSet<ASN1OctetString>(); |
| | | TreeSet<byte[]> newKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | TreeSet<byte[]> oldKeys = |
| | | new TreeSet<byte[]>(comparator); |
| | | indexAttribute(newAttributes, newKeys); |
| | | indexAttribute(oldAttributes, oldKeys); |
| | | |
| | |
| | | * @param keys The set into which the generated keys will be inserted. |
| | | */ |
| | | private void indexAttribute(List<Attribute> attrList, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (attrList == null) return; |
| | | |
| | |
| | | * @param keys The set into which the keys will be inserted. |
| | | */ |
| | | private void indexValues(Set<AttributeValue> values, |
| | | Set<ASN1OctetString> keys) |
| | | Set<byte[]> keys) |
| | | { |
| | | if (values == null) return; |
| | | |
| | |
| | | * @param value A byte array containing the normalized attribute value |
| | | * @param set A set into which the keys will be inserted. |
| | | */ |
| | | private void substringKeys(byte[] value, Set<ASN1OctetString> set) |
| | | private void substringKeys(byte[] value, Set<byte[]> set) |
| | | { |
| | | byte[] keyBytes; |
| | | |
| | |
| | | { |
| | | int len = Math.min(substrLength, remain); |
| | | keyBytes = makeSubstringKey(value, i, len); |
| | | set.add(new ASN1OctetString(keyBytes)); |
| | | set.add(keyBytes); |
| | | } |
| | | } |
| | | |
| | |
| | | EntryID entryID; |
| | | AttributeType attribute; |
| | | AttributeIndex index; |
| | | HashSet<ASN1OctetString> addKeys; |
| | | HashSet<byte[]> addKeys; |
| | | DatabaseEntry key; |
| | | PresenceIndexer presenceIndexer; |
| | | EqualityIndexer equalityIndexer; |
| | |
| | | index = ec.getAttributeIndex(attribute); |
| | | |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | presenceIndexer = new PresenceIndexer(index.getAttributeType()); |
| | | presenceIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.presenceIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | equalityIndexer = new EqualityIndexer(index.getAttributeType()); |
| | | equalityIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.equalityIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | substringIndexer = new SubstringIndexer(index.getAttributeType(), |
| | | index.getConfiguration().getSubstringLength()); |
| | | substringIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.substringIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | orderingIndexer = new OrderingIndexer(index.getAttributeType()); |
| | | orderingIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.orderingIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | |
| | | EntryID entryID; |
| | | AttributeType attribute; |
| | | AttributeIndex index; |
| | | HashSet<ASN1OctetString> addKeys; |
| | | HashSet<byte[]> addKeys; |
| | | DatabaseEntry key; |
| | | EqualityIndexer equalityIndexer; |
| | | SubstringIndexer substringIndexer; |
| | |
| | | attribute = entry.getAttribute("cn").get(0).getAttributeType(); |
| | | index = ec.getAttributeIndex(attribute); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | orderingIndexer = new OrderingIndexer(index.getAttributeType()); |
| | | orderingIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.orderingIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | orderingIndexer.indexEntry(null, oldEntry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.orderingIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | substringIndexer = new SubstringIndexer(index.getAttributeType(), |
| | | index.getConfiguration().getSubstringLength()); |
| | | substringIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.substringIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | substringIndexer.indexEntry(null, oldEntry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.substringIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | equalityIndexer = new EqualityIndexer(index.getAttributeType()); |
| | | equalityIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.equalityIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | equalityIndexer.indexEntry(null, oldEntry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(index.equalityIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | |
| | | AttributeType attribute; |
| | | AttributeIndex titleIndex; |
| | | AttributeIndex nameIndex; |
| | | HashSet<ASN1OctetString> addKeys; |
| | | HashSet<byte[]> addKeys; |
| | | DatabaseEntry key; |
| | | PresenceIndexer presenceIndexer; |
| | | EqualityIndexer equalityIndexer; |
| | |
| | | nameIndex = ec.getAttributeIndex(attribute); |
| | | |
| | | //This current entry in the DB shouldn't be in the presence titleIndex. |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys.add(new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | addKeys = new HashSet<byte[]>(); |
| | | addKeys.add(AttributeIndex.presenceKey.getData()); |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(titleIndex.presenceIndex.containsID(null, key, entryID), |
| | | ConditionResult.FALSE); |
| | | |
| | | //This current entry should be in the presence nameIndex. |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys.add(new ASN1OctetString(AttributeIndex.presenceKey.getData())); |
| | | addKeys = new HashSet<byte[]>(); |
| | | addKeys.add(AttributeIndex.presenceKey.getData()); |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | } |
| | | assertEquals(nameIndex.presenceIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | |
| | | assertFalse(entry.getAttribute("employeenumber").contains(new |
| | | Attribute("employeenumber", "1"))); |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | presenceIndexer = new PresenceIndexer(titleIndex.getAttributeType()); |
| | | presenceIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(titleIndex.presenceIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | presenceIndexer = new PresenceIndexer(nameIndex.getAttributeType()); |
| | | presenceIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(nameIndex.presenceIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | orderingIndexer = new OrderingIndexer(titleIndex.getAttributeType()); |
| | | orderingIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(titleIndex.orderingIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | orderingIndexer = new OrderingIndexer(nameIndex.getAttributeType()); |
| | | orderingIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(nameIndex.orderingIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | equalityIndexer = new EqualityIndexer(titleIndex.getAttributeType()); |
| | | equalityIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(titleIndex.equalityIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | equalityIndexer = new EqualityIndexer(nameIndex.getAttributeType()); |
| | | equalityIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(nameIndex.equalityIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | substringIndexer = new SubstringIndexer(titleIndex.getAttributeType(), |
| | | titleIndex.getConfiguration().getSubstringLength()); |
| | | substringIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(titleIndex.substringIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |
| | | |
| | | addKeys = new HashSet<ASN1OctetString>(); |
| | | addKeys = new HashSet<byte[]>(); |
| | | substringIndexer = new SubstringIndexer(nameIndex.getAttributeType(), |
| | | nameIndex.getConfiguration().getSubstringLength()); |
| | | substringIndexer.indexEntry(null, entry, addKeys); |
| | | |
| | | key = new DatabaseEntry(); |
| | | for (ASN1OctetString keyBytes : addKeys) { |
| | | key.setData(keyBytes.value()); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | assertEquals(nameIndex.substringIndex.containsID(null, key, entryID), |
| | | ConditionResult.TRUE); |
| | | } |