IGNITE-4920 Fixed.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ead06b06 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ead06b06 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ead06b06 Branch: refs/heads/ignite-gg-8.0.3.ea6-clients-test Commit: ead06b06f4b164998bfc5853dfa28cac4b618d8d Parents: f2c9d6c Author: Aleksei Scherbakov <[email protected]> Authored: Mon Apr 10 19:46:18 2017 +0300 Committer: Aleksei Scherbakov <[email protected]> Committed: Mon Apr 10 19:46:18 2017 +0300 ---------------------------------------------------------------------- .../deployment/local/LocalDeploymentSpi.java | 12 +- .../p2p/GridP2PLocalDeploymentSelfTest.java | 109 +++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/ead06b06/modules/core/src/main/java/org/apache/ignite/spi/deployment/local/LocalDeploymentSpi.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/spi/deployment/local/LocalDeploymentSpi.java b/modules/core/src/main/java/org/apache/ignite/spi/deployment/local/LocalDeploymentSpi.java index 68ef178..87fa452 100644 --- a/modules/core/src/main/java/org/apache/ignite/spi/deployment/local/LocalDeploymentSpi.java +++ b/modules/core/src/main/java/org/apache/ignite/spi/deployment/local/LocalDeploymentSpi.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentMap; import org.apache.ignite.IgniteLogger; +import org.apache.ignite.IgniteSystemProperties; import org.apache.ignite.compute.ComputeTask; import org.apache.ignite.compute.ComputeTaskName; import org.apache.ignite.internal.util.GridAnnotationsCache; @@ -68,6 +69,13 @@ import org.jsr166.ConcurrentLinkedHashMap; @IgnoreIfPeerClassLoadingDisabled public class LocalDeploymentSpi extends IgniteSpiAdapter implements DeploymentSpi, LocalDeploymentSpiMBean { /** */ + public static final String IGNITE_DEPLOYMENT_ADDITIONAL_CHECK = "ignite.deployment.additional.check"; + + /** */ + private static final boolean ENABLE_IGNITE_DEPLOYMENT_ADDITIONAL_CHECK = + IgniteSystemProperties.getBoolean(IGNITE_DEPLOYMENT_ADDITIONAL_CHECK); + + /** */ @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) @LoggerResource private IgniteLogger log; @@ -333,7 +341,9 @@ public class LocalDeploymentSpi extends IgniteSpiAdapter implements DeploymentSp // Check classes with class loader only when classes points to classes to avoid redundant check. // Resources map contains two entries for class with task name(alias). if (entry.getKey().equals(entry.getValue()) && isResourceExist(ldr, entry.getKey()) && - !U.hasParent(clsLdrToIgnore, ldr) && ldrRsrcs.remove(ldr, clsLdrRsrcs)) { + !U.hasParent(clsLdrToIgnore, ldr) && + (!ENABLE_IGNITE_DEPLOYMENT_ADDITIONAL_CHECK || clsLdrRsrcs.containsKey(entry.getKey())) && + ldrRsrcs.remove(ldr, clsLdrRsrcs)) { // Add class loaders in collection to notify listener outside synchronization block. rmvClsLdrs.add(ldr); http://git-wip-us.apache.org/repos/asf/ignite/blob/ead06b06/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PLocalDeploymentSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PLocalDeploymentSelfTest.java b/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PLocalDeploymentSelfTest.java index 05f102c..8884ea8 100644 --- a/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PLocalDeploymentSelfTest.java +++ b/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PLocalDeploymentSelfTest.java @@ -24,6 +24,9 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteException; import org.apache.ignite.cluster.ClusterNode; @@ -33,11 +36,17 @@ import org.apache.ignite.compute.ComputeJobResult; import org.apache.ignite.compute.ComputeTaskAdapter; import org.apache.ignite.configuration.DeploymentMode; import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.util.lang.GridPeerDeployAware; +import org.apache.ignite.lang.IgniteCallable; import org.apache.ignite.resources.IgniteInstanceResource; import org.apache.ignite.testframework.config.GridTestProperties; import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; import org.apache.ignite.testframework.junits.common.GridCommonTest; +import static org.apache.ignite.IgniteSystemProperties.IGNITE_CACHE_REMOVED_ENTRIES_TTL; +import static org.apache.ignite.spi.deployment.local.LocalDeploymentSpi.IGNITE_DEPLOYMENT_ADDITIONAL_CHECK; + /** * Test to make sure that if job executes on the same node, it reuses the same class loader as task. */ @@ -205,6 +214,106 @@ public class GridP2PLocalDeploymentSelfTest extends GridCommonAbstractTest { } /** + * Tests concurrent deployment using delegating classloader for the task. + */ + public void testConcurrentDeploymentWithDelegatingClassloader() throws Exception { + depMode = DeploymentMode.SHARED; + + // Force rmvQueue removal task to run very often. + System.setProperty(IGNITE_CACHE_REMOVED_ENTRIES_TTL, "1"); + System.setProperty(IGNITE_DEPLOYMENT_ADDITIONAL_CHECK, "true"); + + try { + final Ignite ignite = startGrid(); + + final ClassLoader delegate = ignite.getClass().getClassLoader(); + + final ClassLoader root = new DelegateClassLoader(null, delegate); + + final AtomicBoolean stop = new AtomicBoolean(); + + IgniteInternalFuture<?> fut = multithreadedAsync(new Callable<Void>() { + @Override public Void call() throws Exception { + while (!stop.get()) { + final Class<?> clazz = root.loadClass("org.apache.ignite.p2p.GridP2PLocalDeploymentSelfTest$TestClosure"); + + ignite.compute(). + call((IgniteCallable) clazz.getDeclaredConstructor(ClassLoader.class).newInstance(root)); + } + + return null; + } + }, 1); + + ignite.scheduler().runLocal(new Runnable() { + @Override public void run() { + stop.set(true); + } + }, 10, TimeUnit.SECONDS); + + fut.get(); + } finally { + stopAllGrids(); + + System.clearProperty(IGNITE_CACHE_REMOVED_ENTRIES_TTL); + System.clearProperty(IGNITE_DEPLOYMENT_ADDITIONAL_CHECK); + } + } + + /** */ + private static class TestClosure implements IgniteCallable, GridPeerDeployAware { + /** */ + transient ClassLoader clsLdr; + + /** + * @param cls Class. + */ + public TestClosure(ClassLoader cls) { + this.clsLdr = cls; + } + + /** {@inheritDoc} */ + public Object call() throws Exception { + return null; + } + + /** {@inheritDoc} */ + public Class<?> deployClass() { + return this.getClass(); + } + + /** {@inheritDoc} */ + public ClassLoader classLoader() { + return clsLdr; + } + } + + /** */ + private static class DelegateClassLoader extends ClassLoader { + /** Delegate class loader. */ + private ClassLoader delegateClsLdr; + + /** + * @param parent Parent. + * @param delegateClsLdr Delegate class loader. + */ + public DelegateClassLoader(ClassLoader parent, ClassLoader delegateClsLdr) { + super(parent); // Parent doesn't matter. + this.delegateClsLdr = delegateClsLdr; + } + + /** {@inheritDoc} */ + @Override public URL getResource(String name) { + return delegateClsLdr.getResource(name); + } + + /** {@inheritDoc} */ + @Override public Class<?> loadClass(String name) throws ClassNotFoundException { + return delegateClsLdr.loadClass(name); + } + } + + /** * Simple resource. */ public static class UserResource {
