From 3d5b2a62fbad7b6fdd6a43a2f654d675c2de479a Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 05 Jul 2011 16:11:32 +0000
Subject: [PATCH] Fix OPENDJ-244: Replication fails when replication server is configured for a network interface which is not an alias of localhost/127.0.0.1

---
 opends/src/server/org/opends/server/replication/server/ReplicationServer.java |  166 ++++++++++++++++++++++++++-----------------------------
 1 files changed, 79 insertions(+), 87 deletions(-)

diff --git a/opends/src/server/org/opends/server/replication/server/ReplicationServer.java b/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
index c529d5a..1f87290 100644
--- a/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
+++ b/opends/src/server/org/opends/server/replication/server/ReplicationServer.java
@@ -26,22 +26,22 @@
  *      Portions Copyright 2011 ForgeRock AS
  */
 package org.opends.server.replication.server;
+
+
+
 import static org.opends.messages.ReplicationMessages.*;
 import static org.opends.server.loggers.ErrorLogger.logError;
 import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
 import static org.opends.server.loggers.debug.DebugLogger.getTracer;
 import static org.opends.server.util.ServerConstants.EOL;
 import static org.opends.server.util.StaticUtils.getFileForPath;
+import static org.opends.server.util.StaticUtils.isLocalAddress;
 import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.StringReader;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.UnknownHostException;
+import java.net.*;
 import java.util.*;
 
 import org.opends.messages.Category;
@@ -53,39 +53,15 @@
 import org.opends.server.admin.std.meta.VirtualAttributeCfgDefn.*;
 import org.opends.server.admin.std.server.ReplicationServerCfg;
 import org.opends.server.admin.std.server.UserDefinedVirtualAttributeCfg;
-import org.opends.server.api.Backend;
-import org.opends.server.api.BackupTaskListener;
-import org.opends.server.api.ExportTaskListener;
-import org.opends.server.api.ImportTaskListener;
-import org.opends.server.api.RestoreTaskListener;
-import org.opends.server.api.VirtualAttributeProvider;
+import org.opends.server.api.*;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.WorkflowImpl;
 import org.opends.server.core.networkgroups.NetworkGroup;
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.replication.common.*;
-import org.opends.server.replication.protocol.ProtocolSession;
-import org.opends.server.replication.protocol.ReplServerStartMsg;
-import org.opends.server.replication.protocol.ReplSessionSecurity;
-import org.opends.server.replication.protocol.ReplicationMsg;
-import org.opends.server.replication.protocol.ServerStartECLMsg;
-import org.opends.server.replication.protocol.ServerStartMsg;
-import org.opends.server.replication.protocol.StartECLSessionMsg;
-import org.opends.server.replication.protocol.StartMsg;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.BackupConfig;
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
-import org.opends.server.types.DebugLogLevel;
-import org.opends.server.types.DirectoryException;
-import org.opends.server.types.Entry;
-import org.opends.server.types.LDIFExportConfig;
-import org.opends.server.types.LDIFImportConfig;
-import org.opends.server.types.RestoreConfig;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-import org.opends.server.types.VirtualAttributeRule;
+import org.opends.server.replication.protocol.*;
+import org.opends.server.types.*;
 import org.opends.server.util.LDIFReader;
 import org.opends.server.util.ServerConstants;
 import org.opends.server.util.TimeThread;
@@ -94,16 +70,14 @@
 import com.sleepycat.je.DatabaseException;
 import org.opends.server.types.SearchScope;
 
+
+
 /**
- * ReplicationServer Listener.
- *
- * This singleton is the main object of the replication server
- * It waits for the incoming connections and create listener
- * and publisher objects for
- * connection with LDAP servers and with replication servers
- *
- * It is responsible for creating the replication server replicationServerDomain
- * and managing it
+ * ReplicationServer Listener. This singleton is the main object of the
+ * replication server It waits for the incoming connections and create listener
+ * and publisher objects for connection with LDAP servers and with replication
+ * servers It is responsible for creating the replication server
+ * replicationServerDomain and managing it
  */
 public final class ReplicationServer
   implements ConfigurationChangeListener<ReplicationServerCfg>,
@@ -126,7 +100,6 @@
   private final Map<String, ReplicationServerDomain> baseDNs =
           new HashMap<String, ReplicationServerDomain>();
 
-  private String localURL = "null";
   private volatile boolean shutdown = false;
   private ReplicationDbEnv dbEnv;
   private int rcvWindow;
@@ -413,12 +386,17 @@
       while (!shutdown)
       {
         /*
-         * periodically check that we are connected to all other replication
+         * Periodically check that we are connected to all other replication
          * servers and if not establish the connection
          */
         for (ReplicationServerDomain domain : getReplicationServerDomains())
         {
-          Set<String> connectedReplServers = domain.getChangelogs();
+          // Create a normalized set of server URLs.
+          final Set<String> connectedReplServers = new HashSet<String>();
+          for (String url : domain.getChangelogs())
+          {
+            connectedReplServers.add(normalizeServerURL(url));
+          }
 
           /*
            * check that all replication server in the config are in the
@@ -426,51 +404,38 @@
            */
           for (String serverURL : replicationServers)
           {
-            int separator = serverURL.lastIndexOf(':');
-            String port = serverURL.substring(separator + 1);
-            String hostname = serverURL.substring(0, separator);
-
+            final int separator = serverURL.lastIndexOf(':');
+            final String portString = serverURL.substring(separator + 1);
+            final int port = Integer.parseInt(portString);
+            final String hostname = serverURL.substring(0, separator);
+            final InetAddress inetAddress;
             try
             {
-              InetAddress inetAddress = InetAddress
-                  .getByName(hostname);
-              String serverAddress = inetAddress.getHostAddress()
-                  + ":" + port;
-              String alternServerAddress = null;
-
-              if (hostname.equalsIgnoreCase("localhost"))
-              {
-                // if "localhost" was used as the hostname in the configuration
-                // also check is the connection is already opened with the
-                // local address.
-                alternServerAddress = InetAddress.getLocalHost()
-                    .getHostAddress() + ":" + port;
-              }
-
-              if (inetAddress.equals(InetAddress.getLocalHost()))
-              {
-                // if the host address is the local one, also check
-                // if the connection is already opened with the "localhost"
-                // address
-                alternServerAddress = "127.0.0.1" + ":" + port;
-              }
-
-              if ((serverAddress.compareTo("127.0.0.1:"
-                  + replicationPort) != 0)
-                  && (serverAddress.compareTo(this.localURL) != 0)
-                  && (!connectedReplServers.contains(serverAddress)
-                      && ((alternServerAddress == null) || !connectedReplServers
-                      .contains(alternServerAddress))))
-              {
-                connect(serverURL, domain.getBaseDn());
-              }
+              inetAddress = InetAddress.getByName(hostname);
             }
-            catch (IOException e)
+            catch (UnknownHostException e)
             {
-              Message message = ERR_COULD_NOT_SOLVE_HOSTNAME
-                  .get(hostname);
+              // If the host name cannot be resolved then no chance of
+              // connecting anyway.
+              Message message = ERR_COULD_NOT_SOLVE_HOSTNAME.get(hostname);
               logError(message);
+              continue;
             }
+
+            // Avoid connecting to self.
+            if (isLocalAddress(inetAddress) && (port == replicationPort))
+            {
+              continue;
+            }
+
+            // Don't connect to a server if it is already connected.
+            final String normalizedServerURL = normalizeServerURL(serverURL);
+            if (connectedReplServers.contains(normalizedServerURL))
+            {
+              continue;
+            }
+
+            connect(serverURL, domain.getBaseDn());
           }
         }
 
@@ -574,9 +539,7 @@
        * Open replicationServer socket
        */
       String localhostname = InetAddress.getLocalHost().getHostName();
-      String localAdddress = InetAddress.getLocalHost().getHostAddress();
       serverURL = localhostname + ":" + String.valueOf(changelogPort);
-      localURL = localAdddress + ":" + String.valueOf(changelogPort);
       listenSocket = new ServerSocket();
       listenSocket.bind(new InetSocketAddress(changelogPort));
 
@@ -1074,9 +1037,7 @@
 
         replicationPort = newPort;
         String localhostname = InetAddress.getLocalHost().getHostName();
-        String localAdddress = InetAddress.getLocalHost().getHostAddress();
         serverURL = localhostname + ":" + String.valueOf(replicationPort);
-        localURL = localAdddress + ":" + String.valueOf(replicationPort);
         listenSocket = new ServerSocket();
         listenSocket.bind(new InetSocketAddress(replicationPort));
 
@@ -2047,4 +2008,35 @@
     return dbDirname;
   }
 
+
+
+  private String normalizeServerURL(final String url)
+  {
+    final int separator = url.lastIndexOf(':');
+    final String portString = url.substring(separator + 1);
+    final String hostname = url.substring(0, separator);
+    try
+    {
+      final InetAddress inetAddress = InetAddress.getByName(hostname);
+
+      if (isLocalAddress(inetAddress))
+      {
+        // It doesn't matter whether we use an IP or hostname here.
+        return InetAddress.getLocalHost().getHostAddress() + ":" + portString;
+      }
+      else
+      {
+        return inetAddress.getHostAddress() + ":" + portString;
+      }
+    }
+    catch (UnknownHostException e)
+    {
+      // This should not happen, but if it does then just default to the
+      // original URL.
+      Message message = ERR_COULD_NOT_SOLVE_HOSTNAME.get(hostname);
+      logError(message);
+
+      return url;
+    }
+  }
 }

--
Gitblit v1.10.0