opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/BackendImpl.java
@@ -27,7 +27,6 @@ package org.opends.server.backends.jeb; import static com.sleepycat.je.EnvironmentConfig.*; import static org.opends.messages.BackendMessages.*; import static org.opends.messages.JebMessages.*; import static org.opends.server.backends.jeb.ConfigurableEnvironment.*; @@ -206,14 +205,11 @@ 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); diskMonitor = newDiskMonitor(cfg); if (diskMonitor != null) { DirectoryServer.registerMonitorProvider(diskMonitor); } //Register as an AlertGenerator. DirectoryServer.registerAlertGenerator(this); @@ -221,6 +217,18 @@ cfg.addLocalDBChangeListener(this); } private DiskSpaceMonitor newDiskMonitor(LocalDBBackendCfg cfg) throws ConfigException, InitializationException { File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); DiskSpaceMonitor dm = new DiskSpaceMonitor(getBackendID() + " backend", backendDirectory, cfg.getDiskLowThreshold(), cfg.getDiskFullThreshold(), 5, TimeUnit.SECONDS, this); dm.initializeMonitorProvider(null); return dm; } /** {@inheritDoc} */ @Override public void finalizeBackend() @@ -1000,11 +1008,9 @@ baseDNs = newBaseDNsArray; } if(cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() || cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold()) if (diskMonitor != null) { diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold()); diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold()); updateDiskMonitor(diskMonitor, newCfg); } // Put the new configuration in place. @@ -1018,6 +1024,15 @@ return ccr; } /** * @param newCfg */ private void updateDiskMonitor(DiskSpaceMonitor dm, LocalDBBackendCfg newCfg) { dm.setFullThreshold(newCfg.getDiskFullThreshold()); dm.setLowThreshold(newCfg.getDiskLowThreshold()); } private void removeDeletedBaseDNs(SortedSet<DN> newBaseDNs) throws DirectoryException { for (DN baseDN : cfg.getBaseDN()) opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
@@ -27,17 +27,23 @@ import static com.persistit.Transaction.CommitPolicy.*; import static java.util.Arrays.*; import static org.opends.messages.ConfigMessages.ERR_CONFIG_BACKEND_INSANE_MODE; import static org.opends.messages.ConfigMessages.ERR_CONFIG_BACKEND_MODE_INVALID; import static org.opends.messages.JebMessages.*; import static org.opends.server.util.StaticUtils.*; import java.io.File; import java.io.FilenameFilter; import java.util.HashMap; import java.util.List; import java.util.Map; import org.forgerock.i18n.LocalizableMessage; import org.forgerock.i18n.slf4j.LocalizedLogger; import org.forgerock.opendj.config.server.ConfigChangeResult; import org.forgerock.opendj.ldap.ByteSequence; import org.forgerock.opendj.ldap.ByteString; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.backends.pluggable.spi.Cursor; @@ -49,6 +55,9 @@ import org.opends.server.backends.pluggable.spi.UpdateFunction; import org.opends.server.backends.pluggable.spi.WriteOperation; import org.opends.server.backends.pluggable.spi.WriteableStorage; import org.opends.server.config.ConfigException; import org.opends.server.core.DirectoryServer; import org.opends.server.types.FilePermission; import com.persistit.Configuration; import com.persistit.Configuration.BufferPoolConfiguration; @@ -65,7 +74,7 @@ import com.persistit.exception.RollbackException; /** PersistIt database implementation of the {@link Storage} engine. */ public final class PersistItStorage implements Storage public final class PersistItStorage implements Storage, ConfigurationChangeListener<PersistitBackendCfg> { private static final String VOLUME_NAME = "dj"; /** The buffer / page size used by the PersistIt storage. */ @@ -504,6 +513,7 @@ throw new IllegalStateException(e); } } config.removePersistitChangeListener(this); } /** {@inheritDoc} */ @@ -537,6 +547,7 @@ bufferPoolCfg.setFraction(cfg.getDBCachePercent() / 100.0f); } dbCfg.setCommitPolicy(cfg.isDBTxnNoSync() ? SOFT : GROUP); cfg.addPersistitChangeListener(this); } private BufferPoolConfiguration getBufferPoolCfg() @@ -553,8 +564,9 @@ /** {@inheritDoc} */ @Override public void open() public void open() throws Exception { setupStorageFiles(); try { db = new Persistit(dbCfg); @@ -621,21 +633,15 @@ /** {@inheritDoc} */ @Override public Importer startImport() public Importer startImport() throws Exception { clearAndCreateDbDir(backendDirectory); open(); return new ImporterImpl(); } /** * Replace persistit reserved comma character with an underscore character. * * @param suffix * the suffix name to convert * @return a new String suitable for use as a suffix name */ public String toSuffixName(final String suffix) /** {@inheritDoc} */ public String toSafeSuffixName(final String suffix) { return suffix.replaceAll("[,=]", "_"); } @@ -700,7 +706,7 @@ }; } /* /** * TODO: it would be nice to use the low-level key/value APIs. They seem quite * inefficient at the moment for simple byte arrays. */ @@ -735,4 +741,235 @@ } return null; } /** {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable(PersistitBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) { boolean acceptable = true; File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); //Make sure the directory either already exists or is able to create. if (!backendDirectory.exists()) { if(!backendDirectory.mkdirs()) { unacceptableReasons.add(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath())); acceptable = false; } else { backendDirectory.delete(); } } else if (!backendDirectory.isDirectory()) { unacceptableReasons.add(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath())); acceptable = false; } try { FilePermission newBackendPermission = FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions()); //Make sure the mode will allow the server itself access to the database if(!newBackendPermission.isOwnerWritable() || !newBackendPermission.isOwnerReadable() || !newBackendPermission.isOwnerExecutable()) { LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get( cfg.getDBDirectoryPermissions()); unacceptableReasons.add(message); acceptable = false; } } catch(Exception e) { unacceptableReasons.add(ERR_CONFIG_BACKEND_MODE_INVALID.get(cfg.dn())); acceptable = false; } return acceptable; } /** {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange(PersistitBackendCfg cfg) { final ConfigChangeResult ccr = new ConfigChangeResult(); try { // Create the directory if it doesn't exist. if(!cfg.getDBDirectory().equals(this.config.getDBDirectory())) { File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); if (!backendDirectory.exists()) { if (!backendDirectory.mkdirs()) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath())); return ccr; } } //Make sure the directory is valid. else if (!backendDirectory.isDirectory()) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath())); return ccr; } ccr.setAdminActionRequired(true); ccr.addMessage(NOTE_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(this.config.getDBDirectory(), cfg.getDBDirectory())); } if (!cfg.getDBDirectoryPermissions().equalsIgnoreCase(config.getDBDirectoryPermissions()) || !cfg.getDBDirectory().equals(this.config.getDBDirectory())) { FilePermission backendPermission; try { backendPermission = FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions()); } catch(Exception e) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn())); return ccr; } // Make sure the mode will allow the server itself access to the database if(!backendPermission.isOwnerWritable() || !backendPermission.isOwnerReadable() || !backendPermission.isOwnerExecutable()) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_CONFIG_BACKEND_INSANE_MODE.get(cfg.getDBDirectoryPermissions())); return ccr; } // Get the backend database backendDirectory permissions and apply if(FilePermission.canSetPermissions()) { File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); try { if (!FilePermission.setPermissions(backendDirectory, backendPermission)) { logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory); } } catch(Exception e) { // Log an warning that the permissions were not set. logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e); } } } this.config = cfg; } catch (Exception e) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(LocalizableMessage.raw(stackTraceToSingleLineString(e))); } return ccr; } /** {@inheritDoc} */ private void setupStorageFiles() throws Exception { // Create the directory if it doesn't exist. if (!backendDirectory.exists()) { if(!backendDirectory.mkdirs()) { LocalizableMessage message = ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()); throw new ConfigException(message); } } //Make sure the directory is valid. else if (!backendDirectory.isDirectory()) { throw new ConfigException(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath())); } FilePermission backendPermission; try { backendPermission = FilePermission.decodeUNIXMode(config.getDBDirectoryPermissions()); } catch(Exception e) { throw new ConfigException(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn())); } //Make sure the mode will allow the server itself access to //the database if(!backendPermission.isOwnerWritable() || !backendPermission.isOwnerReadable() || !backendPermission.isOwnerExecutable()) { LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get( config.getDBDirectoryPermissions()); throw new ConfigException(message); } // Get the backend database backendDirectory permissions and apply if(FilePermission.canSetPermissions()) { try { if(!FilePermission.setPermissions(backendDirectory, backendPermission)) { logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory); } } catch(Exception e) { // Log an warning that the permissions were not set. logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e); } } } /** {@inheritDoc} */ public void removeStorageFiles() throws StorageRuntimeException { if (!backendDirectory.isDirectory()) { LocalizableMessage msg = ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()); throw new StorageRuntimeException(msg.toString()); } try { File[] files = backendDirectory.listFiles(); for (File f : files) { f.delete(); } } catch (Exception e) { logger.traceException(e); LocalizableMessage message = ERR_JEB_REMOVE_FAIL.get(e.getMessage()); throw new StorageRuntimeException(message.toString(), e); } } } opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
@@ -26,19 +26,60 @@ package org.opends.server.backends.persistit; import static org.opends.server.util.StaticUtils.getFileForPath; import java.io.File; import java.util.concurrent.TimeUnit; import org.forgerock.opendj.config.server.ConfigException; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.backends.pluggable.BackendImpl; import org.opends.server.backends.pluggable.spi.Storage; import org.opends.server.extensions.DiskSpaceMonitor; import org.opends.server.types.InitializationException; /** * Class defined in the configuration for this backend type. */ public class PitBackend extends BackendImpl { /** {@inheritDoc} */ @Override protected Storage newStorageInstance() { return new PersistItStorage(); } /** {@inheritDoc} */ @Override public DiskSpaceMonitor newDiskMonitor(PluggableBackendCfg cfg) throws ConfigException, InitializationException { PersistitBackendCfg config = (PersistitBackendCfg) cfg; File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); DiskSpaceMonitor dm = new DiskSpaceMonitor(getBackendID() + " backend", backendDirectory, config.getDiskLowThreshold(), config.getDiskFullThreshold(), 5, TimeUnit.SECONDS, this); dm.initializeMonitorProvider(null); return dm; } /** {@inheritDoc} */ @Override public void updateDiskMonitor(DiskSpaceMonitor dm, PluggableBackendCfg newConfig) { PersistitBackendCfg newCfg = (PersistitBackendCfg) newConfig; dm.setFullThreshold(newCfg.getDiskFullThreshold()); dm.setLowThreshold(newCfg.getDiskLowThreshold()); } /** {@inheritDoc} */ protected File getBackupDirectory(PluggableBackendCfg cfg) { PersistitBackendCfg config = (PersistitBackendCfg) cfg; File parentDir = getFileForPath(config.getDBDirectory()); return new File(parentDir, config.getBackendId()); } } opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
@@ -35,7 +35,6 @@ import java.io.File; import java.io.IOException; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import org.forgerock.i18n.LocalizableMessage; @@ -47,7 +46,7 @@ import org.forgerock.util.Reject; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.meta.BackendIndexCfgDefn; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.api.AlertGenerator; import org.opends.server.api.Backend; import org.opends.server.api.DiskSpaceMonitorHandler; @@ -65,14 +64,14 @@ * This is an implementation of a Directory Server Backend which stores entries * locally in a Berkeley DB JE database. */ public abstract class BackendImpl extends Backend<PersistitBackendCfg> implements ConfigurationChangeListener<PersistitBackendCfg>, AlertGenerator, public abstract class BackendImpl extends Backend<PluggableBackendCfg> implements ConfigurationChangeListener<PluggableBackendCfg>, AlertGenerator, DiskSpaceMonitorHandler { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** The configuration of this backend. */ private PersistitBackendCfg cfg; private PluggableBackendCfg cfg; /** The root JE container to use for this backend. */ private RootContainer rootContainer; @@ -83,6 +82,7 @@ private DN[] baseDNs; private MonitorProvider<?> rootContainerMonitor; /** Disk space monitoring if the storage supports it. */ private DiskSpaceMonitor diskMonitor; /** The controls supported by this backend. */ @@ -128,7 +128,7 @@ /** {@inheritDoc} */ @Override public void configureBackend(PersistitBackendCfg cfg) throws ConfigException public void configureBackend(PluggableBackendCfg cfg) throws ConfigException { Reject.ifNull(cfg); @@ -179,27 +179,44 @@ 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); diskMonitor = newDiskMonitor(cfg); if (diskMonitor != null) { DirectoryServer.registerMonitorProvider(diskMonitor); } //Register as an AlertGenerator. DirectoryServer.registerAlertGenerator(this); // Register this backend as a change listener. cfg.addPersistitChangeListener(this); cfg.addPluggableChangeListener(this); } /** * Let the storage create a new disk monitor if supported. * * @param cfg this storage current configuration * @return a new disk monitor if supported or null * * @throws ConfigException if configuration is incorrect * @throws InitializationException when disk monitor cannot be initialized */ protected abstract DiskSpaceMonitor newDiskMonitor(PluggableBackendCfg cfg) throws ConfigException, InitializationException; /** * Updates the disk monitor when configuration changes. * * @param dm the disk monitor to update * @param newCfg the new configuration */ protected abstract void updateDiskMonitor(DiskSpaceMonitor dm, PluggableBackendCfg newCfg); /** {@inheritDoc} */ @Override public void finalizeBackend() { super.finalizeBackend(); cfg.removePersistitChangeListener(this); cfg.removePluggableChangeListener(this); // Deregister our base DNs. for (DN dn : rootContainer.getBaseDNs()) @@ -722,8 +739,7 @@ public void createBackup(BackupConfig backupConfig) throws DirectoryException { BackupManager backupManager = new BackupManager(getBackendID()); File parentDir = getFileForPath(cfg.getDBDirectory()); File backendDir = new File(parentDir, cfg.getBackendId()); File backendDir = getBackupDirectory(cfg); Storage storage = newStorageInstance(); backupConfig.setFilesToBackupFilter(storage.getFilesToBackupFilter()); backupManager.createBackup(backendDir, backupConfig); @@ -735,7 +751,6 @@ */ protected abstract Storage newStorageInstance(); /** {@inheritDoc} */ @Override public void removeBackup(BackupDirectory backupDirectory, String backupID) @@ -745,25 +760,27 @@ backupManager.removeBackup(backupDirectory, backupID); } /** {@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()); File backendDir = getBackupDirectory(cfg); backupManager.restoreBackup(backendDir, restoreConfig); } /** * Returns the backup directory. * * @param cfg the configuration for this backend * @return the backup directory */ protected abstract File getBackupDirectory(PluggableBackendCfg cfg); /** {@inheritDoc} */ @Override public boolean isConfigurationAcceptable(PersistitBackendCfg config, List<LocalizableMessage> unacceptableReasons) public boolean isConfigurationAcceptable(PluggableBackendCfg config, List<LocalizableMessage> unacceptableReasons) { return isConfigurationChangeAcceptable(config, unacceptableReasons); } @@ -772,9 +789,7 @@ /** {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable( PersistitBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) public boolean isConfigurationChangeAcceptable(PluggableBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) { return true; } @@ -783,7 +798,7 @@ /** {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange(final PersistitBackendCfg newCfg) public ConfigChangeResult applyConfigurationChange(final PluggableBackendCfg newCfg) { final ConfigChangeResult ccr = new ConfigChangeResult(); try @@ -807,11 +822,9 @@ baseDNs = newBaseDNsArray; if(cfg.getDiskFullThreshold() != newCfg.getDiskFullThreshold() || cfg.getDiskLowThreshold() != newCfg.getDiskLowThreshold()) if (diskMonitor != null) { diskMonitor.setFullThreshold(newCfg.getDiskFullThreshold()); diskMonitor.setLowThreshold(newCfg.getDiskLowThreshold()); updateDiskMonitor(diskMonitor, newCfg); } // Put the new configuration in place. @@ -906,7 +919,7 @@ * The StorageRuntimeException to be converted. * @return DirectoryException created from exception. */ DirectoryException createDirectoryException(StorageRuntimeException e) private DirectoryException createDirectoryException(StorageRuntimeException e) { if (true) // FIXME JNR { opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -60,7 +60,7 @@ import org.opends.server.admin.server.ConfigurationDeleteListener; import org.opends.server.admin.std.server.BackendIndexCfg; import org.opends.server.admin.std.server.BackendVLVIndexCfg; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.api.Backend; import org.opends.server.api.ClientConnection; import org.opends.server.api.EntryCache; @@ -109,14 +109,14 @@ * the guts of the backend API methods for LDAP operations. */ public class EntryContainer implements SuffixContainer, ConfigurationChangeListener<PersistitBackendCfg> implements SuffixContainer, ConfigurationChangeListener<PluggableBackendCfg> { private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); /** The name of the entry database. */ public static final String ID2ENTRY_DATABASE_NAME = ID2ENTRY_INDEX_NAME; private static final String ID2ENTRY_DATABASE_NAME = ID2ENTRY_INDEX_NAME; /** The name of the DN database. */ public static final String DN2ID_DATABASE_NAME = DN2ID_INDEX_NAME; private static final String DN2ID_DATABASE_NAME = DN2ID_INDEX_NAME; /** The name of the children index database. */ private static final String ID2CHILDREN_DATABASE_NAME = ID2CHILDREN_INDEX_NAME; /** The name of the subtree index database. */ @@ -141,7 +141,7 @@ private final DN baseDN; /** The backend configuration. */ private PersistitBackendCfg config; private PluggableBackendCfg config; /** The JE database environment. */ private final Storage storage; @@ -441,8 +441,8 @@ * @param rootContainer The root container this entry container is in. * @throws ConfigException if a configuration related error occurs. */ public EntryContainer(DN baseDN, String databasePrefix, Backend<?> backend, PersistitBackendCfg config, Storage env, RootContainer rootContainer) EntryContainer(DN baseDN, String databasePrefix, Backend<?> backend, PluggableBackendCfg config, Storage env, RootContainer rootContainer) throws ConfigException { this.backend = backend; @@ -452,7 +452,7 @@ this.rootContainer = rootContainer; this.databasePrefix = databasePrefix; config.addPersistitChangeListener(this); config.addPluggableChangeListener(this); attributeJEIndexCfgManager = new AttributeJEIndexCfgManager(); config.addBackendIndexAddListener(attributeJEIndexCfgManager); @@ -475,7 +475,7 @@ * @throws StorageRuntimeException If an error occurs in the JE database. * @throws ConfigException if a configuration related error occurs. */ public void open(WriteableStorage txn) throws StorageRuntimeException, ConfigException void open(WriteableStorage txn) throws StorageRuntimeException, ConfigException { try { @@ -577,7 +577,7 @@ } // Deregister any listeners. config.removePersistitChangeListener(this); config.removePluggableChangeListener(this); config.removeBackendIndexAddListener(attributeJEIndexCfgManager); config.removeBackendIndexDeleteListener(attributeJEIndexCfgManager); config.removeBackendVLVIndexAddListener(vlvJEIndexCfgManager); @@ -668,7 +668,7 @@ * @param attrType The attribute type for which an attribute index is needed. * @return The attribute index or null if there is none for that type. */ public AttributeIndex getAttributeIndex(AttributeType attrType) AttributeIndex getAttributeIndex(AttributeType attrType) { return attrIndexMap.get(attrType); } @@ -688,7 +688,7 @@ * @param vlvIndexName The vlv index name for which an vlv index is needed. * @return The VLV index or null if there is none with that name. */ public VLVIndex getVLVIndex(String vlvIndexName) VLVIndex getVLVIndex(String vlvIndexName) { return vlvIndexMap.get(vlvIndexName); } @@ -721,7 +721,7 @@ * @return The highest entry ID. * @throws StorageRuntimeException If an error occurs in the JE database. */ public EntryID getHighestEntryID(ReadableStorage txn) throws StorageRuntimeException EntryID getHighestEntryID(ReadableStorage txn) throws StorageRuntimeException { Cursor cursor = txn.openCursor(id2entry.getName()); try @@ -750,7 +750,7 @@ * the entry does not exist. * @throws StorageRuntimeException If an error occurs in the JE database. */ public long getNumSubordinates(final DN entryDN, final boolean subtree) long getNumSubordinates(final DN entryDN, final boolean subtree) throws StorageRuntimeException { try @@ -801,7 +801,7 @@ * @throws StorageRuntimeException If an error occurs in the JE database. * @throws CanceledOperationException if this operation should be cancelled. */ public void search(final SearchOperation searchOperation) void search(final SearchOperation searchOperation) throws DirectoryException, StorageRuntimeException, CanceledOperationException { try @@ -819,7 +819,7 @@ searchOperation.getRequestControl(ServerSideSortRequestControl.DECODER); if (sortRequest != null && !sortRequest.containsSortKeys() && sortRequest.isCritical()) { /** /* * If the control's criticality field is true then the server SHOULD * do the following: return unavailableCriticalExtension as a return * code in the searchResultDone message; include the @@ -1316,7 +1316,7 @@ * @throws DirectoryException * If an error occurs retrieving the entry */ public Entry getEntry(ReadableStorage txn, EntryID entryID) throws DirectoryException Entry getEntry(ReadableStorage txn, EntryID entryID) throws DirectoryException { // Try the entry cache first. final EntryCache entryCache = getEntryCache(); @@ -1421,12 +1421,8 @@ } // Process the candidate entry. if (entry != null) { // Filter the entry if it is in scope. if (isInScope(candidatesAreInScope, searchScope, aBaseDN, entry) && (manageDsaIT || entry.getReferralURLs() == null) && searchOperation.getFilter().matchesEntry(entry)) if (entry != null && isInScope(candidatesAreInScope, searchScope, aBaseDN, entry) && (manageDsaIT || entry.getReferralURLs() == null) && searchOperation.getFilter().matchesEntry(entry)) { if (pageRequest != null && searchOperation.getEntriesSent() == pageRequest.getSize()) @@ -1448,7 +1444,6 @@ } } } } searchOperation.checkIfCanceled(false); } @@ -1521,7 +1516,7 @@ * @throws StorageRuntimeException If an error occurs in the JE database. * @throws CanceledOperationException if this operation should be cancelled. */ public void addEntry(final Entry entry, final AddOperation addOperation) void addEntry(final Entry entry, final AddOperation addOperation) throws StorageRuntimeException, DirectoryException, CanceledOperationException { try @@ -1676,7 +1671,7 @@ * @throws StorageRuntimeException If an error occurs in the JE database. * @throws CanceledOperationException if this operation should be cancelled. */ public void deleteEntry(final DN entryDN, final DeleteOperation deleteOperation) void deleteEntry(final DN entryDN, final DeleteOperation deleteOperation) throws DirectoryException, StorageRuntimeException, CanceledOperationException { try @@ -1934,7 +1929,7 @@ * @throws DirectoryException If a problem occurs while trying to make the * determination. */ public boolean entryExists(final DN entryDN) throws DirectoryException private boolean entryExists(final DN entryDN) throws DirectoryException { // Try the entry cache first. EntryCache<?> entryCache = DirectoryServer.getEntryCache(); @@ -1975,7 +1970,7 @@ * the entry. * @throws StorageRuntimeException An error occurred during a database operation. */ public Entry getEntry(final DN entryDN) throws StorageRuntimeException, DirectoryException Entry getEntry(final DN entryDN) throws StorageRuntimeException, DirectoryException { try { @@ -2060,7 +2055,7 @@ * @throws DirectoryException If a Directory Server error occurs. * @throws CanceledOperationException if this operation should be cancelled. */ public void replaceEntry(final Entry oldEntry, final Entry newEntry, final ModifyOperation modifyOperation) void replaceEntry(final Entry oldEntry, final Entry newEntry, final ModifyOperation modifyOperation) throws StorageRuntimeException, DirectoryException, CanceledOperationException { try @@ -2187,7 +2182,7 @@ * modify DN operation. * @throws StorageRuntimeException If an error occurs in the JE database. */ public void renameEntry(final DN currentDN, final Entry entry, final ModifyDNOperation modifyDNOperation) void renameEntry(final DN currentDN, final Entry entry, final ModifyDNOperation modifyDNOperation) throws StorageRuntimeException, DirectoryException, CanceledOperationException { try @@ -2640,7 +2635,7 @@ * @param newSuffixDN The new DN of the renamed or moved entry. * @return The new DN of the subordinate entry. */ public static DN modDN(DN oldDN, int oldSuffixLen, DN newSuffixDN) static DN modDN(DN oldDN, int oldSuffixLen, DN newSuffixDN) { int oldDNNumComponents = oldDN.size(); int oldDNKeepComponents = oldDNNumComponents - oldSuffixLen; @@ -2745,7 +2740,7 @@ * @return The number of entries stored in this entry container. * @throws StorageRuntimeException If an error occurs in the JE database. */ public long getEntryCount(ReadableStorage txn) throws StorageRuntimeException long getEntryCount(ReadableStorage txn) throws StorageRuntimeException { final EntryID entryID = dn2id.get(txn, baseDN, false); if (entryID != null) @@ -2793,7 +2788,7 @@ * Get a list of the databases opened by the entryContainer. * @param dbList A list of database containers. */ public void listDatabases(List<DatabaseContainer> dbList) void listDatabases(List<DatabaseContainer> dbList) { dbList.add(dn2id); dbList.add(id2entry); @@ -2847,7 +2842,7 @@ * @throws StorageRuntimeException If an error occurs while removing the entry * container. */ public void delete(WriteableStorage txn) throws StorageRuntimeException void delete(WriteableStorage txn) throws StorageRuntimeException { List<DatabaseContainer> databases = new ArrayList<DatabaseContainer>(); listDatabases(databases); @@ -2866,7 +2861,7 @@ * @throws StorageRuntimeException If an error occurs while attempting to delete the * database. */ public void deleteDatabase(WriteableStorage txn, DatabaseContainer database) throws StorageRuntimeException void deleteDatabase(WriteableStorage txn, DatabaseContainer database) throws StorageRuntimeException { if(database == state) { @@ -3011,7 +3006,7 @@ * @param dn A DN which is in the scope of the base DN. * @return The parent DN, or null if the given DN is the base DN. */ public DN getParentWithinBase(DN dn) DN getParentWithinBase(DN dn) { if (dn.equals(baseDN)) { @@ -3023,7 +3018,7 @@ /** {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable( PersistitBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) PluggableBackendCfg cfg, List<LocalizableMessage> unacceptableReasons) { // This is always true because only all config attributes used // by the entry container should be validated by the admin framework. @@ -3032,7 +3027,7 @@ /** {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange(final PersistitBackendCfg cfg) public ConfigChangeResult applyConfigurationChange(final PluggableBackendCfg cfg) { final ConfigChangeResult ccr = new ConfigChangeResult(); @@ -3345,6 +3340,6 @@ /** {@inheritDoc} */ @Override public String toString() { return databasePrefix.toString(); return databasePrefix; } } opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
@@ -4054,7 +4054,7 @@ } finally { rootContainer.removeFiles(); storage.removeStorageFiles(); } } opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
@@ -26,15 +26,24 @@ */ package org.opends.server.backends.pluggable; import static org.opends.messages.BackendMessages.*; import static org.opends.messages.ConfigMessages.*; import static org.opends.messages.JebMessages.*; import static org.opends.messages.UtilityMessages.*; import static org.opends.server.core.DirectoryServer.*; import static org.opends.server.util.StaticUtils.*; import static org.opends.messages.BackendMessages.ERR_LDIF_BACKEND_CANNOT_CREATE_LDIF_READER; import static org.opends.messages.BackendMessages.ERR_LDIF_BACKEND_ERROR_READING_LDIF; import static org.opends.messages.JebMessages.ERR_JEB_CACHE_PRELOAD; import static org.opends.messages.JebMessages.ERR_JEB_REMOVE_FAIL; import static org.opends.messages.JebMessages.ERR_JEB_ENTRY_CONTAINER_ALREADY_REGISTERED; import static org.opends.messages.JebMessages.ERR_JEB_IMPORT_PARENT_NOT_FOUND; import static org.opends.messages.JebMessages.NOTE_JEB_IMPORT_FINAL_STATUS; import static org.opends.messages.JebMessages.NOTE_JEB_IMPORT_PROGRESS_REPORT; import static org.opends.messages.JebMessages.WARN_JEB_IMPORT_ENTRY_EXISTS; import static org.opends.messages.UtilityMessages.ERR_LDIF_SKIP; import static org.opends.server.core.DirectoryServer.getServerErrorResultCode; import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; import java.io.File; import java.util.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -45,9 +54,8 @@ import org.forgerock.opendj.config.server.ConfigChangeResult; import org.forgerock.opendj.config.server.ConfigException; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.server.PersistitBackendCfg; import org.opends.server.admin.std.server.PluggableBackendCfg; import org.opends.server.api.CompressedSchema; import org.opends.server.backends.persistit.PersistItStorage; import org.opends.server.backends.pluggable.spi.ReadOperation; import org.opends.server.backends.pluggable.spi.ReadableStorage; import org.opends.server.backends.pluggable.spi.Storage; @@ -58,7 +66,6 @@ import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.Entry; import org.opends.server.types.FilePermission; import org.opends.server.types.InitializationException; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.LDIFImportResult; @@ -67,13 +74,13 @@ import org.opends.server.util.LDIFReader; import org.opends.server.util.RuntimeInformation; /** * Wrapper class for the JE environment. Root container holds all the entry * containers for each base DN. It also maintains all the openings and closings * of the entry containers. */ public class RootContainer implements ConfigurationChangeListener<PersistitBackendCfg> public class RootContainer implements ConfigurationChangeListener<PluggableBackendCfg> { /** Logs the progress of the import. */ private static final class ImportProgress implements Runnable @@ -112,16 +119,14 @@ private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); private static final int IMPORT_PROGRESS_INTERVAL = 10000; private static final int KB = 1024; /** The JE database environment. */ private PersistItStorage storage; // FIXME JNR do not hardcode here private Storage storage; private final File backendDirectory; /** The backend to which this entry root container belongs. */ private final BackendImpl backend; /** The backend configuration. */ private PersistitBackendCfg config; private PluggableBackendCfg config; /** The database environment monitor for this JE environment. */ private DatabaseEnvironmentMonitor monitor; @@ -134,26 +139,25 @@ /** The compressed schema manager for this backend. */ private JECompressedSchema compressedSchema; /** * Creates a new RootContainer object. Each root container represents a JE * environment. * * @param config The configuration of the JE backend. * @param backend A reference to the JE back end that is creating this * root container. * @param config * The configuration of the JE backend. * @param backend * A reference to the JE back end that is creating this root * container. */ public RootContainer(BackendImpl backend, PersistitBackendCfg config) RootContainer(BackendImpl backend, PluggableBackendCfg config) { this.backend = backend; this.config = config; this.backendDirectory = new File(getFileForPath(config.getDBDirectory()), config.getBackendId()); getMonitorProvider().enableFilterUseStats(config.isIndexFilterAnalyzerEnabled()); getMonitorProvider().setMaxEntries(config.getIndexFilterAnalyzerMaxFilters()); config.addPersistitChangeListener(this); config.addPluggableChangeListener(this); } /** @@ -167,20 +171,33 @@ } /** * Imports information from an LDIF file into this backend. * This method should only be called if {@code supportsLDIFImport} returns {@code true}. * Note that the server will not explicitly initialize this backend before calling this method. * Imports information from an LDIF file into this backend. This method should * only be called if {@code supportsLDIFImport} returns {@code true}. <p>Note * that the server will not explicitly initialize this backend before calling * this method. * * @param importConfig The configuration to use when performing the import. * @param importConfig * The configuration to use when performing the import. * @return information about the result of the import processing. * @throws DirectoryException If a problem occurs while performing the LDIF import. * @throws DirectoryException * If a problem occurs while performing the LDIF import. */ LDIFImportResult importLDIF(LDIFImportConfig importConfig) throws DirectoryException { RuntimeInformation.logInfo(); if (Importer.mustClearBackend(importConfig, config)) { removeFiles(); try { Storage storage = backend.newStorageInstance(); storage.initialize(config); storage.removeStorageFiles(); } catch (Exception e) { LocalizableMessage m = ERR_JEB_REMOVE_FAIL.get(e.getMessage()); throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), m, e); } } try { @@ -275,8 +292,8 @@ { rate = 1000f * reader.getEntriesRead() / importTime; } logger.info(NOTE_JEB_IMPORT_FINAL_STATUS, reader.getEntriesRead(), importCount, reader.getEntriesIgnored(), reader.getEntriesRejected(), 0, importTime / 1000, rate); logger.info(NOTE_JEB_IMPORT_FINAL_STATUS, reader.getEntriesRead(), importCount, reader.getEntriesIgnored(), reader.getEntriesRejected(), 0, importTime / 1000, rate); return new LDIFImportResult(reader.getEntriesRead(), reader.getEntriesRejected(), reader.getEntriesIgnored()); } finally @@ -311,35 +328,6 @@ } /** * Removes all the files from the rootContainer's directory. * * @throws StorageRuntimeException If a problem occurred */ void removeFiles() throws StorageRuntimeException { if (!backendDirectory.isDirectory()) { LocalizableMessage msg = ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath()); throw new StorageRuntimeException(msg.toString()); } try { File[] jdbFiles = backendDirectory.listFiles(); for (File f : jdbFiles) { f.delete(); } } catch (Exception e) { logger.traceException(e); LocalizableMessage message = ERR_JEB_REMOVE_FAIL.get(e.getMessage()); throw new StorageRuntimeException(message.toString(), e); } } /** * Opens the root container. * * @throws StorageRuntimeException @@ -349,64 +337,9 @@ */ void open() throws StorageRuntimeException, ConfigException { // Create the directory if it doesn't exist. if (!backendDirectory.exists()) { if(!backendDirectory.mkdirs()) { LocalizableMessage message = ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath()); throw new ConfigException(message); } } //Make sure the directory is valid. else if (!backendDirectory.isDirectory()) { throw new ConfigException(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath())); } FilePermission backendPermission; try { backendPermission = FilePermission.decodeUNIXMode(config.getDBDirectoryPermissions()); } catch(Exception e) { throw new ConfigException(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn())); } //Make sure the mode will allow the server itself access to //the database if(!backendPermission.isOwnerWritable() || !backendPermission.isOwnerReadable() || !backendPermission.isOwnerExecutable()) { LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get( config.getDBDirectoryPermissions()); throw new ConfigException(message); } // Get the backend database backendDirectory permissions and apply if(FilePermission.canSetPermissions()) { try { if(!FilePermission.setPermissions(backendDirectory, backendPermission)) { logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory); } } catch(Exception e) { // Log an warning that the permissions were not set. logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e); } } try { storage = (PersistItStorage) backend.newStorageInstance(); storage = backend.newStorageInstance(); storage.initialize(config); storage.open(); storage.write(new WriteOperation() @@ -433,21 +366,24 @@ * containers opened in a non transactional root container will also be non * transactional. * * @param baseDN The base DN of the entry container to open. * @param name The name of the entry container or <CODE>NULL</CODE> to open * the default entry container for the given base DN. * @param txn The database transaction * @param baseDN * The base DN of the entry container to open. * @param name * The name of the entry container or <CODE>NULL</CODE> to open the * default entry container for the given base DN. * @param txn * The database transaction * @return The opened entry container. * @throws StorageRuntimeException If an error occurs while opening the entry * container. * @throws ConfigException If an configuration error occurs while opening * the entry container. * @throws StorageRuntimeException * If an error occurs while opening the entry container. * @throws ConfigException * If an configuration error occurs while opening the entry container. */ public EntryContainer openEntryContainer(DN baseDN, String name, WriteableStorage txn) EntryContainer openEntryContainer(DN baseDN, String name, WriteableStorage txn) throws StorageRuntimeException, ConfigException { String databasePrefix; if(name == null || name.equals("")) if (name == null || "".equals(name)) { databasePrefix = baseDN.toIrreversibleReadableString(); } @@ -456,8 +392,8 @@ databasePrefix = name; } EntryContainer ec = new EntryContainer(baseDN, storage.toSuffixName(databasePrefix), backend, config, storage, this); EntryContainer ec = new EntryContainer(baseDN, storage.toSafeSuffixName(databasePrefix), backend, config, storage, this); ec.open(txn); return ec; } @@ -465,13 +401,14 @@ /** * Registers the entry container for a base DN. * * @param baseDN The base DN of the entry container to close. * @param entryContainer The entry container to register for the baseDN. * @throws InitializationException If an error occurs while opening the * entry container. * @param baseDN * The base DN of the entry container to close. * @param entryContainer * The entry container to register for the baseDN. * @throws InitializationException * If an error occurs while opening the entry container. */ public void registerEntryContainer(DN baseDN, EntryContainer entryContainer) throws InitializationException void registerEntryContainer(DN baseDN, EntryContainer entryContainer) throws InitializationException { EntryContainer ec1 = this.entryContainers.get(baseDN); @@ -479,8 +416,8 @@ // another to be opened. if (ec1 != null) { throw new InitializationException(ERR_JEB_ENTRY_CONTAINER_ALREADY_REGISTERED.get( ec1.getDatabasePrefix(), baseDN)); throw new InitializationException(ERR_JEB_ENTRY_CONTAINER_ALREADY_REGISTERED.get(ec1.getDatabasePrefix(), baseDN)); } this.entryContainers.put(baseDN, entryContainer); @@ -489,16 +426,19 @@ /** * Opens the entry containers for multiple base DNs. * * @param baseDNs The base DNs of the entry containers to open. * @throws StorageRuntimeException If a database error occurs while opening * the entry container. * @throws InitializationException If an initialization error occurs while * opening the entry container. * @throws ConfigException If a configuration error occurs while * opening the entry container. * @param baseDNs * The base DNs of the entry containers to open. * @throws StorageRuntimeException * If a database error occurs while opening the entry container. * @throws InitializationException * If an initialization error occurs while opening the entry * container. * @throws ConfigException * If a configuration error occurs while opening the entry * container. */ private void openAndRegisterEntryContainers(WriteableStorage txn, Set<DN> baseDNs) throws StorageRuntimeException, InitializationException, ConfigException private void openAndRegisterEntryContainers(WriteableStorage txn, Set<DN> baseDNs) throws StorageRuntimeException, InitializationException, ConfigException { EntryID highestID = null; for(DN baseDN : baseDNs) @@ -518,11 +458,12 @@ /** * Unregisters the entry container for a base DN. * * @param baseDN The base DN of the entry container to close. * @param baseDN * The base DN of the entry container to close. * @return The entry container that was unregistered or NULL if a entry * container for the base DN was not registered. */ public EntryContainer unregisterEntryContainer(DN baseDN) EntryContainer unregisterEntryContainer(DN baseDN) { return entryContainers.remove(baseDN); } @@ -541,7 +482,7 @@ * Get the DatabaseEnvironmentMonitor object for JE environment used by this * root container. * * @return The DatabaseEnvironmentMonito object. * @return The DatabaseEnvironmentMonitor object. */ public DatabaseEnvironmentMonitor getMonitorProvider() { @@ -558,9 +499,10 @@ * Preload the database cache. There is no preload if the configured preload * time limit is zero. * * @param timeLimit The time limit for the preload process. * @param timeLimit * The time limit for the preload process. */ public void preload(long timeLimit) void preload(long timeLimit) { if (timeLimit > 0) { @@ -601,10 +543,10 @@ /** * Closes this root container. * * @throws StorageRuntimeException If an error occurs while attempting to close * the root container. * @throws StorageRuntimeException * If an error occurs while attempting to close the root container. */ public void close() throws StorageRuntimeException void close() throws StorageRuntimeException { for(DN baseDN : entryContainers.keySet()) { @@ -621,7 +563,7 @@ } compressedSchema.close(); config.removePersistitChangeListener(this); config.removePluggableChangeListener(this); if (storage != null) { @@ -653,10 +595,11 @@ /** * Return the entry container for a specific base DN. * * @param baseDN The base DN of the entry container to retrieve. * @param baseDN * The base DN of the entry container to retrieve. * @return The entry container for the base DN. */ public EntryContainer getEntryContainer(DN baseDN) EntryContainer getEntryContainer(DN baseDN) { EntryContainer ec = null; DN nodeDN = baseDN; @@ -673,14 +616,12 @@ return ec; } /** * Get the backend configuration used by this root container. * * @return The backend configuration used by this root container. */ public PersistitBackendCfg getConfiguration() public PluggableBackendCfg getConfiguration() { return config; } @@ -689,8 +630,8 @@ * Get the total number of entries in this root container. * * @return The number of entries in this root container * @throws StorageRuntimeException If an error occurs while retrieving the entry * count. * @throws StorageRuntimeException * If an error occurs while retrieving the entry count. */ public long getEntryCount() throws StorageRuntimeException { @@ -753,176 +694,28 @@ nextid.set(1); } /** {@inheritDoc} */ @Override public boolean isConfigurationChangeAcceptable( PersistitBackendCfg cfg, public boolean isConfigurationChangeAcceptable(PluggableBackendCfg configuration, List<LocalizableMessage> unacceptableReasons) { boolean acceptable = true; File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); //Make sure the directory either already exists or is able to create. if (!backendDirectory.exists()) { if(!backendDirectory.mkdirs()) { unacceptableReasons.add(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath())); acceptable = false; // Storage has also registered a change listener, delegate to it. return true; } else { backendDirectory.delete(); } } //Make sure the directory is valid. else if (!backendDirectory.isDirectory()) { unacceptableReasons.add(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath())); acceptable = false; } try { FilePermission newBackendPermission = FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions()); //Make sure the mode will allow the server itself access to //the database if(!newBackendPermission.isOwnerWritable() || !newBackendPermission.isOwnerReadable() || !newBackendPermission.isOwnerExecutable()) { LocalizableMessage message = ERR_CONFIG_BACKEND_INSANE_MODE.get( cfg.getDBDirectoryPermissions()); unacceptableReasons.add(message); acceptable = false; } } catch(Exception e) { unacceptableReasons.add(ERR_CONFIG_BACKEND_MODE_INVALID.get(cfg.dn())); acceptable = false; } try { // FIXME JNR validate database specific configuration } catch (Exception e) { unacceptableReasons.add(LocalizableMessage.raw(e.getLocalizedMessage())); acceptable = false; } return acceptable; } /** {@inheritDoc} */ @Override public ConfigChangeResult applyConfigurationChange(PersistitBackendCfg cfg) public ConfigChangeResult applyConfigurationChange(PluggableBackendCfg configuration) { final ConfigChangeResult ccr = new ConfigChangeResult(); getMonitorProvider().enableFilterUseStats(configuration.isIndexFilterAnalyzerEnabled()); getMonitorProvider().setMaxEntries(configuration.getIndexFilterAnalyzerMaxFilters()); try { // Create the directory if it doesn't exist. if(!cfg.getDBDirectory().equals(this.config.getDBDirectory())) { File parentDirectory = getFileForPath(cfg.getDBDirectory()); File backendDirectory = new File(parentDirectory, cfg.getBackendId()); if (!backendDirectory.exists()) { if(!backendDirectory.mkdirs()) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_JEB_CREATE_FAIL.get(backendDirectory.getPath())); return ccr; } } //Make sure the directory is valid. else if (!backendDirectory.isDirectory()) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_JEB_DIRECTORY_INVALID.get(backendDirectory.getPath())); return ccr; } ccr.setAdminActionRequired(true); ccr.addMessage(NOTE_JEB_CONFIG_DB_DIR_REQUIRES_RESTART.get(this.config.getDBDirectory(), cfg.getDBDirectory())); } if (!cfg.getDBDirectoryPermissions().equalsIgnoreCase(config.getDBDirectoryPermissions()) || !cfg.getDBDirectory().equals(this.config.getDBDirectory())) { FilePermission backendPermission; try { backendPermission = FilePermission.decodeUNIXMode(cfg.getDBDirectoryPermissions()); } catch(Exception e) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_CONFIG_BACKEND_MODE_INVALID.get(config.dn())); return ccr; } // Make sure the mode will allow the server itself access to the database if(!backendPermission.isOwnerWritable() || !backendPermission.isOwnerReadable() || !backendPermission.isOwnerExecutable()) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(ERR_CONFIG_BACKEND_INSANE_MODE.get(cfg.getDBDirectoryPermissions())); return ccr; } // Get the backend database backendDirectory permissions and apply if(FilePermission.canSetPermissions()) { File parentDirectory = getFileForPath(config.getDBDirectory()); File backendDirectory = new File(parentDirectory, config.getBackendId()); try { if (!FilePermission.setPermissions(backendDirectory, backendPermission)) { logger.warn(WARN_JEB_UNABLE_SET_PERMISSIONS, backendPermission, backendDirectory); } } catch(Exception e) { // Log an warning that the permissions were not set. logger.warn(WARN_JEB_SET_PERMISSIONS_FAILED, backendDirectory, e); } } } getMonitorProvider().enableFilterUseStats(cfg.isIndexFilterAnalyzerEnabled()); getMonitorProvider().setMaxEntries(cfg.getIndexFilterAnalyzerMaxFilters()); this.config = cfg; } catch (Exception e) { ccr.setResultCode(DirectoryServer.getServerErrorResultCode()); ccr.addMessage(LocalizableMessage.raw(stackTraceToSingleLineString(e))); return ccr; } return ccr; return new ConfigChangeResult(); } /** * Returns whether this container JE database environment is * open, valid and can be used. * Returns whether this container JE database environment is open, valid and * can be used. * * @return {@code true} if valid, or {@code false} otherwise. */ opendj-sdk/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
@@ -115,4 +115,20 @@ /** {@inheritDoc} */ @Override void close(); /** * Remove all files for a backend of this storage. * * @throws StorageRuntimeException if removal fails */ void removeStorageFiles() throws StorageRuntimeException; /** * Replace reserved characters with an underscore character. * * @param databasePrefix * the suffix name to convert * @return a new String suitable for use as a suffix name */ String toSafeSuffixName(String databasePrefix); }