| | |
| | | import org.opends.server.backends.RebuildConfig.RebuildMode; |
| | | import org.opends.server.backends.persistit.PersistItStorage; |
| | | import org.opends.server.backends.pluggable.AttributeIndex.MatchingRuleIndex; |
| | | import org.opends.server.backends.pluggable.ImportLDIFReader.EntryInformation; |
| | | import org.opends.server.backends.pluggable.spi.Cursor; |
| | | import org.opends.server.backends.pluggable.spi.ReadOperation; |
| | | import org.opends.server.backends.pluggable.spi.ReadableTransaction; |
| | |
| | | |
| | | /** The DN attribute type. */ |
| | | private static final AttributeType DN_TYPE; |
| | | static |
| | | { |
| | | AttributeType attrType = DirectoryServer.getAttributeType("dn"); |
| | | if (attrType == null) |
| | | { |
| | | attrType = DirectoryServer.getDefaultAttributeType("dn"); |
| | | } |
| | | DN_TYPE = attrType; |
| | | } |
| | | |
| | | /** Root container. */ |
| | | private final RootContainer rootContainer; |
| | |
| | | |
| | | /** Map of DNs to Suffix objects. */ |
| | | private final Map<DN, Suffix> dnSuffixMap = new LinkedHashMap<>(); |
| | | /** Map of indexIDs to indexes. */ |
| | | /** |
| | | * Map of indexIDs to indexes. |
| | | * <p> |
| | | * Mainly used to support multiple suffixes. Each index in each suffix gets a unique ID to |
| | | * identify which tree it needs to go to in phase two processing. |
| | | */ |
| | | private final ConcurrentHashMap<Integer, Index> indexIDToIndexMap = new ConcurrentHashMap<>(); |
| | | /** Map of indexIDs to entry containers. */ |
| | | private final ConcurrentHashMap<Integer, EntryContainer> indexIDToECMap = new ConcurrentHashMap<>(); |
| | |
| | | /** Number of phase one buffers. */ |
| | | private int phaseOneBufferCount; |
| | | |
| | | static |
| | | { |
| | | AttributeType attrType = DirectoryServer.getAttributeType("dn"); |
| | | if (attrType == null) |
| | | { |
| | | attrType = DirectoryServer.getDefaultAttributeType("dn"); |
| | | } |
| | | DN_TYPE = attrType; |
| | | } |
| | | |
| | | /** |
| | | * Create a new import job with the specified rebuild index config. |
| | | * |
| | |
| | | * @param backendCfg |
| | | * the backend configuration object |
| | | * @return true if the backend must be cleared, false otherwise |
| | | * @see Importer#getSuffix(WriteableTransaction, EntryContainer) for per-suffix cleanups. |
| | | * @see Importer#prepareSuffix(WriteableTransaction, EntryContainer) for per-suffix cleanups. |
| | | */ |
| | | static boolean mustClearBackend(LDIFImportConfig importCfg, PluggableBackendCfg backendCfg) |
| | | { |
| | |
| | | if (suffix != null) |
| | | { |
| | | dnSuffixMap.put(ec.getBaseDN(), suffix); |
| | | generateIndexID(suffix); |
| | | generateIndexIDs(suffix); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Mainly used to support multiple suffixes. Each index in each suffix gets an |
| | | * unique ID to identify which DB it needs to go to in phase two processing. |
| | | */ |
| | | private void generateIndexID(Suffix suffix) |
| | | private void generateIndexIDs(Suffix suffix) |
| | | { |
| | | for (AttributeIndex attributeIndex : suffix.getAttrIndexMap().values()) |
| | | { |
| | |
| | | |
| | | private final Set<ByteString> insertKeySet = new HashSet<>(); |
| | | private final Set<ByteString> deleteKeySet = new HashSet<>(); |
| | | private final EntryInformation entryInfo = new EntryInformation(); |
| | | private Entry oldEntry; |
| | | private EntryID entryID; |
| | | |
| | | @Override |
| | | void call0(WriteableTransaction txn) throws Exception |
| | | { |
| | | try |
| | | { |
| | | while (true) |
| | | EntryInformation entryInfo; |
| | | while ((entryInfo = reader.readEntry(dnSuffixMap)) != null) |
| | | { |
| | | if (importCfg.isCancelled() || isCanceled) |
| | | { |
| | | freeBufferQueue.add(IndexOutputBuffer.poison()); |
| | | return; |
| | | } |
| | | oldEntry = null; |
| | | Entry entry = reader.readEntry(dnSuffixMap, entryInfo); |
| | | if (entry == null) |
| | | { |
| | | break; |
| | | } |
| | | entryID = entryInfo.getEntryID(); |
| | | Suffix suffix = entryInfo.getSuffix(); |
| | | processEntry(txn, entry, suffix); |
| | | processEntry(txn, entryInfo.getEntry(), entryInfo.getEntryID(), entryInfo.getSuffix()); |
| | | } |
| | | flushIndexBuffers(); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | void processEntry(WriteableTransaction txn, Entry entry, Suffix suffix) |
| | | @Override |
| | | void processEntry(WriteableTransaction txn, Entry entry, EntryID entryID, Suffix suffix) |
| | | throws DirectoryException, StorageRuntimeException, InterruptedException |
| | | { |
| | | DN entryDN = entry.getName(); |
| | | |
| | | EntryID oldID = suffix.getDN2ID().get(txn, entryDN); |
| | | if (oldID != null) |
| | | { |
| | | oldEntry = suffix.getID2Entry().get(txn, oldID); |
| | | } |
| | | |
| | | oldEntry = oldID != null ? suffix.getID2Entry().get(txn, oldID) : null; |
| | | if (oldEntry == null) |
| | | { |
| | | if (validateDNs && !dnSanityCheck(txn, entry, suffix)) |
| | |
| | | private final Storage storage; |
| | | private final Map<IndexKey, IndexOutputBuffer> indexBufferMap = new HashMap<>(); |
| | | private final Set<ByteString> insertKeySet = new HashSet<>(); |
| | | private final EntryInformation entryInfo = new EntryInformation(); |
| | | private final IndexKey dnIndexKey = new IndexKey(DN_TYPE, DN2ID_INDEX_NAME, 1); |
| | | |
| | | public ImportTask(final Storage storage) |
| | |
| | | { |
| | | try |
| | | { |
| | | while (true) |
| | | EntryInformation entryInfo; |
| | | while ((entryInfo = reader.readEntry(dnSuffixMap)) != null) |
| | | { |
| | | if (importCfg.isCancelled() || isCanceled) |
| | | { |
| | | freeBufferQueue.add(IndexOutputBuffer.poison()); |
| | | return; |
| | | } |
| | | Entry entry = reader.readEntry(dnSuffixMap, entryInfo); |
| | | if (entry == null) |
| | | { |
| | | break; |
| | | } |
| | | EntryID entryID = entryInfo.getEntryID(); |
| | | Suffix suffix = entryInfo.getSuffix(); |
| | | processEntry(txn, entry, entryID, suffix); |
| | | processEntry(txn, entryInfo.getEntry(), entryInfo.getEntryID(), entryInfo.getSuffix()); |
| | | } |
| | | flushIndexBuffers(); |
| | | } |
| | |
| | | |
| | | private void rebuildIndexMap(WriteableTransaction txn, boolean onlyDegraded) |
| | | { |
| | | final RebuildMode rebuildMode = rebuildConfig.getRebuildMode(); |
| | | for (final Map.Entry<AttributeType, AttributeIndex> mapEntry : suffix.getAttrIndexMap().entrySet()) |
| | | { |
| | | final AttributeType attributeType = mapEntry.getKey(); |
| | | final AttributeIndex attributeIndex = mapEntry.getValue(); |
| | | if (mustRebuild(attributeType, rebuildMode)) |
| | | if (mustRebuild(attributeType)) |
| | | { |
| | | rebuildAttributeIndexes(txn, attributeIndex, attributeType, onlyDegraded); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private boolean mustRebuild(final AttributeType attrType, RebuildMode rebuildMode) |
| | | private boolean mustRebuild(final AttributeType attrType) |
| | | { |
| | | switch (rebuildMode) |
| | | switch (rebuildConfig.getRebuildMode()) |
| | | { |
| | | case ALL: |
| | | case DEGRADED: |
| | |
| | | } |
| | | |
| | | /** |
| | | * A class to hold information about the entry determined by the LDIF reader. |
| | | * Mainly the suffix the entry belongs under and the ID assigned to it by the |
| | | * reader. |
| | | */ |
| | | public class EntryInformation |
| | | { |
| | | private EntryID entryID; |
| | | private Suffix suffix; |
| | | |
| | | /** |
| | | * Return the suffix associated with the entry. |
| | | * |
| | | * @return Entry's suffix instance; |
| | | */ |
| | | private Suffix getSuffix() |
| | | { |
| | | return suffix; |
| | | } |
| | | |
| | | /** |
| | | * Set the suffix instance associated with the entry. |
| | | * |
| | | * @param suffix |
| | | * The suffix associated with the entry. |
| | | */ |
| | | public void setSuffix(Suffix suffix) |
| | | { |
| | | this.suffix = suffix; |
| | | } |
| | | |
| | | /** |
| | | * Set the entry's ID. |
| | | * |
| | | * @param entryID |
| | | * The entry ID to set the entry ID to. |
| | | */ |
| | | public void setEntryID(EntryID entryID) |
| | | { |
| | | this.entryID = entryID; |
| | | } |
| | | |
| | | /** |
| | | * Return the entry ID associated with the entry. |
| | | * |
| | | * @return The entry ID associated with the entry. |
| | | */ |
| | | private EntryID getEntryID() |
| | | { |
| | | return entryID; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * This class is used as an index key for hash maps that need to process multiple suffix index |
| | | * elements into a single queue and/or maps based on both attribute type and index ID (ie., |
| | | * cn.equality, sn.equality,...). |