/** {@inheritDoc} */ @Override() public void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException { BackupManager backupManager = new BackupManager(getBackendID()); File parentDir = getFileForPath(cfg.getDBDirectory()); File backendDir = new File(parentDir, cfg.getBackendId()); backupManager.restoreBackup(backendDir, restoreConfig); }
/** {@inheritDoc} */ @Override() public void finalizeBackend() { // Deregister as a change listener. cfg.removeLocalDBChangeListener(this); // Deregister our base DNs. for (DN dn : rootContainer.getBaseDNs()) { try { DirectoryServer.deregisterBaseDN(dn); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } } DirectoryServer.deregisterMonitorProvider(rootContainerMonitor); DirectoryServer.deregisterMonitorProvider(diskMonitor); // We presume the server will prevent more operations coming into this // backend, but there may be existing operations already in the // backend. We need to wait for them to finish. waitUntilQuiescent(); // Close the database. try { rootContainer.close(); rootContainer = null; } catch (DatabaseException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } Message message = ERR_JEB_DATABASE_EXCEPTION.get(e.getMessage()); logError(message); } // Checksum this db environment and register its offline state id/checksum. DirectoryServer.registerOfflineBackendStateID(this.getBackendID(), checksumDbEnv()); // Deregister the alert generator. DirectoryServer.deregisterAlertGenerator(this); // Make sure the thread counts are zero for next initialization. threadTotalCount.set(0); threadWriteCount.set(0); // Log an informational message. Message message = NOTE_BACKEND_OFFLINE.get(cfg.getBackendId()); logError(message); }
/** {@inheritDoc} */ public boolean isConfigurationChangeAcceptable( LocalDBBackendCfg cfg, List<Message> unacceptableReasons) { // Make sure that the logging level value is acceptable. try { Level.parse(cfg.getDBLoggingLevel()); } catch (Exception e) { Message message = ERR_JEB_INVALID_LOGGING_LEVEL.get( String.valueOf(cfg.getDBLoggingLevel()), String.valueOf(cfg.dn())); unacceptableReasons.add(message); return false; } return true; }
/** * This method will attempt to checksum the current JE db environment by computing the Adler-32 * checksum on the latest JE log file available. * * @return The checksum of JE db environment or zero if checksum failed. */ private long checksumDbEnv() { File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); List<File> jdbFiles = new ArrayList<File>(); if (backendDirectory.isDirectory()) { jdbFiles = Arrays.asList( backendDirectory.listFiles( new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jdb"); } })); } if (!jdbFiles.isEmpty()) { Collections.sort(jdbFiles, Collections.reverseOrder()); FileInputStream fis = null; try { fis = new FileInputStream(jdbFiles.get(0).toString()); CheckedInputStream cis = new CheckedInputStream(fis, new Adler32()); byte[] tempBuf = new byte[8192]; while (cis.read(tempBuf) >= 0) {} return cis.getChecksum().getValue(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } finally { if (fis != null) { try { fis.close(); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } } } } return 0; }
/** {@inheritDoc} */ public void diskFullThresholdReached(DiskSpaceMonitor monitor) { Message msg = ERR_JEB_DISK_FULL_THRESHOLD_REACHED.get( monitor.getDirectory().getPath(), cfg.getBackendId(), monitor.getFreeSpace(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); DirectoryServer.sendAlertNotification(this, ALERT_TYPE_DISK_FULL, msg); }
/** {@inheritDoc} */ public void diskSpaceRestored(DiskSpaceMonitor monitor) { Message msg = NOTE_JEB_DISK_SPACE_RESTORED.get( monitor.getFreeSpace(), monitor.getDirectory().getPath(), cfg.getBackendId(), Math.max(monitor.getLowThreshold(), monitor.getFullThreshold())); logError(msg); }
/** Reads configuration information from the configuration files. */ public void readConfiguration() { List<OpenDsException> ex = new ArrayList<OpenDsException>(); Set<ConnectionHandlerDescriptor> ls = new HashSet<ConnectionHandlerDescriptor>(); Set<BackendDescriptor> bs = new HashSet<BackendDescriptor>(); Set<DN> as = new HashSet<DN>(); try { DirectoryServer.getInstance().initializeConfiguration(); if (mustReadSchema()) { try { readSchema(); if (getSchema() != null) { // Update the schema: so that when we call the server code the // latest schema read on the server we are managing is used. DirectoryServer.setSchema(getSchema()); } } catch (OpenDsException oe) { ex.add(oe); } } // Get the Directory Server configuration handler and use it. RootCfg root = ServerManagementContext.getInstance().getRootConfiguration(); try { AdministrationConnectorCfg adminConnector = root.getAdministrationConnector(); this.adminConnector = getConnectionHandler(adminConnector); } catch (ConfigException ce) { ex.add(ce); } for (String connHandler : root.listConnectionHandlers()) { try { ConnectionHandlerCfg connectionHandler = root.getConnectionHandler(connHandler); ls.add(getConnectionHandler(connectionHandler, connHandler)); } catch (OpenDsException oe) { ex.add(oe); } } isSchemaEnabled = root.getGlobalConfiguration().isCheckSchema(); for (String backendName : root.listBackends()) { try { BackendCfg backend = root.getBackend(backendName); Set<BaseDNDescriptor> baseDNs = new HashSet<BaseDNDescriptor>(); for (DN dn : backend.getBaseDN()) { BaseDNDescriptor baseDN = new BaseDNDescriptor(BaseDNDescriptor.Type.NOT_REPLICATED, dn, null, -1, -1, -1); baseDNs.add(baseDN); } Set<IndexDescriptor> indexes = new HashSet<IndexDescriptor>(); Set<VLVIndexDescriptor> vlvIndexes = new HashSet<VLVIndexDescriptor>(); BackendDescriptor.Type type; if (backend instanceof LocalDBBackendCfg) { type = BackendDescriptor.Type.LOCAL_DB; LocalDBBackendCfg db = (LocalDBBackendCfg) backend; try { for (String indexName : db.listLocalDBIndexes()) { LocalDBIndexCfg index = db.getLocalDBIndex(indexName); indexes.add( new IndexDescriptor( index.getAttribute().getNameOrOID(), index.getAttribute(), null, index.getIndexType(), index.getIndexEntryLimit())); } } catch (OpenDsException oe) { ex.add(oe); } indexes.add(new IndexDescriptor("dn2id", null, null, new TreeSet<IndexType>(), -1)); indexes.add( new IndexDescriptor("id2children", null, null, new TreeSet<IndexType>(), -1)); indexes.add( new IndexDescriptor("id2subtree", null, null, new TreeSet<IndexType>(), -1)); try { for (String vlvIndexName : db.listLocalDBVLVIndexes()) { LocalDBVLVIndexCfg index = db.getLocalDBVLVIndex(vlvIndexName); String s = index.getSortOrder(); List<VLVSortOrder> sortOrder = getVLVSortOrder(s); vlvIndexes.add( new VLVIndexDescriptor( index.getName(), null, index.getBaseDN(), index.getScope(), index.getFilter(), sortOrder, index.getMaxBlockSize())); } } catch (OpenDsException oe) { ex.add(oe); } } else if (backend instanceof LDIFBackendCfg) { type = BackendDescriptor.Type.LDIF; } else if (backend instanceof MemoryBackendCfg) { type = BackendDescriptor.Type.MEMORY; } else if (backend instanceof BackupBackendCfg) { type = BackendDescriptor.Type.BACKUP; } else if (backend instanceof MonitorBackendCfg) { type = BackendDescriptor.Type.MONITOR; } else if (backend instanceof TaskBackendCfg) { type = BackendDescriptor.Type.TASK; } else { type = BackendDescriptor.Type.OTHER; } BackendDescriptor desc = new BackendDescriptor( backend.getBackendId(), baseDNs, indexes, vlvIndexes, -1, backend.isEnabled(), type); for (AbstractIndexDescriptor index : indexes) { index.setBackend(desc); } for (AbstractIndexDescriptor index : vlvIndexes) { index.setBackend(desc); } bs.add(desc); } catch (OpenDsException oe) { ex.add(oe); } } boolean isReplicationSecure = false; try { CryptoManagerCfg cryptoManager = root.getCryptoManager(); isReplicationSecure = cryptoManager.isSSLEncryption(); } catch (OpenDsException oe) { ex.add(oe); } replicationPort = -1; ReplicationSynchronizationProviderCfg sync = null; try { sync = (ReplicationSynchronizationProviderCfg) root.getSynchronizationProvider("Multimaster Synchronization"); } catch (OpenDsException oe) { // Ignore this one } if (sync != null) { try { if (sync.isEnabled() && sync.hasReplicationServer()) { ReplicationServerCfg replicationServer = sync.getReplicationServer(); if (replicationServer != null) { replicationPort = replicationServer.getReplicationPort(); ConnectionHandlerDescriptor.Protocol protocol = isReplicationSecure ? ConnectionHandlerDescriptor.Protocol.REPLICATION_SECURE : ConnectionHandlerDescriptor.Protocol.REPLICATION; Set<CustomSearchResult> emptySet = Collections.emptySet(); ConnectionHandlerDescriptor connHandler = new ConnectionHandlerDescriptor( new HashSet<InetAddress>(), replicationPort, protocol, ConnectionHandlerDescriptor.State.ENABLED, "Multimaster Synchronization", emptySet); ls.add(connHandler); } } String[] domains = sync.listReplicationDomains(); if (domains != null) { for (String domain2 : domains) { ReplicationDomainCfg domain = sync.getReplicationDomain(domain2); DN dn = domain.getBaseDN(); for (BackendDescriptor backend : bs) { for (BaseDNDescriptor baseDN : backend.getBaseDns()) { if (baseDN.getDn().equals(dn)) { baseDN.setType( sync.isEnabled() ? BaseDNDescriptor.Type.REPLICATED : BaseDNDescriptor.Type.DISABLED); baseDN.setReplicaID(domain.getServerId()); } } } } } } catch (OpenDsException oe) { ex.add(oe); } } try { RootDNCfg rootDN = root.getRootDN(); String[] rootUsers = rootDN.listRootDNUsers(); as.clear(); if (rootUsers != null) { for (String rootUser2 : rootUsers) { RootDNUserCfg rootUser = rootDN.getRootDNUser(rootUser2); as.addAll(rootUser.getAlternateBindDN()); } } } catch (OpenDsException oe) { ex.add(oe); } } catch (OpenDsException oe) { ex.add(oe); } catch (final Throwable t) { LOG.log(Level.WARNING, "Error reading configuration: " + t, t); OfflineUpdateException oue = new OfflineUpdateException(ERR_READING_CONFIG_LDAP.get(t.getMessage().toString()), t); ex.add(oue); } if (ex.size() > 0) { if (environmentSettingException != null) { ex.add(0, environmentSettingException); } } for (OpenDsException oe : ex) { LOG.log(Level.WARNING, "Error reading configuration: " + oe, oe); } exceptions = Collections.unmodifiableList(ex); administrativeUsers = Collections.unmodifiableSet(as); listeners = Collections.unmodifiableSet(ls); backends = Collections.unmodifiableSet(bs); }
/** * Rebuild index(es) in the backend instance. Note that the server will not explicitly initialize * this backend before calling this method. * * @param rebuildConfig The rebuild configuration. * @throws ConfigException If an unrecoverable problem arises during initialization. * @throws InitializationException If a problem occurs during initialization that is not related * to the server configuration. * @throws DirectoryException If a Directory Server error occurs. */ public void rebuildBackend(RebuildConfig rebuildConfig) throws InitializationException, ConfigException, DirectoryException { // If the backend already has the root container open, we must use the same // underlying root container boolean openRootContainer = rootContainer == null; /* * If the rootContainer is open, the backend is initialized by something * else. We can't do any rebuild of system indexes while others are using * this backend. */ if (!openRootContainer && rebuildConfig.includesSystemIndex()) { Message message = ERR_JEB_REBUILD_BACKEND_ONLINE.get(); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } try { EnvironmentConfig envConfig; if (openRootContainer) { envConfig = new EnvironmentConfig(); envConfig.setAllowCreate(true); envConfig.setTransactional(false); envConfig.setDurability(Durability.COMMIT_NO_SYNC); envConfig.setLockTimeout(0, TimeUnit.SECONDS); envConfig.setTxnTimeout(0, TimeUnit.SECONDS); envConfig.setConfigParam( EnvironmentConfig.CLEANER_MIN_FILE_UTILIZATION, String.valueOf(cfg.getDBCleanerMinUtilization())); envConfig.setConfigParam( EnvironmentConfig.LOG_FILE_MAX, String.valueOf(cfg.getDBLogFileMax())); Importer importer = new Importer(rebuildConfig, cfg, envConfig); rootContainer = initializeRootContainer(envConfig); importer.rebuildIndexes(rootContainer); } else { envConfig = ConfigurableEnvironment.parseConfigEntry(cfg); Importer importer = new Importer(rebuildConfig, cfg, envConfig); importer.rebuildIndexes(rootContainer); } } catch (ExecutionException execEx) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, execEx); } Message message = ERR_EXECUTION_ERROR.get(execEx.getMessage()); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } catch (InterruptedException intEx) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, intEx); } Message message = ERR_INTERRUPTED_ERROR.get(intEx.getMessage()); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } catch (ConfigException ce) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ce); } throw new DirectoryException( DirectoryServer.getServerErrorResultCode(), ce.getMessageObject()); } catch (JebException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } throw new DirectoryException( DirectoryServer.getServerErrorResultCode(), e.getMessageObject()); } catch (InitializationException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } throw new InitializationException(e.getMessageObject()); } finally { // If a root container was opened in this method as read only, close it // to leave the backend in the same state. if (openRootContainer && rootContainer != null) { try { rootContainer.close(); rootContainer = null; } catch (DatabaseException e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } } } } }
/** {@inheritDoc} */ @Override() public LDIFImportResult importLDIF(LDIFImportConfig importConfig) throws DirectoryException { RuntimeInformation.logInfo(); // If the backend already has the root container open, we must use the same // underlying root container boolean openRootContainer = rootContainer == null; // If the rootContainer is open, the backend is initialized by something // else. // We can't do import while the backend is online. if (!openRootContainer) { Message message = ERR_JEB_IMPORT_BACKEND_ONLINE.get(); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } try { EnvironmentConfig envConfig = new EnvironmentConfig(); envConfig.setAllowCreate(true); envConfig.setTransactional(false); envConfig.setDurability(Durability.COMMIT_NO_SYNC); envConfig.setLockTimeout(0, TimeUnit.SECONDS); envConfig.setTxnTimeout(0, TimeUnit.SECONDS); envConfig.setConfigParam( EnvironmentConfig.CLEANER_MIN_FILE_UTILIZATION, String.valueOf(cfg.getDBCleanerMinUtilization())); envConfig.setConfigParam( EnvironmentConfig.LOG_FILE_MAX, String.valueOf(cfg.getDBLogFileMax())); if (!importConfig.appendToExistingData()) { if (importConfig.clearBackend() || cfg.getBaseDN().size() <= 1) { // We have the writer lock on the environment, now delete the // environment and re-open it. Only do this when we are // importing to all the base DNs in the backend or if the backend only // have one base DN. File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); // If the backend does not exist the import will create it. if (backendDirectory.exists()) { EnvManager.removeFiles(backendDirectory.getPath()); } } } Importer importer = new Importer(importConfig, cfg, envConfig); rootContainer = initializeRootContainer(envConfig); return importer.processImport(rootContainer); } catch (ExecutionException execEx) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, execEx); } if (execEx.getCause() instanceof DirectoryException) { throw ((DirectoryException) execEx.getCause()); } else { Message message = ERR_EXECUTION_ERROR.get(execEx.getMessage()); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } } catch (InterruptedException intEx) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, intEx); } Message message = ERR_INTERRUPTED_ERROR.get(intEx.getMessage()); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), message); } catch (JebException je) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, je); } throw new DirectoryException( DirectoryServer.getServerErrorResultCode(), je.getMessageObject()); } catch (InitializationException ie) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ie); } throw new DirectoryException( DirectoryServer.getServerErrorResultCode(), ie.getMessageObject()); } catch (ConfigException ce) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, ce); } throw new DirectoryException( DirectoryServer.getServerErrorResultCode(), ce.getMessageObject()); } finally { // leave the backend in the same state. try { if (rootContainer != null) { long startTime = System.currentTimeMillis(); rootContainer.close(); long finishTime = System.currentTimeMillis(); long closeTime = (finishTime - startTime) / 1000; Message msg = NOTE_JEB_IMPORT_LDIF_ROOTCONTAINER_CLOSE.get(closeTime); logError(msg); rootContainer = null; } // Sync the environment to disk. if (debugEnabled()) { Message message = NOTE_JEB_IMPORT_CLOSING_DATABASE.get(); TRACER.debugInfo(message.toString()); } } catch (DatabaseException de) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, de); } } } }
/** {@inheritDoc} */ @Override() public void initializeBackend() throws ConfigException, InitializationException { // Checksum this db environment and register its offline state id/checksum. DirectoryServer.registerOfflineBackendStateID(this.getBackendID(), checksumDbEnv()); if (rootContainer == null) { EnvironmentConfig envConfig = ConfigurableEnvironment.parseConfigEntry(cfg); rootContainer = initializeRootContainer(envConfig); } // Preload the database cache. rootContainer.preload(cfg.getPreloadTimeLimit()); try { // Log an informational message about the number of entries. Message message = NOTE_JEB_BACKEND_STARTED.get(cfg.getBackendId(), rootContainer.getEntryCount()); logError(message); } catch (DatabaseException databaseException) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, databaseException); } Message message = WARN_JEB_GET_ENTRY_COUNT_FAILED.get(databaseException.getMessage()); throw new InitializationException(message, databaseException); } for (DN dn : cfg.getBaseDN()) { try { DirectoryServer.registerBaseDN(dn, this, false); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } Message message = ERR_BACKEND_CANNOT_REGISTER_BASEDN.get(String.valueOf(dn), String.valueOf(e)); throw new InitializationException(message, e); } } // Register a monitor provider for the environment. rootContainerMonitor = rootContainer.getMonitorProvider(); DirectoryServer.registerMonitorProvider(rootContainerMonitor); // Register as disk space monitor handler File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); diskMonitor = new DiskSpaceMonitor( getBackendID() + " backend", backendDirectory, cfg.getDiskLowThreshold(), cfg.getDiskFullThreshold(), 5, TimeUnit.SECONDS, this); diskMonitor.initializeMonitorProvider(null); DirectoryServer.registerMonitorProvider(diskMonitor); // Register as an AlertGenerator. DirectoryServer.registerAlertGenerator(this); // Register this backend as a change listener. cfg.addLocalDBChangeListener(this); }
/** {@inheritDoc} */ public DN getComponentEntryDN() { return cfg.dn(); }
/** * Clears all the entries from the backend. This method is for test cases that use the JE backend. * * @throws ConfigException If an unrecoverable problem arises in the process of performing the * initialization. * @throws JebException If an error occurs while removing the data. */ public void clearBackend() throws ConfigException, JebException { // Determine the backend database directory. File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); EnvManager.removeFiles(backendDirectory.getPath()); }
/** {@inheritDoc} */ public ConfigChangeResult applyConfigurationChange(LocalDBBackendCfg newCfg) { ConfigChangeResult ccr; ResultCode resultCode = ResultCode.SUCCESS; ArrayList<Message> messages = new ArrayList<Message>(); try { if (rootContainer != null) { DN[] newBaseDNs = new DN[newCfg.getBaseDN().size()]; newBaseDNs = newCfg.getBaseDN().toArray(newBaseDNs); // Check for changes to the base DNs. for (DN baseDN : cfg.getBaseDN()) { boolean found = false; for (DN dn : newBaseDNs) { if (dn.equals(baseDN)) { found = true; } } if (!found) { // The base DN was deleted. DirectoryServer.deregisterBaseDN(baseDN); EntryContainer ec = rootContainer.unregisterEntryContainer(baseDN); ec.close(); ec.delete(); } } for (DN baseDN : newBaseDNs) { if (!rootContainer.getBaseDNs().contains(baseDN)) { try { // The base DN was added. EntryContainer ec = rootContainer.openEntryContainer(baseDN, null); rootContainer.registerEntryContainer(baseDN, ec); DirectoryServer.registerBaseDN(baseDN, this, false); } catch (Exception e) { if (debugEnabled()) { TRACER.debugCaught(DebugLogLevel.ERROR, e); } resultCode = DirectoryServer.getServerErrorResultCode(); messages.add( ERR_BACKEND_CANNOT_REGISTER_BASEDN.get( String.valueOf(baseDN), String.valueOf(e))); ccr = new ConfigChangeResult(resultCode, false, messages); return ccr; } } } baseDNs = newBaseDNs; } if (cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() || cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold()) { diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold()); diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold()); } // Put the new configuration in place. this.cfg = newCfg; } catch (Exception e) { messages.add(Message.raw(stackTraceToSingleLineString(e))); ccr = new ConfigChangeResult(DirectoryServer.getServerErrorResultCode(), false, messages); return ccr; } ccr = new ConfigChangeResult(resultCode, false, messages); return ccr; }