From 6fa03dbaa5d869bd8db47140545127184dd80a48 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Tue, 14 Jul 2009 00:27:29 +0000
Subject: [PATCH] Follow up to fix for issue 4092 (dsreplication should allow to configure servers with no replication server and servers with only a replication server)

---
 opends/src/ads/org/opends/admin/ads/TopologyCache.java |  162 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 161 insertions(+), 1 deletions(-)

diff --git a/opends/src/ads/org/opends/admin/ads/TopologyCache.java b/opends/src/ads/org/opends/admin/ads/TopologyCache.java
index 47c390f..91900b7 100644
--- a/opends/src/ads/org/opends/admin/ads/TopologyCache.java
+++ b/opends/src/ads/org/opends/admin/ads/TopologyCache.java
@@ -22,11 +22,12 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2008-2009 Sun Microsystems, Inc.
  */
 
 package org.opends.admin.ads;
 
+import java.util.Collection;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -37,6 +38,12 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
 import javax.naming.ldap.LdapName;
 
 import org.opends.admin.ads.ADSContext.ServerProperty;
@@ -44,6 +51,7 @@
 import org.opends.admin.ads.util.ConnectionUtils;
 import org.opends.admin.ads.util.PreferredConnection;
 import org.opends.admin.ads.util.ServerLoader;
+import org.opends.quicksetup.util.Utils;
 
 /**
  * This class allows to read the configuration of the different servers that
@@ -166,6 +174,12 @@
         }
         servers.add(descriptor);
       }
+
+      // Figure out the replication monitoring if it is required.
+      if (getFilter().searchMonitoringInformation())
+      {
+        readReplicationMonitoring();
+      }
     }
     catch (ADSContextException ade)
     {
@@ -178,6 +192,60 @@
   }
 
   /**
+   * Reads the replication monitoring.
+   * @throws NamingException if an error occurs reading the replication
+   * monitoring.
+   */
+  private void readReplicationMonitoring() throws NamingException
+  {
+    Set<ReplicaDescriptor> replicasToUpdate = new HashSet<ReplicaDescriptor>();
+    for (ServerDescriptor server : getServers())
+    {
+      for (ReplicaDescriptor replica : server.getReplicas())
+      {
+        if (replica.isReplicated())
+        {
+          replicasToUpdate.add(replica);
+        }
+      }
+    }
+    for (ServerDescriptor server : getServers())
+    {
+      if (server.isReplicationServer())
+      {
+        Set<ReplicaDescriptor> candidateReplicas =
+          new HashSet<ReplicaDescriptor>();
+        // It contains replication information: analyze it.
+        String repServer = server.getReplicationServerHostPort();
+        for (SuffixDescriptor suffix : getSuffixes())
+        {
+          Set<String> repServers = suffix.getReplicationServers();
+          for (String r : repServers)
+          {
+            if (r.equalsIgnoreCase(repServer))
+            {
+              candidateReplicas.addAll(suffix.getReplicas());
+              break;
+            }
+          }
+        }
+        if (!candidateReplicas.isEmpty())
+        {
+          Set<ReplicaDescriptor> updatedReplicas =
+            new HashSet<ReplicaDescriptor>();
+          updateReplicas(server, candidateReplicas, updatedReplicas);
+          replicasToUpdate.removeAll(updatedReplicas);
+        }
+      }
+
+      if (replicasToUpdate.isEmpty())
+      {
+        break;
+      }
+    }
+  }
+
+  /**
    * Sets the list of LDAP URLs and connection type that are preferred to be
    * used to connect to the servers.  When we have a server to which we can
    * connect using a URL on the list we will try to use it.
@@ -290,4 +358,96 @@
   {
     return adsContext;
   }
+
+  /**
+   * Updates the monitoring information of the provided replicas using the
+   * information located in cn=monitor of a given replication server.
+   * @param replicationServer the replication server.
+   * @param candidateReplicas the collection of replicas that must be updated.
+   * @param updatedReplicas the collection of replicas that are actually
+   * updated.  This list is updated by the method.
+   */
+  private void updateReplicas(ServerDescriptor replicationServer,
+      Collection<ReplicaDescriptor> candidateReplicas,
+      Collection<ReplicaDescriptor> updatedReplicas) throws NamingException
+  {
+    SearchControls ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+    ctls.setReturningAttributes(
+        new String[] {
+            "approx-older-change-not-synchronized-millis", "missing-changes",
+            "domain-name", "server-id"
+        });
+    String filter = "(missing-changes=*)";
+
+    LdapName jndiName = new LdapName("cn=monitor");
+
+    InitialLdapContext ctx = null;
+    try
+    {
+      ServerLoader loader =
+        getServerLoader(replicationServer.getAdsProperties());
+      ctx = loader.createContext();
+      NamingEnumeration monitorEntries = ctx.search(jndiName, filter, ctls);
+
+      while(monitorEntries.hasMore())
+      {
+        SearchResult sr = (SearchResult)monitorEntries.next();
+
+        String dn = ConnectionUtils.getFirstValue(sr, "domain-name");
+        int replicaId = -1;
+        try
+        {
+          replicaId =
+            new Integer(ConnectionUtils.getFirstValue(sr, "server-id"));
+        }
+        catch (Throwable t)
+        {
+          LOG.log(Level.WARNING, "Unexpected error reading replica ID: "+t, t);
+        }
+
+        for (ReplicaDescriptor replica: candidateReplicas)
+        {
+          if (Utils.areDnsEqual(dn, replica.getSuffix().getDN()) &&
+              replica.isReplicated() &&
+              (replica.getReplicationId() == replicaId))
+          {
+            try
+            {
+              replica.setAgeOfOldestMissingChange(
+                  new Long(ConnectionUtils.getFirstValue(sr,
+                      "approx-older-change-not-synchronized-millis")));
+            }
+            catch (Throwable t)
+            {
+              LOG.log(Level.WARNING,
+                  "Unexpected error reading age of oldest change: "+t, t);
+            }
+            try
+            {
+              replica.setMissingChanges(
+                  new Integer(ConnectionUtils.getFirstValue(sr,
+                      "missing-changes")));
+            }
+            catch (Throwable t)
+            {
+              LOG.log(Level.WARNING,
+                  "Unexpected error reading missing changes: "+t, t);
+            }
+            updatedReplicas.add(replica);
+          }
+        }
+      }
+    }
+    catch (NameNotFoundException nse)
+    {
+    }
+    finally
+    {
+      if (ctx != null)
+      {
+        ctx.close();
+      }
+    }
+  }
 }

--
Gitblit v1.10.0