IGNITE-4590 Fixed Lock/unlock operations are hanging when topology changed
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/4bf7fdf4 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/4bf7fdf4 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/4bf7fdf4 Branch: refs/heads/ignite-1.9 Commit: 4bf7fdf40e50aa6aca8fb438fb314c35166802df Parents: ad91eac Author: nikolay tikhonov <[email protected]> Authored: Tue Feb 7 16:18:56 2017 +0300 Committer: sboikov <[email protected]> Committed: Tue Feb 7 16:26:18 2017 +0300 ---------------------------------------------------------------------- .../transactions/IgniteTxLocalAdapter.java | 3 + .../processors/cache/GridCacheTestEntryEx.java | 102 +++++++++---------- .../CacheLockReleaseNodeLeaveTest.java | 65 +++++++++++- 3 files changed, 118 insertions(+), 52 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/4bf7fdf4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java index 777489e..1a9b082 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java @@ -3785,6 +3785,9 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig // so it is safe to get acquired locks. GridCacheMvccCandidate explicitCand = entry.localOwner(); + if (explicitCand == null) + explicitCand = cctx.mvcc().explicitLock(threadId(), entry.txKey()); + if (explicitCand != null) { GridCacheVersion explicitVer = explicitCand.version(); http://git-wip-us.apache.org/repos/asf/ignite/blob/4bf7fdf4/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java index d46dee0..8f0d9b1 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java @@ -280,7 +280,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return true; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public KeyCacheObject key() { return key; } @@ -290,7 +290,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return new IgniteTxKey(key, 0); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public CacheObject rawGet() { return val; } @@ -305,7 +305,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return val != null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public CacheObject rawPut(CacheObject val, long ttl) { CacheObject old = this.val; @@ -315,14 +315,14 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return old; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public Cache.Entry wrap() { assert false; return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public Cache.Entry wrapLazyValue(boolean keepBinary) { assert false; @@ -336,19 +336,19 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Nullable @Override public CacheObject peekVisibleValue() { assert false; return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheVersion obsoleteVersion() { return obsoleteVer; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean obsolete() { return obsoleteVer != null; } @@ -358,7 +358,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return obsoleteVer != null && !obsoleteVer.equals(exclude); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean invalidate(@Nullable GridCacheVersion curVer, GridCacheVersion newVer) throws IgniteCheckedException { assert false; @@ -366,7 +366,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean invalidate(@Nullable CacheEntryPredicate[] filter) throws GridCacheEntryRemovedException, IgniteCheckedException { assert false; @@ -374,7 +374,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean evictInternal(boolean swap, GridCacheVersion obsoleteVer, @Nullable CacheEntryPredicate[] filter) { assert false; @@ -390,7 +390,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean isNew() { assert false; return false; } @@ -400,7 +400,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr assert false; return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public CacheObject innerGet( @Nullable GridCacheVersion ver, @Nullable IgniteInternalTx tx, @@ -417,12 +417,12 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return val; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public void clearReserveForLoad(GridCacheVersion ver) { assert false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public EntryGetResult innerGetAndReserveForLoad( boolean readSwap, boolean updateMetrics, @@ -437,7 +437,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Nullable @Override public EntryGetResult innerGetVersioned( @Nullable GridCacheVersion ver, IgniteInternalTx tx, @@ -456,12 +456,12 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public CacheObject innerReload() { return val; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheUpdateTxResult innerSet(@Nullable IgniteInternalTx tx, UUID evtNodeId, UUID affNodeId, @@ -544,7 +544,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheUpdateTxResult innerRemove( @Nullable IgniteInternalTx tx, UUID evtNodeId, @@ -573,7 +573,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return new GridCacheUpdateTxResult(true, old); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean clear(GridCacheVersion ver, boolean readers) throws IgniteCheckedException { if (ver == null || ver.equals(this.ver)) { val = null; @@ -584,7 +584,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean tmLock(IgniteInternalTx tx, long timeout, @Nullable GridCacheVersion serOrder, @@ -594,12 +594,12 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public void txUnlock(IgniteInternalTx tx) { assert false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean removeLock(GridCacheVersion ver) { GridCacheMvccCandidate doomed = mvcc.candidate(ver); @@ -608,7 +608,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return doomed != null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean markObsolete(GridCacheVersion ver) { if (ver == null || ver.equals(obsoleteVer)) { obsoleteVer = ver; @@ -645,19 +645,19 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheVersion version() { return ver; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean checkSerializableReadVersion(GridCacheVersion ver) { assert false; return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean initialValue( CacheObject val, GridCacheVersion ver, @@ -673,19 +673,19 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean initialValue(KeyCacheObject key, GridCacheSwapEntry unswapped) { assert false; return false; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheVersionedEntryEx versionedEntry(final boolean keepBinary) throws IgniteCheckedException { return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public EntryGetResult versionedValue(CacheObject val, GridCacheVersion curVer, GridCacheVersion newVer, @@ -696,22 +696,22 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean hasLockCandidate(GridCacheVersion ver) { return mvcc.hasCandidate(ver); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedByAny(GridCacheVersion... exclude) { return !mvcc.isEmpty(exclude); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedByThread() { return lockedByThread(Thread.currentThread().getId()); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedLocally(GridCacheVersion lockVer) { return mvcc.isLocallyOwned(lockVer); } @@ -722,52 +722,52 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return lockedLocally(lockVer) || lockedByThread(threadId); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedByThread(long threadId, GridCacheVersion exclude) { return mvcc.isLocallyOwnedByThread(threadId, false, exclude); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedByThread(long threadId) { return mvcc.isLocallyOwnedByThread(threadId, true); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedBy(GridCacheVersion ver) { return mvcc.isOwnedBy(ver); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedByThreadUnsafe(long threadId) { return mvcc.isLocallyOwnedByThread(threadId, true); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedByUnsafe(GridCacheVersion ver) { return mvcc.isOwnedBy(ver); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean lockedLocallyUnsafe(GridCacheVersion lockVer) { return mvcc.isLocallyOwned(lockVer); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public boolean hasLockCandidateUnsafe(GridCacheVersion ver) { return mvcc.hasCandidate(ver); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public Collection<GridCacheMvccCandidate> localCandidates(GridCacheVersion... exclude) { return mvcc.localCandidates(exclude); } - /** @inheritDoc */ + /** {@inheritDoc} */ Collection<GridCacheMvccCandidate> localCandidates(boolean reentries, GridCacheVersion... exclude) { return mvcc.localCandidates(reentries, exclude); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public Collection<GridCacheMvccCandidate> remoteMvccSnapshot(GridCacheVersion... exclude) { return mvcc.remoteCandidates(exclude); } @@ -777,7 +777,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return mvcc.localCandidate(threadId); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheMvccCandidate candidate(GridCacheVersion ver) { return mvcc.candidate(ver); } @@ -795,19 +795,19 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return mvcc.anyOwner(); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public GridCacheMvccCandidate localOwner() { return mvcc.localOwner(); } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public CacheObject valueBytes() { assert false; return null; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public CacheObject valueBytes(GridCacheVersion ver) { assert false; @@ -819,7 +819,7 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return 0; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public long expireTime() { return 0; } @@ -839,12 +839,12 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr return ttl; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public long ttl() { return ttl; } - /** @inheritDoc */ + /** {@inheritDoc} */ @Override public void updateTtl(GridCacheVersion ver, long ttl) { throw new UnsupportedOperationException(); } http://git-wip-us.apache.org/repos/asf/ignite/blob/4bf7fdf4/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockReleaseNodeLeaveTest.java ---------------------------------------------------------------------- diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockReleaseNodeLeaveTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockReleaseNodeLeaveTest.java index e84fd3f..687fe0b 100644 --- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockReleaseNodeLeaveTest.java +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheLockReleaseNodeLeaveTest.java @@ -17,9 +17,13 @@ package org.apache.ignite.internal.processors.cache.distributed; +import java.util.ArrayDeque; +import java.util.Queue; import java.util.concurrent.Callable; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import org.apache.ignite.Ignite; +import org.apache.ignite.IgniteCache; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.IgniteConfiguration; import org.apache.ignite.internal.IgniteInternalFuture; @@ -33,6 +37,7 @@ import org.apache.ignite.transactions.Transaction; import static java.util.concurrent.TimeUnit.SECONDS; import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL; +import static org.apache.ignite.cache.CacheMode.REPLICATED; import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC; import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ; @@ -43,6 +48,9 @@ public class CacheLockReleaseNodeLeaveTest extends GridCommonAbstractTest { /** */ private static final TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true); + /** */ + private static final String REPLICATED_TEST_CACHE = "REPLICATED_TEST_CACHE"; + /** {@inheritDoc} */ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { IgniteConfiguration cfg = super.getConfiguration(gridName); @@ -53,7 +61,12 @@ public class CacheLockReleaseNodeLeaveTest extends GridCommonAbstractTest { ccfg.setAtomicityMode(TRANSACTIONAL); - cfg.setCacheConfiguration(ccfg); + CacheConfiguration ccfg1 = new CacheConfiguration(REPLICATED_TEST_CACHE) + .setCacheMode(REPLICATED) + .setAtomicityMode(TRANSACTIONAL) + .setReadFromBackup(false); + + cfg.setCacheConfiguration(ccfg, ccfg1); return cfg; } @@ -114,6 +127,56 @@ public class CacheLockReleaseNodeLeaveTest extends GridCommonAbstractTest { /** * @throws Exception If failed. */ + public void testLockTopologyChange() throws Exception { + final int nodeCnt = 5; + int threadCnt = 8; + final int keys = 100; + + try { + final AtomicBoolean stop = new AtomicBoolean(false); + + Queue<IgniteInternalFuture<Long>> q = new ArrayDeque<>(nodeCnt); + + for (int i = 0; i < nodeCnt; i++) { + final Ignite ignite = startGrid(i); + + IgniteInternalFuture<Long> f = GridTestUtils.runMultiThreadedAsync(new Runnable() { + @Override public void run() { + while (!Thread.currentThread().isInterrupted() && !stop.get()) { + IgniteCache<Integer, Integer> cache = ignite.cache(REPLICATED_TEST_CACHE); + + for (int i = 0; i < keys; i++) { + Lock lock = cache.lock(i); + lock.lock(); + + cache.put(i, i); + + lock.unlock(); + } + } + } + }, threadCnt, "test-lock-thread"); + + q.add(f); + + U.sleep(1_000); + } + + stop.set(true); + + IgniteInternalFuture<Long> f; + + while ((f = q.poll()) != null) + f.get(2_000); + } + finally { + stopAllGrids(); + } + } + + /** + * @throws Exception If failed. + */ public void testTxLockRelease() throws Exception { startGrids(2);
