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

Fabio Pistolesi
09.51.2016 db9a9aef38522f297f42992fa32478a01e699c65
OPENDJ-3093 Delay initialization for user backends after admin backends have started

Starting all backends at the same time prevented crypto initialization being done before accessing data.
Some subsystems, like groups, register a callback to run internal searches whenever a backend is initialized.
It normally works, since the server has already started, but not at startup, where not all subsystem are up and running.
3 files modified
82 ■■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java 29 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java 51 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/messages/org/opends/messages/core.properties 2 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java
@@ -126,35 +126,50 @@
    {
      throw new ConfigException(ERR_CONFIG_BACKEND_BASE_DOES_NOT_EXIST.get());
    }
    initializeBackends(backendIDsToStart, root);
  }
  /**
   * Initializes specified backends. If a backend has been already initialized, do nothing.
   * This should only be called at Directory Server startup, after #initializeBackendConfig()
   *
   * @param backendIDsToStart
   *           The list of backendID to start. Everything will be started if empty.
   * @param root
   *           The configuration of the server's Root backend
   * @throws ConfigException
   *           If a critical configuration problem prevents the backend
   *           initialization from succeeding.
   */
  public void initializeBackends(Collection<String> backendIDsToStart, RootCfg root) throws ConfigException
  {
    // Initialize existing backends.
    for (String name : root.listBackends())
    {
      // Get the handler's configuration.
      // This will decode and validate its properties.
      final BackendCfg backendCfg = root.getBackend(name);
      final DN backendDN = backendCfg.dn();
      final String backendID = backendCfg.getBackendId();
      if (!backendIDsToStart.isEmpty() && !backendIDsToStart.contains(backendID))
      {
        continue;
      }
      if (DirectoryServer.hasBackend(backendID))
      {
        // Skip this backend if it is already initialized and registered as available.
        continue;
      }
      // Register as a change listener for this backend so that we can be
      // notified when it is disabled or enabled.
      backendCfg.addChangeListener(this);
      final DN backendDN = backendCfg.dn();
      if (!backendCfg.isEnabled())
      {
        logger.debug(INFO_CONFIG_BACKEND_DISABLED, backendDN);
        continue;
      }
      else if (DirectoryServer.hasBackend(backendID))
      {
        logger.warn(WARN_CONFIG_BACKEND_DUPLICATE_BACKEND_ID, backendID, backendDN);
        continue;
      }
      // See if the entry contains an attribute that specifies the class name
      // for the backend implementation.  If it does, then load it and make
opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -894,7 +894,7 @@
      try
      {
        directoryServer.initializeBackends(Arrays.asList("adminRoot", "ads-truststore"));
        directoryServer.initializeRootAndAdminDataBackends();
      }
      catch (InitializationException | ConfigException e)
      {
@@ -1522,7 +1522,7 @@
      new AlertHandlerConfigManager(serverContext).initializeAlertHandlers();
      // Initialize the default entry cache. We have to have one before
      // <CODE>initializeBackends()</CODE> method kicks in further down.
      // <CODE>initializeRootAndAdminDataBackends()</CODE> method kicks in further down.
      entryCacheConfigManager = new EntryCacheConfigManager(serverContext);
      entryCacheConfigManager.initializeDefaultEntryCache();
@@ -1553,7 +1553,19 @@
      initializeGroupManager();
      AccessControlConfigManager.getInstance().initializeAccessControl(serverContext);
      initializeBackends(Collections.<String> emptyList());
      // Initialize backends needed by CryptoManagerSync for accessing keys.
      // PreInitialization callbacks (for Groups, for example) may require these to be fully available
      // before starting data backends.
      initializeRootAndAdminDataBackends();
      initializeAuthenticationPolicyComponents();
      // Synchronization of ADS with the crypto manager.
      // Need access to ADS keys before confidential backends and synchronization start to be able to
      // decode encrypted data in the backend by reading them from the trust store.
      new CryptoManagerSync();
      initializeRemainingBackends();
      createAndRegisterRemainingWorkflows();
@@ -1573,15 +1585,8 @@
      monitorConfigManager = new MonitorConfigManager(serverContext);
      monitorConfigManager.initializeMonitorProviders();
      initializeAuthenticationPolicyComponents();
      pluginConfigManager.initializeUserPlugins(null);
      // Synchronization of ADS with the crypto manager.
      // Need access to ADS keys before synchronization starts to be able to decode encrypted data in the backend
      // by reading them from the trust store.
      new CryptoManagerSync();
      if (!environmentConfig.disableSynchronization())
      {
        synchronizationProviderConfigManager = new SynchronizationProviderConfigManager(serverContext);
@@ -1813,24 +1818,11 @@
    directoryServer.backendInitializationListeners.remove(listener);
  }
  /**
   * Initializes the set of backends defined in the Directory Server.
   *
   * @param backends The list of backends to initialize. All backends will be initialized
   *                 if empty.
   * @throws  ConfigException  If there is a configuration problem with any of
   *                           the backends.
   *
   * @throws  InitializationException  If a problem occurs while initializing
   *                                   the backends that is not related to the
   *                                   server configuration.
   */
  private void initializeBackends(Collection<String> backends) throws ConfigException, InitializationException
  private void initializeRootAndAdminDataBackends() throws ConfigException, InitializationException
  {
    backendConfigManager = new BackendConfigManager(serverContext);
    backendConfigManager.initializeBackendConfig(backends);
    backendConfigManager.initializeBackendConfig(Arrays.asList("adminRoot", "ads-truststore"));
    // Make sure to initialize the root DSE backend separately after all other backends.
    RootDSEBackendCfg rootDSECfg;
    try
    {
@@ -1848,6 +1840,15 @@
    rootDSEBackend.openBackend();
  }
  private void initializeRemainingBackends() throws ConfigException, InitializationException
  {
    if (backendConfigManager == null)
    {
      throw new InitializationException(ERR_MISSING_ADMIN_BACKENDS.get());
    }
    backendConfigManager.initializeBackends(Collections.<String>emptyList(), serverContext.getRootConfig());
  }
  /**
   * Creates a set of workflows for a given backend and registers the
   * workflows with the default network group, the internal network group
opendj-server-legacy/src/messages/org/opends/messages/core.properties
@@ -1326,3 +1326,5 @@
NOTE_DISK_SPACE_RESTORED_751=The free space (%d bytes) on the disk containing directory %s is now above the \
 threshold
ERR_CANNOT_HASH_DATA_752=Cannot properly use SHA-1 using the java provider. Verify java.security is properly configured
ERR_MISSING_ADMIN_BACKENDS_753=Cannot complete initialization of server's backends because the root and \
 administrative backends have not been initialized yet.