ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akuznet...@apache.org
Subject [1/5] ignite git commit: IGNITE-3408 - Provided basic implementation of AddressResolver
Date Thu, 04 Aug 2016 09:53:59 GMT
Repository: ignite
Updated Branches:
  refs/heads/ignite-3443 8033f119e -> d8b92b4b4


IGNITE-3408 - Provided basic implementation of AddressResolver


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

Branch: refs/heads/ignite-3443
Commit: a90d05b30f39da001156fdd4053790f8cd352406
Parents: ae23dab
Author: Valentin Kulichenko <valentin.lulichenko@gmail.com>
Authored: Wed Aug 3 22:00:15 2016 -0700
Committer: Valentin Kulichenko <valentin.lulichenko@gmail.com>
Committed: Wed Aug 3 22:00:15 2016 -0700

----------------------------------------------------------------------
 .../configuration/BasicAddressResolver.java     | 146 ++++++++++++
 .../spi/GridTcpSpiForwardingSelfTest.java       | 237 +++++++++++++++++--
 2 files changed, 364 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a90d05b3/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java
b/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java
new file mode 100644
index 0000000..d29689f
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/BasicAddressResolver.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.configuration;
+
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ * Basic implementation of {@link AddressResolver}.
+ * <p>
+ * Allows to provide simple mapping between different address, which is useful
+ * different parts of the cluster are located in different subnetworks and port
+ * forwarding on the router is used for communication between them. Another
+ * common case is Docker environment which can create a pair of public and private
+ * address per container.
+ * <p>
+ * There are two different types of mapping supported by this implementation of
+ * {@link AddressResolver}.
+ * <p>
+ * First type maps specific socket addresses (host and port pairs) are mapped to
+ * each other. This is useful for port forwarding, where multiple nodes will
+ * typically map to the same external address (router), but with different port
+ * numbers. Here is the example:
+ * <pre name="code" class="xml">
+ * &lt;property name=&quot;addressResolver&quot;&gt;
+ *     &lt;bean class=&quot;org.apache.ignite.configuration.BasicAddressResolver&quot;&gt;
+ *         &lt;constructor-arg&gt;
+ *             &lt;map&gt;
+ *                 &lt;entry key=&quot;10.0.0.1:47100&quot; value=&quot;123.123.123.123:1111&quot;/&gt;
+ *                 &lt;entry key=&quot;10.0.0.2:47100&quot; value=&quot;123.123.123.123:2222&quot;/&gt;
+ *                 &lt;entry key=&quot;10.0.0.3:47100&quot; value=&quot;123.123.123.123:3333&quot;/&gt;
+ *             &lt;/map&gt;
+ *         &lt;/constructor-arg&gt;
+ *     &lt;/bean&gt;
+ * &lt;/property&gt;
+ * </pre>
+ * <p>
+ * Second type maps one host to another. In this case any internal address a node
+ * is bound to will be mapped to the corresponding external host with the same
+ * host number. Here is the example:
+ * <pre name="code" class="xml">
+ * &lt;property name=&quot;addressResolver&quot;&gt;
+ *     &lt;bean class=&quot;org.apache.ignite.configuration.BasicAddressResolver&quot;&gt;
+ *         &lt;constructor-arg&gt;
+ *             &lt;map&gt;
+ *                 &lt;entry key=&quot;10.0.0.1&quot; value=&quot;123.123.123.123&quot;/&gt;
+ *             &lt;/map&gt;
+ *         &lt;/constructor-arg&gt;
+ *     &lt;/bean&gt;
+ * &lt;/property&gt;
+ * </pre>
+ * Here any port on {@code 10.0.0.1} will be mapped to the same port number on {@code 123.123.123.123}.
+ * E.g., {@code 10.0.0.1:47100} will be mapped to {@code 123.123.123.123:47100}, and {@code
10.0.0.1:47500}
+ * will be mapped to {@code 123.123.123.123:47500}.
+ * <p>
+ * Two types of mappings described above can be mixed within one address resolver.
+ */
+public class BasicAddressResolver implements AddressResolver {
+    /** Address map. */
+    private final Map<InetAddress, InetAddress> inetAddrMap;
+
+    /** Socket address map. */
+    private final Map<InetSocketAddress, InetSocketAddress> inetSockAddrMap;
+
+    /**
+     * Created the address resolver.
+     *
+     * @param addrMap Address mappings.
+     * @throws UnknownHostException If any of the hosts can't be resolved.
+     */
+    public BasicAddressResolver(Map<String, String> addrMap) throws UnknownHostException
{
+        if (addrMap == null || addrMap.isEmpty())
+            throw new IllegalArgumentException("At least one address mapping is required.");
+
+        inetAddrMap = U.newHashMap(addrMap.size());
+        inetSockAddrMap = U.newHashMap(addrMap.size());
+
+        for (Map.Entry<String, String> e : addrMap.entrySet()) {
+            String from = e.getKey();
+            String to = e.getValue();
+
+            if (F.isEmpty(from) || F.isEmpty(to))
+                throw new IllegalArgumentException("Invalid address mapping: " + e);
+
+            String[] fromArr = from.split(":");
+            String[] toArr = to.split(":");
+
+            assert fromArr.length > 0;
+            assert toArr.length > 0;
+
+            if (fromArr.length == 1) {
+                if (toArr.length != 1)
+                    throw new IllegalArgumentException("Invalid address mapping: " + e);
+
+                inetAddrMap.put(InetAddress.getByName(fromArr[0]), InetAddress.getByName(toArr[0]));
+            }
+            else if (fromArr.length == 2) {
+                if (toArr.length != 2)
+                    throw new IllegalArgumentException("Invalid address mapping: " + e);
+
+                inetSockAddrMap.put(new InetSocketAddress(fromArr[0], Integer.parseInt(fromArr[1])),
+                    new InetSocketAddress(toArr[0], Integer.parseInt(toArr[1])));
+            }
+            else
+                throw new IllegalArgumentException("Invalid address mapping: " + e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<InetSocketAddress> getExternalAddresses(InetSocketAddress
addr)
+        throws IgniteCheckedException {
+        InetSocketAddress inetSockAddr = inetSockAddrMap.get(addr);
+
+        if (inetSockAddr != null)
+            return Collections.singletonList(inetSockAddr);
+
+        InetAddress inetAddr = inetAddrMap.get(addr.getAddress());
+
+        if (inetAddr != null)
+            return Collections.singletonList(new InetSocketAddress(inetAddr, addr.getPort()));
+
+        return Collections.emptyList();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a90d05b3/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java
b/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java
index 0c3ae12..652e47f 100644
--- a/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/spi/GridTcpSpiForwardingSelfTest.java
@@ -23,10 +23,12 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.Callable;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.AddressResolver;
+import org.apache.ignite.configuration.BasicAddressResolver;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.util.nio.GridCommunicationClient;
 import org.apache.ignite.internal.util.typedef.F;
@@ -35,10 +37,11 @@ import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.internal.TcpDiscoveryNode;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 /**
- * Test for {@link org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi} and {@link org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi}.
+ * Test for {@link TcpDiscoverySpi} and {@link TcpCommunicationSpi}.
  */
 public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest {
     /** */
@@ -65,30 +68,34 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest
{
     /** */
     private static final int commExtPort2 = 20100;
 
+    /** */
+    private AddressResolver resolver;
+
+    /** */
+    private boolean ipFinderUseLocPorts;
+
     /** {@inheritDoc} */
     @SuppressWarnings({"IfMayBeConditional", "deprecation"})
     @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception
{
         TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
-        ipFinder.setAddresses(Arrays.asList("127.0.0.1:" + extPort1, "127.0.0.1:" + extPort2));
+
+        if (ipFinderUseLocPorts)
+            ipFinder.setAddresses(Arrays.asList("127.0.0.1:" + locPort1, "127.0.0.1:" + locPort2));
+        else
+            ipFinder.setAddresses(Arrays.asList("127.0.0.1:" + extPort1, "127.0.0.1:" + extPort2));
 
         TcpDiscoverySpi spi = new TcpDiscoverySpi();
 
         final int locPort;
-        final int extPort;
-        final int commExtPort;
         final int commLocPort;
 
         if (getTestGridName(0).equals(gridName)) {
             locPort = locPort1;
-            extPort = extPort1;
             commLocPort = commLocPort1;
-            commExtPort = commExtPort1;
         }
         else if (getTestGridName(1).equals(gridName)) {
             locPort = locPort2;
-            extPort = extPort2;
             commLocPort = commLocPort2;
-            commExtPort = commExtPort2;
         }
         else
             throw new IllegalArgumentException("Unknown grid name");
@@ -106,6 +113,7 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest
{
         TcpCommunicationSpi commSpi = new TcpCommunicationSpi() {
             @Override protected GridCommunicationClient createTcpClient(ClusterNode node)
throws IgniteCheckedException {
                 Map<String, Object> attrs = new HashMap<>(node.attributes());
+
                 attrs.remove(createSpiAttributeName(ATTR_PORT));
 
                 ((TcpDiscoveryNode)node).setAttributes(attrs);
@@ -121,16 +129,9 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest
{
 
         cfg.setCommunicationSpi(commSpi);
 
-        final Map<InetSocketAddress, ? extends Collection<InetSocketAddress>>
mp = F.asMap(
-            new InetSocketAddress("127.0.0.1", locPort), F.asList(new InetSocketAddress("127.0.0.1",
extPort)),
-            new InetSocketAddress("127.0.0.1", commLocPort), F.asList(new InetSocketAddress("127.0.0.1",
commExtPort))
-        );
+        assert resolver != null;
 
-        cfg.setAddressResolver(new AddressResolver() {
-            @Override public Collection<InetSocketAddress> getExternalAddresses(InetSocketAddress
addr) {
-                return mp.get(addr);
-            }
-        });
+        cfg.setAddressResolver(resolver);
 
         return cfg;
     }
@@ -138,8 +139,206 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest
{
     /**
      * @throws Exception If any error occurs.
      */
+    public void testCustomResolver() throws Exception {
+        final Map<InetSocketAddress, Collection<InetSocketAddress>> map = new
HashMap<>();
+
+        map.put(new InetSocketAddress("127.0.0.1", locPort1), F.asList(new InetSocketAddress("127.0.0.1",
extPort1)));
+        map.put(new InetSocketAddress("127.0.0.1", commLocPort1), F.asList(new InetSocketAddress("127.0.0.1",
commExtPort1)));
+        map.put(new InetSocketAddress("127.0.0.1", locPort2), F.asList(new InetSocketAddress("127.0.0.1",
extPort2)));
+        map.put(new InetSocketAddress("127.0.0.1", commLocPort2), F.asList(new InetSocketAddress("127.0.0.1",
commExtPort2)));
+
+        resolver = new AddressResolver() {
+            @Override public Collection<InetSocketAddress> getExternalAddresses(InetSocketAddress
addr) {
+                return map.get(addr);
+            }
+        };
+
+        doTestForward();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBasicResolverMapPorts() throws Exception {
+        Map<String, String> map = new HashMap<>();
+
+        map.put("127.0.0.1:" + locPort1, "127.0.0.1:" + extPort1);
+        map.put("127.0.0.1:" + commLocPort1, "127.0.0.1:" + commExtPort1);
+        map.put("127.0.0.1:" + locPort2, "127.0.0.1:" + extPort2);
+        map.put("127.0.0.1:" + commLocPort2, "127.0.0.1:" + commExtPort2);
+
+        resolver = new BasicAddressResolver(map);
+
+        doTestForward();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBasicResolverMapAddress() throws Exception {
+        Map<String, String> map = new HashMap<>();
+
+        map.put("127.0.0.1", "127.0.0.1");
+
+        resolver = new BasicAddressResolver(map);
+
+        ipFinderUseLocPorts = true;
+
+        doTestForward();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBasicResolverErrors() throws Exception {
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    return new BasicAddressResolver(null);
+                }
+            },
+            IllegalArgumentException.class,
+            "At least one address mapping is required."
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    return new BasicAddressResolver(new HashMap<String, String>());
+                }
+            },
+            IllegalArgumentException.class,
+            "At least one address mapping is required."
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("from", null);
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: from=null"
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("from", "");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: from="
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put(null, "to");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: null=to"
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("", "to");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: =to"
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("from", "to:1111");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: from=to:1111"
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("from:1111", "to");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: from:1111=to"
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("from:1111:2222", "to:1111");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: from:1111:2222=to:1111"
+        );
+
+        GridTestUtils.assertThrows(
+            log,
+            new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Map<String, String> map = new HashMap<>();
+
+                    map.put("from:1111", "to:1111:2222");
+
+                    return new BasicAddressResolver(map);
+                }
+            },
+            IllegalArgumentException.class,
+            "Invalid address mapping: from:1111=to:1111:2222"
+        );
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     @SuppressWarnings("UnusedDeclaration")
-    public void testForward() throws Exception {
+    private void doTestForward() throws Exception {
         InetAddress locHost = InetAddress.getByName("127.0.0.1");
 
         try (
@@ -163,4 +362,4 @@ public class GridTcpSpiForwardingSelfTest extends GridCommonAbstractTest
{
             assertEquals(F.asList(13, 13), t);
         }
     }
-}
\ No newline at end of file
+}


Mime
View raw message