ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject ignite git commit: ignite-1607 WIP
Date Thu, 15 Oct 2015 13:37:09 GMT
Repository: ignite
Updated Branches:
  refs/heads/ignite-1607 001b42e78 -> 177ae71e2


ignite-1607 WIP


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

Branch: refs/heads/ignite-1607
Commit: 177ae71e220e87617b640de8337c2b27ea5737a2
Parents: 001b42e
Author: sboikov <sboikov@gridgain.com>
Authored: Thu Oct 15 16:37:00 2015 +0300
Committer: sboikov <sboikov@gridgain.com>
Committed: Thu Oct 15 16:37:00 2015 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheEntryEx.java      |  12 +-
 .../processors/cache/GridCacheMapEntry.java     |  13 +
 .../processors/cache/GridCacheMvcc.java         | 136 ++++++++--
 .../cache/GridCacheMvccCandidate.java           |  26 +-
 .../distributed/GridDistributedCacheEntry.java  |   4 +-
 .../distributed/dht/GridDhtCacheEntry.java      |  16 +-
 .../distributed/dht/GridDhtLockFuture.java      |   1 +
 .../distributed/dht/GridDhtTxPrepareFuture.java |  64 ++++-
 .../colocated/GridDhtColocatedLockFuture.java   |   6 +-
 .../cache/local/GridLocalCacheEntry.java        |  10 +-
 .../cache/transactions/IgniteTxManager.java     |  21 +-
 .../CacheSerializableTransactionsTest.java      | 255 ++++++++++++++++---
 .../cache/GridCacheMvccFlagsTest.java           |   6 +-
 .../cache/GridCacheMvccPartitionedSelfTest.java | 164 ++++++++++++
 .../processors/cache/GridCacheMvccSelfTest.java |   3 +-
 .../processors/cache/GridCacheTestEntryEx.java  |   7 +
 16 files changed, 650 insertions(+), 94 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
index ebbc736..d00929a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
@@ -542,7 +542,9 @@ public interface GridCacheEntryEx {
      * @throws GridDistributedLockCancelledException If lock has been cancelled.
      * @throws IgniteCheckedException If failed.
      */
-    public boolean tmLock(IgniteInternalTx tx, long timeout, @Nullable GridCacheVersion serReadVer)
+    public boolean tmLock(IgniteInternalTx tx,
+        long timeout,
+        @Nullable GridCacheVersion serReadVer)
         throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException;
 
     /**
@@ -594,6 +596,14 @@ public interface GridCacheEntryEx {
     public GridCacheVersion version() throws GridCacheEntryRemovedException;
 
     /**
+     * Checks if there was read/write conflict in serializable transaction.
+     *
+     * @param serReadVer Version read in serializable transaction.
+     * @return {@code True} if version check passed.
+     */
+    public boolean checkSerializableReadVersion(GridCacheVersion serReadVer);
+
+    /**
      * Peeks into entry without loading value or updating statistics.
      *
      * @param heap Read from heap flag.

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index c734629..8d7d6ac 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -44,6 +44,7 @@ import org.apache.ignite.internal.processors.cache.extras.GridCacheObsoleteEntry
 import org.apache.ignite.internal.processors.cache.extras.GridCacheTtlEntryExtras;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 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.version.GridCachePlainVersionedEntry;
@@ -2832,6 +2833,18 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         return ver;
     }
 
+    /** {@inheritDoc} */
+    @Override public synchronized boolean checkSerializableReadVersion(GridCacheVersion serReadVer) {
+        assert !obsolete() : this;
+
+        if (!serReadVer.equals(ver)) {
+            if (!((isStartVersion() || deletedUnlocked()) && serReadVer.equals(IgniteTxEntry.READ_NEW_ENTRY_VER)))
+                return false;
+        }
+
+        return true;
+    }
+
     /**
      * Gets hash value for the entry key.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
index c2102bd..e9c68f6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvcc.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.Deque;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -53,6 +54,32 @@ public final class GridCacheMvcc {
     /** Logger. */
     private static volatile IgniteLogger log;
 
+    /** */
+    private static final Comparator<GridCacheVersion> SER_VER_COMPARATOR = new Comparator<GridCacheVersion>() {
+        @Override public int compare(GridCacheVersion ver1, GridCacheVersion ver2) {
+            long time1 = ver1.globalTime();
+            long time2 = ver2.globalTime();
+
+            if (time1 == time2) {
+                int nodeOrder1 = ver1.nodeOrder();
+                int nodeOrder2 = ver2.nodeOrder();
+
+                if (nodeOrder1 == nodeOrder2) {
+                    long order1 = ver1.order();
+                    long order2 = ver2.order();
+
+                    assert order1 != order2;
+
+                    return order1 > order2 ? 1 : -1;
+                }
+                else
+                    return nodeOrder1 > nodeOrder2 ? 1 : -1;
+            }
+            else
+                return time1 > time2 ? 1 : -1;
+        }
+    };
+
     /** Cache context. */
     @GridToStringExclude
     private final GridCacheContext<?, ?> cctx;
@@ -160,8 +187,9 @@ public final class GridCacheMvcc {
 
     /**
      * @param cand Candidate to add.
+     * @return {@code False} if failed to add candidate and transaction should be cancelled.
      */
-    private void add0(GridCacheMvccCandidate cand) {
+    private boolean add0(GridCacheMvccCandidate cand) {
         assert cand != null;
 
         // Local.
@@ -171,31 +199,59 @@ public final class GridCacheMvcc {
 
             if (!cand.nearLocal()) {
                 if (!locs.isEmpty()) {
-                    GridCacheMvccCandidate c = locs.getFirst();
+                    if (cand.serializable()) {
+                        GridCacheMvccCandidate last = locs.getLast();
+
+                        if (!last.serializable())
+                            return false;
+
+                        GridCacheVersion lastOrder = last.serializableOrder();
+
+                        assert lastOrder != null : last;
+
+                        GridCacheVersion candOrder = cand.serializableOrder();
+
+                        assert candOrder != null : cand;
 
-                    if (c.owner()) {
+                        int cmp = SER_VER_COMPARATOR.compare(lastOrder, candOrder);
+
+                        assert cmp != 0;
+
+                        if (cmp > 0)
+                            return false;
+
+                        locs.addLast(cand);
+
+                        return true;
+                    }
+
+                    GridCacheMvccCandidate first = locs.getFirst();
+
+                    if (first.owner()) {
                         // If reentry, add at the beginning. Note that
                         // no reentry happens for DHT-local candidates.
-                        if (!cand.dhtLocal() && c.threadId() == cand.threadId()) {
+                        if (!cand.dhtLocal() && first.threadId() == cand.threadId()) {
+                            assert !first.serializable();
+
                             cand.setOwner();
                             cand.setReady();
                             cand.setReentry();
 
                             locs.addFirst(cand);
 
-                            return;
+                            return true;
                         }
                     }
 
                     // Iterate in reverse order.
                     for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(locs.size()); it.hasPrevious(); ) {
-                        c = it.previous();
+                        GridCacheMvccCandidate c = it.previous();
 
                         assert !c.version().equals(cand.version()) : "Versions can't match [existing=" + c +
                             ", new=" + cand + ']';
 
-                        // Add after the owner.
-                        if (c.owner()) {
+                        // Add after the owner or serializable tx.
+                        if (c.owner() || c.serializable()) {
                             // Threads are checked above.
                             assert cand.dhtLocal() || c.threadId() != cand.threadId();
 
@@ -204,7 +260,7 @@ public final class GridCacheMvcc {
 
                             it.add(cand);
 
-                            return;
+                            return true;
                         }
 
                         // If not the owner, add after the lesser version.
@@ -214,7 +270,7 @@ public final class GridCacheMvcc {
 
                             it.add(cand);
 
-                            return;
+                            return true;
                         }
                     }
                 }
@@ -228,6 +284,8 @@ public final class GridCacheMvcc {
         }
         // Remote.
         else {
+            assert !cand.serializable() : cand;
+
             if (rmts == null)
                 rmts = new LinkedList<>();
 
@@ -241,12 +299,14 @@ public final class GridCacheMvcc {
                 if (cand.owner())
                     cur.setOwner();
 
-                return;
+                return true;
             }
 
             // Either list is empty or candidate is last.
             rmts.add(cand);
         }
+
+        return true;
     }
 
     /**
@@ -456,6 +516,7 @@ public final class GridCacheMvcc {
             threadId,
             ver,
             timeout,
+            /*serializable order*/null,
             reenter,
             tx,
             implicitSingle,
@@ -484,6 +545,7 @@ public final class GridCacheMvcc {
         long threadId,
         GridCacheVersion ver,
         long timeout,
+        @Nullable GridCacheVersion serOrder,
         boolean reenter,
         boolean tx,
         boolean implicitSingle,
@@ -528,12 +590,17 @@ public final class GridCacheMvcc {
             tx,
             implicitSingle,
             /*near-local*/false,
-            dhtLoc
+            dhtLoc,
+            serOrder
         );
 
-        cctx.mvcc().addLocal(cand);
+        if (!add0(cand)) {
+            assert serOrder != null : cand;
 
-        add0(cand);
+            return null;
+        }
+
+        cctx.mvcc().addLocal(cand);
 
         return cand;
     }
@@ -575,7 +642,8 @@ public final class GridCacheMvcc {
             tx,
             implicitSingle,
             nearLoc,
-            false
+            false,
+            null
         );
 
         addRemote(cand);
@@ -596,11 +664,28 @@ public final class GridCacheMvcc {
      * @param implicitSingle Implicit flag.
      * @return Add remote candidate.
      */
-    public GridCacheMvccCandidate addNearLocal(GridCacheEntryEx parent, UUID nodeId,
-        @Nullable UUID otherNodeId, long threadId, GridCacheVersion ver, long timeout, boolean tx,
+    public GridCacheMvccCandidate addNearLocal(GridCacheEntryEx parent,
+        UUID nodeId,
+        @Nullable UUID otherNodeId,
+        long threadId,
+        GridCacheVersion ver,
+        long timeout,
+        boolean tx,
         boolean implicitSingle) {
-        GridCacheMvccCandidate cand = new GridCacheMvccCandidate(parent, nodeId, otherNodeId, null, threadId, ver,
-            timeout, /*local*/true, /*reentry*/false, tx, implicitSingle, /*near loc*/true, /*dht loc*/false);
+        GridCacheMvccCandidate cand = new GridCacheMvccCandidate(parent,
+            nodeId,
+            otherNodeId,
+            null,
+            threadId,
+            ver,
+            timeout,
+            /*local*/true,
+            /*reentry*/false,
+            tx,
+            implicitSingle,
+            /*near loc*/true,
+            /*dht loc*/false,
+            null);
 
         add0(cand);
 
@@ -854,7 +939,18 @@ public final class GridCacheMvcc {
             }
         }
 
-        if (locs != null) {
+        if (locs != null && !locs.isEmpty()) {
+            GridCacheMvccCandidate first = locs.getFirst();
+
+            if (first.serializable()) {
+                if (first.owner() || !first.ready())
+                    return;
+
+                first.setOwner();
+
+                return;
+            }
+
             for (ListIterator<GridCacheMvccCandidate> it = locs.listIterator(); it.hasNext(); ) {
                 GridCacheMvccCandidate cand = it.next();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/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 f19a054..aba8318 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
@@ -126,6 +126,9 @@ public class GridCacheMvccCandidate implements Externalizable,
     @GridToStringInclude
     private transient volatile GridCacheVersion ownerVer;
 
+    /** */
+    private GridCacheVersion serOrder;
+
     /**
      * Empty constructor required by {@link Externalizable}.
      */
@@ -147,6 +150,7 @@ public class GridCacheMvccCandidate implements Externalizable,
      * @param singleImplicit Single-key-implicit-transaction flag.
      * @param nearLoc Near-local flag.
      * @param dhtLoc DHT local flag.
+     * @param serOrder Version for serializable transactions ordering.
      */
     public GridCacheMvccCandidate(
         GridCacheEntryEx parent,
@@ -161,7 +165,9 @@ public class GridCacheMvccCandidate implements Externalizable,
         boolean tx,
         boolean singleImplicit,
         boolean nearLoc,
-        boolean dhtLoc) {
+        boolean dhtLoc,
+        @Nullable GridCacheVersion serOrder
+    ) {
         assert nodeId != null;
         assert ver != null;
         assert parent != null;
@@ -173,6 +179,7 @@ public class GridCacheMvccCandidate implements Externalizable,
         this.threadId = threadId;
         this.ver = ver;
         this.timeout = timeout;
+        this.serOrder = serOrder;
 
         mask(LOCAL, loc);
         mask(REENTRY, reentry);
@@ -244,7 +251,8 @@ public class GridCacheMvccCandidate implements Externalizable,
             tx(),
             singleImplicit(),
             nearLocal(),
-            dhtLocal());
+            dhtLocal(),
+            serializableOrder());
 
         reentry.topVer = topVer;
 
@@ -452,6 +460,20 @@ public class GridCacheMvccCandidate implements Externalizable,
     }
 
     /**
+     * @return Serializable transaction flag.
+     */
+    public boolean serializable() {
+        return serOrder != null;
+    }
+
+    /**
+     * @return Version for serializable transactions ordering.
+     */
+    @Nullable public GridCacheVersion serializableOrder() {
+        return serOrder;
+    }
+
+    /**
      * @return {@code True} if this candidate is a reentry.
      */
     public boolean reentry() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/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 0bfbe7d..d564768 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
@@ -743,7 +743,9 @@ public class GridDistributedCacheEntry extends GridCacheMapEntry {
     }
 
     /** {@inheritDoc} */
-    @Override public boolean tmLock(IgniteInternalTx tx, long timeout, GridCacheVersion serReadVer)
+    @Override public boolean tmLock(IgniteInternalTx tx,
+        long timeout,
+        GridCacheVersion serReadVer)
         throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException {
         if (tx.local())
             // Null is returned if timeout is negative and there is other lock owner.

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
index 9c10a0a..c483e01 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheEntry.java
@@ -180,6 +180,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
         AffinityTopologyVersion topVer,
         long threadId,
         GridCacheVersion ver,
+        @Nullable GridCacheVersion serOrder,
         @Nullable GridCacheVersion serReadVer,
         long timeout,
         boolean reenter,
@@ -187,6 +188,9 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
         boolean implicitSingle)
         throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException
     {
+        assert serReadVer == null || serOrder != null;
+        assert !reenter || serOrder == null;
+
         GridCacheMvccCandidate cand;
         GridCacheMvccCandidate prev;
         GridCacheMvccCandidate owner;
@@ -203,10 +207,8 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
             if (serReadVer != null) {
                 unswap(false);
 
-                if (!serReadVer.equals(this.ver)) {
-                    if (!((isNew() || deleted()) && serReadVer.equals(IgniteTxEntry.READ_NEW_ENTRY_VER)))
-                        return null;
-                }
+                if (!checkSerializableReadVersion(serReadVer))
+                    return null;
             }
 
             GridCacheMvcc mvcc = mvccExtras();
@@ -228,6 +230,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
                 threadId,
                 ver,
                 timeout,
+                serOrder,
                 reenter,
                 tx,
                 implicitSingle,
@@ -265,7 +268,9 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
     }
 
     /** {@inheritDoc} */
-    @Override public boolean tmLock(IgniteInternalTx tx, long timeout, GridCacheVersion serReadVer)
+    @Override public boolean tmLock(IgniteInternalTx tx,
+        long timeout,
+        GridCacheVersion serReadVer)
         throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException {
         if (tx.local()) {
             GridDhtTxLocalAdapter dhtTx = (GridDhtTxLocalAdapter)tx;
@@ -277,6 +282,7 @@ public class GridDhtCacheEntry extends GridDistributedCacheEntry {
                 tx.topologyVersion(),
                 tx.threadId(),
                 tx.xidVersion(),
+                (tx.optimistic() && tx.serializable()) ? tx.nearXidVersion() : null,
                 serReadVer,
                 timeout,
                 /*reenter*/false,

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
index c64d909..016d030 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
@@ -402,6 +402,7 @@ public final class GridDhtLockFuture extends GridCompoundIdentityFuture<Boolean>
             threadId,
             lockVer,
             null,
+            null,
             timeout,
             /*reenter*/false,
             inTx(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index b0f72dc..f25ee33 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -57,6 +57,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.dr.GridDrType;
+import org.apache.ignite.internal.transactions.IgniteTxOptimisticCheckedException;
 import org.apache.ignite.internal.util.F0;
 import org.apache.ignite.internal.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.util.GridLeanSet;
@@ -469,9 +470,18 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
         if (log.isDebugEnabled())
             log.debug("Marking all local candidates as ready: " + this);
 
-        Iterable<IgniteTxEntry> checkEntries =
-            (tx.optimistic() && tx.serializable()) ? F.concat(false, writes, reads) : writes;
+        readyLocks(writes);
 
+        if (tx.optimistic() && tx.serializable())
+            readyLocks(reads);
+
+        locksReady = true;
+    }
+
+    /**
+     * @param checkEntries Entries.
+     */
+    private void readyLocks(Iterable<IgniteTxEntry> checkEntries) {
         for (IgniteTxEntry txEntry : checkEntries) {
             GridCacheContext cacheCtx = txEntry.context();
 
@@ -511,8 +521,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
                 }
             }
         }
-
-        locksReady = true;
     }
 
     /**
@@ -903,10 +911,58 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
     }
 
     /**
+     * @param entries Entries.
+     * @return Not null exception if version check failed.
+     */
+    @Nullable private IgniteTxOptimisticCheckedException checkReadConflict(Collection<IgniteTxEntry> entries) {
+        for (IgniteTxEntry entry : entries) {
+            GridCacheVersion serReadVer = entry.serializableReadVersion();
+
+            if (serReadVer != null && !entry.cached().checkSerializableReadVersion(serReadVer)) {
+                GridCacheContext cctx = entry.context();
+
+                return new IgniteTxOptimisticCheckedException("Failed to prepare transaction, " +
+                    "read conflict [key=" + entry.key().value(cctx.cacheObjectContext(), false) +
+                    ", cache=" + cctx.name() + ']');
+            }
+        }
+
+        return null;
+    }
+
+    /**
      *
      */
     private void prepare0() {
         try {
+            if (tx.optimistic() && tx.serializable()) {
+                IgniteTxOptimisticCheckedException err0 = checkReadConflict(writes);
+
+                if (err0 == null)
+                    err0 = checkReadConflict(reads);
+
+                if (err0 != null) {
+                    err.compareAndSet(null, err0);
+
+                    final GridNearTxPrepareResponse res = createPrepareResponse();
+
+                    tx.rollbackAsync().listen(new CI1<IgniteInternalFuture<IgniteInternalTx>>() {
+                        @Override public void apply(IgniteInternalFuture<IgniteInternalTx> fut) {
+                            if (GridDhtTxPrepareFuture.super.onDone(res, res.error())) {
+                                try {
+                                    sendPrepareResponse(res);
+                                }
+                                catch (IgniteCheckedException e) {
+                                    U.error(log, "Failed to send prepare response for transaction: " + tx, e);
+                                }
+                            }
+                        }
+                    });
+
+                    return;
+                }
+            }
+
             // We are holding transaction-level locks for entries here, so we can get next write version.
             onEntriesLocked();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/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 be09f54..c9969e3 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
@@ -323,7 +323,8 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                     inTx(),
                     inTx() && tx.implicitSingle(),
                     false,
-                    false);
+                    false,
+                    null);
 
                 cand.topologyVersion(topVer.get());
             }
@@ -342,7 +343,8 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                     inTx(),
                     inTx() && tx.implicitSingle(),
                     false,
-                    false);
+                    false,
+                    null);
 
                 cand.topologyVersion(topVer.get());
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/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 fcc6abe..32c2fa9 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
@@ -95,10 +95,8 @@ public class GridLocalCacheEntry extends GridCacheMapEntry {
             checkObsolete();
 
             if (serReadVer != null) {
-                if (!serReadVer.equals(this.ver)) {
-                    if (!((isNew() || deleted()) && serReadVer.equals(IgniteTxEntry.READ_NEW_ENTRY_VER)))
-                        return null;
-                }
+                if (!checkSerializableReadVersion(serReadVer))
+                    return null;
             }
 
             GridCacheMvcc mvcc = mvccExtras();
@@ -201,7 +199,9 @@ public class GridLocalCacheEntry extends GridCacheMapEntry {
     }
 
     /** {@inheritDoc} */
-    @Override public boolean tmLock(IgniteInternalTx tx, long timeout, GridCacheVersion serReadVer)
+    @Override public boolean tmLock(IgniteInternalTx tx,
+        long timeout,
+        GridCacheVersion serReadVer)
         throws GridCacheEntryRemovedException {
         GridCacheMvccCandidate cand = addLocal(
             tx.threadId(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
index 21053a2..24ea634 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
@@ -29,7 +29,6 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ConcurrentNavigableMap;
-import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteClientDisconnectedException;
@@ -1375,20 +1374,12 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
         throws IgniteCheckedException {
         assert tx.optimistic() || !tx.local();
 
-        long timeout;
+        long remainingTime = U.currentTimeMillis() - (tx.startTime() + tx.timeout());
 
-        boolean ser = tx.optimistic() && tx.serializable();
-
-        if (!ser) {
-            long remainingTime = U.currentTimeMillis() - (tx.startTime() + tx.timeout());
-
-            // For serializable transactions, failure to acquire lock means
-            // that there is a serializable conflict. For all other isolation levels,
-            // we wait for the lock.
-            timeout = tx.timeout() == 0 ? 0 : remainingTime;
-        }
-        else
-            timeout = -1L;
+        // For serializable transactions, failure to acquire lock means
+        // that there is a serializable conflict. For all other isolation levels,
+        // we wait for the lock.
+        long timeout = tx.timeout() == 0 ? 0 : remainingTime;
 
         for (IgniteTxEntry txEntry1 : entries) {
             // Check if this entry was prepared before.
@@ -1406,7 +1397,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
 
                     GridCacheVersion serReadVer = txEntry1.serializableReadVersion();
 
-                    assert serReadVer == null || ser : txEntry1;
+                    assert serReadVer == null || (tx.optimistic() && tx.serializable()) : txEntry1;
 
                     if (!entry1.tmLock(tx, timeout, serReadVer)) {
                         // Unlock locks locked so far.

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
index 2342a5d..0c9debf 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheSerializableTransactionsTest.java
@@ -25,8 +25,10 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -2750,38 +2752,47 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
      * @throws Exception If failed.
      */
     public void testAccountTx1() throws Exception {
-        accountTx(false, false, TestMemoryMode.HEAP);
+        accountTx(false, false, false, TestMemoryMode.HEAP);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testAccountTxNearCache() throws Exception {
-        accountTx(false, true, TestMemoryMode.HEAP);
+    public void testAccountTx2() throws Exception {
+        accountTx(true, false, false, TestMemoryMode.HEAP);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testAccountTx2() throws Exception {
-        accountTx(true, false, TestMemoryMode.HEAP);
+    public void testAccountTxWithNonSerializable() throws Exception {
+        accountTx(false, false, true, TestMemoryMode.HEAP);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testAccountTxNearCache() throws Exception {
+        accountTx(false, true, false, TestMemoryMode.HEAP);
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testAccountTxOffheapTiered() throws Exception {
-        accountTx(false, false, TestMemoryMode.OFFHEAP_TIERED);
+        accountTx(false, false, false, TestMemoryMode.OFFHEAP_TIERED);
     }
 
     /**
      * @param getAll If {@code true} uses getAll/putAll in transaction.
      * @param nearCache If {@code true} near cache is enabled.
+     * @param nonSer If {@code true} starts threads executing non-serializable transactions.
      * @param memMode Test memory mode.
      * @throws Exception If failed.
      */
     private void accountTx(final boolean getAll,
         final boolean nearCache,
+        final boolean nonSer,
         TestMemoryMode memMode) throws Exception {
         final Ignite ignite0 = ignite(0);
 
@@ -2808,6 +2819,67 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
 
             final long stopTime = System.currentTimeMillis() + 10_000;
 
+            IgniteInternalFuture<?> nonSerFut = null;
+
+            if (nonSer) {
+                nonSerFut = runMultiThreadedAsync(new Callable<Void>() {
+                    @Override public Void call() throws Exception {
+                        int nodeIdx = idx.getAndIncrement() % clients.size();
+
+                        Ignite node = clients.get(nodeIdx);
+
+                        Thread.currentThread().setName("update-pessimistic-" + node.name());
+
+                        log.info("Pessimistic tx thread: " + node.name());
+
+                        final IgniteTransactions txs = node.transactions();
+
+                        final IgniteCache<Integer, Account> cache =
+                            nearCache ? node.createNearCache(cacheName, new NearCacheConfiguration<Integer, Account>()) :
+                                node.<Integer, Account>cache(cacheName);
+
+                        assertNotNull(cache);
+
+                        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                        while (U.currentTimeMillis() < stopTime) {
+                            int id1 = rnd.nextInt(ACCOUNTS);
+
+                            int id2 = rnd.nextInt(ACCOUNTS);
+
+                            while (id2 == id1)
+                                id2 = rnd.nextInt(ACCOUNTS);
+
+                            if (id1 > id2) {
+                                int tmp = id1;
+                                id1 = id2;
+                                id2 = tmp;
+                            }
+
+                            try (Transaction tx = txs.txStart(PESSIMISTIC, REPEATABLE_READ)) {
+                                Account a1 = cache.get(id1);
+                                Account a2 = cache.get(id2);
+
+                                assertNotNull(a1);
+                                assertNotNull(a2);
+
+                                if (a1.value() > 0) {
+                                    a1 = new Account(a1.value() - 1);
+                                    a2 = new Account(a2.value() + 1);
+                                }
+
+                                cache.put(id1, a1);
+                                cache.put(id2, a2);
+
+                                tx.commit();
+                            }
+                        }
+
+                        return null;
+                    }
+                }, 10, "non-ser-thread");
+            }
+
             IgniteInternalFuture<?> fut = runMultiThreadedAsync(new Callable<Void>() {
                 @Override public Void call() throws Exception {
                     int nodeIdx = idx.getAndIncrement() % clients.size();
@@ -2898,6 +2970,9 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
 
             fut.get(30_000);
 
+            if (nonSerFut != null)
+                nonSerFut.get();
+
             int sum = 0;
 
             for (int i = 0; i < ACCOUNTS; i++) {
@@ -2962,53 +3037,100 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    public void testConflictResolution() throws Exception {
+        final Ignite ignite = ignite(0);
+
+        final String cacheName =
+            ignite.createCache(cacheConfiguration(PARTITIONED, FULL_SYNC, 1, false, false)).getName();
+
+        try {
+            final Map<Integer, Integer> keys = new HashMap<>();
+
+            for (int i = 0; i < 500; i++)
+                keys.put(i, i);
+
+            final int THREADS = 5;
+
+            for (int i = 0; i < 10; i++) {
+                final CyclicBarrier barrier = new CyclicBarrier(THREADS);
+
+                final AtomicInteger commitCntr = new AtomicInteger(0);
+
+                GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+                    @Override public Void call() throws Exception {
+                        IgniteCache<Integer, Integer> cache = ignite.cache(cacheName);
+
+                        IgniteTransactions txs = cache.unwrap(Ignite.class).transactions();
+
+                        try (Transaction tx = txs.txStart(OPTIMISTIC, SERIALIZABLE)) {
+                            cache.putAll(keys);
+
+                            barrier.await();
+
+                            tx.commit();
+
+                            commitCntr.incrementAndGet();
+                        }
+                        catch (TransactionOptimisticException e) {
+                            log.info("Optimistic error: " + e);
+                        }
+
+                        return null;
+                    }
+                }, THREADS, "update-thread").get();
+
+                int commits = commitCntr.get();
+
+                log.info("Iteration [iter=" + i + ", commits=" + commits + ']');
+
+                assertTrue(commits > 0);
+            }
+        }
+        finally {
+            ignite.destroyCache(cacheName);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testConcurrentUpdateNoDeadlock() throws Exception {
-        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, false, false);
+        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, false, false, false);
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testConcurrentUpdateNoDeadlockGetPut() throws Exception {
-        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, true, false);
+        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, true, false, false);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testConcurrentUpdateNoDeadlockNodeRestart() throws Exception {
-        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(1)), 10, false, true);
+    public void testConcurrentUpdateNoDeadlockWithNonSerializable() throws Exception {
+        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(0)), 10, true, false, true);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testConcurrentUpdateNoDeadlockFromClients() throws Exception {
-        concurrentUpdateNoDeadlock(clients(), 20, false, false);
+    public void testConcurrentUpdateNoDeadlockNodeRestart() throws Exception {
+        concurrentUpdateNoDeadlock(Collections.singletonList(ignite(1)), 10, false, true, false);
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testConcurrentUpdateNoDeadlockFromClientsNodeRestart() throws Exception {
-        concurrentUpdateNoDeadlock(clients(), 20, false, true);
+    public void testConcurrentUpdateNoDeadlockFromClients() throws Exception {
+        concurrentUpdateNoDeadlock(clients(), 20, false, false, false);
     }
 
     /**
-     * @return Client nodes.
+     * @throws Exception If failed.
      */
-    private List<Ignite> clients() {
-        List<Ignite> clients = new ArrayList<>();
-
-        for (int i = 0; i < CLIENTS; i++) {
-            Ignite ignite = ignite(SRVS + i);
-
-            assertTrue(ignite.configuration().isClientMode());
-
-            clients.add(ignite);
-        }
-
-        return clients;
+    public void testConcurrentUpdateNoDeadlockFromClientsNodeRestart() throws Exception {
+        concurrentUpdateNoDeadlock(clients(), 20, false, true, false);
     }
 
     /**
@@ -3016,12 +3138,15 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
      * @param threads Number of threads executing updates.
      * @param get If {@code true} gets value in transaction.
      * @param restart If {@code true} restarts one node.
+     * @param nonSer If {@code true} starts threads executing non-serializable transactions.
      * @throws Exception If failed.
      */
     private void concurrentUpdateNoDeadlock(final List<Ignite> updateNodes,
         int threads,
         final boolean get,
-        final boolean restart) throws Exception {
+        final boolean restart,
+        final boolean nonSer
+    ) throws Exception {
         if (FAST)
             return;
 
@@ -3065,6 +3190,45 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
 
                     final AtomicInteger idx = new AtomicInteger();
 
+                    IgniteInternalFuture<?> nonSerFut = null;
+
+                    if (nonSer) {
+                        nonSerFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
+                            @Override public Void call() throws Exception {
+                                int nodeIdx = idx.getAndIncrement() % updateNodes.size();
+
+                                Ignite node = updateNodes.get(nodeIdx);
+
+                                log.info("Non-serializable tx thread: " + node.name());
+
+                                final IgniteCache<Integer, Integer> cache = node.cache(cacheName);
+
+                                assertNotNull(cache);
+
+                                final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                                while (U.currentTimeMillis() < stopTime) {
+                                    final TreeMap<Integer, Integer> map = new TreeMap<>();
+
+                                    for (int i = 0; i < KEYS / 2; i++)
+                                        map.put(rnd.nextInt(KEYS), rnd.nextInt());
+
+                                    TransactionConcurrency concurrency = rnd.nextBoolean() ? PESSIMISTIC : OPTIMISTIC;
+
+                                    doInTransaction(node, concurrency, REPEATABLE_READ, new Callable<Void>() {
+                                        @Override public Void call() throws Exception {
+                                            cache.putAll(map);
+
+                                            return null;
+                                        }
+                                    });
+                                }
+
+                                return null;
+                            }
+                        }, 5, "non-ser-thread");
+                    }
+
                     IgniteInternalFuture<?> updateFut = GridTestUtils.runMultiThreadedAsync(new Callable<Void>() {
                         @Override public Void call() throws Exception {
                             int nodeIdx = idx.getAndIncrement() % updateNodes.size();
@@ -3082,17 +3246,17 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
                             final ThreadLocalRandom rnd = ThreadLocalRandom.current();
 
                             while (U.currentTimeMillis() < stopTime) {
-                                final Map<Integer, Integer> keys = new LinkedHashMap<>();
+                                final Map<Integer, Integer> map = new LinkedHashMap<>();
 
                                 for (int i = 0; i < KEYS / 2; i++)
-                                    keys.put(rnd.nextInt(KEYS), rnd.nextInt());
+                                    map.put(rnd.nextInt(KEYS), rnd.nextInt());
 
                                 try {
                                     if (restart) {
                                         doInTransaction(node, OPTIMISTIC, SERIALIZABLE, new Callable<Void>() {
                                             @Override public Void call() throws Exception {
                                                 if (get) {
-                                                    for (Map.Entry<Integer, Integer> e : keys.entrySet()) {
+                                                    for (Map.Entry<Integer, Integer> e : map.entrySet()) {
                                                         if (rnd.nextBoolean()) {
                                                             cache.get(e.getKey());
 
@@ -3104,7 +3268,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
                                                     }
                                                 }
                                                 else
-                                                    cache.putAll(keys);
+                                                    cache.putAll(map);
 
                                                 return null;
                                             }
@@ -3113,7 +3277,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
                                     else {
                                         try (Transaction tx = txs.txStart(OPTIMISTIC, SERIALIZABLE)) {
                                             if (get) {
-                                                for (Map.Entry<Integer, Integer> e : keys.entrySet()) {
+                                                for (Map.Entry<Integer, Integer> e : map.entrySet()) {
                                                     if (rnd.nextBoolean()) {
                                                         cache.get(e.getKey());
 
@@ -3125,7 +3289,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
                                                 }
                                             }
                                             else
-                                                cache.putAll(keys);
+                                                cache.putAll(map);
 
                                             tx.commit();
                                         }
@@ -3147,6 +3311,9 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
 
                     updateFut.get(60, SECONDS);
 
+                    if (nonSerFut != null)
+                        nonSerFut.get(60, SECONDS);
+
                     IgniteCache<Integer, Integer> cache = srv.cache(cacheName);
 
                     for (int key = 0; key < KEYS; key++) {
@@ -3260,8 +3427,7 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
         final TransactionIsolation isolation,
         final IgniteClosure<IgniteCache<Integer, Integer>, Void> c) throws Exception {
         IgniteInternalFuture<?> fut = GridTestUtils.runAsync(new Callable<Void>() {
-            @Override
-            public Void call() throws Exception {
+            @Override public Void call() throws Exception {
                 IgniteTransactions txs = cache.unwrap(Ignite.class).transactions();
 
                 try (Transaction tx = txs.txStart(concurrency, isolation)) {
@@ -3401,6 +3567,23 @@ public class CacheSerializableTransactionsTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @return Client nodes.
+     */
+    private List<Ignite> clients() {
+        List<Ignite> clients = new ArrayList<>();
+
+        for (int i = 0; i < CLIENTS; i++) {
+            Ignite ignite = ignite(SRVS + i);
+
+            assertTrue(ignite.configuration().isClientMode());
+
+            clients.add(ignite);
+        }
+
+        return clients;
+    }
+
+    /**
      *
      */
     private static class TestStoreFactory implements Factory<CacheStore<Integer, Integer>> {

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java
index 084bc75..234f362 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFlagsTest.java
@@ -88,7 +88,8 @@ public class GridCacheMvccFlagsTest extends GridCommonAbstractTest {
             true,
             true,
             true,
-            true
+            true,
+            null
         );
 
         c.setOwner();
@@ -128,7 +129,8 @@ public class GridCacheMvccFlagsTest extends GridCommonAbstractTest {
             false,
             false,
             false,
-            false
+            false,
+            null
         );
 
         short flags = c.flags();

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
index 0af7183..1b97663 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
@@ -595,6 +595,170 @@ public class GridCacheMvccPartitionedSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testSerializableLocks() throws Exception {
+        checkSerializableAdd(false);
+
+        checkSerializableAdd(true);
+
+        checkNonSerializableConflict();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    private void checkNonSerializableConflict() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        UUID nodeId = UUID.randomUUID();
+
+        GridCacheMvcc mvcc = new GridCacheMvcc(cache.context());
+
+        GridCacheTestEntryEx e = new GridCacheTestEntryEx(cache.context(), "1");
+
+        GridCacheMvccCandidate cand1 = mvcc.addLocal(e,
+            nodeId,
+            null,
+            1,
+            version(1),
+            0,
+            null,
+            false,
+            true,
+            false,
+            true
+        );
+
+        assertNotNull(cand1);
+
+        GridCacheMvccCandidate cand2 = mvcc.addLocal(e,
+            nodeId,
+            null,
+            1,
+            version(2),
+            0,
+            new GridCacheVersion(0, 0, 30, 1),
+            false,
+            true,
+            false,
+            true
+        );
+
+        assertNull(cand2);
+    }
+
+    /**
+     * @param incVer If {@code true} lock version is incremented.
+     * @throws Exception If failed.
+     */
+    private void checkSerializableAdd(boolean incVer) throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        UUID nodeId = UUID.randomUUID();
+
+        GridCacheMvcc mvcc = new GridCacheMvcc(cache.context());
+
+        GridCacheTestEntryEx e = new GridCacheTestEntryEx(cache.context(), "1");
+
+        GridCacheVersion serOrder1 = new GridCacheVersion(0, 0, 10, 1);
+        GridCacheVersion serOrder2 = new GridCacheVersion(0, 0, 20, 1);
+        GridCacheVersion serOrder3 = new GridCacheVersion(0, 0, 15, 1);
+        GridCacheVersion serOrder4 = new GridCacheVersion(0, 0, 30, 1);
+
+        GridCacheVersion ver1 = incVer ? version(1) : version(4);
+        GridCacheVersion ver2 = incVer ? version(2) : version(3);
+        GridCacheVersion ver3 = incVer ? version(3) : version(2);
+        GridCacheVersion ver4 = incVer ? version(4) : version(1);
+
+        GridCacheMvccCandidate cand1 = mvcc.addLocal(e,
+            nodeId,
+            null,
+            1,
+            ver1,
+            0,
+            serOrder1,
+            false,
+            true,
+            false,
+            true
+            );
+
+        assertNotNull(cand1);
+
+        GridCacheMvccCandidate cand2 = mvcc.addLocal(e,
+            nodeId,
+            null,
+            2,
+            ver2,
+            0,
+            serOrder2,
+            false,
+            true,
+            false,
+            true
+        );
+
+        assertNotNull(cand2);
+
+        GridCacheMvccCandidate cand3 = mvcc.addLocal(e,
+            nodeId,
+            null,
+            3,
+            ver3,
+            0,
+            serOrder3,
+            false,
+            true,
+            false,
+            true
+        );
+
+        assertNull(cand3);
+
+        GridCacheMvccCandidate cand4 = mvcc.addLocal(e,
+            nodeId,
+            null,
+            4,
+            ver4,
+            0,
+            serOrder4,
+            false,
+            true,
+            false,
+            true
+        );
+
+        assertNotNull(cand4);
+
+        GridCacheMvccCandidate owner = mvcc.recheck();
+
+        assertNull(owner);
+
+        cand2.setReady();
+
+        owner = mvcc.recheck();
+
+        assertNull(owner);
+
+        cand1.setReady();
+
+        owner = mvcc.recheck();
+
+        assertSame(cand1, owner);
+
+        owner = mvcc.recheck();
+
+        assertSame(cand1, owner);
+
+        mvcc.remove(cand1.version());
+
+        owner = mvcc.recheck();
+
+        assertSame(cand2, owner);
+    }
+
+    /**
      * Gets version based on order.
      *
      * @param order Order.

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java
index cdf8eca..59f9a9d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccSelfTest.java
@@ -101,7 +101,8 @@ public class GridCacheMvccSelfTest extends GridCommonAbstractTest {
             true,
             false,
             false,
-            false
+            false,
+            null
         );
 
         Marshaller marshaller = getTestResources().getMarshaller();

http://git-wip-us.apache.org/repos/asf/ignite/blob/177ae71e/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 6b2a6c4..dd3c79a 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
@@ -630,6 +630,13 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
     }
 
     /** @inheritDoc */
+    @Override public boolean checkSerializableReadVersion(GridCacheVersion ver) {
+        assert false;
+
+        return false;
+    }
+
+    /** @inheritDoc */
     @Override public boolean initialValue(
         CacheObject val,
         GridCacheVersion ver,


Mime
View raw message