| | |
| | | * |
| | | * |
| | | * 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); |