IGNITE-4111 Fixed NPE on client connect before disco impl is initialized - 
Fixes #5650.

Signed-off-by: Alexey Goncharuk <[email protected]>


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

Branch: refs/heads/ignite-10639
Commit: c48f3bc1046b1c496e0261edf7a693efc728b8f6
Parents: 4ae29fc
Author: NSAmelchev <[email protected]>
Authored: Tue Dec 18 18:50:38 2018 +0300
Committer: Alexey Goncharuk <[email protected]>
Committed: Tue Dec 18 18:55:54 2018 +0300

----------------------------------------------------------------------
 .../spi/discovery/tcp/TcpDiscoverySpi.java      |   4 +
 ...IgniteTcpCommunicationConnectOnInitTest.java | 172 +++++++++++++++++++
 .../IgniteSpiCommunicationSelfTestSuite.java    |   2 +
 3 files changed, 178 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c48f3bc1/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
index ce3370e..c48fa11 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/TcpDiscoverySpi.java
@@ -451,6 +451,10 @@ public class TcpDiscoverySpi extends IgniteSpiAdapter 
implements IgniteDiscovery
 
     /** {@inheritDoc} */
     @Override public Collection<ClusterNode> getRemoteNodes() {
+        // Return empty nodes for resolving compatibility until implementation 
started.
+        if (impl == null)
+            return Collections.emptyList();
+
         return impl.getRemoteNodes();
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c48f3bc1/modules/core/src/test/java/org/apache/ignite/spi/communication/tcp/IgniteTcpCommunicationConnectOnInitTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/spi/communication/tcp/IgniteTcpCommunicationConnectOnInitTest.java
 
b/modules/core/src/test/java/org/apache/ignite/spi/communication/tcp/IgniteTcpCommunicationConnectOnInitTest.java
new file mode 100644
index 0000000..0293316
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/spi/communication/tcp/IgniteTcpCommunicationConnectOnInitTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.spi.communication.tcp;
+
+import java.net.BindException;
+import java.net.InetSocketAddress;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.nio.GridNioServer;
+import org.apache.ignite.internal.util.nio.GridNioServerListenerAdapter;
+import org.apache.ignite.internal.util.nio.GridNioSession;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.communication.tcp.messages.HandshakeWaitMessage;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Testing {@link TcpCommunicationSpi} that will send the wait handshake 
message on received connections until SPI
+ * context initialized.
+ */
+@RunWith(JUnit4.class)
+public class IgniteTcpCommunicationConnectOnInitTest extends 
GridCommonAbstractTest {
+    /** */
+    private static final int START_PORT = 55443;
+
+    /** */
+    private volatile CountDownLatch commStartLatch;
+
+    /** */
+    private volatile int commSpiBoundedPort;
+
+    /** */
+    private volatile String commSpiSrvAddr;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String 
igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        cfg.setCommunicationSpi(new TestCommunicationSpi());
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @Test
+    public void testClientConnectBeforeDiscoveryStarted() throws Exception {
+        GridNioServer<?> srvr = startServer();
+
+        try {
+            commStartLatch = new CountDownLatch(1);
+
+            IgniteInternalFuture<Boolean> fut = GridTestUtils.runAsync(() -> {
+                startGrid(0);
+
+                return true;
+            });
+
+            assertTrue(commStartLatch.await(5_000, TimeUnit.MILLISECONDS));
+
+            SocketChannel ch = SocketChannel.open(new 
InetSocketAddress(commSpiSrvAddr, commSpiBoundedPort));
+
+            GridNioSession ses = srvr.createSession(ch, null, false, 
null).get();
+
+            boolean wait = GridTestUtils.waitForCondition(
+                () -> ses.bytesReceived() == 
HandshakeWaitMessage.MESSAGE_FULL_SIZE, 1000);
+
+            assertTrue("Handshake not started.", wait);
+
+            fut.get();
+        }
+        finally {
+            srvr.stop();
+        }
+    }
+
+    /**
+     * Starts custom server.
+     *
+     * @return Started server.
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    private GridNioServer<?> startServer() throws Exception {
+        int srvPort = START_PORT;
+
+        for (int i = 0; i < 10; i++) {
+            try {
+                GridNioServerListenerAdapter lsnr = new 
GridNioServerListenerAdapter() {
+                    @Override public void onConnected(GridNioSession ses) {
+                        // No-op.
+                    }
+
+                    @Override public void onDisconnected(GridNioSession ses, 
@Nullable Exception e) {
+                        // No-op.
+                    }
+
+                    @Override public void onMessage(GridNioSession ses, Object 
msg) {
+                        // No-op.
+                    }
+                };
+
+                GridNioServer<?> srvr = GridNioServer.builder()
+                    .address(U.getLocalHost())
+                    .port(srvPort)
+                    .listener(lsnr)
+                    .logger(log)
+                    .selectorCount(Runtime.getRuntime().availableProcessors())
+                    .igniteInstanceName("nio-test-grid")
+                    .filters().build();
+
+                srvr.start();
+
+                return srvr;
+            }
+            catch (IgniteCheckedException e) {
+                if (i < 9 && e.hasCause(BindException.class)) {
+                    log.error("Failed to start server, will try another port 
[err=" + e + ", port=" + srvPort + ']');
+
+                    U.sleep(1000);
+
+                    srvPort++;
+                }
+                else
+                    throw e;
+            }
+        }
+
+        fail("Failed to start server.");
+
+        return null;
+    }
+
+    /** */
+    private class TestCommunicationSpi extends TcpCommunicationSpi {
+        /** {@inheritDoc} */
+        @Override public void spiStart(String igniteInstanceName) throws 
IgniteSpiException {
+            super.spiStart(igniteInstanceName);
+
+            commSpiBoundedPort = boundPort();
+
+            commSpiSrvAddr = getLocalAddress();
+
+            commStartLatch.countDown();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c48f3bc1/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiCommunicationSelfTestSuite.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiCommunicationSelfTestSuite.java
 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiCommunicationSelfTestSuite.java
index 6a38c55..5a208e6 100644
--- 
a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiCommunicationSelfTestSuite.java
+++ 
b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteSpiCommunicationSelfTestSuite.java
@@ -36,6 +36,7 @@ import 
org.apache.ignite.spi.communication.tcp.GridTcpCommunicationSpiStartStopS
 import 
org.apache.ignite.spi.communication.tcp.GridTcpCommunicationSpiTcpFailureDetectionSelfTest;
 import 
org.apache.ignite.spi.communication.tcp.GridTcpCommunicationSpiTcpNoDelayOffSelfTest;
 import 
org.apache.ignite.spi.communication.tcp.GridTcpCommunicationSpiTcpSelfTest;
+import 
org.apache.ignite.spi.communication.tcp.IgniteTcpCommunicationConnectOnInitTest;
 import 
org.apache.ignite.spi.communication.tcp.IgniteTcpCommunicationHandshakeWaitSslTest;
 import 
org.apache.ignite.spi.communication.tcp.IgniteTcpCommunicationHandshakeWaitTest;
 import 
org.apache.ignite.spi.communication.tcp.IgniteTcpCommunicationRecoveryAckClosureSelfTest;
@@ -92,6 +93,7 @@ public class IgniteSpiCommunicationSelfTestSuite extends 
TestSuite {
 
         suite.addTest(new 
JUnit4TestAdapter(IgniteTcpCommunicationHandshakeWaitTest.class));
         suite.addTest(new 
JUnit4TestAdapter(IgniteTcpCommunicationHandshakeWaitSslTest.class));
+        suite.addTest(new 
JUnit4TestAdapter(IgniteTcpCommunicationConnectOnInitTest.class));
 
         //suite.addTest(new TestSuite(GridCacheDhtLockBackupSelfTest.class));
 

Reply via email to