From db9a9aef38522f297f42992fa32478a01e699c65 Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Tue, 14 Jun 2016 16:10:09 +0000
Subject: [PATCH] OPENDJ-3093 Delay initialization for user backends after admin backends have started

---
 opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java      |   51 +++++++++++++------------
 opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java |   29 +++++++++++---
 opendj-server-legacy/src/messages/org/opends/messages/core.properties               |    2 +
 3 files changed, 50 insertions(+), 32 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java
index 713a629..b8fbed6 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java
+++ b/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
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index c1f30c7..793f144 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/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
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/core.properties b/opendj-server-legacy/src/messages/org/opends/messages/core.properties
index c669c17..9d127f7 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/core.properties
+++ b/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.

--
Gitblit v1.10.0