| | |
| | | } |
| | | |
| | | /** |
| | | * Byte string key comparator. The default lexicographic byte string |
| | | * comparator. |
| | | * <p> |
| | | * This is the byte string equivalent of {@link KeyComparator}. |
| | | * <p> |
| | | * Note: Matt reckons we could simply use ByteString.compareTo(), |
| | | * but I am using this for now as an intermediate step. |
| | | */ |
| | | public static class BSKeyComparator implements Comparator<ByteString> |
| | | { |
| | | /** |
| | | * Compares its two arguments for order. Returns a negative integer, zero, |
| | | * or a positive integer as the first argument is less than, equal to, or |
| | | * greater than the second. |
| | | * |
| | | * @param a |
| | | * the first object to be compared. |
| | | * @param b |
| | | * the second object to be compared. |
| | | * @return a negative integer, zero, or a positive integer as the first |
| | | * argument is less than, equal to, or greater than the second. |
| | | */ |
| | | @Override |
| | | public int compare(ByteString a, ByteString b) |
| | | { |
| | | int i; |
| | | for (i = 0; i < a.length() && i < b.length(); i++) |
| | | { |
| | | if (a.byteAt(i) > b.byteAt(i)) |
| | | { |
| | | return 1; |
| | | } |
| | | else if (a.byteAt(i) < b.byteAt(i)) |
| | | { |
| | | return -1; |
| | | } |
| | | } |
| | | if (a.length() == b.length()) |
| | | { |
| | | return 0; |
| | | } |
| | | if (a.length() > b.length()) |
| | | { |
| | | return 1; |
| | | } |
| | | else |
| | | { |
| | | return -1; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieve the entry IDs that might match an approximate filter. |
| | | * |
| | | * @param approximateFilter The approximate filter. |
| | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | import org.opends.server.admin.server.ConfigurationAddListener; |
| | | import org.opends.server.admin.server.ConfigurationChangeListener; |
| | |
| | | import org.opends.server.api.ClientConnection; |
| | | import org.opends.server.api.EntryCache; |
| | | import org.opends.server.api.plugin.PluginResult; |
| | | import org.forgerock.opendj.config.server.ConfigException; |
| | | import org.opends.server.controls.*; |
| | | import org.opends.server.core.*; |
| | | import org.opends.server.protocols.ldap.LDAPResultCode; |
| | | import org.opends.server.types.*; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.opends.server.util.ServerConstants; |
| | | import org.opends.server.util.StaticUtils; |
| | | |
| | |
| | | // Remove the id2c and id2s records for this entry. |
| | | if(indexBuffer != null) |
| | | { |
| | | byte[] leafIDKeyBytes = |
| | | JebFormat.entryIDToDatabase(leafID.longValue()); |
| | | ByteString leafIDKeyBytes = ByteString.valueOf(leafID.longValue()); |
| | | id2children.delete(indexBuffer, leafIDKeyBytes); |
| | | id2subtree.delete(indexBuffer, leafIDKeyBytes); |
| | | } |
| | |
| | | |
| | | if(indexBuffer != null) |
| | | { |
| | | byte[] parentIDBytes = |
| | | JebFormat.entryIDToDatabase(parentID.longValue()); |
| | | ByteString parentIDBytes = ByteString.valueOf(parentID.longValue()); |
| | | // Remove from id2children. |
| | | if (isParent) |
| | | { |
| | |
| | | // Add the new ID to id2children and id2subtree of new apex parent entry. |
| | | if(isApexEntryMoved) |
| | | { |
| | | EntryID parentID; |
| | | byte[] parentIDKeyBytes; |
| | | boolean isParent = true; |
| | | for (DN dn = getParentWithinBase(newEntry.getName()); dn != null; |
| | | dn = getParentWithinBase(dn)) |
| | | { |
| | | parentID = dn2id.get(txn, dn, LockMode.DEFAULT); |
| | | parentIDKeyBytes = |
| | | JebFormat.entryIDToDatabase(parentID.longValue()); |
| | | EntryID parentID = dn2id.get(txn, dn, LockMode.DEFAULT); |
| | | ByteString parentIDKeyBytes = ByteString.valueOf(parentID.longValue()); |
| | | if(isParent) |
| | | { |
| | | id2children.insertID(buffer, parentIDKeyBytes, newID); |
| | |
| | | // the old apex parent entry. |
| | | if(oldSuperiorDN != null && isApexEntryMoved) |
| | | { |
| | | EntryID parentID; |
| | | byte[] parentIDKeyBytes; |
| | | boolean isParent = true; |
| | | for (DN dn = oldSuperiorDN; dn != null; dn = getParentWithinBase(dn)) |
| | | { |
| | | parentID = dn2id.get(txn, dn, LockMode.DEFAULT); |
| | | parentIDKeyBytes = |
| | | JebFormat.entryIDToDatabase(parentID.longValue()); |
| | | EntryID parentID = dn2id.get(txn, dn, LockMode.DEFAULT); |
| | | ByteString parentIDKeyBytes = ByteString.valueOf(parentID.longValue()); |
| | | if(isParent) |
| | | { |
| | | id2children.removeID(buffer, parentIDKeyBytes, oldID); |
| | |
| | | { |
| | | // All the subordinates will be renumbered so we have to rebuild |
| | | // id2c and id2s with the new ID. |
| | | byte[] oldIDKeyBytes = JebFormat.entryIDToDatabase(oldID.longValue()); |
| | | ByteString oldIDKeyBytes = ByteString.valueOf(oldID.longValue()); |
| | | id2children.delete(buffer, oldIDKeyBytes); |
| | | id2subtree.delete(buffer, oldIDKeyBytes); |
| | | |
| | |
| | | for (DN dn = oldSuperiorDN; dn != null; dn = getParentWithinBase(dn)) |
| | | { |
| | | EntryID parentID = dn2id.get(txn, dn, LockMode.DEFAULT); |
| | | byte[] parentIDKeyBytes = |
| | | JebFormat.entryIDToDatabase(parentID.longValue()); |
| | | ByteString parentIDKeyBytes = ByteString.valueOf(parentID.longValue()); |
| | | id2subtree.removeID(buffer, parentIDKeyBytes, oldID); |
| | | } |
| | | } |
| | |
| | | { |
| | | // All the subordinates will be renumbered so we have to rebuild |
| | | // id2c and id2s with the new ID. |
| | | byte[] oldIDKeyBytes = JebFormat.entryIDToDatabase(oldID.longValue()); |
| | | ByteString oldIDKeyBytes = ByteString.valueOf(oldID.longValue()); |
| | | id2children.delete(buffer, oldIDKeyBytes); |
| | | id2subtree.delete(buffer, oldIDKeyBytes); |
| | | |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Iterator; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | |
| | | /** |
| | | * Represents a set of Entry IDs. It can represent a set where the IDs are |
| | |
| | | * The database key containing this set, if the set was constructed |
| | | * directly from the database. |
| | | */ |
| | | private byte[] keyBytes = null; |
| | | private ByteString keyBytes; |
| | | |
| | | /** |
| | | * Create a new undefined set. |
| | |
| | | */ |
| | | public EntryIDSet(byte[] keyBytes, byte[] bytes) |
| | | { |
| | | this(keyBytes != null ? ByteString.wrap(keyBytes) : null, bytes); |
| | | } |
| | | |
| | | /** |
| | | * Create a new entry ID set from the raw database value. |
| | | * |
| | | * @param keyBytes |
| | | * The database key that contains this value. |
| | | * @param bytes |
| | | * The database value, or null if there are no entry IDs. |
| | | */ |
| | | public EntryIDSet(ByteString keyBytes, byte[] bytes) |
| | | { |
| | | this.keyBytes = keyBytes; |
| | | |
| | | if (bytes == null) |
| | |
| | | long[] n1 = new long[n.length]; |
| | | long last = -1; |
| | | int j = 0; |
| | | for (int i = 0; i < n.length; i++) |
| | | for (long l : n) |
| | | { |
| | | if (n[i] != last) |
| | | if (l != last) |
| | | { |
| | | last = n1[j++] = n[i]; |
| | | last = n1[j++] = l; |
| | | } |
| | | } |
| | | if (j == n1.length) |
| | |
| | | * Get a string representation of this object. |
| | | * @return A string representation of this object. |
| | | */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | StringBuilder buffer = new StringBuilder(16); |
| | |
| | | * |
| | | * @return An EntryID iterator. |
| | | */ |
| | | @Override |
| | | public Iterator<EntryID> iterator() |
| | | { |
| | | if (values == null) |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.util.*; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | |
| | | import com.sleepycat.je.DatabaseEntry; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * Implementation of an Indexer for the children index. |
| | | */ |
| | | public class ID2CIndexer extends Indexer |
| | | { |
| | | /** |
| | | * The comparator for keys generated by this class. |
| | | */ |
| | | private static final Comparator<byte[]> comparator = |
| | | new AttributeIndex.KeyComparator(); |
| | | |
| | | /** |
| | | * Create a new indexer for a children index. |
| | | */ |
| | | public ID2CIndexer() |
| | |
| | | * used to name an index created using this object. |
| | | * @return A string representation of this object. |
| | | */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | return "id2children"; |
| | | } |
| | | |
| | | /** |
| | | * Get the comparator that must be used to compare index keys |
| | | * generated by this class. |
| | | * |
| | | * @return A byte array comparator. |
| | | */ |
| | | public Comparator<byte[]> getComparator() |
| | | { |
| | | return comparator; |
| | | } |
| | | |
| | | /** |
| | | * Generate the set of index keys for an entry. |
| | | * |
| | | * @param entry The entry. |
| | | * @param addKeys The set into which the generated keys will be inserted. |
| | | */ |
| | | public void indexEntry(Entry entry, Set<byte[]> addKeys) |
| | | @Override |
| | | public void indexEntry(Entry entry, Set<ByteString> addKeys) |
| | | { |
| | | // The superior entry IDs are in the entry attachment. |
| | | ArrayList ids = (ArrayList)entry.getAttachment(); |
| | | ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment(); |
| | | |
| | | // Skip the entry's own ID. |
| | | Iterator iter = ids.iterator(); |
| | | Iterator<EntryID> iter = ids.iterator(); |
| | | iter.next(); |
| | | |
| | | // Get the parent ID. |
| | | if (iter.hasNext()) |
| | | { |
| | | DatabaseEntry nodeIDData = ((EntryID)iter.next()).getDatabaseEntry(); |
| | | addKeys.add(nodeIDData.getData()); |
| | | DatabaseEntry nodeIDData = iter.next().getDatabaseEntry(); |
| | | addKeys.add(ByteString.wrap(nodeIDData.getData())); |
| | | } |
| | | } |
| | | |
| | |
| | | * @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) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | // Nothing to do. |
| | | } |
| | |
| | | * @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) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | // Nothing to do. |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.util.*; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | |
| | | import com.sleepycat.je.DatabaseEntry; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * Implementation of an Indexer for the subtree index. |
| | | */ |
| | | public class ID2SIndexer extends Indexer |
| | | { |
| | | /** |
| | | * The comparator for keys generated by this class. |
| | | */ |
| | | private static final Comparator<byte[]> comparator = |
| | | new AttributeIndex.KeyComparator(); |
| | | |
| | | /** |
| | | * Create a new indexer for a subtree index. |
| | | */ |
| | | public ID2SIndexer() |
| | |
| | | * used to name an index created using this object. |
| | | * @return A string representation of this object. |
| | | */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | return "id2subtree"; |
| | | } |
| | | |
| | | /** |
| | | * Get the comparator that must be used to compare index keys |
| | | * generated by this class. |
| | | * |
| | | * @return A byte array comparator. |
| | | */ |
| | | public Comparator<byte[]> getComparator() |
| | | { |
| | | return comparator; |
| | | } |
| | | |
| | | /** |
| | | * Generate the set of index keys for an entry. |
| | | * |
| | | * @param entry The entry. |
| | | * @param addKeys The set into which the generated keys will be inserted. |
| | | */ |
| | | public void indexEntry(Entry entry, Set<byte[]> addKeys) |
| | | @Override |
| | | public void indexEntry(Entry entry, Set<ByteString> addKeys) |
| | | { |
| | | // The superior entry IDs are in the entry attachment. |
| | | ArrayList ids = (ArrayList)entry.getAttachment(); |
| | | ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment(); |
| | | |
| | | // Skip the entry's own ID. |
| | | Iterator iter = ids.iterator(); |
| | | Iterator<EntryID> iter = ids.iterator(); |
| | | iter.next(); |
| | | |
| | | // Iterate through the superior IDs. |
| | | while (iter.hasNext()) |
| | | { |
| | | DatabaseEntry nodeIDData = ((EntryID)iter.next()).getDatabaseEntry(); |
| | | addKeys.add(nodeIDData.getData()); |
| | | DatabaseEntry nodeIDData = iter.next().getDatabaseEntry(); |
| | | addKeys.add(ByteString.wrap(nodeIDData.getData())); |
| | | } |
| | | } |
| | | |
| | |
| | | * @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) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | // Nothing to do. |
| | | } |
| | |
| | | * @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) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | // Nothing to do. |
| | | } |
| | |
| | | import java.util.*; |
| | | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.opends.server.backends.jeb.importLDIF.ImportIDSet; |
| | | import org.opends.server.types.DirectoryException; |
| | |
| | | private final Comparator<byte[]> comparator; |
| | | |
| | | /** |
| | | * The comparator for index keys. |
| | | */ |
| | | private final Comparator<ByteString> bsComparator; |
| | | |
| | | /** |
| | | * The limit on the number of entry IDs that may be indexed by one key. |
| | | */ |
| | | private int indexEntryLimit; |
| | |
| | | * A flag to indicate if a rebuild process is running on this index. |
| | | * During the rebuild process, we assume that no entryIDSets are |
| | | * accurate and return an undefined set on all read operations. |
| | | * However all write opeations will succeed. The rebuildRunning |
| | | * flag overrides all behaviours of the trusted flag. |
| | | * However all write operations will succeed. The rebuildRunning |
| | | * flag overrides all behaviors of the trusted flag. |
| | | */ |
| | | private boolean rebuildRunning = false; |
| | | |
| | |
| | | * @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 env The JE Environment |
| | | * @param entryContainer The database entryContainer holding this index. |
| | | * @throws DatabaseException If an error occurs in the JE database. |
| | | */ |
| | |
| | | super(name, env, entryContainer); |
| | | this.indexer = indexer; |
| | | this.comparator = indexer.getComparator(); |
| | | this.bsComparator = indexer.getBSComparator(); |
| | | this.indexEntryLimit = indexEntryLimit; |
| | | this.cursorEntryLimit = cursorEntryLimit; |
| | | this.maintainCount = maintainCount; |
| | |
| | | * count is exceeded. False if it already exists in the entry ID set |
| | | * for the given key. |
| | | */ |
| | | public boolean insertID(IndexBuffer buffer, byte[] keyBytes, |
| | | public boolean insertID(IndexBuffer buffer, ByteString keyBytes, |
| | | EntryID entryID) |
| | | { |
| | | TreeMap<byte[], IndexBuffer.BufferedIndexValues> bufferedOperations = |
| | | TreeMap<ByteString, IndexBuffer.BufferedIndexValues> bufferedOperations = |
| | | buffer.getBufferedIndex(this); |
| | | IndexBuffer.BufferedIndexValues values = null; |
| | | |
| | | if(bufferedOperations == null) |
| | | { |
| | | bufferedOperations = new TreeMap<byte[], |
| | | IndexBuffer.BufferedIndexValues>(comparator); |
| | | bufferedOperations = |
| | | new TreeMap<ByteString, IndexBuffer.BufferedIndexValues>(bsComparator); |
| | | buffer.putBufferedIndex(this, bufferedOperations); |
| | | } |
| | | else |
| | |
| | | public boolean insertID(Transaction txn, DatabaseEntry key, EntryID entryID) |
| | | throws DatabaseException |
| | | { |
| | | OperationStatus status; |
| | | DatabaseEntry entryIDData = entryID.getDatabaseEntry(); |
| | | DatabaseEntry data = new DatabaseEntry(); |
| | | boolean success = false; |
| | | |
| | | if(maintainCount) |
| | | { |
| | |
| | | } |
| | | else |
| | | { |
| | | status = read(txn, key, data, LockMode.READ_COMMITTED); |
| | | final OperationStatus status = read(txn, key, data, LockMode.READ_COMMITTED); |
| | | if(status == OperationStatus.SUCCESS) |
| | | { |
| | | EntryIDSet entryIDList = |
| | |
| | | { |
| | | if(rebuildRunning || trusted) |
| | | { |
| | | status = insert(txn, key, entryIDData); |
| | | if(status == OperationStatus.KEYEXIST) |
| | | if (insert(txn, key, entryIDData) == OperationStatus.KEYEXIST) |
| | | { |
| | | for(int i = 1; i < phantomWriteRetires; i++) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | return success; |
| | | return false; |
| | | } |
| | | |
| | | |
| | |
| | | * count is exceeded. False if it already exists in the entry ID set |
| | | * for the given key. |
| | | */ |
| | | public boolean removeID(IndexBuffer buffer, byte[] keyBytes, |
| | | public boolean removeID(IndexBuffer buffer, ByteString keyBytes, |
| | | EntryID entryID) |
| | | { |
| | | TreeMap<byte[], IndexBuffer.BufferedIndexValues> bufferedOperations = |
| | | TreeMap<ByteString, IndexBuffer.BufferedIndexValues> bufferedOperations = |
| | | buffer.getBufferedIndex(this); |
| | | IndexBuffer.BufferedIndexValues values = null; |
| | | |
| | | if(bufferedOperations == null) |
| | | { |
| | | bufferedOperations = new TreeMap<byte[], |
| | | IndexBuffer.BufferedIndexValues>(comparator); |
| | | bufferedOperations = |
| | | new TreeMap<ByteString, IndexBuffer.BufferedIndexValues>(bsComparator); |
| | | buffer.putBufferedIndex(this, bufferedOperations); |
| | | } |
| | | else |
| | |
| | | * @param buffer The index buffer to use to store the deleted keys |
| | | * @param keyBytes The index key bytes. |
| | | */ |
| | | public void delete(IndexBuffer buffer, byte[] keyBytes) |
| | | public void delete(IndexBuffer buffer, ByteString keyBytes) |
| | | { |
| | | TreeMap<byte[], IndexBuffer.BufferedIndexValues> bufferedOperations = |
| | | TreeMap<ByteString, IndexBuffer.BufferedIndexValues> bufferedOperations = |
| | | buffer.getBufferedIndex(this); |
| | | IndexBuffer.BufferedIndexValues values = null; |
| | | |
| | | if(bufferedOperations == null) |
| | | { |
| | | bufferedOperations = new TreeMap<byte[], |
| | | IndexBuffer.BufferedIndexValues>(comparator); |
| | | bufferedOperations = |
| | | new TreeMap<ByteString, IndexBuffer.BufferedIndexValues>(bsComparator); |
| | | buffer.putBufferedIndex(this, bufferedOperations); |
| | | } |
| | | else |
| | |
| | | public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | HashSet<byte[]> addKeys = new HashSet<byte[]>(); |
| | | boolean success = true; |
| | | |
| | | HashSet<ByteString> addKeys = new HashSet<ByteString>(); |
| | | indexer.indexEntry(entry, addKeys); |
| | | |
| | | for (byte[] keyBytes : addKeys) |
| | | boolean success = true; |
| | | for (ByteString keyBytes : addKeys) |
| | | { |
| | | if(!insertID(buffer, keyBytes, entryID)) |
| | | { |
| | | success = false; |
| | | } |
| | | } |
| | | |
| | | return success; |
| | | } |
| | | |
| | |
| | | public boolean addEntry(Transaction txn, EntryID entryID, Entry entry) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | TreeSet<byte[]> addKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | boolean success = true; |
| | | |
| | | TreeSet<ByteString> addKeys = |
| | | new TreeSet<ByteString>(indexer.getBSComparator()); |
| | | indexer.indexEntry(entry, addKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (byte[] keyBytes : addKeys) |
| | | boolean success = true; |
| | | for (ByteString keyBytes : addKeys) |
| | | { |
| | | key.setData(keyBytes); |
| | | key.setData(keyBytes.toByteArray()); |
| | | if(!insertID(txn, key, entryID)) |
| | | { |
| | | success = false; |
| | | } |
| | | } |
| | | |
| | | return success; |
| | | } |
| | | |
| | |
| | | public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | HashSet<byte[]> delKeys = new HashSet<byte[]>(); |
| | | |
| | | HashSet<ByteString> delKeys = new HashSet<ByteString>(); |
| | | indexer.indexEntry(entry, delKeys); |
| | | |
| | | for (byte[] keyBytes : delKeys) |
| | | for (ByteString keyBytes : delKeys) |
| | | { |
| | | removeID(buffer, keyBytes, entryID); |
| | | } |
| | |
| | | public void removeEntry(Transaction txn, EntryID entryID, Entry entry) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | TreeSet<byte[]> delKeys = new TreeSet<byte[]>(indexer.getComparator()); |
| | | |
| | | TreeSet<ByteString> delKeys = |
| | | new TreeSet<ByteString>(indexer.getBSComparator()); |
| | | indexer.indexEntry(entry, delKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (byte[] keyBytes : delKeys) |
| | | for (ByteString keyBytes : delKeys) |
| | | { |
| | | key.setData(keyBytes); |
| | | key.setData(keyBytes.toByteArray()); |
| | | removeID(txn, key, entryID); |
| | | } |
| | | } |
| | |
| | | List<Modification> mods) |
| | | throws DatabaseException |
| | | { |
| | | TreeMap<byte[], Boolean> modifiedKeys = |
| | | new TreeMap<byte[], Boolean>(indexer.getComparator()); |
| | | |
| | | TreeMap<ByteString, Boolean> modifiedKeys = |
| | | new TreeMap<ByteString, Boolean>(indexer.getBSComparator()); |
| | | indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (Map.Entry<byte[], Boolean> modifiedKey : modifiedKeys.entrySet()) |
| | | for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet()) |
| | | { |
| | | key.setData(modifiedKey.getKey()); |
| | | key.setData(modifiedKey.getKey().toByteArray()); |
| | | if(modifiedKey.getValue()) |
| | | { |
| | | insertID(txn, key, entryID); |
| | |
| | | List<Modification> mods) |
| | | throws DatabaseException |
| | | { |
| | | TreeMap<byte[], Boolean> modifiedKeys = |
| | | new TreeMap<byte[], Boolean>(indexer.getComparator()); |
| | | |
| | | TreeMap<ByteString, Boolean> modifiedKeys = |
| | | new TreeMap<ByteString, Boolean>(indexer.getBSComparator()); |
| | | indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys); |
| | | for (Map.Entry<byte[], Boolean> modifiedKey : modifiedKeys.entrySet()) |
| | | |
| | | for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet()) |
| | | { |
| | | if(modifiedKey.getValue()) |
| | | { |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import com.sleepycat.je.Transaction; |
| | | import com.sleepycat.je.DatabaseException; |
| | | import com.sleepycat.je.DatabaseEntry; |
| | | |
| | | import java.util.*; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.types.DirectoryException; |
| | | |
| | | import com.sleepycat.je.DatabaseEntry; |
| | | import com.sleepycat.je.DatabaseException; |
| | | import com.sleepycat.je.Transaction; |
| | | |
| | | /** |
| | | * A buffered index is used to buffer multiple reads or writes to the |
| | | * same index key into a single read or write. |
| | |
| | | * The buffered records stored as a map from the record key to the |
| | | * buffered value for that key for each index. |
| | | */ |
| | | private LinkedHashMap<Index, |
| | | TreeMap<byte[], BufferedIndexValues>> bufferedIndexes; |
| | | private LinkedHashMap<Index, TreeMap<ByteString, BufferedIndexValues>> bufferedIndexes; |
| | | |
| | | /** |
| | | * The buffered records stored as a set of buffered VLV values |
| | |
| | | /** |
| | | * A simple class representing a pair of added and deleted indexed IDs. |
| | | */ |
| | | public static class BufferedIndexValues { |
| | | static class BufferedIndexValues |
| | | { |
| | | EntryIDSet addedIDs; |
| | | EntryIDSet deletedIDs; |
| | | } |
| | |
| | | /** |
| | | * A simple class representing a pair of added and deleted VLV values. |
| | | */ |
| | | public static class BufferedVLVValues { |
| | | static class BufferedVLVValues |
| | | { |
| | | TreeSet<SortValues> addedValues; |
| | | TreeSet<SortValues> deletedValues; |
| | | } |
| | |
| | | public IndexBuffer(EntryContainer entryContainer) |
| | | { |
| | | bufferedIndexes = |
| | | new LinkedHashMap<Index, TreeMap<byte[], BufferedIndexValues>>(); |
| | | new LinkedHashMap<Index, TreeMap<ByteString, BufferedIndexValues>>(); |
| | | bufferedVLVIndexes = new LinkedHashMap<VLVIndex, BufferedVLVValues>(); |
| | | this.entryContainer = entryContainer; |
| | | } |
| | |
| | | * @return The buffered values or <code>null</code> if there are |
| | | * no buffered values for the specified index. |
| | | */ |
| | | public TreeMap<byte[], BufferedIndexValues> getBufferedIndex(Index index) |
| | | public TreeMap<ByteString, BufferedIndexValues> getBufferedIndex(Index index) |
| | | { |
| | | return bufferedIndexes.get(index); |
| | | } |
| | |
| | | * @param index The index affected by the buffered values. |
| | | * @param bufferedValues The buffered values for the index. |
| | | */ |
| | | public void putBufferedIndex(Index index, TreeMap<byte[], |
| | | BufferedIndexValues> bufferedValues) |
| | | public void putBufferedIndex(Index index, |
| | | TreeMap<ByteString, BufferedIndexValues> bufferedValues) |
| | | { |
| | | bufferedIndexes.put(index, bufferedValues); |
| | | } |
| | |
| | | public void flush(Transaction txn) |
| | | throws DatabaseException, DirectoryException |
| | | { |
| | | TreeMap<byte[], BufferedIndexValues> bufferedValues; |
| | | BufferedVLVValues bufferedVLVValues; |
| | | byte[] keyBytes; |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | |
| | | for(AttributeIndex attributeIndex : |
| | |
| | | { |
| | | for(Index index : attributeIndex.getAllIndexes()) |
| | | { |
| | | bufferedValues = bufferedIndexes.remove(index); |
| | | TreeMap<ByteString, BufferedIndexValues> bufferedValues = |
| | | bufferedIndexes.remove(index); |
| | | |
| | | if(bufferedValues != null) |
| | | { |
| | | Iterator<Map.Entry<byte[], BufferedIndexValues>> keyIterator = |
| | | Iterator<Map.Entry<ByteString, BufferedIndexValues>> keyIterator = |
| | | bufferedValues.entrySet().iterator(); |
| | | while(keyIterator.hasNext()) |
| | | { |
| | | Map.Entry<byte[], BufferedIndexValues> bufferedKey = |
| | | Map.Entry<ByteString, BufferedIndexValues> bufferedKey = |
| | | keyIterator.next(); |
| | | keyBytes = bufferedKey.getKey(); |
| | | key.setData(keyBytes); |
| | | key.setData(bufferedKey.getKey().toByteArray()); |
| | | |
| | | index.updateKey(txn, key, bufferedKey.getValue().deletedIDs, |
| | | bufferedKey.getValue().addedIDs); |
| | |
| | | |
| | | for(VLVIndex vlvIndex : entryContainer.getVLVIndexes()) |
| | | { |
| | | bufferedVLVValues = bufferedVLVIndexes.remove(vlvIndex); |
| | | |
| | | BufferedVLVValues bufferedVLVValues = bufferedVLVIndexes.remove(vlvIndex); |
| | | if(bufferedVLVValues != null) |
| | | { |
| | | vlvIndex.updateIndex(txn, bufferedVLVValues.addedValues, |
| | |
| | | } |
| | | |
| | | Index id2children = entryContainer.getID2Children(); |
| | | bufferedValues = bufferedIndexes.remove(id2children); |
| | | TreeMap<ByteString, BufferedIndexValues> bufferedValues = |
| | | bufferedIndexes.remove(id2children); |
| | | |
| | | if(bufferedValues != null) |
| | | { |
| | | Iterator<Map.Entry<byte[], BufferedIndexValues>> keyIterator = |
| | | Iterator<Map.Entry<ByteString, BufferedIndexValues>> keyIterator = |
| | | bufferedValues.entrySet().iterator(); |
| | | while(keyIterator.hasNext()) |
| | | { |
| | | Map.Entry<byte[], BufferedIndexValues> bufferedKey = |
| | | Map.Entry<ByteString, BufferedIndexValues> bufferedKey = |
| | | keyIterator.next(); |
| | | keyBytes = bufferedKey.getKey(); |
| | | key.setData(keyBytes); |
| | | key.setData(bufferedKey.getKey().toByteArray()); |
| | | |
| | | id2children.updateKey(txn, key, bufferedKey.getValue().deletedIDs, |
| | | bufferedKey.getValue().addedIDs); |
| | |
| | | |
| | | if(bufferedValues != null) |
| | | { |
| | | Iterator<Map.Entry<byte[], BufferedIndexValues>> keyIterator = |
| | | Iterator<Map.Entry<ByteString, BufferedIndexValues>> keyIterator = |
| | | bufferedValues.entrySet().iterator(); |
| | | while(keyIterator.hasNext()) |
| | | { |
| | | Map.Entry<byte[], BufferedIndexValues> bufferedKey = |
| | | Map.Entry<ByteString, BufferedIndexValues> bufferedKey = |
| | | keyIterator.next(); |
| | | keyBytes = bufferedKey.getKey(); |
| | | key.setData(keyBytes); |
| | | key.setData(bufferedKey.getKey().toByteArray()); |
| | | |
| | | id2subtree.updateKey(txn, key, bufferedKey.getValue().deletedIDs, |
| | | bufferedKey.getValue().addedIDs); |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2012 ForgeRock AS. |
| | | * Portions copyright 2012-2014 ForgeRock AS. |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | |
| | | import java.util.Comparator; |
| | | import java.util.Set; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.backends.jeb.AttributeIndex.BSKeyComparator; |
| | | import org.opends.server.backends.jeb.AttributeIndex.KeyComparator; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | |
| | | /** |
| | | * This class attempts to abstract the generation and comparison of keys |
| | |
| | | public abstract class Indexer |
| | | { |
| | | /** |
| | | * Get the comparator that must be used to compare index keys |
| | | * generated by this class. |
| | | * The comparator for keys generated by this class. |
| | | */ |
| | | private static final KeyComparator comparator = new KeyComparator(); |
| | | private static final BSKeyComparator bsComparator = new BSKeyComparator(); |
| | | |
| | | /** |
| | | * Get the comparator that must be used to compare index keys generated by |
| | | * this class. |
| | | * |
| | | * @return A byte array comparator. |
| | | */ |
| | | public abstract Comparator<byte[]> getComparator(); |
| | | public final Comparator<byte[]> getComparator() |
| | | { |
| | | return comparator; |
| | | } |
| | | |
| | | /** |
| | | * Get the comparator that must be used to compare index keys generated by |
| | | * this class. |
| | | * |
| | | * @return A byte string comparator. |
| | | */ |
| | | public final Comparator<ByteString> getBSComparator() |
| | | { |
| | | return bsComparator; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public abstract void indexEntry(Entry entry, Set<byte[]> keys); |
| | | public abstract void indexEntry(Entry entry, Set<ByteString> keys); |
| | | |
| | | /** |
| | | * Generate the set of index keys to be added and the set of index keys |
| | |
| | | * @param modifiedKeys The map into which the modified keys will be inserted. |
| | | */ |
| | | public abstract void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | Map<byte[], Boolean> modifiedKeys); |
| | | Map<ByteString, Boolean> modifiedKeys); |
| | | |
| | | /** |
| | | * Generate the set of index keys to be added and the set of index keys |
| | |
| | | */ |
| | | public abstract void modifyEntry(Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Map<byte[], Boolean> modifiedKeys); |
| | | Map<ByteString, Boolean> modifiedKeys); |
| | | |
| | | } |
| | |
| | | */ |
| | | 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 java.util.TreeSet; |
| | | |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | |
| | | 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. |
| | | */ |
| | |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Gets the comparator that must be used to compare index keys |
| | | * generated by this class. |
| | | * |
| | | * @return A byte array comparator. |
| | | */ |
| | | @Override |
| | | public Comparator<byte[]> getComparator() |
| | | { |
| | | return comparator; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public void indexEntry(Entry entry, Set<byte[]> keys) |
| | | public void indexEntry(Entry entry, Set<ByteString> keys) |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | */ |
| | | @Override |
| | | public void replaceEntry(Entry oldEntry, Entry newEntry, |
| | | Map<byte[], Boolean> modifiedKeys) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | |
| | | @Override |
| | | public void modifyEntry(Entry oldEntry, Entry newEntry, |
| | | List<Modification> mods, |
| | | Map<byte[], Boolean> modifiedKeys) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | |
| | | * @param keys The set into which the generated keys will be inserted. |
| | | */ |
| | | private void indexAttribute(List<Attribute> attrList, |
| | | Set<byte[]> keys) |
| | | Set<ByteString> keys) |
| | | { |
| | | if (attrList == null) return; |
| | | |
| | | Set<ByteString> keysBS = new TreeSet<ByteString>(); |
| | | for (Attribute attr : attrList) |
| | | { |
| | | if (!attr.isVirtual()) |
| | |
| | | { |
| | | try |
| | | { |
| | | extensibleIndexer.createKeys(null, value.getValue(), null, keysBS); |
| | | extensibleIndexer.createKeys(null, value.getValue(), null, keys); |
| | | } |
| | | catch (DecodeException e) |
| | | { |
| | |
| | | } |
| | | } |
| | | } |
| | | for (ByteString key : keysBS) |
| | | { |
| | | keys.add(key.toByteArray()); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | * be inserted or <code>false</code> otherwise. |
| | | */ |
| | | private void indexAttribute(List<Attribute> attrList, |
| | | Map<byte[], Boolean> modifiedKeys, |
| | | Map<ByteString, Boolean> modifiedKeys, |
| | | Boolean insert) |
| | | { |
| | | if (attrList == null) return; |
| | | |
| | | final Set<byte[]> keys = new HashSet<byte[]>(); |
| | | final Set<ByteString> keys = new HashSet<ByteString>(); |
| | | indexAttribute(attrList, keys); |
| | | computeModifiedKeys(modifiedKeys, insert, keys); |
| | | } |
| | |
| | | * @param keys |
| | | * The index keys to map. |
| | | */ |
| | | private static void computeModifiedKeys(Map<byte[], Boolean> modifiedKeys, |
| | | Boolean insert, final Set<byte[]> keys) |
| | | private static void computeModifiedKeys(Map<ByteString, Boolean> modifiedKeys, |
| | | Boolean insert, Set<ByteString> keys) |
| | | { |
| | | for (byte[] key : keys) |
| | | for (ByteString key : keys) |
| | | { |
| | | Boolean cInsert = modifiedKeys.get(key); |
| | | if (cInsert == null) |
| | |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.opends.server.backends.jeb.importLDIF.ImportIDSet; |
| | | import org.opends.server.types.DirectoryException; |
| | |
| | | * @param state |
| | | * The state database to persist index state info. |
| | | * @param env |
| | | * The JE Environemnt |
| | | * The JE Environment |
| | | * @param entryContainer |
| | | * The database entryContainer holding this index. |
| | | * @throws DatabaseException |
| | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean insertID(IndexBuffer buffer, byte[] keyBytes, EntryID entryID) |
| | | public boolean insertID(IndexBuffer buffer, ByteString keyBytes, |
| | | EntryID entryID) |
| | | { |
| | | return true; |
| | | } |
| | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public boolean removeID(IndexBuffer buffer, byte[] keyBytes, EntryID entryID) |
| | | public boolean removeID(IndexBuffer buffer, ByteString keyBytes, |
| | | EntryID entryID) |
| | | { |
| | | return true; |
| | | } |
| | |
| | | |
| | | /** {@inheritDoc} */ |
| | | @Override |
| | | public void delete(IndexBuffer buffer, byte[] keyBytes) |
| | | public void delete(IndexBuffer buffer, ByteString keyBytes) |
| | | { |
| | | // Do nothing. |
| | | } |
| | |
| | | * |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.types.Attribute; |
| | | import org.opends.server.types.AttributeType; |
| | | import org.opends.server.types.Entry; |
| | | import org.opends.server.types.Modification; |
| | | import org.opends.server.types.AttributeType; |
| | | |
| | | import java.util.Comparator; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * An implementation of an Indexer for attribute presence. |
| | |
| | | public class PresenceIndexer extends Indexer |
| | | { |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | * Get a string representation of this object. |
| | | * @return A string representation of this object. |
| | | */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | return attributeType.getNameOrOID() + ".presence"; |
| | | } |
| | | |
| | | /** |
| | | * Get the comparator that must be used to compare index keys |
| | | * generated by this class. |
| | | * |
| | | * @return A byte array comparator. |
| | | */ |
| | | public Comparator<byte[]> getComparator() |
| | | { |
| | | 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. |
| | | */ |
| | | public void indexEntry(Entry entry, Set<byte[]> keys) |
| | | @Override |
| | | public void indexEntry(Entry entry, Set<ByteString> keys) |
| | | { |
| | | List<Attribute> attrList = |
| | | entry.getAttribute(attributeType); |
| | |
| | | { |
| | | if (!attrList.isEmpty()) |
| | | { |
| | | keys.add(AttributeIndex.presenceKey.getData()); |
| | | keys.add(getPresenceKeyData()); |
| | | } |
| | | } |
| | | } |
| | |
| | | * @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) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | |
| | | { |
| | | if(newAttributes != null) |
| | | { |
| | | modifiedKeys.put(AttributeIndex.presenceKey.getData(), true); |
| | | modifiedKeys.put(getPresenceKeyData(), true); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if(newAttributes == null) |
| | | { |
| | | modifiedKeys.put(AttributeIndex.presenceKey.getData(), false); |
| | | modifiedKeys.put(getPresenceKeyData(), false); |
| | | } |
| | | } |
| | | } |
| | |
| | | * @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) |
| | | Map<ByteString, Boolean> modifiedKeys) |
| | | { |
| | | List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true); |
| | | List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true); |
| | |
| | | { |
| | | if(newAttributes != null) |
| | | { |
| | | modifiedKeys.put(AttributeIndex.presenceKey.getData(), true); |
| | | modifiedKeys.put(getPresenceKeyData(), true); |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if(newAttributes == null) |
| | | { |
| | | modifiedKeys.put(AttributeIndex.presenceKey.getData(), false); |
| | | modifiedKeys.put(getPresenceKeyData(), false); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private ByteString getPresenceKeyData() |
| | | { |
| | | return ByteString.wrap(AttributeIndex.presenceKey.getData()); |
| | | } |
| | | } |
| | |
| | | |
| | | if (entryIDList.isDefined()) |
| | | { |
| | | final byte[] value = key.getData(); |
| | | final ByteString value = ByteString.wrap(key.getData()); |
| | | EntryID prevID = null; |
| | | |
| | | for (EntryID id : entryIDList) |
| | |
| | | // require referenced external variables to be final. |
| | | final AtomicBoolean foundMatchingKey = new AtomicBoolean(false); |
| | | |
| | | Set<byte[]> dummySet = new AbstractSet<byte[]>() |
| | | Set<ByteString> dummySet = new AbstractSet<ByteString>() |
| | | { |
| | | @Override |
| | | public Iterator<byte[]> iterator() |
| | | public Iterator<ByteString> iterator() |
| | | { |
| | | // The set is always empty. |
| | | return Collections.<byte[]>emptySet().iterator(); |
| | | return Collections.<ByteString> emptySet().iterator(); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean add(byte[] e) |
| | | public boolean add(ByteString e) |
| | | { |
| | | if (Arrays.equals(e, value)) { |
| | | if (value.equals(e)) |
| | | { |
| | | // We could terminate processing at this point by throwing an |
| | | // UnsupportedOperationException, but this optimization is |
| | | // already ugly enough. |
| | |
| | | logger.trace("Reference to entry " |
| | | + "<%s> which does not match the value%n%s", |
| | | entry.getName(), |
| | | keyDump(index, value)); |
| | | keyDump(index, value.toByteArray())); |
| | | } |
| | | } |
| | | } |
| | |
| | | verifyAttributeInIndex(presenceIndex, txn, presenceKey, entryID); |
| | | } |
| | | |
| | | final DatabaseEntry key = new DatabaseEntry(); |
| | | for (Attribute attr : attrList) |
| | | { |
| | | final AttributeType attrType = attr.getAttributeType(); |
| | |
| | | |
| | | if (equalityIndex != null) |
| | | { |
| | | // TODO JNR reuse DatabaseEntry object for all indexes? |
| | | DatabaseEntry key = new DatabaseEntry(normalizedBytes); |
| | | key.setData(normalizedBytes); |
| | | verifyAttributeInIndex(equalityIndex, txn, key, entryID); |
| | | } |
| | | |
| | | if (substringIndex != null) |
| | | { |
| | | Set<ByteString> keyBytesSet = |
| | | attrIndex.substringKeys(normalizedBytes); |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (ByteString keyBytes : keyBytesSet) |
| | | for (ByteString keyBytes : attrIndex.substringKeys(normalizedBytes)) |
| | | { |
| | | key.setData(keyBytes.toByteArray()); |
| | | verifyAttributeInIndex(substringIndex, txn, key, entryID); |
| | |
| | | |
| | | if (orderingIndex != null) |
| | | { |
| | | normalizedBytes = normalize(attrType.getOrderingMatchingRule(), bsValue); |
| | | DatabaseEntry key = new DatabaseEntry(normalizedBytes); |
| | | key.setData(normalize(attrType.getOrderingMatchingRule(), bsValue)); |
| | | verifyAttributeInIndex(orderingIndex, txn, key, entryID); |
| | | } |
| | | |
| | | if (approximateIndex != null) |
| | | { |
| | | normalizedBytes = normalize(attrType.getApproximateMatchingRule(), bsValue); |
| | | DatabaseEntry key = new DatabaseEntry(normalizedBytes); |
| | | key.setData(normalize(attrType.getApproximateMatchingRule(), bsValue)); |
| | | verifyAttributeInIndex(approximateIndex, txn, key, entryID); |
| | | } |
| | | } |
| | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.util.Utils; |
| | | import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn; |
| | | import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType; |
| | |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.extensions.DiskSpaceMonitor; |
| | | import org.opends.server.types.*; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.opends.server.util.LDIFReader; |
| | | import org.opends.server.util.Platform; |
| | | import org.opends.server.util.StaticUtils; |
| | |
| | | */ |
| | | private class AppendReplaceTask extends ImportTask |
| | | { |
| | | private final Set<byte[]> insertKeySet = new HashSet<byte[]>(), |
| | | deleteKeySet = new HashSet<byte[]>(); |
| | | private final Set<ByteString> insertKeySet = new HashSet<ByteString>(); |
| | | private final Set<ByteString> deleteKeySet = new HashSet<ByteString>(); |
| | | private final EntryInformation entryInfo = new EntryInformation(); |
| | | private Entry oldEntry; |
| | | private EntryID entryID; |
| | |
| | | { |
| | | deleteKeySet.clear(); |
| | | index.indexer.indexEntry(oldEntry, deleteKeySet); |
| | | for (byte[] delKey : deleteKeySet) |
| | | for (ByteString delKey : deleteKeySet) |
| | | { |
| | | processKey(index, delKey, entryID, indexComparator, indexKey, false); |
| | | processKey(index, delKey.toByteArray(), entryID, indexComparator, indexKey, false); |
| | | } |
| | | } |
| | | insertKeySet.clear(); |
| | | index.indexer.indexEntry(entry, insertKeySet); |
| | | for (byte[] key : insertKeySet) |
| | | for (ByteString key : insertKeySet) |
| | | { |
| | | processKey(index, key, entryID, indexComparator, indexKey, true); |
| | | processKey(index, key.toByteArray(), entryID, indexComparator, indexKey, true); |
| | | } |
| | | } |
| | | } |
| | |
| | | { |
| | | private final Map<IndexKey, IndexOutputBuffer> indexBufferMap = |
| | | new HashMap<IndexKey, IndexOutputBuffer>(); |
| | | private final Set<byte[]> insertKeySet = new HashSet<byte[]>(); |
| | | private final Set<ByteString> insertKeySet = new HashSet<ByteString>(); |
| | | private final EntryInformation entryInfo = new EntryInformation(); |
| | | private DatabaseEntry keyEntry = new DatabaseEntry(), |
| | | valEntry = new DatabaseEntry(); |
| | |
| | | { |
| | | insertKeySet.clear(); |
| | | index.indexer.indexEntry(entry, insertKeySet); |
| | | for (byte[] key : insertKeySet) |
| | | for (ByteString key : insertKeySet) |
| | | { |
| | | processKey(index, key, entryID, indexComparator, indexKey, true); |
| | | processKey(index, key.toByteArray(), entryID, indexComparator, indexKey, true); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | import java.util.*; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ConditionResult; |
| | | import org.forgerock.opendj.ldap.DereferenceAliasesPolicy; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | |
| | | 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; |
| | |
| | | private void assertIndexContainsID(Indexer indexer, Entry entry, Index index, |
| | | EntryID entryID) |
| | | { |
| | | Set<byte[]> addKeys = new HashSet<byte[]>(); |
| | | Set<ByteString> addKeys = new HashSet<ByteString>(); |
| | | indexer.indexEntry(entry, addKeys); |
| | | |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (byte[] keyBytes : addKeys) |
| | | for (ByteString keyBytes : addKeys) |
| | | { |
| | | key.setData(keyBytes); |
| | | key.setData(keyBytes.toByteArray()); |
| | | assertEquals(index.containsID(null, key, entryID), TRUE); |
| | | } |
| | | } |
| | |
| | | private void assertIndexContainsID(Indexer indexer, Entry entry, |
| | | Index index, EntryID entryID, ConditionResult expected) |
| | | { |
| | | Set<byte[]> addKeys = new HashSet<byte[]>(); |
| | | Set<ByteString> addKeys = new HashSet<ByteString>(); |
| | | indexer.indexEntry(entry, addKeys); |
| | | |
| | | assertIndexContainsID(addKeys, index, entryID, expected); |
| | | } |
| | | |
| | | private void assertIndexContainsID(Set<byte[]> addKeys, Index index, |
| | | private void assertIndexContainsID(Set<ByteString> addKeys, Index index, |
| | | EntryID entryID, ConditionResult expected) |
| | | { |
| | | DatabaseEntry key = new DatabaseEntry(); |
| | | for (byte[] keyBytes : addKeys) { |
| | | key.setData(keyBytes); |
| | | for (ByteString keyBytes : addKeys) |
| | | { |
| | | key.setData(keyBytes.toByteArray()); |
| | | assertEquals(index.containsID(null, key, entryID), expected); |
| | | } |
| | | assertEquals(index.containsID(null, key, entryID), expected); |
| | | } |
| | | |
| | | @Test(dependsOnMethods = {"testSearchNotIndexed", "testAdd", |
| | |
| | | AttributeType attribute; |
| | | AttributeIndex titleIndex; |
| | | AttributeIndex nameIndex; |
| | | Set<byte[]> addKeys; |
| | | Set<ByteString> addKeys; |
| | | Indexer presenceIndexer; |
| | | Indexer equalityIndexer; |
| | | Indexer substringIndexer; |
| | |
| | | attribute = DirectoryServer.getAttributeType("name"); |
| | | nameIndex = ec.getAttributeIndex(attribute); |
| | | |
| | | // This current entry in the DB shouldn't be in the presence |
| | | // titleIndex. |
| | | addKeys = new HashSet<byte[]>(); |
| | | addKeys.add(AttributeIndex.presenceKey.getData()); |
| | | // This current entry in the DB shouldn't be in the presence titleIndex. |
| | | addKeys = new HashSet<ByteString>(); |
| | | addKeys.add(ByteString.wrap(AttributeIndex.presenceKey.getData())); |
| | | assertIndexContainsID(addKeys, titleIndex.presenceIndex, entryID, FALSE); |
| | | |
| | | // This current entry should be in the presence nameIndex. |
| | | addKeys = new HashSet<byte[]>(); |
| | | addKeys.add(AttributeIndex.presenceKey.getData()); |
| | | addKeys = new HashSet<ByteString>(); |
| | | addKeys.add(ByteString.wrap(AttributeIndex.presenceKey.getData())); |
| | | assertIndexContainsID(addKeys, nameIndex.presenceIndex, entryID, TRUE); |
| | | |
| | | List<Control> noControls = new ArrayList<Control>(0); |
| | |
| | | */ |
| | | package org.opends.server.backends.jeb; |
| | | |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.types.*; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.util.StaticUtils; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | |
| | | import static org.opends.server.util.ServerConstants.OC_TOP; |
| | | import static org.opends.server.util.ServerConstants.OC_EXTENSIBLE_OBJECT; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.core.DirectoryServer; |
| | | import org.opends.server.types.*; |
| | | import org.opends.server.util.StaticUtils; |
| | | import org.testng.annotations.AfterClass; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | import static org.testng.Assert.*; |
| | | |
| | | import com.sleepycat.je.DatabaseEntry; |
| | | import com.sleepycat.je.LockMode; |
| | | import com.sleepycat.je.OperationStatus; |
| | | import com.sleepycat.je.Transaction; |
| | | import com.sleepycat.je.LockMode; |
| | | |
| | | import java.util.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | | import static org.testng.Assert.*; |
| | | |
| | | public class TestVerifyJob extends JebTestCase |
| | | { |
| | |
| | | idBytes[15] = (byte)1; |
| | | //bad jeb format |
| | | idBytes[23] = (byte) 0x04; |
| | | idSet=new EntryIDSet(null, idBytes); |
| | | idSet = newEntryIDSet(idBytes); |
| | | id2child.writeKey(txn, key, idSet); |
| | | performBECleanVerify("id2children", 6); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | private EntryIDSet newEntryIDSet(byte[] idBytes) |
| | | { |
| | | return new EntryIDSet((ByteString) null, idBytes); |
| | | } |
| | | |
| | | /** |
| | | * Runs clean verify against the id2subtree index after adding |
| | | * various errors in that index file. |
| | |
| | | idBytes[3] = (byte)0xff; |
| | | //non-subordinate |
| | | idBytes[15] = (byte)1; |
| | | idSet=new EntryIDSet(null, idBytes); |
| | | idSet = newEntryIDSet(idBytes); |
| | | id2subtree.writeKey(txn, key, idSet); |
| | | //Try to break JebFormat version of key entry |
| | | key=addID2EntryReturnKey(junkDN, 4, true); |
| | | idBytes[3]=(byte) 0x04; |
| | | idBytes[15]=(byte)0x00; |
| | | EntryIDSet idSet1=new EntryIDSet(null, idBytes); |
| | | EntryIDSet idSet1 = newEntryIDSet(idBytes); |
| | | id2subtree.writeKey(txn, key, idSet1); |
| | | //put invalid key -- no EntryID matches |
| | | key= new EntryID(45).getDatabaseEntry(); |
| | | idSet=new EntryIDSet(null, idBytes); |
| | | idSet = newEntryIDSet(idBytes); |
| | | id2subtree.writeKey(txn, key, idSet); |
| | | performBECleanVerify("id2subtree", 7); |
| | | } |
| | |
| | | DatabaseEntry key=addID2EntryReturnKey(noParentDN, 10, false); |
| | | byte[] idBytes=new byte[16]; |
| | | idBytes[7]=(byte) 0x0A; |
| | | EntryIDSet idSet=new EntryIDSet(null, idBytes); |
| | | EntryIDSet idSet = newEntryIDSet(idBytes); |
| | | id2child.writeKey(txn, key, idSet); |
| | | //Add child entry - don't worry about key |
| | | addID2EntryReturnKey(cDN, 11, false); |
| | |
| | | //add parent key/IDSet with bad IDset id |
| | | byte[] idBytesp=new byte[16]; |
| | | idBytesp[7]=(byte) 0xFF; |
| | | EntryIDSet idSetp=new EntryIDSet(null, idBytesp); |
| | | EntryIDSet idSetp = newEntryIDSet(idBytesp); |
| | | id2child.writeKey(txn, keyp, idSetp); |
| | | performBECompleteVerify("id2children", 3); |
| | | } |