From 2973e1ec450dcfd99e193176ddbe25eafc652e17 Mon Sep 17 00:00:00 2001
From: lutoff <lutoff@localhost>
Date: Wed, 05 Nov 2008 10:06:27 +0000
Subject: [PATCH] Fix for issue #3544 (upgrade fails during verification of replication)

---
 opends/src/server/org/opends/server/core/DirectoryServer.java                   |   23 ++
 opends/src/server/org/opends/server/admin/AdministrationDataSync.java           |  338 ++++++++++++++++++++++++++++++++++++++++++
 opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java              |   16 ++
 opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java |   25 +++
 opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java       |   40 +++++
 opends/src/server/org/opends/server/util/ServerConstants.java                   |   15 +
 6 files changed, 453 insertions(+), 4 deletions(-)

diff --git a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
index 1a45d5b..30d55f0 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/upgrader/Upgrader.java
@@ -892,6 +892,8 @@
           InProcessServerController ipsc =
                   new InProcessServerController(getInstallation());
           InProcessServerController.disableConnectionHandlers(true);
+          InProcessServerController.disableAdminDataSynchronization(true);
+          InProcessServerController.disableSynchronization(true);
           ipsc.startServer();
           LOG.log(Level.INFO, "start server finished");
           notifyListeners(getFormattedDoneWithLineBreak());
@@ -1969,7 +1971,21 @@
   {
     Installation installation = getInstallation() ;
     File installDir  = installation.getRootDirectory();
+    try
+    {
+      installDir = installDir.getCanonicalFile();
+    }
+    catch (Exception e) {
+      installDir  = installation.getRootDirectory();
+    }
     File instanceDir = installation.getInstanceDirectory();
+    try
+    {
+      instanceDir = instanceDir.getCanonicalFile();
+    }
+    catch (Exception e) {
+      instanceDir = installation.getInstanceDirectory();
+    }
     return installDir.getAbsolutePath().equals(instanceDir.getAbsolutePath());
   }
 
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java b/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
index 312e090..69f7f20 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/InProcessServerController.java
@@ -259,6 +259,31 @@
   }
 
   /**
+   * Disables the server's synchronization provider upon startup.  The server
+   * when started is otherwise up and running but will not accept any
+   * synchronization message. This could be useful, for example,
+   * in an upgrade mode where it might be helpful to start the server
+   * but don't want it to appear externally.
+   * @param disable boolean that when true disables synchronization provider
+   *  when the server is started.
+   */
+  static public void disableSynchronization(boolean disable) {
+    System.setProperty(
+            "org.opends.server.DisableSynchronization",
+            disable ? "true" : "false");
+  }
+  /**
+   * Disables the admin data synchronization upon startup.
+   * @param disable boolean that when true disables connection handlers when
+   * the server is started.
+   */
+  static public void disableAdminDataSynchronization(boolean disable) {
+    System.setProperty(
+            "org.opends.server.DisableAdminDataSynchronization",
+            disable ? "true" : "false");
+  }
+
+  /**
    * Stops a server that had been running 'in process'.
    */
   public void stopServer() {
diff --git a/opends/src/server/org/opends/server/admin/AdministrationDataSync.java b/opends/src/server/org/opends/server/admin/AdministrationDataSync.java
new file mode 100644
index 0000000..7664712
--- /dev/null
+++ b/opends/src/server/org/opends/server/admin/AdministrationDataSync.java
@@ -0,0 +1,338 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2006-2008 Sun Microsystems, Inc.
+ */
+package org.opends.server.admin;
+
+
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.protocols.asn1.ASN1OctetString;
+import org.opends.server.protocols.internal.InternalClientConnection;
+import org.opends.server.protocols.internal.InternalSearchOperation;
+import org.opends.server.protocols.ldap.LDAPFilter;
+import org.opends.server.schema.DirectoryStringSyntax;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.DN;
+import org.opends.server.types.DereferencePolicy;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.LDAPException;
+import org.opends.server.types.Modification;
+import org.opends.server.types.ModificationType;
+import org.opends.server.types.ResultCode;
+import org.opends.server.types.SearchResultEntry;
+import org.opends.server.types.SearchScope;
+
+
+/**
+ * Check if information found in "cn=admin data" is coherent with
+ * cn=config. If and inconsistancy is detected, we log a warning message
+ * and update "cn=admin data"
+ */
+public final class AdministrationDataSync
+{
+
+  /**
+   * The root connection.
+   */
+  private InternalClientConnection internalConnection;
+
+  /**
+   * The attribute name used to store the port.
+   * TODO Use the default one.
+   */
+  private static final String LDAP_PORT = "ds-cfg-listen-port";
+
+  /**
+   * Create an object that will syncrhonize configuration and the admin data.
+   *
+   * @param internalConnection The root connection.
+   */
+  public AdministrationDataSync(InternalClientConnection internalConnection)
+  {
+    this.internalConnection = internalConnection ;
+  }
+
+  /**
+   * Check if information found in "cn=admin data" is coherent with
+   * cn=config. If and inconsistancy is detected, we log a warning message
+   * and update "cn=admin data"
+   */
+  public void synchronize()
+  {
+    // Check if the admin connector is in sync
+    checkAdminConnector();
+  }
+
+  /**
+   * Check if the admin connector is in sync. The desynchronization could
+   * occurs after the upgrade from 1.0.
+   */
+  private void checkAdminConnector()
+  {
+    // Look for the server registration in "cn=admin data"
+    DN serverEntryDN = searchServerEntry();
+    if (serverEntryDN == null)
+    {
+      // Nothing to do
+      return;
+    }
+
+    // Get the admin port
+    String adminPort =
+      getAttr("cn=Administration Connector,cn=config", LDAP_PORT);
+    if (adminPort == null)
+    {
+      // best effort.
+      return ;
+    }
+
+    LinkedList<Modification> mods = new LinkedList<Modification>();
+    // adminport
+    String attName = "adminport";
+    AttributeType attrType =
+    DirectoryServer.getAttributeType(attName.toLowerCase());
+    if (attrType == null)
+    {
+      attrType = DirectoryServer.getDefaultAttributeType(attName.toLowerCase());
+    }
+    mods.add(new Modification(ModificationType.REPLACE, Attributes
+        .create(attrType, adminPort)));
+
+    // adminEnabled
+    attName = "adminEnabled";
+    attrType = DirectoryServer.getAttributeType(attName.toLowerCase());
+    if (attrType == null)
+    {
+      attrType = DirectoryServer.getDefaultAttributeType(attName.toLowerCase());
+    }
+    mods.add(new Modification(ModificationType.REPLACE, Attributes
+        .create(attrType, "true")));
+
+    // Process modification
+    internalConnection.processModify(serverEntryDN,mods);
+  }
+
+  /**
+   * Look for the DN of the local register server.
+   * Assumption: default Connection Handler naming is used.
+   *
+   * @return The DN of the local register server or null.
+   */
+  private DN searchServerEntry()
+  {
+    DN returnDN = null;
+
+    // Get the LDAP and LDAPS port
+    String ldapPort =
+      getAttr("cn=LDAP Connection Handler,cn=Connection Handlers,cn=config",
+          LDAP_PORT);
+    String ldapsPort =
+      getAttr("cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config",
+          LDAP_PORT);
+    boolean ldapsPortEnable = false;
+    String val =
+      getAttr("cn=LDAPS Connection Handler,cn=Connection Handlers,cn=config",
+          "ds-cfg-enabled");
+    if (val != null)
+    {
+      ldapsPortEnable = val.toLowerCase().equals("true");
+    }
+    if ((ldapPort == null) && (ldapsPort == null))
+    {
+      // best effort (see assumption)
+      return null ;
+    }
+
+    // Get the IP address of the local host.
+    String hostName = "";
+    try
+    {
+      hostName = java.net.InetAddress.getLocalHost().getCanonicalHostName();
+    }
+    catch (Throwable t)
+    {
+     // best effort.
+      return null;
+    }
+
+    // Look for a local server with the Ldap Port.
+    InternalSearchOperation op = null;
+    String attrName = "hostname";
+    AttributeType hostnameType = DirectoryServer.getAttributeType(attrName);
+    if (hostnameType == null)
+    {
+      hostnameType = DirectoryServer.getDefaultAttributeType(attrName);
+    }
+    try
+    {
+      op = internalConnection.processSearch("cn=Servers,cn=admin data",
+          SearchScope.SINGLE_LEVEL, "objectclass=*");
+      if (op.getResultCode() == ResultCode.SUCCESS)
+      {
+        Entry entry =  null;
+        for (Entry currentEntry : op.getSearchEntries())
+        {
+          String currentHostname = currentEntry.getAttributeValue(hostnameType,
+              DirectoryStringSyntax.DECODER);
+          try
+          {
+            String currentIPAddress = java.net.InetAddress.getByName(
+                currentHostname).getCanonicalHostName();
+            if (currentIPAddress.equals(hostName))
+            {
+              // Check if one of the port match
+              attrName = "ldapport";
+              AttributeType portType =
+                DirectoryServer.getAttributeType(attrName);
+              if (portType == null)
+              {
+                portType = DirectoryServer.getDefaultAttributeType(attrName);
+              }
+              String currentport = currentEntry.getAttributeValue(portType,
+                  DirectoryStringSyntax.DECODER);
+              if (currentport.equals(ldapPort))
+              {
+                entry = currentEntry ;
+                break ;
+              }
+              if (ldapsPortEnable)
+              {
+                attrName = "ldapsport";
+                portType = DirectoryServer.getAttributeType(attrName);
+                if (portType == null)
+                {
+                  portType = DirectoryServer.getDefaultAttributeType(attrName);
+                }
+                currentport = currentEntry.getAttributeValue(portType,
+                    DirectoryStringSyntax.DECODER);
+                if (currentport.equals(ldapsPort))
+                {
+                  entry = currentEntry;
+                  break;
+                }
+              }
+            }
+          }
+          catch(Exception e)
+          {
+            // best effort.
+            continue;
+          }
+        }
+
+        if (entry != null)
+        {
+          returnDN = entry.getDN();
+        }
+      }
+
+    } catch (DirectoryException e)
+    {
+      // never happens because the filter is always valid.
+      return null;
+    }
+    return returnDN;
+  }
+
+  /**
+   * get an attribute from and entry.
+   * @param DN the DN of the entry.
+   * @param attrName the attribute name.
+   * @return The Administration connector port.
+   */
+  private String getAttr(String baseDN, String attrName)
+  {
+    String value = null  ;
+    //
+    // prepare the ldap search
+    LDAPFilter filter;
+    try
+    {
+      filter = LDAPFilter.decode("objectclass=*");
+    }
+    catch (LDAPException e)
+    {
+      // can not happen
+      // best effort.
+      // TODO Log an Error.
+      return null;
+    }
+
+    ASN1OctetString asn1BaseDn = new ASN1OctetString(baseDN);
+    LinkedHashSet<String> attributes = new LinkedHashSet<String>(1);
+    attributes.add(attrName);
+    InternalSearchOperation search = internalConnection.processSearch(
+        asn1BaseDn,
+        SearchScope.BASE_OBJECT,
+        DereferencePolicy.DEREF_ALWAYS, 0, 0, false,
+        filter,attributes);
+
+    if ((search.getResultCode() != ResultCode.SUCCESS))
+    {
+      // can not happen
+      // best effort.
+      // TODO Log an Error.
+      return null;
+    }
+
+    SearchResultEntry adminConnectorEntry = null;
+    /*
+     * Read the port from the PORT attribute
+     */
+    LinkedList<SearchResultEntry> result = search.getSearchEntries();
+    if (!result.isEmpty())
+    {
+      adminConnectorEntry = result.getFirst();
+    }
+
+    AttributeType attrType = DirectoryServer.getAttributeType(attrName);
+    if (attrType == null)
+    {
+      attrType = DirectoryServer.getDefaultAttributeType(attrName);
+    }
+
+    List<Attribute> attrs = adminConnectorEntry.getAttribute(attrType);
+
+    if (attrs == null)
+    {
+      // can not happen
+      // best effort.
+      // TODO Log an Error.
+      return null;
+    }
+
+    // Get the attribute value
+    value = attrs.get(0).iterator().next().getStringValue();
+    return value;
+  }
+
+}
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 5d5c9ff..6f5b117 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -26,6 +26,7 @@
  */
 package org.opends.server.core;
 
+import org.opends.server.admin.AdministrationDataSync;
 import org.opends.server.admin.ClassLoaderProvider;
 import org.opends.server.admin.server.ServerManagementContext;
 import org.opends.server.admin.std.meta.GlobalCfgDefn.WorkflowConfigurationMode;
@@ -1448,9 +1449,14 @@
 
 
       // Initialize any synchronization providers that may be defined.
-      synchronizationProviderConfigManager =
-           new SynchronizationProviderConfigManager();
-      synchronizationProviderConfigManager.initializeSynchronizationProviders();
+      if (!environmentConfig.disableSynchronization())
+      {
+        synchronizationProviderConfigManager =
+          new SynchronizationProviderConfigManager();
+        synchronizationProviderConfigManager
+            .initializeSynchronizationProviders();
+      }
+
 
 
       // Create and initialize the work queue.
@@ -1495,7 +1501,16 @@
       sendAlertNotification(this, ALERT_TYPE_SERVER_STARTED, message);
 
       // Force the root connection to be initialized.
-      InternalClientConnection.getRootConnection();
+      InternalClientConnection rootConnection =
+        InternalClientConnection.getRootConnection();
+
+      // Determine whether or not we should synchronized admin data.
+      if (! environmentConfig.disableAdminDataSynchronization())
+      {
+        AdministrationDataSync admDataSync = new AdministrationDataSync(
+            rootConnection);
+        admDataSync.synchronize();
+      }
 
       // If a server.starting file exists, then remove it.
       File serverStartingFile =
diff --git a/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java b/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
index 8cbe32a..ee6aa25 100644
--- a/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
+++ b/opends/src/server/org/opends/server/types/DirectoryEnvironmentConfig.java
@@ -981,7 +981,47 @@
     return disableStr.equalsIgnoreCase("true");
   }
 
+  /**
+   * Indicates whether the Directory Server startup process should
+   * skip the synchronization provider creation and initialization
+   * phases.
+   *
+   * @return  {@code true} if the Directory Server should not start
+   *          its synchronization provider, or {@code false} if the
+   *          synchronization provider should be enabled.
+   */
+  public boolean disableSynchronization()
+  {
+    String disableStr =
+         getProperty(PROPERTY_DISABLE_SYNCHRONIZATION);
+    if (disableStr == null)
+    {
+      return false;
+    }
 
+    return disableStr.equalsIgnoreCase("true");
+  }
+
+  /**
+   * Indicates whether the Directory Server startup process should
+   * skip the synchronization between admin data and the
+   * configuration.
+   *
+   * @return  {@code true} if the Directory Server should start
+   *          synchronization between admin data and the
+   *          configuration.
+   */
+  public boolean disableAdminDataSynchronization()
+  {
+    String disableStr =
+         getProperty(PROPERTY_DISABLE_ADMIN_DATA_SYNCHRONIZATION);
+    if (disableStr == null)
+    {
+      return false;
+    }
+
+    return disableStr.equalsIgnoreCase("true");
+  }
 
   /**
    * Specifies whether the Directory Server startup process should
diff --git a/opends/src/server/org/opends/server/util/ServerConstants.java b/opends/src/server/org/opends/server/util/ServerConstants.java
index b93944f..954c585 100644
--- a/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -2627,7 +2627,22 @@
   public static final String PROPERTY_DISABLE_CONNECTION_HANDLERS =
        "org.opends.server.DisableConnectionHandlers";
 
+  /**
+   * The name of the system property that can be used to disable any
+   * synchronization provider that may be enabled in the server configuration.
+   * This may be used to start the server in a mode where it will not accept any
+   * external connections, but may still be used for processing internal
+   * operations.
+   */
+  public static final String PROPERTY_DISABLE_SYNCHRONIZATION =
+       "org.opends.server.DisableSynchronization";
 
+  /**
+   * The name of the system property that can be used to disable the
+   * synchronization between between administration data.
+   */
+  public static final String PROPERTY_DISABLE_ADMIN_DATA_SYNCHRONIZATION =
+       "org.opends.server.DisableAdminDataSynchronization";
 
   /**
    * The name of the system property that can be used to indicate whether

--
Gitblit v1.10.0