| | |
| | | package org.opends.server.backends.pluggable; |
| | | |
| | | import static org.opends.messages.JebMessages.*; |
| | | import static org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType.*; |
| | | import static org.opends.server.admin.std.meta.BackendIndexCfgDefn.IndexType.*; |
| | | import static org.opends.server.backends.pluggable.IndexOutputBuffer.*; |
| | | import static org.opends.server.util.DynamicConstants.*; |
| | | import static org.opends.server.util.ServerConstants.*; |
| | |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.spi.IndexingOptions; |
| | | import org.forgerock.util.Utils; |
| | | import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType; |
| | | import org.opends.server.admin.std.server.LocalDBBackendCfg; |
| | | import org.opends.server.admin.std.server.LocalDBIndexCfg; |
| | | import org.opends.server.admin.std.meta.BackendIndexCfgDefn.IndexType; |
| | | import org.opends.server.admin.std.server.BackendIndexCfg; |
| | | import org.opends.server.admin.std.server.PersistitBackendCfg; |
| | | import org.opends.server.admin.std.server.PluggableBackendCfg; |
| | | import org.opends.server.api.DiskSpaceMonitorHandler; |
| | | import org.opends.server.backends.RebuildConfig; |
| | | import org.opends.server.backends.RebuildConfig.RebuildMode; |
| | |
| | | /** Import configuration. */ |
| | | private final LDIFImportConfig importConfiguration; |
| | | /** Backend configuration. */ |
| | | private final LocalDBBackendCfg backendConfiguration; |
| | | private final PersistitBackendCfg backendConfiguration; |
| | | |
| | | /** LDIF reader. */ |
| | | private ImportLDIFReader reader; |
| | |
| | | * @throws ConfigException |
| | | * If a problem occurs during initialization. |
| | | */ |
| | | public Importer(RebuildConfig rebuildConfig, LocalDBBackendCfg cfg) throws InitializationException, |
| | | public Importer(RebuildConfig rebuildConfig, PersistitBackendCfg cfg) throws InitializationException, |
| | | StorageRuntimeException, ConfigException |
| | | { |
| | | this.importConfiguration = null; |
| | |
| | | * |
| | | * @param importConfiguration |
| | | * The LDIF import configuration. |
| | | * @param localDBBackendCfg |
| | | * @param backendCfg |
| | | * The local DB back-end configuration. |
| | | * @throws InitializationException |
| | | * If a problem occurs during initialization. |
| | |
| | | * @throws StorageRuntimeException |
| | | * If an error occurred when opening the DB. |
| | | */ |
| | | public Importer(LDIFImportConfig importConfiguration, LocalDBBackendCfg localDBBackendCfg) |
| | | public Importer(LDIFImportConfig importConfiguration, PersistitBackendCfg backendCfg) |
| | | throws InitializationException, ConfigException, StorageRuntimeException |
| | | { |
| | | this.rebuildManager = null; |
| | | this.importConfiguration = importConfiguration; |
| | | this.backendConfiguration = localDBBackendCfg; |
| | | this.backendConfiguration = backendCfg; |
| | | |
| | | if (importConfiguration.getThreadCount() == 0) |
| | | { |
| | |
| | | } |
| | | |
| | | // Determine the number of indexes. |
| | | this.indexCount = getTotalIndexCount(localDBBackendCfg); |
| | | this.indexCount = getTotalIndexCount(backendCfg); |
| | | |
| | | this.clearedBackend = mustClearBackend(importConfiguration, localDBBackendCfg); |
| | | this.clearedBackend = mustClearBackend(importConfiguration, backendCfg); |
| | | this.scratchFileWriterList = |
| | | new ArrayList<ScratchFileWriterTask>(indexCount); |
| | | this.scratchFileWriterFutures = new CopyOnWriteArrayList<Future<Void>>(); |
| | | |
| | | this.tempDir = getTempDir(localDBBackendCfg, importConfiguration.getTmpDirectory()); |
| | | this.tempDir = getTempDir(backendCfg, importConfiguration.getTmpDirectory()); |
| | | recursiveDelete(tempDir); |
| | | if (!tempDir.exists() && !tempDir.mkdirs()) |
| | | { |
| | |
| | | /** |
| | | * Returns whether the backend must be cleared. |
| | | * |
| | | * @param importCfg the import configuration object |
| | | * @param backendCfg the backend configuration object |
| | | * @param importCfg |
| | | * the import configuration object |
| | | * @param backendCfg |
| | | * the backend configuration object |
| | | * @return true if the backend must be cleared, false otherwise |
| | | * @see Importer#getSuffix(WriteableStorage, EntryContainer) for per-suffix cleanups. |
| | | */ |
| | | public static boolean mustClearBackend(LDIFImportConfig importCfg, LocalDBBackendCfg backendCfg) |
| | | static boolean mustClearBackend(LDIFImportConfig importCfg, PluggableBackendCfg backendCfg) |
| | | { |
| | | return !importCfg.appendToExistingData() |
| | | && (importCfg.clearBackend() || backendCfg.getBaseDN().size() <= 1); |
| | | } |
| | | |
| | | private File getTempDir(LocalDBBackendCfg localDBBackendCfg, String tmpDirectory) |
| | | private File getTempDir(PluggableBackendCfg backendCfg, String tmpDirectory) |
| | | { |
| | | File parentDir; |
| | | if (tmpDirectory != null) |
| | |
| | | { |
| | | parentDir = getFileForPath(DEFAULT_TMP_DIR); |
| | | } |
| | | return new File(parentDir, localDBBackendCfg.getBackendId()); |
| | | return new File(parentDir, backendCfg.getBackendId()); |
| | | } |
| | | |
| | | private int getTotalIndexCount(LocalDBBackendCfg localDBBackendCfg) |
| | | private int getTotalIndexCount(PluggableBackendCfg backendCfg) |
| | | throws ConfigException |
| | | { |
| | | int indexes = 2; // dn2id, dn2uri |
| | | for (String indexName : localDBBackendCfg.listLocalDBIndexes()) |
| | | for (String indexName : backendCfg.listBackendIndexes()) |
| | | { |
| | | LocalDBIndexCfg index = localDBBackendCfg.getLocalDBIndex(indexName); |
| | | BackendIndexCfg index = backendCfg.getBackendIndex(indexName); |
| | | SortedSet<IndexType> types = index.getIndexType(); |
| | | if (types.contains(IndexType.EXTENSIBLE)) |
| | | { |
| | |
| | | this.rootContainer = rootContainer; |
| | | final long startTime = System.currentTimeMillis(); |
| | | |
| | | DiskSpaceMonitor tmpMonitor = createDiskSpaceMonitor(tempDir, "backend index rebuild tmp directory"); |
| | | tmpMonitor.initializeMonitorProvider(null); |
| | | DirectoryServer.registerMonitorProvider(tmpMonitor); |
| | | File parentDirectory = getFileForPath(backendConfiguration.getDBDirectory()); |
| | | File backendDirectory = new File(parentDirectory, backendConfiguration.getBackendId()); |
| | | DiskSpaceMonitor dbMonitor = createDiskSpaceMonitor(backendDirectory, "backend index rebuild DB directory"); |
| | | dbMonitor.initializeMonitorProvider(null); |
| | | DirectoryServer.registerMonitorProvider(dbMonitor); |
| | | |
| | | try |
| | | { |
| | | rootContainer.getStorage().write(new WriteOperation() |
| | |
| | | { |
| | | logger.traceException(e); |
| | | } |
| | | finally |
| | | { |
| | | DirectoryServer.deregisterMonitorProvider(tmpMonitor); |
| | | DirectoryServer.deregisterMonitorProvider(dbMonitor); |
| | | tmpMonitor.finalizeMonitorProvider(); |
| | | dbMonitor.finalizeMonitorProvider(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | InterruptedException, ExecutionException |
| | | { |
| | | this.rootContainer = rootContainer; |
| | | DiskSpaceMonitor tmpMonitor = null; |
| | | DiskSpaceMonitor dbMonitor = null; |
| | | try { |
| | | try |
| | | { |
| | |
| | | throw new InitializationException(message, ioe); |
| | | } |
| | | |
| | | tmpMonitor = createDiskSpaceMonitor(tempDir, "backend import tmp directory"); |
| | | tmpMonitor.initializeMonitorProvider(null); |
| | | DirectoryServer.registerMonitorProvider(tmpMonitor); |
| | | File parentDirectory = getFileForPath(backendConfiguration.getDBDirectory()); |
| | | File backendDirectory = new File(parentDirectory, backendConfiguration.getBackendId()); |
| | | dbMonitor = createDiskSpaceMonitor(backendDirectory, "backend import DB directory"); |
| | | dbMonitor.initializeMonitorProvider(null); |
| | | DirectoryServer.registerMonitorProvider(dbMonitor); |
| | | |
| | | logger.info(NOTE_JEB_IMPORT_STARTING, DirectoryServer.getVersionString(), |
| | | BUILD_ID, REVISION_NUMBER); |
| | | logger.info(NOTE_JEB_IMPORT_THREAD_COUNT, threadCount); |
| | |
| | | // Do nothing. |
| | | } |
| | | } |
| | | if (tmpMonitor != null) |
| | | { |
| | | DirectoryServer.deregisterMonitorProvider(tmpMonitor); |
| | | tmpMonitor.finalizeMonitorProvider(); |
| | | } |
| | | if (dbMonitor != null) |
| | | { |
| | | DirectoryServer.deregisterMonitorProvider(dbMonitor); |
| | | dbMonitor.finalizeMonitorProvider(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private DiskSpaceMonitor createDiskSpaceMonitor(File dir, String backendSuffix) |
| | | { |
| | | final LocalDBBackendCfg cfg = backendConfiguration; |
| | | return new DiskSpaceMonitor(cfg.getBackendId() + " " + backendSuffix, dir, |
| | | cfg.getDiskLowThreshold(), cfg.getDiskFullThreshold(), 5, TimeUnit.SECONDS, this); |
| | | } |
| | | |
| | | private void recursiveDelete(File dir) |
| | | { |
| | | if (dir.listFiles() != null) |
| | |
| | | private final RebuildConfig rebuildConfig; |
| | | |
| | | /** Local DB backend configuration. */ |
| | | private final LocalDBBackendCfg cfg; |
| | | private final PluggableBackendCfg cfg; |
| | | |
| | | /** Map of index keys to indexes. */ |
| | | private final Map<IndexKey, Index> indexMap = |
| | |
| | | * @param cfg |
| | | * The local DB configuration to use. |
| | | */ |
| | | public RebuildIndexManager(RebuildConfig rebuildConfig, LocalDBBackendCfg cfg) |
| | | public RebuildIndexManager(RebuildConfig rebuildConfig, PluggableBackendCfg cfg) |
| | | { |
| | | super(null); |
| | | this.rebuildConfig = rebuildConfig; |
| | |
| | | } |
| | | } |
| | | |
| | | private int getRebuildListIndexCount(LocalDBBackendCfg cfg) |
| | | private int getRebuildListIndexCount(PluggableBackendCfg cfg) |
| | | throws StorageRuntimeException, ConfigException, InitializationException |
| | | { |
| | | final List<String> rebuildList = rebuildConfig.getRebuildList(); |
| | |
| | | else |
| | | { |
| | | boolean found = false; |
| | | for (final String idx : cfg.listLocalDBIndexes()) |
| | | for (final String idx : cfg.listBackendIndexes()) |
| | | { |
| | | if (idx.equalsIgnoreCase(index)) |
| | | { |
| | | found = true; |
| | | final LocalDBIndexCfg indexCfg = cfg.getLocalDBIndex(idx); |
| | | final BackendIndexCfg indexCfg = cfg.getBackendIndex(idx); |
| | | indexCount += getAttributeIndexCount(indexCfg.getIndexType(), |
| | | PRESENCE, EQUALITY, ORDERING, SUBSTRING, APPROXIMATE); |
| | | indexCount += getExtensibleIndexCount(indexCfg); |
| | |
| | | return new InitializationException(ERR_JEB_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(index)); |
| | | } |
| | | |
| | | private boolean findExtensibleMatchingRule(LocalDBBackendCfg cfg, String indexExRuleName) throws ConfigException |
| | | private boolean findExtensibleMatchingRule(PluggableBackendCfg cfg, String indexExRuleName) throws ConfigException |
| | | { |
| | | for (String idx : cfg.listLocalDBIndexes()) |
| | | for (String idx : cfg.listBackendIndexes()) |
| | | { |
| | | LocalDBIndexCfg indexCfg = cfg.getLocalDBIndex(idx); |
| | | BackendIndexCfg indexCfg = cfg.getBackendIndex(idx); |
| | | if (indexCfg.getIndexType().contains(EXTENSIBLE)) |
| | | { |
| | | for (String exRule : indexCfg.getIndexExtensibleMatchingRule()) |
| | |
| | | return result; |
| | | } |
| | | |
| | | private int getExtensibleIndexCount(LocalDBIndexCfg indexCfg) |
| | | private int getExtensibleIndexCount(BackendIndexCfg indexCfg) |
| | | { |
| | | int result = 0; |
| | | if (indexCfg.getIndexType().contains(EXTENSIBLE)) |