Repository: ignite Updated Branches: refs/heads/ignite-3478 987a57e33 -> 39f7ae974
IGNITE-6071 White list of exceptions to suppress in createTcpClient. This closes #2575. Signed-off-by: nikolay_tikhonov <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/4c31549c Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/4c31549c Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/4c31549c Branch: refs/heads/ignite-3478 Commit: 4c31549c1916860203b9d83b2421fc163ad2dd78 Parents: 8266a98 Author: nikolay_tikhonov <[email protected]> Authored: Thu Oct 26 14:24:27 2017 +0300 Committer: nikolay_tikhonov <[email protected]> Committed: Thu Oct 26 14:24:27 2017 +0300 ---------------------------------------------------------------------- .../communication/tcp/TcpCommunicationSpi.java | 3 +- .../ignite/spi/discovery/tcp/ServerImpl.java | 2 + ...entConnectAfterCommunicationFailureTest.java | 156 +++++++++++++++++++ .../IgniteClientReconnectTestSuite.java | 4 +- 4 files changed, 163 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/4c31549c/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java index 065609f..1bff8ee 100755 --- a/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/communication/tcp/TcpCommunicationSpi.java @@ -3337,7 +3337,8 @@ public class TcpCommunicationSpi extends IgniteSpiAdapter implements Communicati } } - if (X.hasCause(errs, ConnectException.class, HandshakeException.class)) + if (!X.hasCause(errs, SocketTimeoutException.class, HandshakeTimeoutException.class, + IgniteSpiOperationTimeoutException.class)) throw errs; } http://git-wip-us.apache.org/repos/asf/ignite/blob/4c31549c/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java index 4c2a0ad..efe531a 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/discovery/tcp/ServerImpl.java @@ -730,6 +730,8 @@ class ServerImpl extends TcpDiscoveryImpl { finally { U.closeQuiet(sock); } + + U.sleep(200); } } catch (Throwable t) { http://git-wip-us.apache.org/repos/asf/ignite/blob/4c31549c/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientConnectAfterCommunicationFailureTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientConnectAfterCommunicationFailureTest.java b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientConnectAfterCommunicationFailureTest.java new file mode 100644 index 0000000..301d5f2 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientConnectAfterCommunicationFailureTest.java @@ -0,0 +1,156 @@ +/* + * 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.internal; + +import java.util.Arrays; +import java.util.UUID; +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cluster.ClusterNode; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.util.nio.GridCommunicationClient; +import org.apache.ignite.internal.util.typedef.internal.U; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +/** + * Tests client to be able restore connection to cluster on subsequent attempts after communication problems. + */ +public class IgniteClientConnectAfterCommunicationFailureTest extends GridCommonAbstractTest { + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + } + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + cfg.setNetworkTimeout(500); + cfg.setCommunicationSpi(new TcpCommunicationSpi(gridName.contains("block"))); + + if (gridName.contains("client")) { + cfg.setClientMode(true); + } + + return cfg; + } + + /** + * @throws Exception If failed. + */ + public void testClientReconnects() throws Exception { + Ignite srv1 = startGrid("server1"); + Ignite srv2 = startGrid("server2"); + startGrid("client-block"); + + assertEquals(1, srv2.cluster().forClients().nodes().size()); + assertEquals(1, srv1.cluster().forClients().nodes().size()); + } + + /** + * @throws Exception If failed. + */ + public void testClientThreadsSuspended() throws Exception { + Ignite srv1 = startGrid("server1"); + Ignite srv2 = startGrid("server2"); + Ignite client = startGrid("client"); + + boolean blockedAnything = false; + + for (Thread thread : Thread.getAllStackTraces().keySet()) { + if (thread.getName().contains("%client%")) { + thread.suspend(); + blockedAnything = true; + } + } + + Thread.sleep(10000); + + for (Thread thread : Thread.getAllStackTraces().keySet()) { + if (thread.getName().contains("%client%")) + thread.resume(); + } + + for (int j = 0; j < 10; j++) { + boolean topOk = true; + + for (Ignite node : Arrays.asList(srv1, srv2, client)) { + if (node.cluster().nodes().size() != 3) { + U.warn(log, "Grid size is incorrect (will re-run check in 1000 ms) " + + "[name=" + node.name() + ", size=" + node.cluster().nodes().size() + ']'); + + topOk = false; + + break; + } + } + + if (topOk) + return; + else + Thread.sleep(1000); + } + + assertTrue(blockedAnything); + assertEquals(1, srv2.cluster().forClients().nodes().size()); + assertEquals(1, srv1.cluster().forClients().nodes().size()); + } + + /** + * Will never connect with the first node id, normal operation after. + */ + private class TcpCommunicationSpi extends org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi { + /** + * Whether this instance should actually block. + */ + private final boolean isBlocking; + + /** + * Local node ID that is prevented from creating connections. + */ + private volatile UUID blockedNodeId = null; + + /** + * + * @param isBlocking Whether this instance should actually block. + */ + public TcpCommunicationSpi(boolean isBlocking) { + this.isBlocking = isBlocking; + } + + /** {@inheritDoc} */ + @Override protected GridCommunicationClient createTcpClient(ClusterNode node, int connIdx) + throws IgniteCheckedException { + if (blockHandshakeOnce(getLocalNode().id())) { + throw new IgniteCheckedException("Node is blocked"); + } + + return super.createTcpClient(node, connIdx); + } + + /** Check if this connection is blocked. */ + private boolean blockHandshakeOnce(UUID nodeId) { + if (isBlocking && (blockedNodeId == null || blockedNodeId.equals(nodeId))) { + blockedNodeId = nodeId; + return true; + } + return false; + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/4c31549c/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteClientReconnectTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteClientReconnectTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteClientReconnectTestSuite.java index 03d3fe2..d0e907c 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteClientReconnectTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteClientReconnectTestSuite.java @@ -18,6 +18,7 @@ package org.apache.ignite.testsuites; import junit.framework.TestSuite; +import org.apache.ignite.internal.IgniteClientConnectAfterCommunicationFailureTest; import org.apache.ignite.internal.IgniteClientReconnectApiExceptionTest; import org.apache.ignite.internal.IgniteClientReconnectAtomicsTest; import org.apache.ignite.internal.IgniteClientReconnectBinaryContexTest; @@ -43,6 +44,7 @@ public class IgniteClientReconnectTestSuite extends TestSuite { public static TestSuite suite() throws Exception { TestSuite suite = new TestSuite("Ignite Client Reconnect Test Suite"); + suite.addTestSuite(IgniteClientConnectAfterCommunicationFailureTest.class); suite.addTestSuite(IgniteClientReconnectStopTest.class); suite.addTestSuite(IgniteClientReconnectApiExceptionTest.class); suite.addTestSuite(IgniteClientReconnectDiscoveryStateTest.class); @@ -59,4 +61,4 @@ public class IgniteClientReconnectTestSuite extends TestSuite { return suite; } -} \ No newline at end of file +}
