You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by dg...@apache.org on 2019/09/19 08:02:14 UTC
[ignite] branch master updated: IGNITE-12119 Fixed peer Class
Loading has no retries - Fixes #6821.
This is an automated email from the ASF dual-hosted git repository.
dgovorukhin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 27434c5 IGNITE-12119 Fixed peer Class Loading has no retries - Fixes #6821.
27434c5 is described below
commit 27434c5c6d909f3779875b0085ff6d99a7cd8847
Author: Ivan Bessonov <be...@gmail.com>
AuthorDate: Thu Sep 19 11:01:59 2019 +0300
IGNITE-12119 Fixed peer Class Loading has no retries - Fixes #6821.
Signed-off-by: Dmitriy Govorukhin <dm...@gmail.com>
---
.../managers/deployment/GridDeployment.java | 7 +
.../deployment/GridDeploymentClassLoader.java | 35 +++-
.../deployment/GridDeploymentCommunication.java | 15 +-
.../deployment/GridDeploymentPerVersionStore.java | 14 +-
.../GridPeerDeploymentRetryModifiedTest.java | 176 +++++++++++++++++++++
.../internal/GridPeerDeploymentRetryTest.java | 158 ++++++++++++++++++
.../ignite/testsuites/IgniteBasicTestSuite.java | 5 +
.../ignite/tests/p2p/CacheDeploymentTestTask4.java | 87 ++++++++++
8 files changed, 489 insertions(+), 8 deletions(-)
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeployment.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeployment.java
index c47649d..a24cd7c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeployment.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeployment.java
@@ -30,8 +30,10 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicStampedReference;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.compute.ComputeTask;
import org.apache.ignite.configuration.DeploymentMode;
import org.apache.ignite.internal.processors.task.GridInternal;
@@ -42,6 +44,7 @@ import org.apache.ignite.internal.util.lang.GridPeerDeployAware;
import org.apache.ignite.internal.util.lang.GridTuple;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiTuple;
@@ -498,6 +501,10 @@ public class GridDeployment extends GridMetadataAwareAdapter implements GridDepl
}
}
}
+ catch (IgniteException e) {
+ if (!X.hasCause(e, TimeoutException.class))
+ throw e;
+ }
}
return cls;
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentClassLoader.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentClassLoader.java
index 640b0c7..346c4d2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentClassLoader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentClassLoader.java
@@ -28,7 +28,9 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeoutException;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.DeploymentMode;
@@ -37,6 +39,7 @@ import org.apache.ignite.internal.util.GridBoundedLinkedHashSet;
import org.apache.ignite.internal.util.GridByteArrayList;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteUuid;
@@ -445,6 +448,9 @@ class GridDeploymentClassLoader extends ClassLoader implements GridDeploymentInf
// Catch Throwable to secure against any errors resulted from
// corrupted class definitions or other user errors.
catch (Exception e) {
+ if (X.hasCause(e, TimeoutException.class))
+ throw e;
+
throw new ClassNotFoundException("Failed to load class due to unexpected error: " + name, e);
}
@@ -581,6 +587,8 @@ class GridDeploymentClassLoader extends ClassLoader implements GridDeploymentInf
IgniteCheckedException err = null;
+ TimeoutException te = null;
+
for (UUID nodeId : nodeListCp) {
if (nodeId.equals(ctx.discovery().localNode().id()))
// Skip local node as it is already used as parent class loader.
@@ -598,7 +606,14 @@ class GridDeploymentClassLoader extends ClassLoader implements GridDeploymentInf
}
try {
- GridDeploymentResponse res = comm.sendResourceRequest(path, ldrId, node, endTime);
+ GridDeploymentResponse res = null;
+
+ try {
+ res = comm.sendResourceRequest(path, ldrId, node, endTime);
+ }
+ catch (TimeoutException e) {
+ te = e;
+ }
if (res == null) {
String msg = "Failed to send class-loading request to node (is node alive?) [node=" +
@@ -657,12 +672,28 @@ class GridDeploymentClassLoader extends ClassLoader implements GridDeploymentInf
}
}
+ if (te != null) {
+ err.addSuppressed(te);
+
+ throw new IgniteException(err);
+ }
+
throw new ClassNotFoundException("Failed to peer load class [class=" + name + ", nodeClsLdrs=" +
nodeLdrMapCp + ", parentClsLoader=" + getParent() + ']', err);
}
/** {@inheritDoc} */
@Nullable @Override public InputStream getResourceAsStream(String name) {
+ try {
+ return getResourceAsStreamEx(name);
+ }
+ catch (TimeoutException ignore) {
+ return null;
+ }
+ }
+
+ /** */
+ @Nullable public InputStream getResourceAsStreamEx(String name) throws TimeoutException {
assert !Thread.holdsLock(mux);
if (byteMap != null && name.endsWith(".class")) {
@@ -702,7 +733,7 @@ class GridDeploymentClassLoader extends ClassLoader implements GridDeploymentInf
* @param name Resource name.
* @return InputStream for resource or {@code null} if resource could not be found.
*/
- @Nullable private InputStream sendResourceRequest(String name) {
+ @Nullable private InputStream sendResourceRequest(String name) throws TimeoutException {
assert !Thread.holdsLock(mux);
long endTime = computeEndTime(p2pTimeout);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java
index daa9647..2f76ac3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentCommunication.java
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.UUID;
+import java.util.concurrent.TimeoutException;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.cluster.ClusterNode;
@@ -354,7 +355,7 @@ class GridDeploymentCommunication {
* @throws IgniteCheckedException Thrown if there is no connection with remote node.
*/
GridDeploymentResponse sendResourceRequest(final String rsrcName, IgniteUuid clsLdrId,
- final ClusterNode dstNode, long threshold) throws IgniteCheckedException {
+ final ClusterNode dstNode, long threshold) throws IgniteCheckedException, TimeoutException {
assert rsrcName != null;
assert dstNode != null;
assert clsLdrId != null;
@@ -471,13 +472,21 @@ class GridDeploymentCommunication {
timeout = threshold - U.currentTimeMillis();
}
+
+ if (timeout <= 0)
+ throw new TimeoutException();
}
catch (InterruptedException e) {
// Interrupt again to get it in the users code.
Thread.currentThread().interrupt();
- throw new IgniteCheckedException("Got interrupted while waiting for response from node: " +
- dstNode.id(), e);
+ TimeoutException te = new TimeoutException(
+ "Got interrupted while waiting for response from node: " + dstNode.id()
+ );
+
+ te.initCause(e);
+
+ throw te;
}
}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentPerVersionStore.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentPerVersionStore.java
index d537d39..abd17a3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentPerVersionStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/deployment/GridDeploymentPerVersionStore.java
@@ -29,6 +29,7 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeoutException;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.configuration.DeploymentMode;
import org.apache.ignite.events.DeploymentEvent;
@@ -701,7 +702,7 @@ public class GridDeploymentPerVersionStore extends GridDeploymentStoreAdapter {
return false;
// Temporary class loader.
- ClassLoader temp = new GridDeploymentClassLoader(
+ GridDeploymentClassLoader temp = new GridDeploymentClassLoader(
IgniteUuid.fromUuid(ctx.localNodeId()),
meta.userVersion(),
meta.deploymentMode(),
@@ -724,7 +725,14 @@ public class GridDeploymentPerVersionStore extends GridDeploymentStoreAdapter {
InputStream rsrcIn = null;
try {
- rsrcIn = temp.getResourceAsStream(path);
+ boolean timeout = false;
+
+ try {
+ rsrcIn = temp.getResourceAsStreamEx(path);
+ }
+ catch (TimeoutException e) {
+ timeout = true;
+ }
boolean found = rsrcIn != null;
@@ -744,7 +752,7 @@ public class GridDeploymentPerVersionStore extends GridDeploymentStoreAdapter {
return false;
}
- else
+ else if (!timeout)
// Cache result if classloader is still alive.
ldrRsrcCache.put(clsName, found);
}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridPeerDeploymentRetryModifiedTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridPeerDeploymentRetryModifiedTest.java
new file mode 100644
index 0000000..e8535b4
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/GridPeerDeploymentRetryModifiedTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.net.MalformedURLException;
+import java.net.URL;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DeploymentMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.testframework.GridTestExternalClassLoader;
+import org.apache.ignite.testframework.config.GridTestProperties;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ * Tests affinity and affinity mapper P2P loading.
+ */
+public class GridPeerDeploymentRetryModifiedTest extends GridCommonAbstractTest {
+ /** */
+ private static final String EXT_TASK_CLASS_NAME = "org.apache.ignite.tests.p2p.CacheDeploymentTestTask4";
+
+ /** URL of classes. */
+ private static final URL[] URLS;
+
+ /** Current deployment mode. Used in {@link #getConfiguration(String)}. */
+ private DeploymentMode depMode;
+
+ /**
+ * Initialize URLs.
+ */
+ static {
+ try {
+ URLS = new URL[] {new URL(GridTestProperties.getProperty("p2p.uri.cls"))};
+ }
+ catch (MalformedURLException e) {
+ throw new RuntimeException("Define property p2p.uri.cls", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.setCommunicationSpi(new TestRecordingCommunicationSpi());
+ cfg.setDeploymentMode(depMode);
+
+ cfg.setCacheConfiguration(new CacheConfiguration().setName(DEFAULT_CACHE_NAME));
+
+ return cfg;
+ }
+
+ /**
+ *
+ */
+ public GridPeerDeploymentRetryModifiedTest() {
+ super(false);
+ }
+
+ /**
+ * Test {@link DeploymentMode#PRIVATE} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testPrivateMode() throws Exception {
+ depMode = DeploymentMode.PRIVATE;
+
+ deploymentTest();
+ }
+
+ /**
+ * Test {@link DeploymentMode#ISOLATED} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testIsolatedMode() throws Exception {
+ depMode = DeploymentMode.ISOLATED;
+
+ deploymentTest();
+ }
+
+ /**
+ * Test {@link DeploymentMode#CONTINUOUS} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testContinuousMode() throws Exception {
+ depMode = DeploymentMode.CONTINUOUS;
+
+ deploymentTest();
+ }
+
+ /**
+ * Test {@link DeploymentMode#SHARED} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testSharedMode() throws Exception {
+ depMode = DeploymentMode.SHARED;
+
+ deploymentTest();
+ }
+
+ /** @throws Exception If failed. */
+ private void deploymentTest() throws Exception {
+ Ignite g1 = startGrid(1);
+ IgniteEx g2 = startGrid(2);
+
+ try {
+ GridTestExternalClassLoader ldr = new GridTestExternalClassLoader(URLS);
+
+ ClusterNode node = g1.cluster().node(g2.cluster().localNode().id());
+
+ g1.compute(g1.cluster().forRemotes()).execute(
+ (ComputeTask<Object, T2>)ldr.loadClass(EXT_TASK_CLASS_NAME).newInstance(),
+ new T2<>(node, null)
+ );
+
+ TestRecordingCommunicationSpi rec1 =
+ (TestRecordingCommunicationSpi)g1.configuration().getCommunicationSpi();
+
+ rec1.blockMessages((n, message) -> message instanceof GridDeploymentResponse);
+
+ ComputeTask<Object, T2> task = (ComputeTask<Object, T2>)ldr.loadClass(EXT_TASK_CLASS_NAME).newInstance();
+
+ try {
+ g1.compute(g1.cluster().forRemotes()).withTimeout(2000).execute(task, new T2<>(node, "foo"));
+
+ fail("Exception should be thrown");
+ }
+ catch (IgniteException ignore) {
+ // Expected exception.
+ //ignore.printStackTrace();
+ }
+
+ rec1.stopBlock(false, null, true, true);
+
+ try {
+ g1.compute(g1.cluster().forRemotes()).execute(task, new T2<>(node, "bar"));
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ assertFalse(g2.cache(DEFAULT_CACHE_NAME).containsKey("foo"));
+ assertTrue(g2.cache(DEFAULT_CACHE_NAME).containsKey("bar"));
+ }
+ finally {
+ stopAllGrids(true);
+ }
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridPeerDeploymentRetryTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridPeerDeploymentRetryTest.java
new file mode 100644
index 0000000..df80b11
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/GridPeerDeploymentRetryTest.java
@@ -0,0 +1,158 @@
+/*
+ * 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.net.MalformedURLException;
+import java.net.URL;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeTask;
+import org.apache.ignite.configuration.DeploymentMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.deployment.GridDeploymentResponse;
+import org.apache.ignite.testframework.GridTestExternalClassLoader;
+import org.apache.ignite.testframework.config.GridTestProperties;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Test;
+
+/**
+ * Tests affinity and affinity mapper P2P loading.
+ */
+public class GridPeerDeploymentRetryTest extends GridCommonAbstractTest {
+ /** */
+ private static final String EXT_TASK_CLASS_NAME = "org.apache.ignite.tests.p2p.CacheDeploymentTestTask2";
+
+ /** URL of classes. */
+ private static final URL[] URLS;
+
+ /** Current deployment mode. Used in {@link #getConfiguration(String)}. */
+ private DeploymentMode depMode;
+
+ /**
+ * Initialize URLs.
+ */
+ static {
+ try {
+ URLS = new URL[] {new URL(GridTestProperties.getProperty("p2p.uri.cls"))};
+ }
+ catch (MalformedURLException e) {
+ throw new RuntimeException("Define property p2p.uri.cls", e);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.setCommunicationSpi(new TestRecordingCommunicationSpi());
+ cfg.setDeploymentMode(depMode);
+
+ return cfg;
+ }
+
+ /**
+ *
+ */
+ public GridPeerDeploymentRetryTest() {
+ super(false);
+ }
+
+ /**
+ * Test {@link DeploymentMode#PRIVATE} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testPrivateMode() throws Exception {
+ depMode = DeploymentMode.PRIVATE;
+
+ deploymentTest();
+ }
+
+ /**
+ * Test {@link DeploymentMode#ISOLATED} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testIsolatedMode() throws Exception {
+ depMode = DeploymentMode.ISOLATED;
+
+ deploymentTest();
+ }
+
+ /**
+ * Test {@link DeploymentMode#CONTINUOUS} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testContinuousMode() throws Exception {
+ depMode = DeploymentMode.CONTINUOUS;
+
+ deploymentTest();
+ }
+
+ /**
+ * Test {@link DeploymentMode#SHARED} mode.
+ *
+ * @throws Exception if error occur.
+ */
+ @Test
+ public void testSharedMode() throws Exception {
+ depMode = DeploymentMode.SHARED;
+
+ deploymentTest();
+ }
+
+ /** @throws Exception If failed. */
+ private void deploymentTest() throws Exception {
+ Ignite g1 = startGrid(1);
+ Ignite g2 = startGrid(2);
+
+ try {
+ GridTestExternalClassLoader ldr = new GridTestExternalClassLoader(URLS);
+
+ TestRecordingCommunicationSpi rec1 =
+ (TestRecordingCommunicationSpi)g1.configuration().getCommunicationSpi();
+
+ rec1.blockMessages((node, message) -> message instanceof GridDeploymentResponse);
+
+ ComputeTask<Object, ?> task = (ComputeTask<Object, ?>)ldr.loadClass(EXT_TASK_CLASS_NAME).newInstance();
+
+ ClusterNode node = g1.cluster().node(g2.cluster().localNode().id());
+
+ try {
+ g1.compute(g1.cluster().forRemotes()).execute(task, node);
+
+ fail("Exception should be thrown");
+ }
+ catch (IgniteException ignore) {
+ // Expected exception.
+ }
+
+ rec1.stopBlock(false, null, true, true);
+
+ g1.compute(g1.cluster().forRemotes()).execute(task, node);
+ }
+ finally {
+ stopAllGrids(true);
+ }
+ }
+}
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
index ac8dd15..0cb88d8 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteBasicTestSuite.java
@@ -33,6 +33,8 @@ import org.apache.ignite.internal.GridLifecycleAwareSelfTest;
import org.apache.ignite.internal.GridLifecycleBeanSelfTest;
import org.apache.ignite.internal.GridMBeansTest;
import org.apache.ignite.internal.GridNodeMetricsLogSelfTest;
+import org.apache.ignite.internal.GridPeerDeploymentRetryModifiedTest;
+import org.apache.ignite.internal.GridPeerDeploymentRetryTest;
import org.apache.ignite.internal.GridProjectionForCachesSelfTest;
import org.apache.ignite.internal.GridReduceSelfTest;
import org.apache.ignite.internal.GridReleaseTypeSelfTest;
@@ -193,6 +195,9 @@ import org.junit.runners.Suite;
WALRecordTest.class,
+ GridPeerDeploymentRetryTest.class,
+ GridPeerDeploymentRetryModifiedTest.class,
+
// Basic DB data structures.
BPlusTreeSelfTest.class,
BPlusTreeFakeReuseSelfTest.class,
diff --git a/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/CacheDeploymentTestTask4.java b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/CacheDeploymentTestTask4.java
new file mode 100644
index 0000000..33b1b88
--- /dev/null
+++ b/modules/extdata/p2p/src/main/java/org/apache/ignite/tests/p2p/CacheDeploymentTestTask4.java
@@ -0,0 +1,87 @@
+/*
+ * 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.tests.p2p;
+
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJob;
+import org.apache.ignite.compute.ComputeJobAdapter;
+import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.compute.ComputeTaskAdapter;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Test task for {@code GridCacheDeploymentSelfTest}.
+ */
+public class CacheDeploymentTestTask4 extends ComputeTaskAdapter<T2<ClusterNode, String>, Object> {
+ /** Serial version uid. */
+ private static final long serialVersionUID = 0L;
+
+ /** {@inheritDoc} */
+ @NotNull @Override public Map<? extends ComputeJob, ClusterNode> map(List<ClusterNode> subgrid,
+ @Nullable T2<ClusterNode, String> tup) {
+ final String val = tup.getValue();
+
+ return F.asMap(
+ new ComputeJobAdapter() {
+ private static final long serialVersionUID = 0L;
+
+ /** Ignite instance. */
+ @IgniteInstanceResource
+ private Ignite ignite;
+
+ /** {@inheritDoc} */
+ @Override public Object execute() {
+ X.println("Executing CacheDeploymentTestTask4 job on node " +
+ ignite.cluster().localNode().id());
+
+ try {
+ if (val != null)
+ ignite.cache("default").put(val, Val.getVal());
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return null;
+ }
+ },
+ tup.get1()
+ );
+ }
+
+ /** */
+ public static class Val {
+ /** */
+ private static Object getVal() {
+ return new CacheDeploymentTestValue();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Nullable @Override public Object reduce(List<ComputeJobResult> results) {
+ return null;
+ }
+}