This is an automated email from the ASF dual-hosted git repository. sboikov pushed a commit to branch ignite-835 in repository https://gitbox.apache.org/repos/asf/ignite.git
commit af58de599e013c4eae99dcdb4f0a2971de6ed47f Author: sboikov <sboi...@apache.org> AuthorDate: Thu Jan 24 19:02:23 2019 +0300 ignite-835 --- .../distributed/CacheLockChangingTopologyTest.java | 158 +++++++++++++++++++++ .../distributed/GridCacheLockAbstractTest.java | 8 ++ .../ignite/testsuites/IgniteCacheTestSuite3.java | 3 + 3 files changed, 169 insertions(+) diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockChangingTopologyTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockChangingTopologyTest.java new file mode 100644 index 0000000..22519b0 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockChangingTopologyTest.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.processors.cache.distributed; + +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; +import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.NearCacheConfiguration; +import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.concurrent.Callable; +import java.util.concurrent.ThreadLocalRandom; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; + +/** + * + */ +@RunWith(JUnit4.class) +public class CacheLockChangingTopologyTest extends GridCommonAbstractTest { + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + stopAllGrids(); + } + + /** + * @throws Exception If failed. + */ + @Test + public void testLockOnChangingTopology_Partitioned() throws Exception { + lockOnChangingTopology(CacheMode.PARTITIONED, false); + } + + /** + * @throws Exception If failed. + */ + @Test + public void testLockOnChangingTopology_PartitionedNearEnabled() throws Exception { + lockOnChangingTopology(CacheMode.PARTITIONED, true); + } + + /** + * @throws Exception If failed. + */ + @Test + public void testLockOnChangingTopology_Replicated() throws Exception { + lockOnChangingTopology(CacheMode.REPLICATED, false); + } + + /** + * @throws Exception If failed. + */ + private void lockOnChangingTopology(CacheMode cacheMode, boolean nearEnabled) throws Exception { + Ignite ignite = startGrid(0); + + CacheConfiguration<Long, Long> ccfg = new CacheConfiguration<>(DEFAULT_CACHE_NAME); + + ccfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); + ccfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC); + ccfg.setCacheMode(cacheMode); + + if (nearEnabled) + ccfg.setNearConfiguration(new NearCacheConfiguration<>()); + + IgniteCache<Long, Long> cache = ignite.createCache(ccfg); + + IgniteInternalFuture<?> nodeStart = GridTestUtils.runAsync(new Callable<Void>() { + @Override public Void call() throws Exception { + for (int i = 0; i < 3; i++) { + Thread.sleep(ThreadLocalRandom.current().nextLong(500) + 1000); + + startGrid(1); + + awaitPartitionMapExchange(); + } + + return null; + } + }); + + long stopTime = System.currentTimeMillis() + 60_000; + + long cnt = 0; + + final AtomicReference<Throwable> err = new AtomicReference<>(); + + while (!nodeStart.isDone() && System.currentTimeMillis() < stopTime) { + final long key = cnt++ % 100; + + info("Iteration: " + cnt); + + final Lock lock = cache.lock(key); + + boolean unlocked = false; + + lock.lock(); + + try { + Thread t = new Thread(new Runnable() { + @Override public void run() { + try { + lock.lock(); + lock.unlock(); + } + catch (Throwable e) { + err.set(e); + } + } + }); + + t.setName("lock-thread"); + t.start(); + + Thread.sleep(ThreadLocalRandom.current().nextLong(100) + 50); + + // Check lock was not acquired while it is still locked. + assertTrue(t.isAlive()); + + lock.unlock(); + + unlocked = true; + + t.join(); + } finally { + if (!unlocked) + lock.unlock(); + } + + if (err.get() != null) + fail("Unexpected error: " + err); + } + + assertTrue("Failed to wait for node start", nodeStart.isDone()); + } +} \ No newline at end of file diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheLockAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheLockAbstractTest.java index 71b76dc..16069ce 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheLockAbstractTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheLockAbstractTest.java @@ -516,6 +516,14 @@ public abstract class GridCacheLockAbstractTest extends GridCommonAbstractTest { */ @Test public void testLockReentrancy() throws Throwable { + /** + * awaitPartitionMapExchange is needed, otherwise deadlock is possible: + * main thread acquires lock and starts and wait for new thread while lock is acquired. + * New thread tries to get lock, at this moment exchanges starts and new thread + * waits for it. But exchange is not able to finish since there is acquired lock. + */ + awaitPartitionMapExchange(); + Affinity<Integer> aff = ignite1.affinity(DEFAULT_CACHE_NAME); for (int i = 10; i < 100; i++) { diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java index 81e0749..cd31fe0 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java @@ -37,6 +37,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheGroupsTest; import org.apache.ignite.internal.processors.cache.IgniteCacheInterceptorSelfTestSuite; import org.apache.ignite.internal.processors.cache.IgniteCacheScanPredicateDeploymentSelfTest; import org.apache.ignite.internal.processors.cache.distributed.CacheAsyncOperationsTest; +import org.apache.ignite.internal.processors.cache.distributed.CacheLockChangingTopologyTest; import org.apache.ignite.internal.processors.cache.distributed.GridCacheMixedModeSelfTest; import org.apache.ignite.internal.processors.cache.distributed.IgniteTxGetAfterStopTest; import org.apache.ignite.internal.processors.cache.distributed.IgniteTxRemoveTimeoutObjectsNearTest; @@ -130,6 +131,8 @@ public class IgniteCacheTestSuite3 { GridTestUtils.addTestIfNeeded(suite,GridCacheReplicatedPreloadLifecycleSelfTest.class, ignoredTests); GridTestUtils.addTestIfNeeded(suite,GridCacheSyncReplicatedPreloadSelfTest.class, ignoredTests); + GridTestUtils.addTestIfNeeded(suite, CacheLockChangingTopologyTest.class, ignoredTests); + //GridTestUtils.addTestIfNeeded(suite,GridCacheReplicatedEntrySetSelfTest.class, ignoredTests); //GridTestUtils.addTestIfNeeded(suite,GridCacheReplicatedMarshallerTxTest.class, ignoredTests); //GridTestUtils.addTestIfNeeded(suite,GridCacheReplicatedOnheapFullApiSelfTest.class, ignoredTests);