You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/09/30 05:01:59 UTC

[35/41] ignite git commit: ignite-1279 Fixed mvcc code to use IgniteTxKey instead of KeyCacheObject

ignite-1279 Fixed mvcc code to use IgniteTxKey instead of KeyCacheObject


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/c6bb01b4
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/c6bb01b4
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/c6bb01b4

Branch: refs/heads/ignite-1168
Commit: c6bb01b49cfef14310355148c4937aab8489da13
Parents: e5c3ca3
Author: sboikov <sb...@gridgain.com>
Authored: Tue Sep 29 09:20:25 2015 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Sep 29 09:20:25 2015 +0300

----------------------------------------------------------------------
 .../cache/GridCacheExplicitLockSpan.java        |  13 +-
 .../cache/GridCacheMvccCandidate.java           |   5 +-
 .../processors/cache/GridCacheMvccManager.java  |  47 +++---
 .../distributed/GridDistributedCacheEntry.java  |   2 +-
 .../dht/colocated/GridDhtColocatedCache.java    |  12 +-
 .../colocated/GridDhtColocatedLockFuture.java   |  16 ++-
 .../dht/preloader/GridDhtPreloader.java         |   2 +-
 .../cache/distributed/near/GridNearTxLocal.java |   2 +-
 .../cache/local/GridLocalCacheEntry.java        |   2 +-
 .../processors/cache/CrossCacheLockTest.java    | 142 +++++++++++++++++++
 .../GridCacheFinishPartitionsSelfTest.java      |   5 +-
 .../testsuites/IgniteCacheTestSuite4.java       |   3 +
 12 files changed, 201 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheExplicitLockSpan.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheExplicitLockSpan.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheExplicitLockSpan.java
index 2261c7d..df32e77 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheExplicitLockSpan.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheExplicitLockSpan.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import java.util.concurrent.locks.ReentrantLock;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -46,7 +47,7 @@ public class GridCacheExplicitLockSpan extends ReentrantLock {
 
     /** Pending candidates. */
     @GridToStringInclude
-    private final Map<KeyCacheObject, Deque<GridCacheMvccCandidate>> cands = new HashMap<>();
+    private final Map<IgniteTxKey, Deque<GridCacheMvccCandidate>> cands = new HashMap<>();
 
     /** Span lock release future. */
     @GridToStringExclude
@@ -77,7 +78,7 @@ public class GridCacheExplicitLockSpan extends ReentrantLock {
             if (cands.isEmpty())
                 return false;
 
-            assert this.topVer.equals(this.topVer);
+            assert this.topVer.equals(topVer);
 
             Deque<GridCacheMvccCandidate> deque = ensureDeque(cand.key());
 
@@ -137,7 +138,7 @@ public class GridCacheExplicitLockSpan extends ReentrantLock {
      * @param ver Version (or {@code null} if any candidate should be removed.)
      * @return Removed candidate if matches given parameters.
      */
-    public GridCacheMvccCandidate removeCandidate(KeyCacheObject key, @Nullable GridCacheVersion ver) {
+    public GridCacheMvccCandidate removeCandidate(IgniteTxKey key, @Nullable GridCacheVersion ver) {
         lock();
 
         try {
@@ -187,7 +188,7 @@ public class GridCacheExplicitLockSpan extends ReentrantLock {
      *
      * @param key Key.
      */
-    public void markOwned(KeyCacheObject key) {
+    public void markOwned(IgniteTxKey key) {
         lock();
 
         try {
@@ -210,7 +211,7 @@ public class GridCacheExplicitLockSpan extends ReentrantLock {
      * @param ver Version to lookup (if {@code null} - return any).
      * @return Last added explicit lock candidate, if any, or {@code null}.
      */
-    @Nullable public GridCacheMvccCandidate candidate(KeyCacheObject key, @Nullable final GridCacheVersion ver) {
+    @Nullable public GridCacheMvccCandidate candidate(IgniteTxKey key, @Nullable final GridCacheVersion ver) {
         lock();
 
         try {
@@ -257,7 +258,7 @@ public class GridCacheExplicitLockSpan extends ReentrantLock {
      * @param key Key to look up.
      * @return Deque.
      */
-    private Deque<GridCacheMvccCandidate> ensureDeque(KeyCacheObject key) {
+    private Deque<GridCacheMvccCandidate> ensureDeque(IgniteTxKey key) {
         Deque<GridCacheMvccCandidate> deque = cands.get(key);
 
         if (deque == null) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java
index e784f42..f19a054 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccCandidate.java
@@ -27,6 +27,7 @@ import java.util.UUID;
 import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -554,13 +555,13 @@ public class GridCacheMvccCandidate implements Externalizable,
     /**
      * @return Key.
      */
-    public KeyCacheObject key() {
+    public IgniteTxKey key() {
         GridCacheEntryEx parent0 = parent;
 
         if (parent0 == null)
             throw new IllegalStateException("Parent entry was not initialized for MVCC candidate: " + this);
 
-        return parent0.key();
+        return parent0.txKey();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
index e2d0302..dd51da2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
@@ -698,8 +698,8 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @return {@code True} if added.
      */
     public boolean addLocal(GridCacheMvccCandidate cand) {
-        assert cand.key() != null;
-        assert cand.local();
+        assert cand.key() != null : cand;
+        assert cand.local() : cand;
 
         if (cand.dhtLocal() && dhtLocCands.add(cand)) {
             if (log.isDebugEnabled())
@@ -717,8 +717,8 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @return {@code True} if removed.
      */
     public boolean removeLocal(GridCacheMvccCandidate cand) {
-        assert cand.key() != null;
-        assert cand.local();
+        assert cand.key() != null : cand;
+        assert cand.local() : cand;
 
         if (cand.dhtLocal() && dhtLocCands.remove(cand)) {
             if (log.isDebugEnabled())
@@ -825,7 +825,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @param threadId Thread id. If -1, all threads will be checked.
      * @return {@code True} if locked by any or given thread (depending on {@code threadId} value).
      */
-    public boolean isLockedByThread(KeyCacheObject key, long threadId) {
+    public boolean isLockedByThread(IgniteTxKey key, long threadId) {
         if (threadId < 0) {
             for (GridCacheExplicitLockSpan span : pendingExplicit.values()) {
                 GridCacheMvccCandidate cand = span.candidate(key, null);
@@ -853,7 +853,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @param key Key.
      * @param threadId Thread id.
      */
-    public void markExplicitOwner(KeyCacheObject key, long threadId) {
+    public void markExplicitOwner(IgniteTxKey key, long threadId) {
         assert threadId > 0;
 
         GridCacheExplicitLockSpan span = pendingExplicit.get(threadId);
@@ -871,7 +871,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @return Candidate.
      */
     public GridCacheMvccCandidate removeExplicitLock(long threadId,
-        KeyCacheObject key,
+        IgniteTxKey key,
         @Nullable GridCacheVersion ver)
     {
         assert threadId > 0;
@@ -897,7 +897,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @return Last added explicit lock candidate for given thread id and key or {@code null} if
      *      no such candidate.
      */
-    @Nullable public GridCacheMvccCandidate explicitLock(long threadId, KeyCacheObject key) {
+    @Nullable public GridCacheMvccCandidate explicitLock(long threadId, IgniteTxKey key) {
         if (threadId < 0)
             return explicitLock(key, null);
         else {
@@ -914,7 +914,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @param ver Version.
      * @return Lock candidate that satisfies given criteria or {@code null} if no such candidate.
      */
-    @Nullable public GridCacheMvccCandidate explicitLock(KeyCacheObject key, @Nullable GridCacheVersion ver) {
+    @Nullable public GridCacheMvccCandidate explicitLock(IgniteTxKey key, @Nullable GridCacheVersion ver) {
         for (GridCacheExplicitLockSpan span : pendingExplicit.values()) {
             GridCacheMvccCandidate cand = span.candidate(key, ver);
 
@@ -1019,45 +1019,40 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
 
     /**
      * @param keys Key for which locks should be released.
+     * @param cacheId Cache ID.
      * @param topVer Topology version.
      * @return Future that signals when all locks for given keys are released.
      */
     @SuppressWarnings("unchecked")
-    public IgniteInternalFuture<?> finishKeys(Collection<KeyCacheObject> keys, AffinityTopologyVersion topVer) {
+    public IgniteInternalFuture<?> finishKeys(Collection<KeyCacheObject> keys,
+        final int cacheId,
+        AffinityTopologyVersion topVer) {
         if (!(keys instanceof Set))
             keys = new HashSet<>(keys);
 
         final Collection<KeyCacheObject> keys0 = keys;
 
-        return finishLocks(new P1<KeyCacheObject>() {
-            @Override public boolean apply(KeyCacheObject key) {
-                return keys0.contains(key);
+        return finishLocks(new P1<GridDistributedCacheEntry>() {
+            @Override public boolean apply(GridDistributedCacheEntry e) {
+                return e.context().cacheId() == cacheId && keys0.contains(e.key());
             }
         }, topVer);
     }
 
     /**
-     * @param keyFilter Key filter.
+     * @param filter Entry filter.
      * @param topVer Topology version.
      * @return Future that signals when all locks for given partitions will be released.
      */
-    private IgniteInternalFuture<?> finishLocks(@Nullable final IgnitePredicate<KeyCacheObject> keyFilter, AffinityTopologyVersion topVer) {
+    private IgniteInternalFuture<?> finishLocks(@Nullable final IgnitePredicate<GridDistributedCacheEntry> filter,
+        AffinityTopologyVersion topVer) {
         assert topVer.topologyVersion() != 0;
 
         if (topVer.equals(AffinityTopologyVersion.NONE))
             return new GridFinishedFuture();
 
-        final FinishLockFuture finishFut = new FinishLockFuture(
-            keyFilter == null ?
-                locked() :
-                F.view(locked(),
-                    new P1<GridDistributedCacheEntry>() {
-                        @Override public boolean apply(GridDistributedCacheEntry e) {
-                            return F.isAll(e.key(), keyFilter);
-                        }
-                    }
-                ),
-            topVer);
+        final FinishLockFuture finishFut =
+            new FinishLockFuture(filter == null ? locked() : F.view(locked(), filter), topVer);
 
         finishFuts.add(finishFut);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
index 6904e56..d4f0d6c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedCacheEntry.java
@@ -849,7 +849,7 @@ public class GridDistributedCacheEntry extends GridCacheMapEntry {
                     GridCacheContext cctx0 = cand.parent().context();
 
                     GridDistributedCacheEntry e =
-                        (GridDistributedCacheEntry)cctx0.cache().peekEx(cand.key());
+                        (GridDistributedCacheEntry)cctx0.cache().peekEx(cand.parent().key());
 
                     if (e != null)
                         e.recheck();

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
index c8425e9..f38126d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
@@ -59,6 +59,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLock
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTransactionalCache;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearUnlockRequest;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalAdapter;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalEx;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -172,14 +173,14 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
     @Override public boolean isLocked(K key) {
         KeyCacheObject cacheKey = ctx.toCacheKeyObject(key);
 
-        return ctx.mvcc().isLockedByThread(cacheKey, -1);
+        return ctx.mvcc().isLockedByThread(ctx.txKey(cacheKey), -1);
     }
 
     /** {@inheritDoc} */
     @Override public boolean isLockedByThread(K key) {
         KeyCacheObject cacheKey = ctx.toCacheKeyObject(key);
 
-        return ctx.mvcc().isLockedByThread(cacheKey, Thread.currentThread().getId());
+        return ctx.mvcc().isLockedByThread(ctx.txKey(cacheKey), Thread.currentThread().getId());
     }
 
     /** {@inheritDoc} */
@@ -450,11 +451,12 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
 
             for (K key : keys) {
                 KeyCacheObject cacheKey = ctx.toCacheKeyObject(key);
+                IgniteTxKey txKey = ctx.txKey(cacheKey);
 
                 GridDistributedCacheEntry entry = peekExx(cacheKey);
 
                 GridCacheMvccCandidate lock =
-                    ctx.mvcc().removeExplicitLock(Thread.currentThread().getId(), cacheKey, null);
+                    ctx.mvcc().removeExplicitLock(Thread.currentThread().getId(), txKey, null);
 
                 if (lock != null) {
                     final AffinityTopologyVersion topVer = lock.topologyVersion();
@@ -566,7 +568,9 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
             Collection<KeyCacheObject> locKeys = new LinkedList<>();
 
             for (KeyCacheObject key : keys) {
-                GridCacheMvccCandidate lock = ctx.mvcc().removeExplicitLock(threadId, key, ver);
+                IgniteTxKey txKey = ctx.txKey(key);
+
+                GridCacheMvccCandidate lock = ctx.mvcc().removeExplicitLock(threadId, txKey, ver);
 
                 if (lock != null) {
                     AffinityTopologyVersion topVer = lock.topologyVersion();

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
index 1a08265..33a5cbd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
@@ -293,10 +293,12 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
      * @throws IgniteCheckedException If failed to add entry due to external locking.
      */
     @Nullable private GridCacheMvccCandidate addEntry(GridDistributedCacheEntry entry) throws IgniteCheckedException {
-        GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId, entry.key());
+        IgniteTxKey txKey = entry.txKey();
+
+        GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId, txKey);
 
         if (inTx()) {
-            IgniteTxEntry txEntry = tx.entry(entry.txKey());
+            IgniteTxEntry txEntry = tx.entry(txKey);
 
             txEntry.cached(entry);
 
@@ -317,7 +319,7 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                     lockVer,
                     timeout,
                     true,
-                    tx.entry(entry.txKey()).locked(),
+                    tx.entry(txKey).locked(),
                     inTx(),
                     inTx() && tx.implicitSingle(),
                     false,
@@ -1045,7 +1047,7 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                     }
                     else {
                         for (KeyCacheObject key : keys)
-                            cctx.mvcc().markExplicitOwner(key, threadId);
+                            cctx.mvcc().markExplicitOwner(cctx.txKey(key), threadId);
                     }
 
                     try {
@@ -1084,7 +1086,7 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
             if (!cctx.affinity().primary(cctx.localNode(), key, topVer)) {
                 // Remove explicit locks added so far.
                 for (KeyCacheObject k : keys)
-                    cctx.mvcc().removeExplicitLock(threadId, k, lockVer);
+                    cctx.mvcc().removeExplicitLock(threadId, cctx.txKey(k), lockVer);
 
                 return false;
             }
@@ -1409,7 +1411,7 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                                 log.debug("Processed response for entry [res=" + res + ", entry=" + entry + ']');
                         }
                         else
-                            cctx.mvcc().markExplicitOwner(k, threadId);
+                            cctx.mvcc().markExplicitOwner(cctx.txKey(k), threadId);
 
                         if (retval && cctx.events().isRecordable(EVT_CACHE_OBJECT_READ)) {
                             cctx.events().addEvent(cctx.affinity().partition(k),
@@ -1448,7 +1450,7 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
             undoLocks(false, false);
 
             for (KeyCacheObject key : GridDhtColocatedLockFuture.this.keys)
-                cctx.mvcc().removeExplicitLock(threadId, key, lockVer);
+                cctx.mvcc().removeExplicitLock(threadId, cctx.txKey(key), lockVer);
 
             mapOnTopology(true, new Runnable() {
                 @Override public void run() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
index 36c80a9..9d5fdca 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
@@ -339,7 +339,7 @@ public class GridDhtPreloader extends GridCachePreloaderAdapter {
      * @param msg Force keys message.
      */
     private void processForceKeysRequest(final ClusterNode node, final GridDhtForceKeysRequest msg) {
-        IgniteInternalFuture<?> fut = cctx.mvcc().finishKeys(msg.keys(), msg.topologyVersion());
+        IgniteInternalFuture<?> fut = cctx.mvcc().finishKeys(msg.keys(), msg.cacheId(), msg.topologyVersion());
 
         if (fut.isDone())
             processForceKeysRequest0(node, msg);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index 8975b4a..ea96649 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -421,7 +421,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     @Override protected void updateExplicitVersion(IgniteTxEntry txEntry, GridCacheEntryEx entry)
         throws GridCacheEntryRemovedException {
         if (entry.detached()) {
-            GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId(), entry.key());
+            GridCacheMvccCandidate cand = cctx.mvcc().explicitLock(threadId(), entry.txKey());
 
             if (cand != null && !xidVersion().equals(cand.version())) {
                 GridCacheVersion candVer = cand.version();

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java
index a4f6c92..cacac13 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCacheEntry.java
@@ -270,7 +270,7 @@ public class GridLocalCacheEntry extends GridCacheMapEntry {
                 if (!cand.used()) {
                     GridCacheContext cctx0 = cand.parent().context();
 
-                    GridLocalCacheEntry e = (GridLocalCacheEntry)cctx0.cache().peekEx(cand.key());
+                    GridLocalCacheEntry e = (GridLocalCacheEntry)cctx0.cache().peekEx(cand.parent().key());
 
                     // At this point candidate may have been removed and entry destroyed,
                     // so we check for null.

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CrossCacheLockTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CrossCacheLockTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CrossCacheLockTest.java
new file mode 100644
index 0000000..9fa13bc
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CrossCacheLockTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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;
+
+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.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ *
+ */
+public class CrossCacheLockTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final int GRID_CNT = 4;
+
+    /** */
+    private static final String CACHE1 = "cache1";
+
+    /** */
+    private static final String CACHE2 = "cache2";
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+        if (gridName.equals(getTestGridName(GRID_CNT - 1)))
+            cfg.setClientMode(true);
+
+        CacheConfiguration ccfg1 = new CacheConfiguration();
+        ccfg1.setName(CACHE1);
+        ccfg1.setBackups(1);
+        ccfg1.setAtomicityMode(TRANSACTIONAL);
+
+        CacheConfiguration ccfg2 = new CacheConfiguration();
+        ccfg2.setName(CACHE2);
+        ccfg2.setAtomicityMode(TRANSACTIONAL);
+
+        cfg.setCacheConfiguration(ccfg1, ccfg2);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(GRID_CNT - 1);
+
+        startGrid(GRID_CNT - 1);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLockUnlock() throws Exception {
+        for (int i = 0; i < GRID_CNT; i++) {
+            Ignite ignite = ignite(i);
+
+            log.info("Check node: " + ignite.name());
+
+            IgniteCache<Integer, Integer> cache1 = ignite.cache(CACHE1);
+            IgniteCache<Integer, Integer> cache2 = ignite.cache(CACHE2);
+
+            for (int k = 0; k < 1000; k++) {
+                Lock lock1 = null;
+                Lock lock2 = null;
+
+                try {
+                    lock1 = cache1.lock(k);
+
+                    assertTrue(lock1.tryLock());
+
+                    assertTrue(cache1.isLocalLocked(k, true));
+                    assertFalse(cache2.isLocalLocked(k, true));
+
+                    lock2 = cache2.lock(k);
+
+                    assertTrue(lock2.tryLock());
+
+                    assertTrue(cache1.isLocalLocked(k, true));
+                    assertTrue(cache2.isLocalLocked(k, true));
+
+                    lock2.unlock();
+
+                    lock2 = null;
+
+                    assertTrue(cache1.isLocalLocked(k, true));
+                    assertFalse(cache2.isLocalLocked(k, true));
+
+                    lock1.unlock();
+
+                    lock1 = null;
+
+                    assertFalse(cache1.isLocalLocked(k, true));
+                    assertFalse(cache2.isLocalLocked(k, true));
+                }
+                finally {
+                    if (lock1 != null)
+                        lock1.unlock();
+
+                    if (lock2 != null)
+                        lock2.unlock();
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheFinishPartitionsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheFinishPartitionsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheFinishPartitionsSelfTest.java
index d61394f..f6877cc 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheFinishPartitionsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheFinishPartitionsSelfTest.java
@@ -206,10 +206,13 @@ public class GridCacheFinishPartitionsSelfTest extends GridCacheAbstractSelfTest
             KeyCacheObject cacheKey = internal.context().toCacheKeyObject(key);
 
             IgniteInternalFuture<?> nearFut = internal.context().mvcc().finishKeys(Collections.singletonList(cacheKey),
+                internal.context().cacheId(),
                 new AffinityTopologyVersion(2));
 
             IgniteInternalFuture<?> dhtFut = internal.context().near().dht().context().mvcc().finishKeys(
-                Collections.singletonList(cacheKey), new AffinityTopologyVersion(2));
+                Collections.singletonList(cacheKey),
+                internal.context().cacheId(),
+                new AffinityTopologyVersion(2));
 
             assert !nearFut.isDone();
             assert !dhtFut.isDone();

http://git-wip-us.apache.org/repos/asf/ignite/blob/c6bb01b4/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
index 959ceb1..80d53e9 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.processors.cache.CacheStoreUsageMultinodeDynam
 import org.apache.ignite.internal.processors.cache.CacheStoreUsageMultinodeStaticStartAtomicTest;
 import org.apache.ignite.internal.processors.cache.CacheStoreUsageMultinodeStaticStartTxTest;
 import org.apache.ignite.internal.processors.cache.CacheSwapUnswapGetTest;
+import org.apache.ignite.internal.processors.cache.CrossCacheLockTest;
 import org.apache.ignite.internal.processors.cache.GridCacheMarshallingNodeJoinSelfTest;
 import org.apache.ignite.internal.processors.cache.GridCacheMultinodeUpdateAtomicNearEnabledSelfTest;
 import org.apache.ignite.internal.processors.cache.GridCacheMultinodeUpdateAtomicSelfTest;
@@ -271,6 +272,8 @@ public class IgniteCacheTestSuite4 extends TestSuite {
 
         suite.addTestSuite(IgniteDynamicCacheFilterTest.class);
 
+        suite.addTestSuite(CrossCacheLockTest.class);
+
         return suite;
     }
 }
\ No newline at end of file