ignite-1607 Implemented deadlock-free optimistic serializable tx mode

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

Branch: refs/heads/ignite-1753-1282
Commit: 9d7543a8dedb85f1dc904b52be3673f4a151f8e7
Parents: db88860
Author: sboikov <sboi...@gridgain.com>
Authored: Wed Oct 28 10:53:29 2015 +0300
Committer: sboikov <sboi...@gridgain.com>
Committed: Wed Oct 28 10:53:30 2015 +0300

----------------------------------------------------------------------
 .../configuration/TransactionConfiguration.java |    6 +-
 .../processors/cache/CacheMetricsImpl.java      |   12 +-
 .../processors/cache/GridCacheAdapter.java      |  459 +-
 .../processors/cache/GridCacheEntryEx.java      |   62 +-
 .../processors/cache/GridCacheMapEntry.java     |  137 +-
 .../processors/cache/GridCacheMvcc.java         |  143 +-
 .../cache/GridCacheMvccCandidate.java           |   26 +-
 .../processors/cache/GridCacheProcessor.java    |   13 -
 .../distributed/GridDistributedCacheEntry.java  |   12 +-
 .../GridDistributedTxRemoteAdapter.java         |   56 +-
 .../dht/CacheDistributedGetFutureAdapter.java   |  158 +
 .../distributed/dht/GridDhtCacheAdapter.java    |   17 +-
 .../distributed/dht/GridDhtCacheEntry.java      |   23 +-
 .../cache/distributed/dht/GridDhtGetFuture.java |  199 +-
 .../distributed/dht/GridDhtLockFuture.java      |    5 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |  105 +-
 .../cache/distributed/dht/GridDhtTxLocal.java   |    4 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |  109 +-
 .../dht/GridPartitionedGetFuture.java           |  179 +-
 .../dht/atomic/GridDhtAtomicCache.java          |   16 +-
 .../dht/colocated/GridDhtColocatedCache.java    |  130 +-
 .../colocated/GridDhtColocatedLockFuture.java   |    6 +-
 .../distributed/near/GridNearAtomicCache.java   |    2 -
 .../distributed/near/GridNearCacheAdapter.java  |   32 +-
 .../distributed/near/GridNearCacheEntry.java    |   81 +-
 .../distributed/near/GridNearGetFuture.java     |  340 +-
 .../distributed/near/GridNearGetRequest.java    |    3 -
 ...arOptimisticSerializableTxPrepareFuture.java |  930 ++++
 .../near/GridNearOptimisticTxPrepareFuture.java |  252 +-
 ...ridNearOptimisticTxPrepareFutureAdapter.java |  222 +
 .../GridNearPessimisticTxPrepareFuture.java     |    8 +-
 .../near/GridNearTransactionalCache.java        |   14 +-
 .../near/GridNearTxFinishFuture.java            |   12 +-
 .../cache/distributed/near/GridNearTxLocal.java |  157 +-
 .../near/GridNearTxPrepareFutureAdapter.java    |   13 +-
 .../cache/local/GridLocalCacheEntry.java        |   23 +-
 .../cache/local/GridLocalLockFuture.java        |    2 +
 .../local/atomic/GridLocalAtomicCache.java      |    9 -
 .../transactions/IgniteTransactionsImpl.java    |    6 -
 .../cache/transactions/IgniteTxAdapter.java     |  123 +-
 .../cache/transactions/IgniteTxEntry.java       |   51 +-
 .../cache/transactions/IgniteTxHandler.java     |    4 +-
 .../transactions/IgniteTxLocalAdapter.java      |  832 ++--
 .../cache/transactions/IgniteTxLocalEx.java     |   27 +-
 .../cache/transactions/IgniteTxManager.java     |  327 +-
 .../cache/version/GridCacheVersionManager.java  |   73 +-
 .../datastreamer/DataStreamerImpl.java          |    2 +-
 .../apache/ignite/transactions/Transaction.java |    2 +-
 .../transactions/TransactionIsolation.java      |    3 +-
 .../cache/CacheNearReaderUpdateTest.java        |  388 ++
 .../CacheSerializableTransactionsTest.java      | 4295 ++++++++++++++++++
 .../cache/CrossCacheTxRandomOperationsTest.java |    6 +
 .../GridCacheAbstractFailoverSelfTest.java      |   14 +-
 .../cache/GridCacheAbstractFullApiSelfTest.java |    4 +-
 .../GridCacheAbstractRemoveFailureTest.java     |   94 +-
 .../GridCacheConcurrentTxMultiNodeTest.java     |    3 -
 .../cache/GridCacheMvccFlagsTest.java           |    6 +-
 .../cache/GridCacheMvccPartitionedSelfTest.java |  164 +
 .../processors/cache/GridCacheMvccSelfTest.java |    3 +-
 .../processors/cache/GridCacheTestEntryEx.java  |   53 +-
 .../processors/cache/IgniteTxAbstractTest.java  |   42 +-
 .../IgniteTxMultiThreadedAbstractTest.java      |  106 +-
 ...onedNearDisabledTxMultiThreadedSelfTest.java |   31 +
 ...niteCacheClientNodeChangingTopologyTest.java |  170 +-
 .../IgniteCacheCrossCacheTxFailoverTest.java    |   19 +
 .../dht/IgniteCacheLockFailoverSelfTest.java    |   11 +
 ...eAtomicInvalidPartitionHandlingSelfTest.java |    6 +-
 .../near/GridCacheNearTxExceptionSelfTest.java  |    1 +
 ...CachePartitionedTxMultiThreadedSelfTest.java |   15 +-
 .../DataStreamerUpdateAfterLoadTest.java        |  184 +
 .../loadtests/hashmap/GridHashMapLoadTest.java  |    6 +-
 .../inmemory/GridTestSwapSpaceSpi.java          |    8 +
 .../junits/common/GridCommonAbstractTest.java   |   19 +-
 .../ignite/testsuites/IgniteCacheTestSuite.java |    4 +-
 .../testsuites/IgniteCacheTestSuite2.java       |    2 +
 .../testsuites/IgniteCacheTestSuite5.java       |   40 +
 .../config/benchmark-multicast.properties       |    5 +-
 .../IgniteAccountSerializableTxBenchmark.java   |   81 +
 .../cache/IgniteAccountTxAbstractBenchmark.java |   61 +
 .../cache/IgniteAccountTxBenchmark.java         |   74 +
 .../cache/IgniteCacheAbstractBenchmark.java     |    7 +-
 .../IgnitePutAllSerializableTxBenchmark.java    |   77 +
 .../ignite/yardstick/cache/model/Account.java   |   42 +
 83 files changed, 9229 insertions(+), 2239 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
index 7d3cebb..fc2a6cb 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/configuration/TransactionConfiguration.java
@@ -92,15 +92,17 @@ public class TransactionConfiguration implements 
Serializable {
      *
      * @return {@code True} if serializable transactions are enabled, {@code 
false} otherwise.
      */
+    @Deprecated
     public boolean isTxSerializableEnabled() {
         return txSerEnabled;
     }
 
     /**
-     * Enables/disables serializable cache transactions. See {@link 
#isTxSerializableEnabled()} for more information.
-     *
      * @param txSerEnabled Flag to enable/disable serializable cache 
transactions.
+
+     * @deprecated This method has no effect, {@link 
TransactionIsolation#SERIALIZABLE} isolation is always enabled.
      */
+    @Deprecated
     public void setTxSerializableEnabled(boolean txSerEnabled) {
         this.txSerEnabled = txSerEnabled;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
index dfa0217..a60c22b 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheMetricsImpl.java
@@ -351,7 +351,7 @@ public class CacheMetricsImpl implements CacheMetrics {
 
     /** {@inheritDoc} */
     @Override public int getTxCommitQueueSize() {
-        return cctx.tm().commitQueueSize();
+        return 0;
     }
 
     /** {@inheritDoc} */
@@ -366,12 +366,12 @@ public class CacheMetricsImpl implements CacheMetrics {
 
     /** {@inheritDoc} */
     @Override public int getTxPrepareQueueSize() {
-        return cctx.tm().prepareQueueSize();
+        return 0;
     }
 
     /** {@inheritDoc} */
     @Override public int getTxStartVersionCountsSize() {
-        return cctx.tm().startVersionCountsSize();
+        return 0;
     }
 
     /** {@inheritDoc} */
@@ -396,17 +396,17 @@ public class CacheMetricsImpl implements CacheMetrics {
 
     /** {@inheritDoc} */
     @Override public int getTxDhtCommitQueueSize() {
-        return cctx.isNear() && dhtCtx != null ? dhtCtx.tm().commitQueueSize() 
: -1;
+        return 0;
     }
 
     /** {@inheritDoc} */
     @Override public int getTxDhtPrepareQueueSize() {
-        return cctx.isNear() && dhtCtx != null ? 
dhtCtx.tm().prepareQueueSize() : -1;
+        return 0;
     }
 
     /** {@inheritDoc} */
     @Override public int getTxDhtStartVersionCountsSize() {
-        return cctx.isNear() && dhtCtx != null ? 
dhtCtx.tm().startVersionCountsSize() : -1;
+        return 0;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index 417b396..74951b5 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -608,7 +608,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             Collections.singletonList(key),
             /*force primary*/false,
             /*skip tx*/false,
-            /*entry*/null,
             /*subj id*/null,
             /*task name*/null,
             /*deserialize portable*/false,
@@ -643,7 +642,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             keys,
             /*force primary*/false,
             /*skip tx*/false,
-            /*entry*/null,
             /*subj id*/null,
             /*task name*/null,
             /*deserialize portable*/false,
@@ -1273,7 +1271,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             F.asList(key),
             /*force primary*/true,
             /*skip tx*/false,
-            /*cached entry*/null,
             /*subject id*/null,
             taskName,
             /*deserialize cache objects*/true,
@@ -1291,7 +1288,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             /*force primary*/true,
             /*skip tx*/false,
             null,
-            null,
             taskName,
             true,
             false,
@@ -1317,7 +1313,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             F.asList(key),
             /*force primary*/false,
             /*skip tx*/false,
-            /*cached entry*/null,
             /*subject id*/null,
             taskName,
             /*deserialize cache objects*/true,
@@ -1339,7 +1334,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             !ctx.config().isReadFromBackup(),
             /*skip tx*/true,
             null,
-            null,
             taskName,
             !ctx.keepPortable(),
             /*skip values*/false,
@@ -1347,184 +1341,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
     }
 
     /**
-     * @param keys Keys.
-     * @param reload Reload flag.
-     * @param tx Transaction.
-     * @param subjId Subject ID.
-     * @param taskName Task name.
-     * @param vis Visitor.
-     * @return Future.
-     */
-    public IgniteInternalFuture<Object> readThroughAllAsync(final 
Collection<KeyCacheObject> keys,
-        boolean reload,
-        boolean skipVals,
-        @Nullable final IgniteInternalTx tx,
-        @Nullable UUID subjId,
-        String taskName,
-        final IgniteBiInClosure<KeyCacheObject, Object> vis) {
-        return ctx.closures().callLocalSafe(new GPC<Object>() {
-            @Nullable @Override public Object call() {
-                try {
-                    ctx.store().loadAll(tx, keys, vis);
-                }
-                catch (IgniteCheckedException e) {
-                    throw new GridClosureException(e);
-                }
-
-                return null;
-            }
-        }, true);
-    }
-
-    /**
-     * @param keys Keys.
-     * @param ret Return flag.
-     * @param skipVals Skip values flag.
-     * @param subjId Subject ID.
-     * @param taskName Task name.
-     * @return Future.
-     */
-    public IgniteInternalFuture<Map<KeyCacheObject, CacheObject>> 
reloadAllAsync0(
-        Collection<KeyCacheObject> keys,
-        boolean ret,
-        boolean skipVals,
-        @Nullable UUID subjId,
-        String taskName)
-    {
-        final AffinityTopologyVersion topVer = 
ctx.affinity().affinityTopologyVersion();
-
-        if (!F.isEmpty(keys)) {
-            final Map<KeyCacheObject, GridCacheVersion> keyVers = new 
HashMap();
-
-            for (KeyCacheObject key : keys) {
-                if (key == null)
-                    continue;
-
-                // Skip primary or backup entries for near cache.
-                if (ctx.isNear() && ctx.affinity().localNode(key, topVer))
-                    continue;
-
-                while (true) {
-                    try {
-                        GridCacheEntryEx entry = entryExSafe(key, topVer);
-
-                        if (entry == null)
-                            break;
-
-                        GridCacheVersion ver = entry.version();
-
-                        keyVers.put(key, ver);
-
-                        break;
-                    }
-                    catch (GridCacheEntryRemovedException ignore) {
-                        if (log.isDebugEnabled())
-                            log.debug("Got removed entry for reload (will 
retry): " + key);
-                    }
-                    catch (GridDhtInvalidPartitionException ignore) {
-                        if (log.isDebugEnabled())
-                            log.debug("Got invalid partition for key (will 
skip): " + key);
-
-                        break;
-                    }
-                }
-            }
-
-            final Map<KeyCacheObject, CacheObject> map =
-                ret ? U.<KeyCacheObject, CacheObject>newHashMap(keys.size()) : 
null;
-
-            final Collection<KeyCacheObject> absentKeys = 
F.view(keyVers.keySet());
-
-            final Collection<KeyCacheObject> loadedKeys = new 
GridConcurrentHashSet<>();
-
-            IgniteInternalFuture<Object> readFut = 
readThroughAllAsync(absentKeys, true, skipVals, null,
-                subjId, taskName, new CI2<KeyCacheObject, Object>() {
-                    /** Version for all loaded entries. */
-                    private GridCacheVersion nextVer = ctx.versions().next();
-
-                    /** {@inheritDoc} */
-                    @Override public void apply(KeyCacheObject key, Object 
val) {
-                        loadedKeys.add(key);
-
-                        GridCacheEntryEx entry = peekEx(key);
-
-                        if (entry != null) {
-                            try {
-                                GridCacheVersion curVer = keyVers.get(key);
-
-                                if (curVer != null) {
-                                    boolean wasNew = entry.isNewLocked();
-
-                                    entry.unswap();
-
-                                    CacheObject cacheVal = 
ctx.toCacheObject(val);
-
-                                    boolean set = 
entry.versionedValue(cacheVal, curVer, nextVer);
-
-                                    ctx.evicts().touch(entry, topVer);
-
-                                    if (map != null) {
-                                        if (set || wasNew)
-                                            map.put(key, cacheVal);
-                                        else {
-                                            CacheObject v = entry.peek(true, 
false, false, null);
-
-                                            if (v != null)
-                                                map.put(key, v);
-                                        }
-                                    }
-
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Set value loaded from store 
into entry [set=" + set + ", " +
-                                            "curVer=" +
-                                            curVer + ", newVer=" + nextVer + 
", entry=" + entry + ']');
-                                    }
-                                }
-                                else {
-                                    if (log.isDebugEnabled()) {
-                                        log.debug("Current version was not 
found (either entry was removed or " +
-                                            "validation was not passed: " + 
entry);
-                                    }
-                                }
-                            }
-                            catch (GridCacheEntryRemovedException ignore) {
-                                if (log.isDebugEnabled()) {
-                                    log.debug("Got removed entry for reload 
(will not store reloaded entry) " +
-                                        "[entry=" + entry + ']');
-                                }
-                            }
-                            catch (IgniteCheckedException e) {
-                                throw new IgniteException(e);
-                            }
-                        }
-                    }
-                });
-
-            return readFut.chain(new CX1<IgniteInternalFuture<Object>, 
Map<KeyCacheObject, CacheObject>>() {
-                @Override public Map<KeyCacheObject, CacheObject> 
applyx(IgniteInternalFuture<Object> e)
-                    throws IgniteCheckedException  {
-                    // Touch all not loaded keys.
-                    for (KeyCacheObject key : absentKeys) {
-                        if (!loadedKeys.contains(key)) {
-                            GridCacheEntryEx entry = peekEx(key);
-
-                            if (entry != null)
-                                ctx.evicts().touch(entry, topVer);
-                        }
-                    }
-
-                    // Make sure there were no exceptions.
-                    e.get();
-
-                    return map;
-                }
-            });
-        }
-
-        return new GridFinishedFuture<>(Collections.<KeyCacheObject, 
CacheObject>emptyMap());
-    }
-
-    /**
      * @param key Key.
      * @param topVer Topology version.
      * @return Entry.
@@ -1662,11 +1478,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
      * @param keys Keys.
      * @param forcePrimary Force primary.
      * @param skipTx Skip tx.
-     * @param entry Entry.
      * @param subjId Subj Id.
      * @param taskName Task name.
      * @param deserializePortable Deserialize portable.
      * @param skipVals Skip values.
+     * @param canRemap Can remap flag.
      * @return Future for the get operation.
      * @see GridCacheAdapter#getAllAsync(Collection)
      */
@@ -1674,7 +1490,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
         @Nullable Collection<? extends K> keys,
         boolean forcePrimary,
         boolean skipTx,
-        @Nullable GridCacheEntryEx entry,
         @Nullable UUID subjId,
         String taskName,
         boolean deserializePortable,
@@ -1687,7 +1502,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return getAllAsync(keys,
             opCtx == null || !opCtx.skipStore(),
-            entry,
             !skipTx,
             subjId,
             taskName,
@@ -1701,7 +1515,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
     /**
      * @param keys Keys.
      * @param readThrough Read through.
-     * @param cached Cached.
      * @param checkTx Check tx.
      * @param subjId Subj Id.
      * @param taskName Task name.
@@ -1709,12 +1522,12 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
      * @param forcePrimary Froce primary.
      * @param expiry Expiry policy.
      * @param skipVals Skip values.
+     * @param canRemap Can remap flag.
      * @return Future for the get operation.
      * @see GridCacheAdapter#getAllAsync(Collection)
      */
     public IgniteInternalFuture<Map<K, V>> getAllAsync(@Nullable final 
Collection<? extends K> keys,
         boolean readThrough,
-        @Nullable GridCacheEntryEx cached,
         boolean checkTx,
         @Nullable final UUID subjId,
         final String taskName,
@@ -1738,7 +1551,8 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             expiry,
             skipVals,
             false,
-            canRemap);
+            canRemap,
+            false);
     }
 
     /**
@@ -1750,10 +1564,12 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
      * @param deserializePortable Deserialize portable flag.
      * @param expiry Expiry policy.
      * @param skipVals Skip values flag.
-     * @param keepCacheObjects Keep cache objects
+     * @param keepCacheObjects Keep cache objects.
+     * @param canRemap Can remap flag.
+     * @param needVer If {@code true} returns values as tuples containing 
value and version.
      * @return Future.
      */
-    public <K1, V1> IgniteInternalFuture<Map<K1, V1>> getAllAsync0(@Nullable 
final Collection<KeyCacheObject> keys,
+    public final <K1, V1> IgniteInternalFuture<Map<K1, V1>> 
getAllAsync0(@Nullable final Collection<KeyCacheObject> keys,
         final boolean readThrough,
         boolean checkTx,
         @Nullable final UUID subjId,
@@ -1762,7 +1578,8 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
         @Nullable IgniteCacheExpiryPolicy expiry,
         final boolean skipVals,
         final boolean keepCacheObjects,
-        boolean canRemap
+        boolean canRemap,
+        final boolean needVer
         ) {
         if (F.isEmpty(keys))
             return new GridFinishedFuture<>(Collections.<K1, V1>emptyMap());
@@ -1782,14 +1599,14 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         if (tx == null || tx.implicit()) {
             try {
-                assert keys != null;
-
                 final AffinityTopologyVersion topVer = tx == null
                     ? (canRemap ? ctx.affinity().affinityTopologyVersion(): 
ctx.shared().exchange().readyAffinityVersion())
                     : tx.topologyVersion();
 
                 final Map<K1, V1> map = new GridLeanMap<>(keys.size());
 
+                final boolean storeEnabled = !skipVals && readThrough && 
ctx.readThrough();
+
                 Map<KeyCacheObject, GridCacheVersion> misses = null;
 
                 for (KeyCacheObject key : keys) {
@@ -1797,29 +1614,43 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                         GridCacheEntryEx entry = entryEx(key);
 
                         try {
-                            CacheObject val = entry.innerGet(null,
+                            T2<CacheObject, GridCacheVersion> res = 
entry.innerGetVersioned(null,
                                 ctx.isSwapOrOffheapEnabled(),
-                                /*don't read-through*/false,
-                                /*fail-fast*/true,
                                 /*unmarshal*/true,
                                 /*update-metrics*/!skipVals,
                                 /*event*/!skipVals,
-                                /*temporary*/false,
                                 subjId,
                                 null,
                                 taskName,
                                 expiry);
 
-                            if (val == null) {
-                                GridCacheVersion ver = entry.version();
+                            if (res == null) {
+                                if (storeEnabled) {
+                                    GridCacheVersion ver = entry.version();
 
-                                if (misses == null)
-                                    misses = new GridLeanMap<>();
+                                    if (misses == null)
+                                        misses = new GridLeanMap<>();
 
-                                misses.put(key, ver);
+                                    misses.put(key, ver);
+                                }
+                                else
+                                    ctx.evicts().touch(entry, topVer);
                             }
                             else {
-                                ctx.addResult(map, key, val, skipVals, 
keepCacheObjects, deserializePortable, true);
+                                if (needVer) {
+                                    assert keepCacheObjects;
+
+                                    map.put((K1)key, (V1)new T2<>(res.get1(), 
res.get2()));
+                                }
+                                else {
+                                    ctx.addResult(map,
+                                        key,
+                                        res.get1(),
+                                        skipVals,
+                                        keepCacheObjects,
+                                        deserializePortable,
+                                        true);
+                                }
 
                                 if (tx == null || (!tx.implicit() && 
tx.isolation() == READ_COMMITTED))
                                     ctx.evicts().touch(entry, topVer);
@@ -1835,19 +1666,10 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                             if (log.isDebugEnabled())
                                 log.debug("Got removed entry in 
getAllAsync(..) method (will retry): " + key);
                         }
-                        catch (GridCacheFilterFailedException ignore) {
-                            if (log.isDebugEnabled())
-                                log.debug("Filter validation failed for entry: 
" + entry);
-
-                            if (tx == null || (!tx.implicit() && 
tx.isolation() == READ_COMMITTED))
-                                ctx.evicts().touch(entry, topVer);
-
-                            break; // While loop.
-                        }
                     }
                 }
 
-                if (!skipVals && misses != null && readThrough && 
ctx.readThrough()) {
+                if (storeEnabled && misses != null) {
                     final Map<KeyCacheObject, GridCacheVersion> loadKeys = 
misses;
 
                     final IgniteTxLocalAdapter tx0 = tx;
@@ -1858,9 +1680,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                         ctx.closures().callLocalSafe(ctx.projectSafe(new 
GPC<Map<K1, V1>>() {
                             @Override public Map<K1, V1> call() throws 
Exception {
                                 ctx.store().loadAll(null/*tx*/, 
loadKeys.keySet(), new CI2<KeyCacheObject, Object>() {
-                                    /** New version for all new entries. */
-                                    private GridCacheVersion nextVer;
-
                                     @Override public void apply(KeyCacheObject 
key, Object val) {
                                         GridCacheVersion ver = 
loadKeys.get(key);
 
@@ -1872,10 +1691,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                                             return;
                                         }
 
-                                        // Initialize next version.
-                                        if (nextVer == null)
-                                            nextVer = ctx.versions().next();
-
                                         loaded.add(key);
 
                                         CacheObject cacheVal = 
ctx.toCacheObject(val);
@@ -1884,22 +1699,33 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                                             GridCacheEntryEx entry = 
entryEx(key);
 
                                             try {
-                                                boolean set = 
entry.versionedValue(cacheVal, ver, nextVer);
+                                                GridCacheVersion verSet = 
entry.versionedValue(cacheVal, ver, null);
+
+                                                boolean set = verSet != null;
 
                                                 if (log.isDebugEnabled())
-                                                    log.debug("Set value 
loaded from store into entry [set=" + set +
-                                                        ", curVer=" + ver + ", 
newVer=" + nextVer + ", " +
+                                                    log.debug("Set value 
loaded from store into entry [" +
+                                                        "set=" + set +
+                                                        ", curVer=" + ver +
+                                                        ", newVer=" + verSet + 
", " +
                                                         "entry=" + entry + 
']');
 
                                                 // Don't put key-value pair 
into result map if value is null.
                                                 if (val != null) {
-                                                    ctx.addResult(map,
-                                                        key,
-                                                        cacheVal,
-                                                        skipVals,
-                                                        keepCacheObjects,
-                                                        deserializePortable,
-                                                        false);
+                                                    if (needVer) {
+                                                        assert 
keepCacheObjects;
+
+                                                        map.put((K1)key, 
(V1)new T2<>(cacheVal, set ? verSet : ver));
+                                                    }
+                                                    else {
+                                                        ctx.addResult(map,
+                                                            key,
+                                                            cacheVal,
+                                                            skipVals,
+                                                            keepCacheObjects,
+                                                            
deserializePortable,
+                                                            false);
+                                                    }
                                                 }
 
                                                 if (tx0 == null || 
(!tx0.implicit() &&
@@ -1992,9 +1818,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             }
         }
         else {
+            assert !needVer;
+
             return asyncOp(tx, new AsyncOp<Map<K1, V1>>(keys) {
                 @Override public IgniteInternalFuture<Map<K1, V1>> 
op(IgniteTxLocalAdapter tx) {
-                    return tx.getAllAsync(ctx, keys, null, 
deserializePortable, skipVals, false, !readThrough);
+                    return tx.getAllAsync(ctx, keys, deserializePortable, 
skipVals, false, !readThrough);
                 }
             });
         }
@@ -2028,7 +1856,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         V prevVal = syncOp(new SyncOp<V>(true) {
             @Override public V op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return (V)tx.putAllAsync(ctx, F.t(key, val), true, null, -1, 
filter).get().value();
+                return (V)tx.putAllAsync(ctx, F.t(key, val), true, 
filter).get().value();
             }
 
             @Override public String toString() {
@@ -2083,7 +1911,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return asyncOp(new AsyncOp<V>() {
             @Override public IgniteInternalFuture<V> op(IgniteTxLocalAdapter 
tx) {
-                return tx.putAllAsync(ctx, F.t(key, val), true, null, -1, 
filter)
+                return tx.putAllAsync(ctx, F.t(key, val), true, filter)
                     
.chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>)RET2VAL);
             }
 
@@ -2122,7 +1950,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         Boolean stored = syncOp(new SyncOp<Boolean>(true) {
             @Override public Boolean op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return tx.putAllAsync(ctx, F.t(key, val), false, null, -1, 
filter).get().success();
+                return tx.putAllAsync(ctx, F.t(key, val), false, 
filter).get().success();
             }
 
             @Override public String toString() {
@@ -2414,7 +2242,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return asyncOp(new AsyncOp<Boolean>() {
             @Override public IgniteInternalFuture<Boolean> 
op(IgniteTxLocalAdapter tx) {
-                return tx.putAllAsync(ctx, F.t(key, val), false, null, -1, 
filter).chain(
+                return tx.putAllAsync(ctx, F.t(key, val), false, filter).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
Boolean>) RET2FLAG);
             }
 
@@ -2449,7 +2277,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return syncOp(new SyncOp<V>(true) {
             @Override public V op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return (V)tx.putAllAsync(ctx, F.t(key, val), true, null, -1, 
ctx.noValArray()).get().value();
+                return (V)tx.putAllAsync(ctx, F.t(key, val), true, 
ctx.noValArray()).get().value();
             }
 
             @Override public String toString() {
@@ -2473,7 +2301,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         IgniteInternalFuture<V> fut = asyncOp(new AsyncOp<V>() {
             @Override public IgniteInternalFuture<V> op(IgniteTxLocalAdapter 
tx) {
-                return tx.putAllAsync(ctx, F.t(key, val), true, null, -1, 
ctx.noValArray())
+                return tx.putAllAsync(ctx, F.t(key, val), true, 
ctx.noValArray())
                     
.chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>) RET2VAL);
             }
 
@@ -2503,7 +2331,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         Boolean stored = syncOp(new SyncOp<Boolean>(true) {
             @Override public Boolean op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return tx.putAllAsync(ctx, F.t(key, val), false, null, -1, 
ctx.noValArray()).get().success();
+                return tx.putAllAsync(ctx, F.t(key, val), false, 
ctx.noValArray()).get().success();
             }
 
             @Override public String toString() {
@@ -2532,7 +2360,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         IgniteInternalFuture<Boolean> fut = asyncOp(new AsyncOp<Boolean>() {
             @Override public IgniteInternalFuture<Boolean> 
op(IgniteTxLocalAdapter tx) {
-                return tx.putAllAsync(ctx, F.t(key, val), false, null, -1, 
ctx.noValArray()).chain(
+                return tx.putAllAsync(ctx, F.t(key, val), false, 
ctx.noValArray()).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
Boolean>)RET2FLAG);
             }
 
@@ -2558,7 +2386,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return syncOp(new SyncOp<V>(true) {
             @Override public V op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return (V)tx.putAllAsync(ctx, F.t(key, val), true, null, -1, 
ctx.hasValArray()).get().value();
+                return (V)tx.putAllAsync(ctx, F.t(key, val), true, 
ctx.hasValArray()).get().value();
             }
 
             @Override public String toString() {
@@ -2582,7 +2410,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         IgniteInternalFuture<V> fut = asyncOp(new AsyncOp<V>() {
             @Override public IgniteInternalFuture<V> op(IgniteTxLocalAdapter 
tx) {
-                return tx.putAllAsync(ctx, F.t(key, val), true, null, -1, 
ctx.hasValArray()).chain(
+                return tx.putAllAsync(ctx, F.t(key, val), true, 
ctx.hasValArray()).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
V>)RET2VAL);
             }
 
@@ -2608,7 +2436,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return syncOp(new SyncOp<Boolean>(true) {
             @Override public Boolean op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return tx.putAllAsync(ctx, F.t(key, val), false, null, -1, 
ctx.hasValArray()).get().success();
+                return tx.putAllAsync(ctx, F.t(key, val), false, 
ctx.hasValArray()).get().success();
             }
 
             @Override public String toString() {
@@ -2628,7 +2456,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return asyncOp(new AsyncOp<Boolean>() {
             @Override public IgniteInternalFuture<Boolean> 
op(IgniteTxLocalAdapter tx) {
-                return tx.putAllAsync(ctx, F.t(key, val), false, null, -1, 
ctx.hasValArray()).chain(
+                return tx.putAllAsync(ctx, F.t(key, val), false, 
ctx.hasValArray()).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
Boolean>) RET2FLAG);
             }
 
@@ -2655,7 +2483,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                 if (ctx.deploymentEnabled())
                     ctx.deploy().registerClass(oldVal);
 
-                return tx.putAllAsync(ctx, F.t(key, newVal), false, null, -1, 
ctx.equalsValArray(oldVal)).get()
+                return tx.putAllAsync(ctx, F.t(key, newVal), false, 
ctx.equalsValArray(oldVal)).get()
                     .success();
             }
 
@@ -2692,7 +2520,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                     }
                 }
 
-                return tx.putAllAsync(ctx, F.t(key, newVal), false, null, -1, 
ctx.equalsValArray(oldVal)).chain(
+                return tx.putAllAsync(ctx, F.t(key, newVal), false, 
ctx.equalsValArray(oldVal)).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
Boolean>)RET2FLAG);
             }
 
@@ -2723,7 +2551,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         syncOp(new SyncInOp(m.size() == 1) {
             @Override public void inOp(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                tx.putAllAsync(ctx, m, false, null, -1, CU.empty0()).get();
+                tx.putAllAsync(ctx, m, false, CU.empty0()).get();
             }
 
             @Override public String toString() {
@@ -2747,7 +2575,7 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return asyncOp(new AsyncInOp(m.keySet()) {
             @Override public IgniteInternalFuture<?> inOp(IgniteTxLocalAdapter 
tx) {
-                return tx.putAllAsync(ctx, m, false, null, -1, 
CU.empty0()).chain(RET2NULL);
+                return tx.putAllAsync(ctx, m, false, 
CU.empty0()).chain(RET2NULL);
             }
 
             @Override public String toString() {
@@ -2769,7 +2597,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         V prevVal = syncOp(new SyncOp<V>(true) {
             @Override public V op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                V ret = tx.removeAllAsync(ctx, Collections.singletonList(key), 
null, true, CU.empty0()).get().value();
+                V ret = tx.removeAllAsync(ctx,
+                    Collections.singletonList(key),
+                    /*retval*/true,
+                    CU.empty0(),
+                    /*singleRmv*/false).get().value();
 
                 if (ctx.config().getInterceptor() != null)
                     return (V)ctx.config().getInterceptor().onBeforeRemove(new 
CacheEntryImpl(key, ret)).get2();
@@ -2802,8 +2634,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
         IgniteInternalFuture<V> fut = asyncOp(new AsyncOp<V>() {
             @Override public IgniteInternalFuture<V> op(IgniteTxLocalAdapter 
tx) {
                 // TODO should we invoke interceptor here?
-                return tx.removeAllAsync(ctx, Collections.singletonList(key), 
null, true, CU.empty0())
-                    
.chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>) RET2VAL);
+                return tx.removeAllAsync(ctx,
+                    Collections.singletonList(key),
+                    /*retval*/true,
+                    CU.empty0(),
+                    
/*singleRmv*/false).chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
V>)RET2VAL);
             }
 
             @Override public String toString() {
@@ -2849,7 +2684,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         syncOp(new SyncInOp(keys.size() == 1) {
             @Override public void inOp(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                tx.removeAllAsync(ctx, keys, null, false, CU.empty0()).get();
+                tx.removeAllAsync(ctx,
+                    keys,
+                    /*retval*/false,
+                    CU.empty0(),
+                    /*singleRmv*/false).get();
             }
 
             @Override public String toString() {
@@ -2875,7 +2714,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         IgniteInternalFuture<Object> fut = asyncOp(new AsyncInOp(keys) {
             @Override public IgniteInternalFuture<?> inOp(IgniteTxLocalAdapter 
tx) {
-                return tx.removeAllAsync(ctx, keys, null, false, 
CU.empty0()).chain(RET2NULL);
+                return tx.removeAllAsync(ctx,
+                    keys,
+                    /*retval*/false,
+                    CU.empty0(),
+                    /*singleRmv*/false).chain(RET2NULL);
             }
 
             @Override public String toString() {
@@ -2902,7 +2745,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         boolean rmv = syncOp(new SyncOp<Boolean>(true) {
             @Override public Boolean op(IgniteTxLocalAdapter tx) throws 
IgniteCheckedException {
-                return tx.removeAllAsync(ctx, Collections.singletonList(key), 
null, false, CU.empty0()).get().success();
+                return tx.removeAllAsync(ctx,
+                    Collections.singletonList(key),
+                    /*retval*/false,
+                    CU.empty0(),
+                    /*singleRmv*/true).get().success();
             }
 
             @Override public String toString() {
@@ -2940,7 +2787,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         IgniteInternalFuture<Boolean> fut = asyncOp(new AsyncOp<Boolean>() {
             @Override public IgniteInternalFuture<Boolean> 
op(IgniteTxLocalAdapter tx) {
-                return tx.removeAllAsync(ctx, Collections.singletonList(key), 
null, false, filter).chain(
+                return tx.removeAllAsync(ctx,
+                    Collections.singletonList(key),
+                    /*retval*/false,
+                    filter,
+                    /*singleRmv*/true).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
Boolean>)RET2FLAG);
             }
 
@@ -2970,9 +2821,9 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
                 return tx.removeAllAsync(ctx,
                     Collections.singletonList(key),
-                    null,
-                    true,
-                    ctx.equalsValArray(val)).get();
+                    /*retval*/true,
+                    ctx.equalsValArray(val),
+                    /*singleRmv*/false).get();
             }
 
             @Override public String toString() {
@@ -3037,8 +2888,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                 return tx.putAllAsync(ctx,
                         F.t(key, newVal),
                         true,
-                        null,
-                        -1,
                         ctx.equalsValArray(oldVal)).get();
             }
 
@@ -3066,13 +2915,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                     return new GridFinishedFuture<>(e);
                 }
 
-                IgniteInternalFuture<GridCacheReturn> fut = 
(IgniteInternalFuture)tx.removeAllAsync(ctx,
+                return (IgniteInternalFuture)tx.removeAllAsync(ctx,
                     Collections.singletonList(key),
-                    null,
-                    true,
-                    ctx.equalsValArray(val));
-
-                return fut;
+                    /*retval*/true,
+                    ctx.equalsValArray(val),
+                    /*singleRmv*/false);
             }
 
             @Override public String toString() {
@@ -3100,14 +2947,10 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                     return new GridFinishedFuture<>(e);
                 }
 
-                IgniteInternalFuture<GridCacheReturn> fut = 
(IgniteInternalFuture)tx.putAllAsync(ctx,
+                return (IgniteInternalFuture)tx.putAllAsync(ctx,
                     F.t(key, newVal),
                     true,
-                    null,
-                    -1,
                     ctx.equalsValArray(oldVal));
-
-                return fut;
             }
 
             @Override public String toString() {
@@ -3135,8 +2978,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                 if (ctx.deploymentEnabled())
                     ctx.deploy().registerClass(val);
 
-                return tx.removeAllAsync(ctx, Collections.singletonList(key), 
null, false,
-                    ctx.equalsValArray(val)).get().success();
+                return tx.removeAllAsync(ctx,
+                    Collections.singletonList(key),
+                    /*retval*/false,
+                    ctx.equalsValArray(val),
+                    /*singleRmv*/false).get().success();
             }
 
             @Override public String toString() {
@@ -3175,8 +3021,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
                     }
                 }
 
-                return tx.removeAllAsync(ctx, Collections.singletonList(key), 
null, false,
-                    ctx.equalsValArray(val)).chain(
+                return tx.removeAllAsync(ctx,
+                    Collections.singletonList(key),
+                    /*retval*/false,
+                    ctx.equalsValArray(val),
+                    /*singleRmv*/false).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, 
Boolean>)RET2FLAG);
             }
 
@@ -3200,7 +3049,11 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
 
         return asyncOp(new AsyncInOp(keys) {
             @Override public IgniteInternalFuture<?> inOp(IgniteTxLocalAdapter 
tx) {
-                return tx.removeAllAsync(ctx, keys, null, false, null);
+                return tx.removeAllAsync(ctx,
+                    keys,
+                    /*retval*/false,
+                    null,
+                    /*singleRmv*/false);
             }
 
             @Override public String toString() {
@@ -4579,7 +4432,6 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
             !ctx.config().isReadFromBackup(),
             /*skip tx*/false,
             null,
-            null,
             taskName,
             deserializePortable,
             false,
@@ -4741,41 +4593,34 @@ public abstract class GridCacheAdapter<K, V> implements 
IgniteInternalCache<K, V
         boolean deserializePortable)
         throws IgniteCheckedException, GridCacheEntryRemovedException
     {
-        try {
-            CacheObject val = entry.innerGet(
-                null,
-                false,
-                false,
-                false,
-                true,
-                false,
-                false,
-                false,
-                null,
-                null,
-                null,
-                null);
-
-            if (val == null)
-                return null;
+        CacheObject val = entry.innerGet(
+            null,
+            false,
+            false,
+            false,
+            true,
+            false,
+            false,
+            false,
+            null,
+            null,
+            null,
+            null);
 
-            KeyCacheObject key = entry.key();
+        if (val == null)
+            return null;
 
-            Object key0 = key.value(ctx.cacheObjectContext(), true);
-            Object val0 = val.value(ctx.cacheObjectContext(), true);
+        KeyCacheObject key = entry.key();
 
-            if (deserializePortable) {
-                key0 = ctx.unwrapPortableIfNeeded(key0, true);
-                val0 = ctx.unwrapPortableIfNeeded(val0, true);
-            }
+        Object key0 = key.value(ctx.cacheObjectContext(), true);
+        Object val0 = val.value(ctx.cacheObjectContext(), true);
 
-            return new CacheEntryImpl<>((K)key0, (V)val0, entry.version());
+        if (deserializePortable) {
+            key0 = ctx.unwrapPortableIfNeeded(key0, true);
+            val0 = ctx.unwrapPortableIfNeeded(val0, true);
         }
-        catch (GridCacheFilterFailedException ignore) {
-            assert false;
 
-            return null;
-        }
+        return new CacheEntryImpl<>((K)key0, (V)val0, entry.version());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/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 430590a..50b01c8 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
@@ -33,6 +33,7 @@ import 
org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import 
org.apache.ignite.internal.processors.cache.version.GridCacheVersionedEntryEx;
 import org.apache.ignite.internal.processors.dr.GridDrType;
 import org.apache.ignite.internal.util.lang.GridTuple3;
+import org.apache.ignite.internal.util.typedef.T2;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -286,12 +287,10 @@ public interface GridCacheEntryEx {
      * @param subjId Subject ID initiated this read.
      * @param transformClo Transform closure to record event.
      * @param taskName Task name.
-     *      together with getting the value is an atomic operation.
      * @param expiryPlc Expiry policy.
      * @return Cached value.
      * @throws IgniteCheckedException If loading value failed.
      * @throws GridCacheEntryRemovedException If entry was removed.
-     * @throws GridCacheFilterFailedException If filter failed.
      */
     @Nullable public CacheObject innerGet(@Nullable IgniteInternalTx tx,
         boolean readSwap,
@@ -305,7 +304,33 @@ public interface GridCacheEntryEx {
         Object transformClo,
         String taskName,
         @Nullable IgniteCacheExpiryPolicy expiryPlc)
-        throws IgniteCheckedException, GridCacheEntryRemovedException, 
GridCacheFilterFailedException;
+        throws IgniteCheckedException, GridCacheEntryRemovedException;
+
+    /**
+     * @param tx Cache transaction.
+     * @param readSwap Flag indicating whether to check swap memory.
+     * @param unmarshal Unmarshal flag.
+     * @param updateMetrics If {@code true} then metrics should be updated.
+     * @param evt Flag to signal event notification.
+     * @param subjId Subject ID initiated this read.
+     * @param transformClo Transform closure to record event.
+     * @param taskName Task name.
+     * @param expiryPlc Expiry policy.
+     * @return Cached value and entry version.
+     * @throws IgniteCheckedException If loading value failed.
+     * @throws GridCacheEntryRemovedException If entry was removed.
+     */
+    @Nullable public T2<CacheObject, GridCacheVersion> innerGetVersioned(
+        IgniteInternalTx tx,
+        boolean readSwap,
+        boolean unmarshal,
+        boolean updateMetrics,
+        boolean evt,
+        UUID subjId,
+        Object transformClo,
+        String taskName,
+        @Nullable IgniteCacheExpiryPolicy expiryPlc)
+        throws IgniteCheckedException, GridCacheEntryRemovedException;
 
     /**
      * Reloads entry from underlying storage.
@@ -334,6 +359,7 @@ public interface GridCacheEntryEx {
      * @param explicitVer Explicit version (if any).
      * @param subjId Subject ID initiated this update.
      * @param taskName Task name.
+     * @param dhtVer Dht version for near cache entry.
      * @return Tuple containing success flag and old value. If success is 
{@code false},
      *      then value is {@code null}.
      * @throws IgniteCheckedException If storing value failed.
@@ -355,7 +381,8 @@ public interface GridCacheEntryEx {
         long drExpireTime,
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
-        String taskName
+        String taskName,
+        @Nullable GridCacheVersion dhtVer
     ) throws IgniteCheckedException, GridCacheEntryRemovedException;
 
     /**
@@ -372,6 +399,7 @@ public interface GridCacheEntryEx {
      * @param explicitVer Explicit version (if any).
      * @param subjId Subject ID initiated this update.
      * @param taskName Task name.
+     * @param dhtVer Dht version for near cache entry.
      * @return Tuple containing success flag and old value. If success is 
{@code false},
      *      then value is {@code null}.
      * @throws IgniteCheckedException If remove failed.
@@ -390,7 +418,8 @@ public interface GridCacheEntryEx {
         GridDrType drType,
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
-        String taskName
+        String taskName,
+        @Nullable GridCacheVersion dhtVer
     ) throws IgniteCheckedException, GridCacheEntryRemovedException;
 
     /**
@@ -409,6 +438,7 @@ public interface GridCacheEntryEx {
      * @param primary If update is performed on primary node (the one which 
assigns version).
      * @param checkVer Whether update should check current version and ignore 
update if current version is
      *      greater than passed in.
+     * @param topVer Topology version.
      * @param filter Optional filter to check.
      * @param drType DR type.
      * @param conflictTtl Conflict TTL (if any).
@@ -510,12 +540,17 @@ public interface GridCacheEntryEx {
      *
      * @param tx Cache transaction.
      * @param timeout Timeout for lock acquisition.
+     * @param serOrder Version for serializable transactions ordering.
+     * @param serReadVer Optional read entry version for optimistic 
serializable transaction.
      * @return {@code True} if lock was acquired, {@code false} otherwise.
      * @throws GridCacheEntryRemovedException If this entry is obsolete.
      * @throws GridDistributedLockCancelledException If lock has been 
cancelled.
      */
-    public boolean tmLock(IgniteInternalTx tx, long timeout) throws 
GridCacheEntryRemovedException,
-        GridDistributedLockCancelledException;
+    public boolean tmLock(IgniteInternalTx tx,
+        long timeout,
+        @Nullable GridCacheVersion serOrder,
+        @Nullable GridCacheVersion serReadVer)
+        throws GridCacheEntryRemovedException, 
GridDistributedLockCancelledException;
 
     /**
      * Unlocks acquired lock.
@@ -566,6 +601,15 @@ 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.
+     * @throws GridCacheEntryRemovedException If entry has been removed.
+     */
+    public boolean checkSerializableReadVersion(GridCacheVersion serReadVer) 
throws GridCacheEntryRemovedException;
+
+    /**
      * Peeks into entry without loading value or updating statistics.
      *
      * @param heap Read from heap flag.
@@ -653,11 +697,11 @@ public interface GridCacheEntryEx {
      * @param val New value.
      * @param curVer Version to match or {@code null} if match is not required.
      * @param newVer Version to set.
-     * @return {@code True} if versioned matched.
+     * @return Non null version if value was set.
      * @throws IgniteCheckedException If index could not be updated.
      * @throws GridCacheEntryRemovedException If entry was removed.
      */
-    public boolean versionedValue(CacheObject val,
+    public GridCacheVersion versionedValue(CacheObject val,
         @Nullable GridCacheVersion curVer,
         @Nullable GridCacheVersion newVer)
         throws IgniteCheckedException, GridCacheEntryRemovedException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/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 4bf0aa1..2111594 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
@@ -37,12 +37,14 @@ import 
org.apache.ignite.internal.managers.deployment.GridDeploymentInfo;
 import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import 
org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
+import 
org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry;
 import org.apache.ignite.internal.processors.cache.extras.GridCacheEntryExtras;
 import 
org.apache.ignite.internal.processors.cache.extras.GridCacheMvccEntryExtras;
 import 
org.apache.ignite.internal.processors.cache.extras.GridCacheObsoleteEntryExtras;
 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;
@@ -59,6 +61,7 @@ import 
org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.internal.util.typedef.T3;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -673,7 +676,7 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         String taskName,
         @Nullable IgniteCacheExpiryPolicy expirePlc)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
-        return innerGet0(tx,
+        return (CacheObject)innerGet0(tx,
             readSwap,
             readThrough,
             evt,
@@ -683,12 +686,39 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
             subjId,
             transformClo,
             taskName,
-            expirePlc);
+            expirePlc,
+            false);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public T2<CacheObject, GridCacheVersion> 
innerGetVersioned(
+        IgniteInternalTx tx,
+        boolean readSwap,
+        boolean unmarshal,
+        boolean updateMetrics,
+        boolean evt,
+        UUID subjId,
+        Object transformClo,
+        String taskName,
+        @Nullable IgniteCacheExpiryPolicy expiryPlc)
+        throws IgniteCheckedException, GridCacheEntryRemovedException {
+        return (T2<CacheObject, GridCacheVersion>)innerGet0(tx,
+            readSwap,
+            false,
+            evt,
+            unmarshal,
+            updateMetrics,
+            false,
+            subjId,
+            transformClo,
+            taskName,
+            expiryPlc,
+            true);
     }
 
     /** {@inheritDoc} */
     @SuppressWarnings({"unchecked", "RedundantTypeArguments", "TooBroadScope"})
-    private CacheObject innerGet0(IgniteInternalTx tx,
+    private Object innerGet0(IgniteInternalTx tx,
         boolean readSwap,
         boolean readThrough,
         boolean evt,
@@ -698,8 +728,11 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         UUID subjId,
         Object transformClo,
         String taskName,
-        @Nullable IgniteCacheExpiryPolicy expiryPlc)
+        @Nullable IgniteCacheExpiryPolicy expiryPlc,
+        boolean retVer)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
+        assert !(retVer && readThrough);
+
         // Disable read-through if there is no store.
         if (readThrough && !cctx.readThrough())
             readThrough = false;
@@ -710,6 +743,7 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         CacheObject ret = null;
 
         GridCacheVersion startVer;
+        GridCacheVersion resVer = null;
 
         boolean expired = false;
 
@@ -840,11 +874,18 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
 
             if (ret != null && expiryPlc != null)
                 updateTtl(expiryPlc);
+
+            if (retVer) {
+                resVer = isNear() ? ((GridNearCacheEntry)this).dhtVersion() : 
this.ver;
+
+                if (resVer == null)
+                    ret = null;
+            }
         }
 
         if (ret != null)
             // If return value is consistent, then done.
-            return ret;
+            return retVer ? new T2<>(ret, resVer) : ret;
 
         boolean loadedFromStore = false;
 
@@ -906,6 +947,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
             }
         }
 
+        assert ret == null || !retVer;
+
         return ret;
     }
 
@@ -1015,7 +1058,8 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         long drExpireTime,
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
-        String taskName
+        String taskName,
+        @Nullable GridCacheVersion dhtVer
     ) throws IgniteCheckedException, GridCacheEntryRemovedException {
         CacheObject old;
 
@@ -1035,6 +1079,14 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         synchronized (this) {
             checkObsolete();
 
+            if (isNear()) {
+                assert dhtVer != null;
+
+                // It is possible that 'get' could load more recent value.
+                if (!((GridNearCacheEntry)this).recordDhtVersion(dhtVer))
+                    return new GridCacheUpdateTxResult(false, null);
+            }
+
             assert tx == null || (!tx.local() && tx.onePhaseCommit()) || 
tx.ownsLock(this) :
                 "Transaction does not own lock for update [entry=" + this + ", 
tx=" + tx + ']';
 
@@ -1169,8 +1221,9 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         GridDrType drType,
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
-        String taskName
-    ) throws IgniteCheckedException, GridCacheEntryRemovedException {
+        String taskName,
+        @Nullable GridCacheVersion dhtVer
+        ) throws IgniteCheckedException, GridCacheEntryRemovedException {
         assert cctx.transactional();
 
         CacheObject old;
@@ -1194,6 +1247,14 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         synchronized (this) {
             checkObsolete();
 
+            if (isNear()) {
+                assert dhtVer != null;
+
+                // It is possible that 'get' could load more recent value.
+                if (!((GridNearCacheEntry)this).recordDhtVersion(dhtVer))
+                    return new GridCacheUpdateTxResult(false, null);
+            }
+
             assert tx == null || (!tx.local() && tx.onePhaseCommit()) || 
tx.ownsLock(this) :
                     "Transaction does not own lock for remove[entry=" + this + 
", tx=" + tx + ']';
 
@@ -2549,6 +2610,13 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
     }
 
     /**
+     * @return {@code True} if this entry should not be evicted from cache.
+     */
+    protected boolean evictionDisabled() {
+        return false;
+    }
+
+    /**
      * <p>
      * Note that {@link #onMarkedObsolete()} should always be called after 
this method
      * returns {@code true}.
@@ -2560,6 +2628,12 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
     protected final boolean markObsolete0(GridCacheVersion ver, boolean clear) 
{
         assert Thread.holdsLock(this);
 
+        if (evictionDisabled()) {
+            assert !obsolete() : this;
+
+            return false;
+        }
+
         GridCacheVersion obsoleteVer = obsoleteVersionExtras();
 
         if (ver != null) {
@@ -2790,6 +2864,25 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         return ver;
     }
 
+    /** {@inheritDoc} */
+    @Override public synchronized boolean 
checkSerializableReadVersion(GridCacheVersion serReadVer)
+        throws GridCacheEntryRemovedException {
+        checkObsolete();
+
+        if (!serReadVer.equals(ver)) {
+            boolean empty = isStartVersion() || deletedUnlocked();
+
+            if (serReadVer.equals(IgniteTxEntry.SER_READ_EMPTY_ENTRY_VER))
+                return empty;
+            else if (serReadVer.equals(IgniteTxEntry.SER_READ_NOT_EMPTY_VER))
+                return !empty;
+
+            return false;
+        }
+
+        return true;
+    }
+
     /**
      * Gets hash value for the entry key.
      *
@@ -3115,16 +3208,22 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
     }
 
     /** {@inheritDoc} */
-    @Override public synchronized boolean versionedValue(CacheObject val,
+    @Override public synchronized GridCacheVersion versionedValue(CacheObject 
val,
         GridCacheVersion curVer,
         GridCacheVersion newVer)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
+
         checkObsolete();
 
         if (curVer == null || curVer.equals(ver)) {
             if (val != this.val) {
+                GridCacheMvcc mvcc = mvccExtras();
+
+                if (mvcc != null && !mvcc.isEmpty())
+                    return null;
+
                 if (newVer == null)
-                    newVer = nextVersion();
+                    newVer = cctx.versions().next();
 
                 CacheObject old = rawGetOrUnmarshalUnlocked(false);
 
@@ -3144,12 +3243,12 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
 
                 // Version does not change for load ops.
                 update(val, expTime, ttl, newVer);
-            }
 
-            return true;
+                return newVer;
+            }
         }
 
-        return false;
+        return null;
     }
 
     /**
@@ -3683,6 +3782,12 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
         try {
             if (F.isEmptyOrNulls(filter)) {
                 synchronized (this) {
+                    if (evictionDisabled()) {
+                        assert !obsolete();
+
+                        return false;
+                    }
+
                     if (obsoleteVersionExtras() != null)
                         return true;
 
@@ -3727,6 +3832,12 @@ public abstract class GridCacheMapEntry extends 
GridMetadataAwareAdapter impleme
                         return false;
 
                     synchronized (this) {
+                        if (evictionDisabled()) {
+                            assert !obsolete();
+
+                            return false;
+                        }
+
                         if (obsoleteVersionExtras() != null)
                             return true;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/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..12583ad 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();
 
-                    if (c.owner()) {
+                        assert candOrder != null : cand;
+
+                        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,
@@ -470,6 +531,7 @@ public final class GridCacheMvcc {
      * @param threadId Thread ID.
      * @param ver Lock version.
      * @param timeout Lock acquisition timeout.
+     * @param serOrder Version for serializable transactions ordering.
      * @param reenter Reentry flag ({@code true} if reentry is allowed).
      * @param tx Transaction flag.
      * @param implicitSingle Implicit flag.
@@ -484,6 +546,7 @@ public final class GridCacheMvcc {
         long threadId,
         GridCacheVersion ver,
         long timeout,
+        @Nullable GridCacheVersion serOrder,
         boolean reenter,
         boolean tx,
         boolean implicitSingle,
@@ -528,12 +591,23 @@ public final class GridCacheMvcc {
             tx,
             implicitSingle,
             /*near-local*/false,
-            dhtLoc
+            dhtLoc,
+            serOrder
         );
 
-        cctx.mvcc().addLocal(cand);
+        if (serOrder == null) {
+            cctx.mvcc().addLocal(cand);
 
-        add0(cand);
+            boolean add = add0(cand);
+
+            assert add : cand;
+        }
+        else {
+            if (!add0(cand))
+                return null;
+
+            cctx.mvcc().addLocal(cand);
+        }
 
         return cand;
     }
@@ -575,7 +649,8 @@ public final class GridCacheMvcc {
             tx,
             implicitSingle,
             nearLoc,
-            false
+            false,
+            null
         );
 
         addRemote(cand);
@@ -596,11 +671,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);
 
@@ -855,9 +947,22 @@ public final class GridCacheMvcc {
         }
 
         if (locs != null) {
+            boolean first = true;
+
             for (ListIterator<GridCacheMvccCandidate> it = 
locs.listIterator(); it.hasNext(); ) {
                 GridCacheMvccCandidate cand = it.next();
 
+                if (first && cand.serializable()) {
+                    if (cand.owner() || !cand.ready())
+                        return;
+
+                    cand.setOwner();
+
+                    return;
+                }
+
+                first = false;
+
                 if (cand.owner())
                     return;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/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/9d7543a8/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index 578ad6c..5bf4ac7 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -139,7 +139,6 @@ import static 
org.apache.ignite.internal.IgniteComponentType.JTA;
 import static 
org.apache.ignite.internal.IgniteNodeAttributes.ATTR_CONSISTENCY_CHECK_SKIPPED;
 import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_TX_CONFIG;
 import static 
org.apache.ignite.internal.processors.cache.GridCacheUtils.isNearEnabled;
-import static org.apache.ignite.transactions.TransactionIsolation.SERIALIZABLE;
 
 /**
  * Cache processor.
@@ -398,15 +397,6 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
             throw new IgniteCheckedException("Cannot start cache in PRIVATE or 
ISOLATED deployment mode: " +
                 ctx.config().getDeploymentMode());
 
-        if (!c.getTransactionConfiguration().isTxSerializableEnabled() &&
-            c.getTransactionConfiguration().getDefaultTxIsolation() == 
SERIALIZABLE)
-            U.warn(log,
-                "Serializable transactions are disabled while default 
transaction isolation is SERIALIZABLE " +
-                    "(most likely misconfiguration - either update 
'isTxSerializableEnabled' or " +
-                    "'defaultTxIsolationLevel' properties) for cache: " + 
U.maskName(cc.getName()),
-                "Serializable transactions are disabled while default 
transaction isolation is SERIALIZABLE " +
-                    "for cache: " + U.maskName(cc.getName()));
-
         if (cc.isWriteBehindEnabled()) {
             if (cfgStore == null)
                 throw new IgniteCheckedException("Cannot enable write-behind 
(writer or store is not provided) " +
@@ -619,9 +609,6 @@ public class GridCacheProcessor extends 
GridProcessorAdapter {
         sharedCtx = createSharedContext(ctx, CU.startStoreSessionListeners(ctx,
             ctx.config().getCacheStoreSessionListenerFactories()));
 
-        ctx.performance().add("Disable serializable transactions (set 
'txSerializableEnabled' to false)",
-            
!ctx.config().getTransactionConfiguration().isTxSerializableEnabled());
-
         for (int i = 0; i < cfgs.length; i++) {
             if (ctx.config().isDaemon() && 
!CU.isMarshallerCache(cfgs[i].getName()))
                 continue;

http://git-wip-us.apache.org/repos/asf/ignite/blob/9d7543a8/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 d4f0d6c..a138d30 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
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
@@ -742,7 +743,10 @@ public class GridDistributedCacheEntry extends 
GridCacheMapEntry {
     }
 
     /** {@inheritDoc} */
-    @Override public boolean tmLock(IgniteInternalTx tx, long timeout)
+    @Override public boolean tmLock(IgniteInternalTx tx,
+        long timeout,
+        @Nullable GridCacheVersion serOrder,
+        GridCacheVersion serReadVer)
         throws GridCacheEntryRemovedException, 
GridDistributedLockCancelledException {
         if (tx.local())
             // Null is returned if timeout is negative and there is other lock 
owner.
@@ -751,8 +755,8 @@ public class GridDistributedCacheEntry extends 
GridCacheMapEntry {
                 tx.xidVersion(),
                 tx.topologyVersion(),
                 timeout,
-                false,
-                true,
+                /*reenter*/false,
+                /*tx*/true,
                 tx.implicitSingle()) != null;
 
         try {
@@ -762,7 +766,7 @@ public class GridDistributedCacheEntry extends 
GridCacheMapEntry {
                 tx.threadId(),
                 tx.xidVersion(),
                 tx.timeout(),
-                true,
+                /*tx*/true,
                 tx.implicitSingle(),
                 tx.ownedVersion(txKey())
             );

Reply via email to