mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
04.18.2015 4fe1767665733394131391080c5c101738a6651c
Minor pluggable backend code cleanup:

* improve type safety: make BackendImpl generic on its configuration type
* push BackendImpl.getBackupDirectory() down to Storage interface
* create and initialize Storage inside BackendImpl.configureBackend()
* rename BackendImpl.newStorageInstance() to configureStorage()
* remove Storage.initialize() and make initialization responsibility of BackendImpl.configureStorage()
* added Storage.supportsBackupAndRestore() so that storage implementations can declare whether they support this functionality
* removed BackupConfig.[gs]etFilesToBackupFilter() since they are no longer needed. In hindsight they should not have been part of BackupConfig anyway.

10 files modified
280 ■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java 72 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java 21 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java 70 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackupManager.java 19 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryCachePreloader.java 5 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java 3 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java 11 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java 47 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/types/BackupConfig.java 30 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java 2 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PersistItStorage.java
@@ -51,7 +51,6 @@
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.api.AlertGenerator;
import org.opends.server.api.DiskSpaceMonitorHandler;
import org.opends.server.backends.pluggable.spi.Cursor;
@@ -515,6 +514,36 @@
  private PersistitBackendCfg config;
  private DiskSpaceMonitor diskMonitor;
  /**
   * Creates a new persistit storage with the provided configuration.
   *
   * @param cfg
   *          The configuration.
   */
  // FIXME: should be package private once importer is decoupled.
  public PersistItStorage(final PersistitBackendCfg cfg)
  {
    backendDirectory = new File(getFileForPath(cfg.getDBDirectory()), cfg.getBackendId());
    config = cfg;
    dbCfg = new Configuration();
    dbCfg.setLogFile(new File(backendDirectory, VOLUME_NAME + ".log").getPath());
    dbCfg.setJournalPath(new File(backendDirectory, VOLUME_NAME + "_journal").getPath());
    dbCfg.setVolumeList(asList(new VolumeSpecification(new File(backendDirectory, VOLUME_NAME).getPath(), null,
        BUFFER_SIZE, 4096, Long.MAX_VALUE / BUFFER_SIZE, 2048, true, false, false)));
    final BufferPoolConfiguration bufferPoolCfg = getBufferPoolCfg();
    bufferPoolCfg.setMaximumCount(Integer.MAX_VALUE);
    if (cfg.getDBCacheSize() > 0)
    {
      bufferPoolCfg.setMaximumMemory(cfg.getDBCacheSize());
    }
    else
    {
      bufferPoolCfg.setFraction(cfg.getDBCachePercent() / 100.0f);
    }
    dbCfg.setCommitPolicy(cfg.isDBTxnNoSync() ? SOFT : GROUP);
    cfg.addPersistitChangeListener(this);
  }
  /** {@inheritDoc} */
  @Override
  public void close()
@@ -543,33 +572,6 @@
    // nothing to do, in persistit you close the volume itself
  }
  /** {@inheritDoc} */
  @Override
  public void initialize(final PluggableBackendCfg configuration)
  {
    final PersistitBackendCfg cfg = (PersistitBackendCfg) configuration;
    backendDirectory = new File(getFileForPath(cfg.getDBDirectory()), cfg.getBackendId());
    config = cfg;
    dbCfg = new Configuration();
    dbCfg.setLogFile(new File(backendDirectory, VOLUME_NAME + ".log").getPath());
    dbCfg.setJournalPath(new File(backendDirectory, VOLUME_NAME + "_journal").getPath());
    dbCfg.setVolumeList(asList(new VolumeSpecification(new File(
        backendDirectory, VOLUME_NAME).getPath(), null, BUFFER_SIZE, 4096,
        Long.MAX_VALUE / BUFFER_SIZE, 2048, true, false, false)));
    final BufferPoolConfiguration bufferPoolCfg = getBufferPoolCfg();
    bufferPoolCfg.setMaximumCount(Integer.MAX_VALUE);
    if (cfg.getDBCacheSize() > 0)
    {
      bufferPoolCfg.setMaximumMemory(cfg.getDBCacheSize());
    }
    else
    {
      bufferPoolCfg.setFraction(cfg.getDBCachePercent() / 100.0f);
    }
    dbCfg.setCommitPolicy(cfg.isDBTxnNoSync() ? SOFT : GROUP);
    cfg.addPersistitChangeListener(this);
  }
  private BufferPoolConfiguration getBufferPoolCfg()
  {
    return dbCfg.getBufferPoolMap().get(BUFFER_SIZE);
@@ -721,6 +723,19 @@
    }
  }
  @Override
  public boolean supportsBackupAndRestore()
  {
    return true;
  }
  @Override
  public File getDirectory()
  {
    File parentDir = getFileForPath(config.getDBDirectory());
    return new File(parentDir, config.getBackendId());
  }
  /** {@inheritDoc} */
  @Override
  public FilenameFilter getFilesToBackupFilter()
@@ -815,7 +830,6 @@
   *
   * @param cfg a (possibly new) backend configuration
   * @param ccr the current list of change results
   * @return true if permissions are valid
   * @throws forwards a file exception
   */
  private void checkDBDirPermissions(PersistitBackendCfg cfg, ConfigChangeResult ccr)
opendj-server-legacy/src/main/java/org/opends/server/backends/persistit/PitBackend.java
@@ -26,32 +26,19 @@
package org.opends.server.backends.persistit;
import static org.opends.server.util.StaticUtils.getFileForPath;
import java.io.File;
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;
/**
 * Class defined in the configuration for this backend type.
 */
public class PitBackend extends BackendImpl
public final class PitBackend extends BackendImpl<PersistitBackendCfg>
{
  /** {@inheritDoc} */
  @Override
  protected Storage newStorageInstance()
  protected Storage configureStorage(PersistitBackendCfg cfg) throws ConfigException
  {
    return new PersistItStorage();
  }
  /** {@inheritDoc} */
  protected File getBackupDirectory(PluggableBackendCfg cfg)
  {
    PersistitBackendCfg config = (PersistitBackendCfg) cfg;
    File parentDir = getFileForPath(config.getDBDirectory());
    return new File(parentDir, config.getBackendId());
    return new PersistItStorage(cfg);
  }
}
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendImpl.java
@@ -32,7 +32,6 @@
import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutionException;
@@ -61,10 +60,13 @@
import org.opends.server.types.*;
/**
 * This is an implementation of a Directory Server Backend which stores entries
 * locally in a Berkeley DB JE database.
 * This is an implementation of a Directory Server Backend which stores entries locally in a
 * Berkeley DB JE database.
 *
 * @param <C>
 *          the type of the BackendCfg for the current backend
 */
public abstract class BackendImpl extends Backend<PluggableBackendCfg> implements
public abstract class BackendImpl<C extends PluggableBackendCfg> extends Backend<C> implements
    ConfigurationChangeListener<PluggableBackendCfg>
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
@@ -81,6 +83,10 @@
  private DN[] baseDNs;
  private MonitorProvider<?> rootContainerMonitor;
  /** The underlying storage engine. */
  private Storage storage;
  /** The controls supported by this backend. */
  private static final Set<String> supportedControls = new HashSet<String>(Arrays.asList(
      OID_SUBTREE_DELETE_CONTROL,
@@ -138,12 +144,13 @@
  /** {@inheritDoc} */
  @Override
  public void configureBackend(PluggableBackendCfg cfg) throws ConfigException
  public void configureBackend(C cfg) throws ConfigException
  {
    Reject.ifNull(cfg);
    this.cfg = cfg;
    baseDNs = this.cfg.getBaseDN().toArray(new DN[0]);
    storage = configureStorage(cfg);
  }
  /** {@inheritDoc} */
@@ -292,8 +299,16 @@
  @Override
  public boolean supports(BackendOperation backendOperation)
  {
    // it supports all the operations so far
    return true;
    switch (backendOperation)
    {
    case BACKUP:
    case RESTORE:
      // Responsibility of the underlying storage.
      return storage.supportsBackupAndRestore();
    default: // INDEXING, LDIF_EXPORT, LDIF_IMPORT
      // Responsibility of this pluggable backend.
      return true;
    }
  }
  /** {@inheritDoc} */
@@ -754,49 +769,39 @@
  @Override
  public void createBackup(BackupConfig backupConfig) throws DirectoryException
  {
    BackupManager backupManager = new BackupManager(getBackendID());
    File backendDir = getBackupDirectory(cfg);
    Storage storage = newStorageInstance();
    backupConfig.setFilesToBackupFilter(storage.getFilesToBackupFilter());
    backupManager.createBackup(backendDir, backupConfig);
    new BackupManager(getBackendID()).createBackup(storage, backupConfig);
  }
  /**
   * Returns the storage corresponding to the backend class defined in the configuration.
   * @return the storage corresponding to the backend class defined in the configuration
   */
  protected abstract Storage newStorageInstance();
  /** {@inheritDoc} */
  @Override
  public void removeBackup(BackupDirectory backupDirectory, String backupID)
      throws DirectoryException
  {
    BackupManager backupManager = new BackupManager(getBackendID());
    backupManager.removeBackup(backupDirectory, backupID);
    new BackupManager(getBackendID()).removeBackup(backupDirectory, backupID);
  }
  /** {@inheritDoc} */
  @Override
  public void restoreBackup(RestoreConfig restoreConfig)
      throws DirectoryException
  public void restoreBackup(RestoreConfig restoreConfig) throws DirectoryException
  {
    BackupManager backupManager = new BackupManager(getBackendID());
    File backendDir = getBackupDirectory(cfg);
    backupManager.restoreBackup(backendDir, restoreConfig);
    new BackupManager(getBackendID()).restoreBackup(storage, restoreConfig);
  }
  /**
   * Returns the backup directory.
   * Creates the storage engine which will be used by this pluggable backend. Implementations should
   * create and configure a new storage engine but not open it.
   *
   * @param cfg the configuration for this backend
   * @return the backup directory
   * @param cfg
   *          the configuration object
   * @return The storage engine to be used by this pluggable backend.
   * @throws ConfigException
   *           If there is an error in the configuration.
   */
  protected abstract File getBackupDirectory(PluggableBackendCfg cfg);
  protected abstract Storage configureStorage(C cfg) throws ConfigException;
  /** {@inheritDoc} */
  @Override
  public boolean isConfigurationAcceptable(PluggableBackendCfg config, List<LocalizableMessage> unacceptableReasons)
  public boolean isConfigurationAcceptable(C config, List<LocalizableMessage> unacceptableReasons)
  {
    return isConfigurationChangeAcceptable(config, unacceptableReasons);
  }
@@ -969,4 +974,9 @@
    EntryCachePreloader preloader = new EntryCachePreloader(this);
    preloader.preload();
  }
  Storage getStorage()
  {
    return storage;
  }
}
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackupManager.java
@@ -56,6 +56,7 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.backends.pluggable.spi.Storage;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.*;
import org.opends.server.util.DynamicConstants;
@@ -123,13 +124,11 @@
   * log files that are unchanged since the previous backup.  The remaining
   * zip entries are the log files themselves, which, for an incremental,
   * only include those files that have changed.
   * @param backendDir The directory of the backend instance for
   * which the backup is required.
   * @param storage The underlying storage to be backed up.
   * @param  backupConfig  The configuration to use when performing the backup.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  void createBackup(File backendDir, BackupConfig backupConfig)
       throws DirectoryException
  void createBackup(Storage storage, BackupConfig backupConfig) throws DirectoryException
  {
    // Get the properties to use for the backup.
    String          backupID        = backupConfig.getBackupID();
@@ -140,7 +139,6 @@
    boolean         encrypt         = backupConfig.encryptData();
    boolean         hash            = backupConfig.hashData();
    boolean         signHash        = backupConfig.signHash();
    FilenameFilter  filenameFilter  = backupConfig.getFilesToBackupFilter();
    HashMap<String,String> backupProperties = new HashMap<String,String>();
@@ -320,8 +318,9 @@
      zipStream.setLevel(Deflater.NO_COMPRESSION);
    }
    File backendDir = storage.getDirectory();
    FilenameFilter filenameFilter = storage.getFilesToBackupFilter();
    File[] logFiles;
    try
    {
      logFiles = backendDir.listFiles(filenameFilter);
@@ -572,14 +571,11 @@
  /**
   * Restore a backend from backup, or verify the backup.
   * @param backendDir The configuration of the backend instance to be
   * restored.
   * @param storage The underlying storage to be backed up.
   * @param  restoreConfig The configuration to use when performing the restore.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  void restoreBackup(File backendDir,
                            RestoreConfig restoreConfig)
       throws DirectoryException
  void restoreBackup(Storage storage, RestoreConfig restoreConfig) throws DirectoryException
  {
    // Get the properties to use for the restore.
    String          backupID        = restoreConfig.getBackupID();
@@ -590,6 +586,7 @@
    // Create a restore directory with a different name to the backend
    // directory.
    File backendDir = storage.getDirectory();
    File restoreDir = new File(backendDir.getPath() + "-restore-" + backupID);
    if (!verifyOnly)
    {
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryCachePreloader.java
@@ -73,7 +73,7 @@
  /**
   * BackendImpl object.
   */
  private final BackendImpl backend;
  private final BackendImpl<?> backend;
  /**
   * Interrupt flag for the arbiter to terminate worker threads.
@@ -141,7 +141,8 @@
   *
   * @param  jeb  The JEB instance to pre-load.
   */
  public EntryCachePreloader(BackendImpl jeb) {
  public EntryCachePreloader(BackendImpl<?> jeb)
  {
    // These should not be exposed as configuration
    // parameters and are only useful for testing.
    syncSleepTime = Long.getLong(
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Importer.java
@@ -4042,8 +4042,7 @@
      returnValues.put("isDBTxnNoSync", true);
      try
      {
        storage = new PersistItStorage();
        storage.initialize(newPersistitBackendCfgProxy(returnValues));
        storage = new PersistItStorage(newPersistitBackendCfgProxy(returnValues));
      }
      catch (Exception e)
      {
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/RootContainer.java
@@ -129,7 +129,7 @@
  private Storage storage;
  /** The backend to which this entry root container belongs. */
  private final BackendImpl backend;
  private final BackendImpl<?> backend;
  /** The backend configuration. */
  private final PluggableBackendCfg config;
  /** The database environment monitor for this JE environment. */
@@ -154,7 +154,7 @@
   *          A reference to the JE back end that is creating this root
   *          container.
   */
  RootContainer(BackendImpl backend, PluggableBackendCfg config)
  RootContainer(BackendImpl<?> backend, PluggableBackendCfg config)
  {
    this.backend = backend;
    this.config = config;
@@ -194,9 +194,7 @@
    {
      try
      {
        Storage storage = backend.newStorageInstance();
        storage.initialize(config);
        storage.removeStorageFiles();
        backend.getStorage().removeStorageFiles();
      }
      catch (Exception e)
      {
@@ -344,8 +342,7 @@
  {
    try
    {
      storage = backend.newStorageInstance();
      storage.initialize(config);
      storage = backend.getStorage();
      storage.open();
      storage.write(new WriteOperation()
      {
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/spi/Storage.java
@@ -26,10 +26,9 @@
package org.opends.server.backends.pluggable.spi;
import java.io.Closeable;
import java.io.File;
import java.io.FilenameFilter;
import org.opends.server.admin.std.server.PluggableBackendCfg;
/**
 * This interface abstracts the underlying storage engine,
 * isolating the pluggable backend generic code from a particular storage engine implementation.
@@ -37,17 +36,6 @@
public interface Storage extends Closeable
{
  /**
   * Initializes the storage engine before opening it.
   *
   * @param cfg
   *          the configuration object
   * @throws Exception
   *           if a problem occurs with the underlying storage engine
   * @see #open() to open the storage engine
   */
  void initialize(PluggableBackendCfg cfg) throws Exception;
  /**
   * Starts the import operation.
   *
   * @return a new Importer object which must be closed to release all resources
@@ -99,12 +87,6 @@
   */
  void closeTree(TreeName treeName);
  /**
   * Returns a filename filter which selects the files to be included in a backup.
   * @return a filename filter which selects the files to be included in a backup
   */
  FilenameFilter getFilesToBackupFilter();
  /** {@inheritDoc} */
  @Override
  void close();
@@ -122,4 +104,31 @@
   * @return the current status of the storage
   */
  StorageStatus getStorageStatus();
  /**
   * Returns {@code true} if this storage supports backup and restore.
   *
   * @return {@code true} if this storage supports backup and restore.
   */
  boolean supportsBackupAndRestore();
  /**
   * Returns the file system directory in which any database files are located. This method is
   * called when performing backup and restore operations.
   *
   * @return The file system directory in which any database files are located.
   * @throws UnsupportedOperationException
   *           If backup and restore is not supported by this storage.
   */
  File getDirectory();
  /**
   * Returns a filename filter which selects the files to be included in a backup. This method is
   * called when performing backup operations.
   *
   * @return A filename filter which selects the files to be included in a backup.
   * @throws UnsupportedOperationException
   *           If backup and restore is not supported by this storage.
   */
  FilenameFilter getFilesToBackupFilter();
}
opendj-server-legacy/src/main/java/org/opends/server/types/BackupConfig.java
@@ -22,12 +22,10 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2015 Forgerock AS
 *      Portions copyright 2015 ForgeRock AS
 */
package org.opends.server.types;
import java.io.FilenameFilter;
/**
 * This class defines a data structure for holding configuration
 * information to use when performing a backup of a Directory Server
@@ -92,12 +90,6 @@
   */
  private String incrementalBaseID;
  /**
   * The filename filter to decide which files should be included as defined
   * by the storage.
   */
  private FilenameFilter filesToBackupFilter;
  /**
   * Creates a new backup configuration that will create a full or
@@ -315,25 +307,5 @@
  {
    this.signHash = signHash;
  }
  /**
   * Returns the storage-defined filename filter deciding which files should go into a backup.
   *
   * @return the storage-defined filename filter deciding which files should go into a backup
   */
  public FilenameFilter getFilesToBackupFilter()
  {
    return filesToBackupFilter;
  }
  /**
   * Sets the storage-defined filter for files belonging to the backend.
   *
   * @param filenameFilter the filenameFilter to set
   */
  public void setFilesToBackupFilter(FilenameFilter filenameFilter)
  {
    this.filesToBackupFilter = filenameFilter;
  }
}
opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/PluggableBackendImplTestCase.java
@@ -827,8 +827,6 @@
    backupPath = TestCaseUtils.createTemporaryDirectory("backup").getAbsolutePath();
    backupDirectory = new BackupDirectory(backupPath, testBaseDN);
    BackupConfig backupConf = new BackupConfig(backupDirectory, backupID, false);
    backupConf.setFilesToBackupFilter(backend.getRootContainer().getStorage().getFilesToBackupFilter());
    backend.createBackup(backupConf);
  }