From 81b66dafd30d3893f5199a7ca5efaae9eff3e180 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Mon, 05 Nov 2007 22:14:14 +0000
Subject: [PATCH] Complete fix for issue 2263.

---
 opends/src/server/org/opends/server/types/Schema.java                                    |    4 
 opends/src/messages/messages/quicksetup.properties                                       |    1 
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java           |   44 ++++++++++++++
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java |   31 +++++++++-
 opends/src/messages/messages/admin_tool.properties                                       |    8 ++
 opends/src/ads/org/opends/admin/ads/ServerDescriptor.java                                |   40 ++++++++++++
 opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java                     |   34 +++++++----
 opends/src/server/org/opends/server/config/ConfigConstants.java                          |    2 
 8 files changed, 142 insertions(+), 22 deletions(-)

diff --git a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index c8890e7..6b8b387 100644
--- a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -57,7 +57,6 @@
   private Map<ServerProperty, Object> serverProperties =
     new HashMap<ServerProperty, Object>();
   private TopologyCacheException lastException;
-
   /**
    * Enumeration containing the different server properties that we can keep in
    * the ServerProperty object.
@@ -129,7 +128,11 @@
      * The instance key-pair public-key certificate. The associated value is a
      * byte[] (ds-cfg-public-key-certificate;binary).
      */
-    INSTANCE_PUBLIC_KEY_CERTIFICATE
+    INSTANCE_PUBLIC_KEY_CERTIFICATE,
+    /**
+     * The schema generation ID.
+     */
+    SCHEMA_GENERATION_ID
   }
 
   private ServerDescriptor()
@@ -425,6 +428,15 @@
   }
 
   /**
+   * Returns the schema generation ID of the server.
+   * @return the schema generation ID of the server.
+   */
+  public String getSchemaReplicationID()
+  {
+    return (String)serverProperties.get(ServerProperty.SCHEMA_GENERATION_ID);
+  }
+
+  /**
    * Returns the last exception that was encountered reading the configuration
    * of the server.  Returns null if there was no problem loading the
    * configuration of the server.
@@ -545,6 +557,7 @@
     updateReplicas(desc, ctx);
     updateReplication(desc, ctx);
     updatePublicKeyCertificate(desc, ctx);
+    updateMiscellaneous(desc, ctx);
 
     desc.serverProperties.put(ServerProperty.HOST_NAME,
         ConnectionUtils.getHostName(ctx));
@@ -995,6 +1008,29 @@
     }
   }
 
+  private static void updateMiscellaneous(ServerDescriptor desc,
+      InitialLdapContext ctx) throws NamingException
+  {
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "ds-sync-generation-id"
+        });
+    String filter = "|(objectclass=*)(objectclass=ldapsubentry)";
+
+    LdapName jndiName = new LdapName("cn=schema");
+    NamingEnumeration listeners = ctx.search(jndiName, filter, ctls);
+
+    while(listeners.hasMore())
+    {
+      SearchResult sr = (SearchResult)listeners.next();
+
+      desc.serverProperties.put(ServerProperty.SCHEMA_GENERATION_ID,
+          getFirstValue(sr, "ds-sync-generation-id"));
+    }
+  }
+
   /**
    Seeds the bound instance's local ads-truststore with a set of instance
    key-pair public key certificates. The result is the instance will trust any
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java
index 7f49dca..d3657a4 100644
--- a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java
@@ -168,6 +168,11 @@
   private BooleanArgument noSchemaReplicationArg;
 
   /**
+   * The 'useSecondServerAsSchemaSource' argument to not replicate schema.
+   */
+  private BooleanArgument useSecondServerAsSchemaSourceArg;
+
+  /**
    * The 'hostName' argument for the source server.
    */
   private StringArgument hostNameSourceArg = null;
@@ -558,6 +563,11 @@
         "noschemareplication", null, "noSchemaReplication",
         INFO_DESCRIPTION_ENABLE_REPLICATION_NO_SCHEMA_REPLICATION.get());
 
+    useSecondServerAsSchemaSourceArg = new BooleanArgument(
+        "usesecondserverasschemasource", null, "useSecondServerAsSchemaSource",
+        INFO_DESCRIPTION_ENABLE_REPLICATION_USE_SECOND_AS_SCHEMA_SOURCE.get(
+            noSchemaReplicationArg.getLongIdentifier()));
+
     enableReplicationSubCmd = new SubCommand(this,
         ENABLE_REPLICATION_SUBCMD_NAME,
         INFO_DESCRIPTION_SUBCMD_ENABLE_REPLICATION.get());
@@ -569,7 +579,8 @@
         hostName2Arg, port2Arg, bindDn2Arg, bindPassword2Arg,
         bindPasswordFile2Arg, useStartTLS2Arg, useSSL2Arg, replicationPort2Arg,
         secureReplication2Arg,
-        skipPortCheckArg, noSchemaReplicationArg
+        skipPortCheckArg, noSchemaReplicationArg,
+        useSecondServerAsSchemaSourceArg
     };
     for (int i=0; i<argsToAdd.length; i++)
     {
@@ -1252,8 +1263,8 @@
 
   /**
    * Returns whether the user asked to not replicate the schema between servers.
-   * @return <CODE>true</CODE> the user asked to not replicate schema and <CODE>
-   * false</CODE> otherwise.
+   * @return <CODE>true</CODE> if the user asked to not replicate schema and
+   * <CODE>false</CODE> otherwise.
    */
   public boolean noSchemaReplication()
   {
@@ -1261,6 +1272,17 @@
   }
 
   /**
+   * Returns whether the user asked to use the second server to initialize the
+   * schema of the first server.
+   * @return <CODE>true</CODE> if the user asked to use the second server to
+   * initialize the schema of the first server and <CODE>false</CODE> otherwise.
+   */
+  public boolean useSecondServerAsSchemaSource()
+  {
+    return useSecondServerAsSchemaSourceArg.isPresent();
+  }
+
+  /**
    * Returns the host name explicitly provided in the disable replication
    * subcommand.
    * @return the host name explicitly provided in the disable replication
@@ -1709,7 +1731,8 @@
         {bindPassword1Arg, bindPasswordFile1Arg},
         {useStartTLS1Arg, useSSL1Arg},
         {bindPassword2Arg, bindPasswordFile2Arg},
-        {useStartTLS2Arg, useSSL2Arg}
+        {useStartTLS2Arg, useSSL2Arg},
+        {noSchemaReplicationArg, useSecondServerAsSchemaSourceArg}
     };
 
     for (int i=0; i< conflictingPairs.length; i++)
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
index 56316ee..f1cce3b 100644
--- a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
@@ -4144,6 +4144,30 @@
       printProgressMessage(formatter.getFormattedDone());
       printProgressMessage(formatter.getLineBreak());
     }
+
+    // If we must initialize the schema do so.
+    if (mustInitializeSchema(server1, server2))
+    {
+      printProgressMessage(formatter.getFormattedWithPoints(
+          INFO_ENABLE_REPLICATION_INITIALIZING_SCHEMA.get(
+              ConnectionUtils.getHostPort(ctxDestination),
+              ConnectionUtils.getHostPort(ctxSource))));
+
+      if (argParser.useSecondServerAsSchemaSource())
+      {
+        ctxSource = ctx2;
+        ctxDestination = ctx1;
+      }
+      else
+      {
+        ctxSource = ctx1;
+        ctxDestination = ctx2;
+      }
+      initializeSuffix(Constants.SCHEMA_DN, ctxSource,
+          ctxDestination, false);
+      printProgressMessage(formatter.getFormattedDone());
+      printProgressMessage(formatter.getLineBreak());
+    }
   }
 
   /**
@@ -6063,4 +6087,24 @@
     }
     return isLocalHost;
   }
+
+  private boolean mustInitializeSchema(ServerDescriptor server1,
+      ServerDescriptor server2)
+  {
+    boolean mustInitializeSchema = false;
+    if (!argParser.noSchemaReplication())
+    {
+      String id1 = server1.getSchemaReplicationID();
+      String id2 = server2.getSchemaReplicationID();
+      if (id1 != null)
+      {
+        mustInitializeSchema = id1.equals(id2);
+      }
+      else
+      {
+        mustInitializeSchema = true;
+      }
+    }
+    return mustInitializeSchema;
+  }
 }
diff --git a/opends/src/messages/messages/admin_tool.properties b/opends/src/messages/messages/admin_tool.properties
index e4ca8b4..f518300 100644
--- a/opends/src/messages/messages/admin_tool.properties
+++ b/opends/src/messages/messages/admin_tool.properties
@@ -425,7 +425,11 @@
 INFO_DESCRIPTION_ENABLE_REPLICATION_SKIPPORT=Skip the check to determine \
  whether the specified replication ports are usable
 INFO_DESCRIPTION_ENABLE_REPLICATION_NO_SCHEMA_REPLICATION=Do not replicate the \
- schema between the servers.
+ schema between the servers
+INFO_DESCRIPTION_ENABLE_REPLICATION_USE_SECOND_AS_SCHEMA_SOURCE=Use the second \
+ server to initialize the schema of the first server.  If this option nor \
+ option {%s} are specified the schema of the first server will be used to \
+ initialize the schema of the second server
 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORD2=Specifies the password \
  to use to bind to the second server whose contents will be replicated.  If no \
  bind DN was specified for the second server the password of the global \
@@ -690,6 +694,8 @@
  on server %s
 INFO_ENABLE_REPLICATION_INITIALIZING_ADS=Initializing Registration information \
  on server %s with the contents of server %s
+INFO_ENABLE_REPLICATION_INITIALIZING_SCHEMA=Initializing schema on server %s \
+ with the contents of server %s
 SEVERE_ERR_REPLICATION_ENABLE_SEEDING_TRUSTSTORE=An unexpected error occurred \
  seeding the truststore contents.  Details: %s
 SEVERE_ERR_INITIALIZING_REPLICATIONID_NOT_FOUND=Error initializing.  Could not \
diff --git a/opends/src/messages/messages/quicksetup.properties b/opends/src/messages/messages/quicksetup.properties
index a1e162e..c9fea42 100644
--- a/opends/src/messages/messages/quicksetup.properties
+++ b/opends/src/messages/messages/quicksetup.properties
@@ -685,6 +685,7 @@
 INFO_PROGRESS_IMPORTING_LDIF=Importing LDIF file %s:
 INFO_PROGRESS_IMPORTING_LDIFS=Importing LDIF files %s:
 INFO_PROGRESS_INITIALIZING_ADS=Initializing Registration information
+INFO_PROGRESS_INITIALIZING_SCHEMA=Initializing schema information
 INFO_PROGRESS_INITIALIZING_SUFFIX=Initializing base DN %s with the contents \
  from %s:
 INFO_PROGRESS_PANEL_TITLE=Progress
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index e9f5a1f..d12972b 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -1894,7 +1894,7 @@
     Set<SuffixDescriptor> suffixes =
       getUserData().getSuffixesToReplicateOptions().getSuffixes();
 
-    /* Initialize local ADS contents using any replica. */
+    /* Initialize local ADS and schema contents using any replica. */
     {
       ServerDescriptor server
        = suffixes.iterator().next().getReplicas().iterator().next().getServer();
@@ -1905,11 +1905,14 @@
         ServerDescriptor s = ServerDescriptor.createStandalone(rCtx);
         for (ReplicaDescriptor replica : s.getReplicas())
         {
-          if (areDnsEqual(replica.getSuffix().getDN(),
-                  ADSContext.getAdministrationSuffixDN()))
+          String dn = replica.getSuffix().getDN();
+          if (areDnsEqual(dn, ADSContext.getAdministrationSuffixDN()))
           {
             suffixes.add(replica.getSuffix());
-            break;
+          }
+          else if (areDnsEqual(dn, Constants.SCHEMA_DN))
+          {
+            suffixes.add(replica.getSuffix());
           }
         }
       }
@@ -1945,17 +1948,23 @@
       String hostPort = server.getHostPort(true);
 
       boolean isADS = areDnsEqual(dn, ADSContext.getAdministrationSuffixDN());
-      if(!isADS)
+      boolean isSchema = areDnsEqual(dn, Constants.SCHEMA_DN);
+      if(isADS)
+      {
+        notifyListeners(getFormattedWithPoints(
+            INFO_PROGRESS_INITIALIZING_ADS.get()));
+      }
+      else if (isSchema)
+      {
+        notifyListeners(getFormattedWithPoints(
+            INFO_PROGRESS_INITIALIZING_SCHEMA.get()));
+      }
+      else
       {
         notifyListeners(getFormattedProgress(
             INFO_PROGRESS_INITIALIZING_SUFFIX.get(dn, hostPort)));
         notifyListeners(getLineBreak());
       }
-      else
-      {
-        notifyListeners(getFormattedWithPoints(
-            INFO_PROGRESS_INITIALIZING_ADS.get()));
-      }
       try
       {
         int replicationId = replica.getReplicationId();
@@ -2025,7 +2034,8 @@
             LOG.log(Level.INFO, "Try number: "+(6 - nTries));
             LOG.log(Level.INFO, "replicationId of source replica: "+
                 replicationId);
-            initializeSuffix(ctx, replicationId, dn, !isADS, hostPort);
+            initializeSuffix(ctx, replicationId, dn, !isADS && !isSchema,
+                hostPort);
             initDone = true;
           }
           catch (PeerNotFoundException pnfe)
@@ -2062,7 +2072,7 @@
         }
         throw ae;
       }
-      if (isADS)
+      if (isADS || isSchema)
       {
         notifyListeners(getFormattedDone());
       }
diff --git a/opends/src/server/org/opends/server/config/ConfigConstants.java b/opends/src/server/org/opends/server/config/ConfigConstants.java
index c002985..07ce3f0 100644
--- a/opends/src/server/org/opends/server/config/ConfigConstants.java
+++ b/opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -1334,7 +1334,7 @@
   public static final String ATTR_SYNCHRONIZATION_STATE_LC = "ds-sync-state";
 
   /**
-   * The name of the attribute that holds the relication generationId,
+   * The name of the attribute that holds the replication generationId,
    * formatted in lowercase.
    */
   public static final String ATTR_SYNCHRONIZATION_GENERATIONID_LC =
diff --git a/opends/src/server/org/opends/server/types/Schema.java b/opends/src/server/org/opends/server/types/Schema.java
index 7e6391a..16692dd 100644
--- a/opends/src/server/org/opends/server/types/Schema.java
+++ b/opends/src/server/org/opends/server/types/Schema.java
@@ -2957,9 +2957,9 @@
   }
 
   /**
-   * Sets the Synchronization state for this schema.
+   * Sets the Synchronization generationId for this schema.
    *
-   * @param  values  Synchronization state for this schema.
+   * @param  values  Synchronization generationId for this schema.
    */
   public void setSynchronizationGenerationId(
               LinkedHashSet<AttributeValue> values)

--
Gitblit v1.10.0