You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ud...@apache.org on 2017/05/22 18:29:44 UTC

[48/69] [abbrv] geode git commit: GEODE-2804 Update InetSocketAddress, when there is IOException.

GEODE-2804 Update InetSocketAddress, when there is IOException.

Geode keeps InetSocketAddress for locators. So, if locators ip
changes in cloud/VM enviroment then Geode process unable to
connect to locator. Thus we have fixed this problem in two way.

a. If Geode client sees IOException while connecting to locator then
we change cached InetAddress to use locator hostname. In this way,
client does DNS query again for locator host.
b. For other Geode process, now we connect to locator using hostname.

Added couple of junit tests for it.


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/e216fde1
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/e216fde1
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/e216fde1

Branch: refs/heads/feature/GEODE-2580
Commit: e216fde1e4b1613bde22112cfb1544be022c3aac
Parents: 90ee3d8
Author: Hitesh Khamesra <hk...@pivotal.io>
Authored: Thu May 11 14:51:00 2017 -0700
Committer: Hitesh Khamesra <hk...@pivotal.io>
Committed: Thu May 18 09:59:13 2017 -0700

----------------------------------------------------------------------
 .../internal/AutoConnectionSourceImpl.java      | 72 ++++++++++++++++++--
 .../membership/gms/membership/GMSJoinLeave.java |  3 +-
 .../internal/tcpserver/TcpClient.java           | 27 +++++++-
 .../internal/JmxManagerLocatorRequest.java      |  5 +-
 .../cli/commands/LauncherLifecycleCommands.java | 12 ++--
 .../AutoConnectionSourceImplJUnitTest.java      | 64 +++++++++++++++++
 6 files changed, 167 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/e216fde1/geode-core/src/main/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImpl.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImpl.java b/geode-core/src/main/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImpl.java
index 53d401a..070451c 100644
--- a/geode-core/src/main/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImpl.java
+++ b/geode-core/src/main/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImpl.java
@@ -204,12 +204,10 @@ public class AutoConnectionSourceImpl implements ConnectionSource {
 
   private ServerLocationResponse queryOneLocator(InetSocketAddress locator,
       ServerLocationRequest request) {
-    InetAddress addr = locator.getAddress();
-    int port = locator.getPort();
     Object returnObj = null;
     try {
       pool.getStats().incLocatorRequests();
-      returnObj = tcpClient.requestToServer(addr, port, request, connectionTimeout);
+      returnObj = tcpClient.requestToServer(locator, request, connectionTimeout, true);
       ServerLocationResponse response = (ServerLocationResponse) returnObj;
       pool.getStats().incLocatorResponses();
       if (response != null) {
@@ -218,6 +216,7 @@ public class AutoConnectionSourceImpl implements ConnectionSource {
       return response;
     } catch (IOException ioe) {
       reportDeadLocator(locator, ioe);
+      updateLocatorInLocatorList(locator);
       return null;
     } catch (ClassNotFoundException e) {
       logger.warn(
@@ -234,6 +233,45 @@ public class AutoConnectionSourceImpl implements ConnectionSource {
     }
   }
 
+  /**
+   * If connecting to the locator fails with an IOException, this may be because the locator's IP
+   * has changed. Add the locator back to the list of locators using host address rather than IP.
+   * This will cause another DNS lookup, hopefully finding the locator.
+   * 
+   * @param locator
+   */
+  protected void updateLocatorInLocatorList(InetSocketAddress locator) {
+    if (locator.getHostName() != null) {
+      LocatorList locatorList = locators.get();
+      List<InetSocketAddress> newLocatorsList = new ArrayList<>();
+
+      for (InetSocketAddress tloc : locatorList.getLocators()) {
+        if (tloc.equals(locator)) {
+          /**
+           * This call doesn't throw UnknownHostException;
+           */
+          InetSocketAddress changeLoc =
+              new InetSocketAddress(locator.getHostName(), locator.getPort());
+          newLocatorsList.add(changeLoc);
+          logger.info("updateLocatorInLocatorList changing locator list: loc form: " + locator
+              + " ,loc to: " + changeLoc);
+        } else {
+          newLocatorsList.add(tloc);
+        }
+      }
+
+      logger.info("updateLocatorInLocatorList locator list from:" + locatorList.getLocators()
+          + " to: " + newLocatorsList);
+
+      LocatorList newLocatorList = new LocatorList(newLocatorsList);
+      locators.set(newLocatorList);
+    }
+  }
+
+  protected List<InetSocketAddress> getCurrentLocators() {
+    return locators.get().locators;
+  }
+
   protected ServerLocationResponse queryLocators(ServerLocationRequest request) {
     Iterator controllerItr = locators.get().iterator();
     ServerLocationResponse response = null;
@@ -276,7 +314,7 @@ public class AutoConnectionSourceImpl implements ConnectionSource {
       badLocators.remove(address);
     }
 
-    newLocators.addAll(badLocators);
+    addbadLocators(newLocators, badLocators);
 
     if (logger.isInfoEnabled()) {
       LocatorList oldLocators = (LocatorList) locators.get();
@@ -300,11 +338,37 @@ public class AutoConnectionSourceImpl implements ConnectionSource {
       }
     }
     LocatorList newLocatorList = new LocatorList(newLocators);
+
     locators.set(newLocatorList);
     onlineLocators.set(new LocatorList(newOnlineLocators));
     pool.getStats().setLocatorCount(newLocators.size());
   }
 
+  /**
+   * This method will add bad locator only when locator with hostname and port is not already in
+   * list.
+   */
+  protected void addbadLocators(List<InetSocketAddress> newLocators,
+      Set<InetSocketAddress> badLocators) {
+    for (InetSocketAddress badLoc : badLocators) {
+      boolean addIt = true;
+      for (InetSocketAddress goodloc : newLocators) {
+        boolean isSameHost = badLoc.getHostName().equals(goodloc.getHostName());
+        if (isSameHost) {
+          boolean isSamePort = badLoc.getPort() == goodloc.getPort();
+          if (isSamePort) {
+            // ip has been changed so don't add this in current list
+            addIt = false;
+            break;
+          }
+        }
+      }
+      if (addIt) {
+        newLocators.add(badLoc);
+      }
+    }
+  }
+
   public void start(InternalPool pool) {
     this.pool = pool;
     pool.getStats().setInitialContacts(((LocatorList) locators.get()).size());

http://git-wip-us.apache.org/repos/asf/geode/blob/e216fde1/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
index 4bf010b..9dc7fe2 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/membership/gms/membership/GMSJoinLeave.java
@@ -1143,8 +1143,7 @@ public class GMSJoinLeave implements JoinLeave, MessageHandler {
         FindCoordinatorRequest request, int connectTimeout)
         throws ClassNotFoundException, IOException {
       TcpClient client = new TcpClient();
-      return client.requestToServer(addr.getAddress(), addr.getPort(), request, connectTimeout,
-          true);
+      return client.requestToServer(addr.getAddress(), addr.getPort(), request, connectTimeout);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/geode/blob/e216fde1/geode-core/src/main/java/org/apache/geode/distributed/internal/tcpserver/TcpClient.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/distributed/internal/tcpserver/TcpClient.java b/geode-core/src/main/java/org/apache/geode/distributed/internal/tcpserver/TcpClient.java
index 6b54170..e9476b5 100644
--- a/geode-core/src/main/java/org/apache/geode/distributed/internal/tcpserver/TcpClient.java
+++ b/geode-core/src/main/java/org/apache/geode/distributed/internal/tcpserver/TcpClient.java
@@ -134,6 +134,7 @@ public class TcpClient {
    */
   public Object requestToServer(InetAddress addr, int port, Object request, int timeout)
       throws IOException, ClassNotFoundException {
+
     return requestToServer(addr, port, request, timeout, true);
   }
 
@@ -146,7 +147,7 @@ public class TcpClient {
    * @param timeout Timeout for sending the message and receiving a reply
    * @param replyExpected Whether to wait for a reply
    *
-   * @return The reply, or null if no reply is expected
+   * @return the reply
    *
    * @throws IOException
    * @throws ClassNotFoundException
@@ -157,8 +158,30 @@ public class TcpClient {
     if (addr == null) {
       ipAddr = new InetSocketAddress(port);
     } else {
-      ipAddr = new InetSocketAddress(addr, port); // fix for bug 30810
+      ipAddr = new InetSocketAddress(addr.getHostName(), port); // fix for bug 30810
     }
+    return requestToServer(ipAddr, request, timeout, replyExpected);
+  }
+
+  /**
+   * Send a request to a Locator
+   * 
+   * @param ipAddr The locator's inet socket address
+   * @param request The request message
+   * @param timeout Timeout for sending the message and receiving a reply
+   * @param replyExpected Whether to wait for a reply
+   *
+   * @return The reply, or null if no reply is expected
+   *
+   * @throws IOException
+   * @throws ClassNotFoundException
+   */
+  public Object requestToServer(InetSocketAddress ipAddr, Object request, int timeout,
+      boolean replyExpected) throws IOException, ClassNotFoundException {
+    /*
+     * InetSocketAddress ipAddr; if (addr == null) { ipAddr = new InetSocketAddress(port); } else {
+     * ipAddr = new InetSocketAddress(addr, port); // fix for bug 30810 }
+     */
 
     long giveupTime = System.currentTimeMillis() + timeout;
 

http://git-wip-us.apache.org/repos/asf/geode/blob/e216fde1/geode-core/src/main/java/org/apache/geode/management/internal/JmxManagerLocatorRequest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/JmxManagerLocatorRequest.java b/geode-core/src/main/java/org/apache/geode/management/internal/JmxManagerLocatorRequest.java
index 0efba01..eb71d38 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/JmxManagerLocatorRequest.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/JmxManagerLocatorRequest.java
@@ -18,6 +18,7 @@ import java.io.DataInput;
 import java.io.DataOutput;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.util.Map;
 import java.util.Properties;
 
@@ -71,6 +72,7 @@ public class JmxManagerLocatorRequest implements DataSerializableFixedID {
       Map<String, String> sslConfigProps) throws IOException {
     Properties distributionConfigProps = new Properties();
     InetAddress networkAddress = InetAddress.getByName(locatorHost);
+    InetSocketAddress inetSockAddr = new InetSocketAddress(networkAddress, locatorPort);
 
     try {
       if (sslConfigProps != null) {
@@ -78,8 +80,7 @@ public class JmxManagerLocatorRequest implements DataSerializableFixedID {
       }
 
       TcpClient client = new TcpClient(new DistributionConfigImpl(distributionConfigProps));
-      Object responseFromServer =
-          client.requestToServer(networkAddress, locatorPort, SINGLETON, msTimeout);
+      Object responseFromServer = client.requestToServer(inetSockAddr, SINGLETON, msTimeout, true);
 
       return (JmxManagerLocatorResponse) responseFromServer;
     } catch (ClassNotFoundException unexpected) {

http://git-wip-us.apache.org/repos/asf/geode/blob/e216fde1/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LauncherLifecycleCommands.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LauncherLifecycleCommands.java b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LauncherLifecycleCommands.java
index 0de41c0..7a2d33d 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LauncherLifecycleCommands.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/LauncherLifecycleCommands.java
@@ -116,6 +116,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.URI;
 import java.net.UnknownHostException;
@@ -685,18 +686,17 @@ public class LauncherLifecycleCommands extends AbstractCommandsSupport {
 
     try {
       final InetAddress networkAddress = InetAddress.getByName(locatorHostName);
+      InetSocketAddress inetSockAddr = new InetSocketAddress(networkAddress, locatorPort);
 
       TcpClient client = new TcpClient();
-      SharedConfigurationStatusResponse statusResponse =
-          (SharedConfigurationStatusResponse) client.requestToServer(networkAddress, locatorPort,
-              new SharedConfigurationStatusRequest(), 10000, true);
+      SharedConfigurationStatusResponse statusResponse = (SharedConfigurationStatusResponse) client
+          .requestToServer(inetSockAddr, new SharedConfigurationStatusRequest(), 10000, true);
 
       for (int i = 0; i < NUM_ATTEMPTS_FOR_SHARED_CONFIGURATION_STATUS; i++) {
         if (statusResponse.getStatus().equals(SharedConfigurationStatus.STARTED)
             || statusResponse.getStatus().equals(SharedConfigurationStatus.NOT_STARTED)) {
-          statusResponse =
-              (SharedConfigurationStatusResponse) client.requestToServer(networkAddress,
-                  locatorPort, new SharedConfigurationStatusRequest(), 10000, true);
+          statusResponse = (SharedConfigurationStatusResponse) client.requestToServer(inetSockAddr,
+              new SharedConfigurationStatusRequest(), 10000, true);
           try {
             Thread.sleep(5000);
           } catch (InterruptedException e) {

http://git-wip-us.apache.org/repos/asf/geode/blob/e216fde1/geode-core/src/test/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImplJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImplJUnitTest.java b/geode-core/src/test/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImplJUnitTest.java
index da3cbdb..9ceb461 100644
--- a/geode-core/src/test/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImplJUnitTest.java
+++ b/geode-core/src/test/java/org/apache/geode/cache/client/internal/AutoConnectionSourceImplJUnitTest.java
@@ -45,15 +45,20 @@ import org.junit.Test;
 import org.junit.contrib.java.lang.system.RestoreSystemProperties;
 import org.junit.experimental.categories.Category;
 
+import junit.framework.Assert;
+
 import java.io.IOException;
 import java.net.ConnectException;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -141,6 +146,65 @@ public class AutoConnectionSourceImplJUnitTest {
     }
   }
 
+  /**
+   * This test validates the AutoConnectionSourceImpl.updateLocatorInLocatorList method. That method
+   * takes InetSocketAddres of locator which unable to connect to locator. And update that
+   * InetSocketAddres with hostaddress of locator in locatorlist.
+   * 
+   * In this test we validate this using identityHashCode.
+   */
+  @Test
+  public void testLocatorIpChange() {
+    int port = 11011;
+    List<InetSocketAddress> locators = new ArrayList();
+    InetSocketAddress floc1 = new InetSocketAddress("fakeLocalHost1", port);
+    InetSocketAddress floc2 = new InetSocketAddress("fakeLocalHost2", port);
+    locators.add(floc1);
+    locators.add(floc2);
+    AutoConnectionSourceImpl src = new AutoConnectionSourceImpl(locators, "", 60 * 1000);
+
+    // This method will create a new InetSocketAddress of floc1
+    src.updateLocatorInLocatorList(floc1);
+
+    List<InetSocketAddress> cLocList = src.getCurrentLocators();
+
+    Assert.assertEquals(2, cLocList.size());
+
+    Iterator<InetSocketAddress> itr = cLocList.iterator();
+
+    while (itr.hasNext()) {
+      InetSocketAddress t = itr.next();
+      Assert.assertFalse("Should have replaced floc1 intsance", t == floc1);
+    }
+  }
+
+  /**
+   * This test validates the AutoConnectionSourceImpl.addbadLocators method. That method adds
+   * badLocator from badLocator list to new Locator list. And it make sure that new locator list
+   * doesn't have similar entry. For that it checks hostname and port only.
+   */
+  @Test
+  public void testAddBadLocator() {
+    int port = 11011;
+    List<InetSocketAddress> locators = new ArrayList();
+    InetSocketAddress floc1 = new InetSocketAddress("fakeLocalHost1", port);
+    InetSocketAddress floc2 = new InetSocketAddress("fakeLocalHost2", port);
+    locators.add(floc1);
+    locators.add(floc2);
+    AutoConnectionSourceImpl src = new AutoConnectionSourceImpl(locators, "", 60 * 1000);
+
+
+    Set<InetSocketAddress> badLocators = new HashSet<>();
+    InetSocketAddress b1 = new InetSocketAddress("fakeLocalHost1", port);
+    InetSocketAddress b2 = new InetSocketAddress("fakeLocalHost3", port);
+    badLocators.add(b1);
+    badLocators.add(b2);
+
+    src.addbadLocators(locators, badLocators);
+
+    Assert.assertEquals(3, locators.size());
+  }
+
   @Test
   public void testNoRespondingLocators() {
     try {