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

jvergara
14.27.2009 528a453c5d271bdf9ef7a7174219950492e5edb6
Follow up to fix for issue 4092 (dsreplication should allow to configure servers with no replication server and servers with only a replication server)

With the fix of 4092, the replication monitoring information for a given replication domain may not be anymore under cn=monitor of the server where the domain is configured. The replication monitoring information is only under cn=monitor of the replication servers.

The following changes wait till all the configuration has been loaded and after that tries to find the replication monitoring information by only searching on the replication servers. If the server does not calculate the whole cn=monitoring tree when a request is made to cn=monitor, the new code should be more efficient than the previous one (since only searching in one replication server should be enough). If it is not the case and the whole cn=monitor is recalculated when a search is made on it, then the new code only adds a new search in most of the cases (the worst case is the one when there are disjoint replication topologies under the same ADS with different replication servers, which is pretty rare).
2 files modified
230 ■■■■ changed files
opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java 68 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCache.java 162 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -1009,7 +1009,6 @@
  throws NamingException
  {
    boolean replicationEnabled = false;
    boolean oneDomainReplicated = false;
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
    ctls.setReturningAttributes(
@@ -1071,7 +1070,6 @@
          Set<String> replicationServers = getValues(sr,
          "ds-cfg-replication-server");
          Set<String> dns = getValues(sr, "ds-cfg-base-dn");
          oneDomainReplicated = dns.size() > 0;
          for (String dn : dns)
          {
            for (ReplicaDescriptor replica : desc.getReplicas())
@@ -1145,72 +1143,6 @@
      /* ignore */
    }
    if (cacheFilter.searchMonitoringInformation())
    {
      ctls = new SearchControls();
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
      ctls.setReturningAttributes(
          new String[] {
              "approx-older-change-not-synchronized-millis", "missing-changes",
              "domain-name", "server-id"
          });
      filter = "(missing-changes=*)";
      jndiName = new LdapName("cn=monitor");
      if (oneDomainReplicated)
      {
        try
        {
          NamingEnumeration monitorEntries = ctx.search(jndiName, filter, ctls);
          while(monitorEntries.hasMore())
          {
            SearchResult sr = (SearchResult)monitorEntries.next();
            String dn = getFirstValue(sr, "domain-name");
            int replicaId = -1;
            try
            {
              replicaId = new Integer(getFirstValue(sr, "server-id"));
            }
            catch (Throwable t)
            {
            }
            for (ReplicaDescriptor replica: desc.getReplicas())
            {
              if (Utils.areDnsEqual(dn, replica.getSuffix().getDN()) &&
                  replica.isReplicated() &&
                  (replica.getReplicationId() == replicaId))
              {
                try
                {
                  replica.setAgeOfOldestMissingChange(
                      new Long(getFirstValue(sr,
                      "approx-older-change-not-synchronized-millis")));
                }
                catch (Throwable t)
                {
                }
                try
                {
                  replica.setMissingChanges(
                      new Integer(getFirstValue(sr, "missing-changes")));
                }
                catch (Throwable t)
                {
                }
              }
            }
          }
        }
        catch (NameNotFoundException nse)
        {
        }
      }
    }
    boolean replicationSecure = false;
    if (replicationEnabled)
    {
opendj-sdk/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();
      }
    }
  }
}