IGNITE-3386 - Reentrant lock is lost when owner leaves topology
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c2b201ed Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c2b201ed Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c2b201ed Branch: refs/heads/ignite-4565-ddl Commit: c2b201ed5bf4bea5dd5aa013f685fdfa02544527 Parents: 840ab99 Author: Evgenii Zhuravlev <[email protected]> Authored: Thu Mar 2 10:27:13 2017 +0300 Committer: Alexey Goncharuk <[email protected]> Committed: Thu Mar 2 10:32:50 2017 +0300 ---------------------------------------------------------------------- .../src/main/java/org/apache/ignite/Ignite.java | 1 + .../datastructures/DataStructuresProcessor.java | 3 +- .../datastructures/GridCacheLockImpl.java | 17 +++++- .../internal/GridCacheRecreateLockTest.java | 62 ++++++++++++++++++++ .../testsuites/IgniteComputeGridTestSuite.java | 2 + 5 files changed, 82 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/c2b201ed/modules/core/src/main/java/org/apache/ignite/Ignite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/Ignite.java b/modules/core/src/main/java/org/apache/ignite/Ignite.java index 0de08d5..7f8974c 100644 --- a/modules/core/src/main/java/org/apache/ignite/Ignite.java +++ b/modules/core/src/main/java/org/apache/ignite/Ignite.java @@ -527,6 +527,7 @@ public interface Ignite extends AutoCloseable { * all threads on other nodes waiting to acquire lock are interrupted. * @param fair If {@code True}, fair lock will be created. * @param create Boolean flag indicating whether data structure should be created if does not exist. + * Will re-create lock if the node that stored the lock left topology and there are no backups left. * @return ReentrantLock for the given name. * @throws IgniteException If reentrant lock could not be fetched or created. */ http://git-wip-us.apache.org/repos/asf/ignite/blob/c2b201ed/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java index 1cad22f..698efd9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/DataStructuresProcessor.java @@ -1396,7 +1396,8 @@ public final class DataStructuresProcessor extends GridProcessorAdapter { name, key, reentrantLockView, - dsCacheCtx); + dsCacheCtx, + create); dsMap.put(key, reentrantLock0); http://git-wip-us.apache.org/repos/asf/ignite/blob/c2b201ed/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java index 3ab7289..1cf78fa 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheLockImpl.java @@ -105,6 +105,9 @@ public final class GridCacheLockImpl implements GridCacheLockEx, Externalizable /** Flag indicating that every operation on this lock should be interrupted. */ private volatile boolean interruptAll; + /** Re-create flag. */ + private volatile boolean reCreate; + /** * Empty constructor required by {@link Externalizable}. */ @@ -522,7 +525,14 @@ public final class GridCacheLockImpl implements GridCacheLockEx, Externalizable GridCacheLockState val = lockView.get(key); if (val == null) - throw new IgniteCheckedException("Failed to find reentrant lock with given name: " + name); + if (reCreate) { + val = new GridCacheLockState(0, ctx.nodeId(), 0, failoverSafe, fair); + + lockView.put(key, val); + } + else + throw new IgniteCheckedException("Failed to find reentrant lock with " + + "the given name: " + name); final long newThreadID = newThread.getId(); @@ -1048,12 +1058,14 @@ public final class GridCacheLockImpl implements GridCacheLockEx, Externalizable * @param key Reentrant lock key. * @param lockView Reentrant lock projection. * @param ctx Cache context. + * @param reCreate If {@code true} reentrant lock will be re-created in case it is not in cache. */ @SuppressWarnings("unchecked") public GridCacheLockImpl(String name, GridCacheInternalKey key, IgniteInternalCache<GridCacheInternalKey, GridCacheLockState> lockView, - GridCacheContext ctx) { + GridCacheContext ctx, + boolean reCreate) { assert name != null; assert key != null; assert ctx != null; @@ -1063,6 +1075,7 @@ public final class GridCacheLockImpl implements GridCacheLockEx, Externalizable this.key = key; this.lockView = lockView; this.ctx = ctx; + this.reCreate = reCreate; log = ctx.logger(getClass()); } http://git-wip-us.apache.org/repos/asf/ignite/blob/c2b201ed/modules/core/src/test/java/org/apache/ignite/internal/GridCacheRecreateLockTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/GridCacheRecreateLockTest.java b/modules/core/src/test/java/org/apache/ignite/internal/GridCacheRecreateLockTest.java new file mode 100644 index 0000000..ae4ef87 --- /dev/null +++ b/modules/core/src/test/java/org/apache/ignite/internal/GridCacheRecreateLockTest.java @@ -0,0 +1,62 @@ +package org.apache.ignite.internal; + +import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.IgniteLock; +import org.apache.ignite.Ignition; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.apache.ignite.testframework.junits.common.GridCommonTest; + +/** + * Create lock after owner node left topology test + */ +@GridCommonTest(group = "Kernal Self") +public class GridCacheRecreateLockTest extends GridCommonAbstractTest { + + /** + * @throws IgniteCheckedException If failed. + */ + public void test() throws Exception { + final Ignite ignite = startNodeAndLock("node1"); + + new Thread(new Runnable() { + @Override public void run() { + try { + Thread.sleep(2000); + } + catch (InterruptedException e) { + e.printStackTrace(); + } + + ignite.close(); + } + }).start(); + + startNodeAndLock("node2"); + } + + private Ignite startNodeAndLock(String name) { + try { + IgniteConfiguration cfg = new IgniteConfiguration(); + cfg.setGridName(name); + + Ignite ignite = Ignition.start(cfg); + + IgniteLock lock = ignite.reentrantLock("lock", true, true, true); + + System.out.println("acquiring lock"); + + lock.lock(); + + System.out.println("acquired lock"); + + return ignite; + } + catch (Exception e) { + assertTrue(false); + } + + return null; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/c2b201ed/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java index 8a501fd..7c8b6a9 100644 --- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java +++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteComputeGridTestSuite.java @@ -22,6 +22,7 @@ import org.apache.ignite.internal.ClusterNodeMetricsSelfTest; import org.apache.ignite.internal.GridAffinityNoCacheSelfTest; import org.apache.ignite.internal.GridAffinitySelfTest; import org.apache.ignite.internal.GridAlwaysFailoverSpiFailSelfTest; +import org.apache.ignite.internal.GridCacheRecreateLockTest; import org.apache.ignite.internal.GridCancelOnGridStopSelfTest; import org.apache.ignite.internal.GridCancelUnusedJobSelfTest; import org.apache.ignite.internal.GridCancelledJobsMetricsSelfTest; @@ -152,6 +153,7 @@ public class IgniteComputeGridTestSuite { suite.addTestSuite(TaskNodeRestartTest.class); suite.addTestSuite(IgniteRoundRobinErrorAfterClientReconnectTest.class); suite.addTestSuite(PublicThreadpoolStarvationTest.class); + suite.addTestSuite(GridCacheRecreateLockTest.class); return suite; }
