Added change to change InetAddress when there is IOException
Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/3a46b791 Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/3a46b791 Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/3a46b791 Branch: refs/heads/feature/GEODE-2804v3 Commit: 3a46b791f5d6f542893e6a708edbe48814aa5913 Parents: 718583b Author: Hitesh Khamesra <hkhame...@pivotal.io> Authored: Tue Jun 13 15:56:33 2017 -0700 Committer: Hitesh Khamesra <hkhame...@pivotal.io> Committed: Tue Jun 27 12:53:07 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 | 1 + .../AutoConnectionSourceImplJUnitTest.java | 64 +++++++++++++++++ 6 files changed, 162 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/3a46b791/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/3a46b791/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 bc3d708..93c5bf8 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 @@ -1187,8 +1187,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/3a46b791/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/3a46b791/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/3a46b791/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 88832ba..b325e18 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 @@ -101,6 +101,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Arrays; http://git-wip-us.apache.org/repos/asf/geode/blob/3a46b791/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 3cc3cfc..9169904 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 {