Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-qry 59204a517 -> 73b5ef6b0


Ignite - Porting GG-9476 to Ignite branch.


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

Branch: refs/heads/ignite-qry
Commit: d8f93450062e83e19bb8c83357a2cb7d6c85f170
Parents: 06fbf57
Author: Alexey Goncharuk <agoncha...@gridgain.com>
Authored: Tue Dec 9 16:23:11 2014 -0800
Committer: Alexey Goncharuk <agoncha...@gridgain.com>
Committed: Tue Dec 9 16:23:11 2014 -0800

----------------------------------------------------------------------
 .../processors/cache/GridCacheMapEntry.java     |  40 ++++--
 .../processors/cache/GridCacheSwapManager.java  |  14 +-
 .../distributed/dht/GridDhtLocalPartition.java  |  32 +++++
 .../distributed/dht/GridDhtLockFuture.java      |   3 +
 .../distributed/dht/GridDhtLockResponse.java    |  12 ++
 .../dht/GridDhtTransactionalCacheAdapter.java   |   2 +
 .../colocated/GridDhtDetachedCacheEntry.java    |   5 +
 .../dht/preloader/GridDhtPreloader.java         |  10 +-
 .../cache/GridCacheOffheapUpdateSelfTest.java   | 130 +++++++++++++++++++
 .../bamboo/GridDataGridTestSuite.java           |   1 +
 10 files changed, 228 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java
index 8427dbe..c2846f2 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheMapEntry.java
@@ -205,6 +205,8 @@ public abstract class GridCacheMapEntry<K, V> implements 
GridCacheEntryEx<K, V>
         if (!isOffHeapValuesOnly()) {
             this.val = val;
             this.valBytes = isStoreValueBytes() ? valBytes : null;
+
+            valPtr = 0;
         }
         else {
             try {
@@ -271,6 +273,14 @@ public abstract class GridCacheMapEntry<K, V> implements 
GridCacheEntryEx<K, V>
         if (!isOffHeapValuesOnly()) {
             if (valBytes != null)
                 return GridCacheValueBytes.marshaled(valBytes);
+
+            try {
+                if (valPtr != 0 && cctx.offheapTiered())
+                    return offheapValueBytes();
+            }
+            catch (GridException e) {
+                throw new GridRuntimeException(e);
+            }
         }
         else {
             if (valPtr != 0) {
@@ -509,6 +519,10 @@ public abstract class GridCacheMapEntry<K, V> implements 
GridCacheEntryEx<K, V>
                         // Set unswapped value.
                         update(val, e.valueBytes(), e.expireTime(), e.ttl(), 
e.version());
 
+                        // Must update valPtr again since update() will reset 
it.
+                        if (cctx.offheapTiered() && e.offheapPointer() > 0)
+                            valPtr = e.offheapPointer();
+
                         return val;
                     }
                     else
@@ -524,16 +538,15 @@ public abstract class GridCacheMapEntry<K, V> implements 
GridCacheEntryEx<K, V>
      * @throws GridException If failed.
      */
     private void swap() throws GridException {
-        if (cctx.isSwapOrOffheapEnabled() && !deletedUnlocked() && 
hasValueUnlocked()) {
+        if (cctx.isSwapOrOffheapEnabled() && !deletedUnlocked() && 
hasValueUnlocked() && !detached()) {
             assert Thread.holdsLock(this);
 
             long expireTime = expireTimeExtras();
 
             if (expireTime > 0 && U.currentTimeMillis() >= expireTime) { // 
Don't swap entry if it's expired.
-                if (cctx.offheapTiered() && valPtr > 0) {
-                    boolean rmv = cctx.swap().removeOffheap(key, 
getOrMarshalKeyBytes());
-
-                    assert rmv;
+                // Entry might have been updated.
+                if (cctx.offheapTiered()) {
+                    cctx.swap().removeOffheap(key, getOrMarshalKeyBytes());
 
                     valPtr = 0;
                 }
@@ -939,9 +952,14 @@ public abstract class GridCacheMapEntry<K, V> implements 
GridCacheEntryEx<K, V>
                         // Update indexes before actual write to entry.
                         updateIndex(ret, null, expTime, nextVer, prevVal);
 
+                    boolean hadValPtr = valPtr != 0;
+
                     // Don't change version for read-through.
                     update(ret, null, expTime, ttl, nextVer);
 
+                    if (hadValPtr && cctx.offheapTiered())
+                        cctx.swap().removeOffheap(key, getOrMarshalKeyBytes());
+
                     if (cctx.deferredDelete() && deletedUnlocked() && 
!isInternal() && !detached())
                         deletedUnlocked(false);
                 }
@@ -1305,14 +1323,14 @@ public abstract class GridCacheMapEntry<K, V> 
implements GridCacheEntryEx<K, V>
                 // can be updated without actually holding entry lock.
                 clearIndex(old);
 
+                boolean hadValPtr = valPtr != 0;
+
                 update(null, null, 0, 0, newVer);
 
-                if (cctx.offheapTiered() && valPtr > 0) {
+                if (cctx.offheapTiered() && hadValPtr) {
                     boolean rmv = cctx.swap().removeOffheap(key, 
getOrMarshalKeyBytes());
 
                     assert rmv;
-
-                    valPtr = 0;
                 }
 
                 if (cctx.deferredDelete() && !detached() && !isInternal()) {
@@ -1921,15 +1939,15 @@ public abstract class GridCacheMapEntry<K, V> 
implements GridCacheEntryEx<K, V>
 
                 enqueueVer = newVer;
 
+                boolean hasValPtr = valPtr != 0;
+
                 // Clear value on backup. Entry will be removed from cache 
when it got evicted from queue.
                 update(null, null, 0, 0, newVer);
 
-                if (cctx.offheapTiered() && valPtr != 0) {
+                if (cctx.offheapTiered() && hasValPtr) {
                     boolean rmv = cctx.swap().removeOffheap(key, 
getOrMarshalKeyBytes());
 
                     assert rmv;
-
-                    valPtr = 0;
                 }
 
                 clearReaders();

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapManager.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapManager.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapManager.java
index 4369213..abf8cb6 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapManager.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/GridCacheSwapManager.java
@@ -580,7 +580,7 @@ public class GridCacheSwapManager<K, V> extends 
GridCacheManagerAdapter<K, V> {
      * @return Read value.
      * @throws GridException If read failed.
      */
-    @Nullable GridCacheSwapEntry<V> read(GridCacheMapEntry<K, V> entry, 
boolean locked) throws GridException {
+    @Nullable GridCacheSwapEntry<V> read(GridCacheEntryEx<K, V> entry, boolean 
locked) throws GridException {
         if (!offheapEnabled && !swapEnabled)
             return null;
 
@@ -592,7 +592,7 @@ public class GridCacheSwapManager<K, V> extends 
GridCacheManagerAdapter<K, V> {
      * @return Read value address.
      * @throws GridException If read failed.
      */
-    @Nullable GridCacheSwapEntry<V> readOffheapPointer(GridCacheMapEntry<K, V> 
entry) throws GridException {
+    @Nullable GridCacheSwapEntry<V> readOffheapPointer(GridCacheEntryEx<K, V> 
entry) throws GridException {
         if (!offheapEnabled)
             return null;
 
@@ -631,7 +631,7 @@ public class GridCacheSwapManager<K, V> extends 
GridCacheManagerAdapter<K, V> {
      * @return Read value.
      * @throws GridException If read failed.
      */
-    @Nullable GridCacheSwapEntry<V> readAndRemove(GridCacheMapEntry<K, V> 
entry) throws GridException {
+    @Nullable GridCacheSwapEntry<V> readAndRemove(GridCacheEntryEx<K, V> 
entry) throws GridException {
         if (!offheapEnabled && !swapEnabled)
             return null;
 
@@ -651,7 +651,7 @@ public class GridCacheSwapManager<K, V> extends 
GridCacheManagerAdapter<K, V> {
 
         final GridCacheQueryManager<K, V> qryMgr = cctx.queries();
 
-        ArrayList<K> keysList = new ArrayList<>(keys);
+        Collection<K> keysList = new ArrayList<>(keys);
         final Collection<GridCacheBatchSwapEntry<K, V>> res = new 
ArrayList<>(keys.size());
 
         // First try removing from offheap.
@@ -831,7 +831,7 @@ public class GridCacheSwapManager<K, V> extends 
GridCacheManagerAdapter<K, V> {
      * @param keyBytes Key bytes.
      * @throws GridException If failed.
      */
-    void remove(final K key, byte[] keyBytes) throws GridException {
+    public void remove(final K key, byte[] keyBytes) throws GridException {
         if (!offheapEnabled && !swapEnabled)
             return;
 
@@ -1091,10 +1091,6 @@ public class GridCacheSwapManager<K, V> extends 
GridCacheManagerAdapter<K, V> {
                 return !done;
             }
 
-            @Override protected void onRemove() {
-                throw new UnsupportedOperationException();
-            }
-
             @Override protected void onClose() throws GridException {
                 if (it != null)
                     it.close();

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLocalPartition.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLocalPartition.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLocalPartition.java
index 62f18ef..b84eaf38 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLocalPartition.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLocalPartition.java
@@ -16,6 +16,7 @@ import org.gridgain.grid.kernal.processors.cache.*;
 import org.gridgain.grid.kernal.processors.cache.distributed.dht.preloader.*;
 import org.gridgain.grid.util.*;
 import org.gridgain.grid.util.future.*;
+import org.gridgain.grid.util.lang.*;
 import org.gridgain.grid.util.tostring.*;
 import org.gridgain.grid.util.typedef.*;
 import org.gridgain.grid.util.typedef.internal.*;
@@ -414,6 +415,8 @@ public class GridDhtLocalPartition<K, V> implements 
Comparable<GridDhtLocalParti
             if (log.isDebugEnabled())
                 log.debug("Evicted partition: " + this);
 
+            clearSwap();
+
             if (cctx.isDrEnabled())
                 cctx.dr().partitionEvicted(id);
 
@@ -448,6 +451,8 @@ public class GridDhtLocalPartition<K, V> implements 
Comparable<GridDhtLocalParti
             if (log.isDebugEnabled())
                 log.debug("Evicted partition: " + this);
 
+            clearSwap();
+
             if (cctx.isDrEnabled())
                 cctx.dr().partitionEvicted(id);
 
@@ -466,6 +471,33 @@ public class GridDhtLocalPartition<K, V> implements 
Comparable<GridDhtLocalParti
     }
 
     /**
+     * Clears swap entries for evicted partition.
+     */
+    private void clearSwap() {
+        assert state() == EVICTED;
+
+        try {
+            GridCloseableIterator<Map.Entry<byte[], GridCacheSwapEntry<V>>> it 
= cctx.swap().iterator(id, false);
+
+            if (it != null) {
+                // We can safely remove these values because no entries will 
be created for evicted partition.
+                while (it.hasNext()) {
+                    Map.Entry<byte[], GridCacheSwapEntry<V>> entry = it.next();
+
+                    byte[] keyBytes = entry.getKey();
+
+                    K key = cctx.marshaller().unmarshal(keyBytes, 
cctx.deploy().globalLoader());
+
+                    cctx.swap().remove(key, keyBytes);
+                }
+            }
+        }
+        catch (GridException e) {
+            U.error(log, "Failed to clear swap for evicted partition: " + 
this, e);
+        }
+    }
+
+    /**
      *
      */
     void onUnlock() {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockFuture.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockFuture.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockFuture.java
index 3662a42..3c47ffe 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockFuture.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockFuture.java
@@ -831,6 +831,9 @@ public final class GridDhtLockFuture<K, V> extends 
GridCompoundIdentityFuture<Bo
                         for (ListIterator<GridDhtCacheEntry<K, V>> it = 
dhtMapping.listIterator(); it.hasNext();) {
                             GridDhtCacheEntry<K, V> e = it.next();
 
+                            // Must unswap entry so that isNewLocked returns 
correct value.
+                            e.unswap(true, false);
+
                             boolean invalidateRdr = e.readerId(n.id()) != null;
 
                             req.addDhtKey(

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockResponse.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockResponse.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockResponse.java
index f13f6cf..f7105c0 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockResponse.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtLockResponse.java
@@ -164,6 +164,12 @@ public class GridDhtLockResponse<K, V> extends 
GridDistributedLockResponse<K, V>
 
         if (preloadEntriesBytes == null && preloadEntries != null)
             preloadEntriesBytes = marshalCollection(preloadEntries, ctx);
+
+        if (preloadEntriesBytes == null && preloadEntries != null) {
+            marshalInfos(preloadEntries, ctx);
+
+            preloadEntriesBytes = marshalCollection(preloadEntries, ctx);
+        }
     }
 
     /** {@inheritDoc} */
@@ -175,6 +181,12 @@ public class GridDhtLockResponse<K, V> extends 
GridDistributedLockResponse<K, V>
 
         if (preloadEntries == null && preloadEntriesBytes != null)
             preloadEntries = unmarshalCollection(preloadEntriesBytes, ctx, 
ldr);
+
+        if (preloadEntries == null && preloadEntriesBytes != null) {
+            preloadEntries = unmarshalCollection(preloadEntriesBytes, ctx, 
ldr);
+
+            unmarshalInfos(preloadEntries, ctx.cacheContext(cacheId), ldr);
+        }
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
index 7c76203..c65cc45 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
@@ -238,6 +238,8 @@ public abstract class GridDhtTransactionalCacheAdapter<K, 
V> extends GridDhtCach
 
                         // Get entry info after candidate is added.
                         if (req.needPreloadKey(i)) {
+                            entry.unswap();
+
                             GridCacheEntryInfo<K, V> info = entry.info();
 
                             if (info != null && !info.isNew() && 
!info.isDeleted())

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/colocated/GridDhtDetachedCacheEntry.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/colocated/GridDhtDetachedCacheEntry.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/colocated/GridDhtDetachedCacheEntry.java
index 323452b..1abd568 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/colocated/GridDhtDetachedCacheEntry.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/colocated/GridDhtDetachedCacheEntry.java
@@ -55,6 +55,11 @@ public class GridDhtDetachedCacheEntry<K, V> extends 
GridDistributedCacheEntry<K
     }
 
     /** {@inheritDoc} */
+    @Nullable @Override public V unswap(boolean ignoreFlags, boolean needVal) 
throws GridException {
+        return null;
+    }
+
+    /** {@inheritDoc} */
     @Override protected void value(@Nullable V val, @Nullable byte[] valBytes) 
{
         this.val = val;
         this.valBytes = valBytes;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
index ce8cd2f..bb86d18 100644
--- 
a/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
+++ 
b/modules/core/src/main/java/org/gridgain/grid/kernal/processors/cache/distributed/dht/preloader/GridDhtPreloader.java
@@ -344,7 +344,15 @@ public class GridDhtPreloader<K, V> extends 
GridCachePreloaderAdapter<K, V> {
                 if (locPart == null && !top.owners(p).contains(loc))
                     res.addMissed(k);
 
-                GridCacheEntryEx<K, V> entry = cctx.dht().peekEx(k);
+                GridCacheEntryEx<K, V> entry;
+
+                if (cctx.isSwapOrOffheapEnabled()) {
+                    entry = cctx.dht().entryEx(k, true);
+
+                    entry.unswap();
+                }
+                else
+                    entry = cctx.dht().peekEx(k);
 
                 // If entry is null, then local partition may have left
                 // after the message was received. In that case, we are

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffheapUpdateSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffheapUpdateSelfTest.java
 
b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffheapUpdateSelfTest.java
new file mode 100644
index 0000000..d69a373
--- /dev/null
+++ 
b/modules/core/src/test/java/org/gridgain/grid/kernal/processors/cache/GridCacheOffheapUpdateSelfTest.java
@@ -0,0 +1,130 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.gridgain.grid.kernal.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.configuration.*;
+import org.gridgain.grid.cache.*;
+import org.gridgain.testframework.junits.common.*;
+
+import static org.gridgain.grid.cache.GridCacheTxConcurrency.*;
+import static org.gridgain.grid.cache.GridCacheTxIsolation.*;
+
+/**
+ * Check for specific support issue.
+ */
+public class GridCacheOffheapUpdateSelfTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setPeerClassLoadingEnabled(false);
+
+        GridCacheConfiguration ccfg = new GridCacheConfiguration();
+
+        ccfg.setCacheMode(GridCacheMode.PARTITIONED);
+        ccfg.setDistributionMode(GridCacheDistributionMode.PARTITIONED_ONLY);
+        ccfg.setAtomicityMode(GridCacheAtomicityMode.TRANSACTIONAL);
+        ccfg.setOffHeapMaxMemory(0);
+        ccfg.setMemoryMode(GridCacheMemoryMode.OFFHEAP_TIERED);
+
+        cfg.setCacheConfiguration(ccfg);
+
+        return cfg;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testUpdateInPessimisticTxOnRemoteNode() throws Exception {
+        try {
+            Ignite ignite = startGrids(2);
+
+            GridCache<Object, Object> rmtCache = ignite.cache(null);
+
+            int key = 0;
+
+            while (!rmtCache.affinity().isPrimary(grid(1).localNode(), key))
+                key++;
+
+            GridCache<Object, Object> locCache = grid(1).cache(null);
+
+            try (GridCacheTx tx = locCache.txStart(PESSIMISTIC, 
REPEATABLE_READ)) {
+                locCache.putxIfAbsent(key, 0);
+
+                tx.commit();
+            }
+
+            try (GridCacheTx tx = rmtCache.txStart(PESSIMISTIC, 
REPEATABLE_READ)) {
+                assertEquals(0, rmtCache.get(key));
+
+                rmtCache.putx(key, 1);
+
+                tx.commit();
+            }
+
+            try (GridCacheTx tx = rmtCache.txStart(PESSIMISTIC, 
REPEATABLE_READ)) {
+                assertEquals(1, rmtCache.get(key));
+
+                rmtCache.putx(key, 2);
+
+                tx.commit();
+            }
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testReadEvictedPartition() throws Exception {
+        try {
+            Ignite grid = startGrid(0);
+
+            GridCache<Object, Object> cache = grid.cache(null);
+
+            for (int i = 0; i < 30; i++)
+                cache.put(i, 0);
+
+            startGrid(1);
+
+            awaitPartitionMapExchange();
+
+            for (int i = 0; i < 30; i++)
+                grid(1).cache(null).put(i, 10);
+
+            // Find a key that does not belong to started node anymore.
+            int key = 0;
+
+            ClusterNode locNode = grid.cluster().localNode();
+
+            for (;key < 30; key++) {
+                if (!cache.affinity().isPrimary(locNode, key) && 
!cache.affinity().isBackup(locNode, key))
+                    break;
+            }
+
+            assertEquals(10, cache.get(key));
+
+            try (GridCacheTx ignored = cache.txStart(OPTIMISTIC, 
REPEATABLE_READ)) {
+                assertEquals(10, cache.get(key));
+            }
+
+            try (GridCacheTx ignored = cache.txStart(PESSIMISTIC, 
READ_COMMITTED)) {
+                assertEquals(10, cache.get(key));
+            }
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/d8f93450/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java
 
b/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java
index 49f5c38..3f53e58 100644
--- 
a/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java
+++ 
b/modules/core/src/test/java/org/gridgain/testsuites/bamboo/GridDataGridTestSuite.java
@@ -187,6 +187,7 @@ public class GridDataGridTestSuite extends TestSuite {
         suite.addTest(new 
TestSuite(GridCacheAtomicExpiredEntriesPreloadSelfTest.class));
 
         suite.addTest(new 
TestSuite(GridCacheReturnValueTransferSelfTest.class));
+        suite.addTest(new TestSuite(GridCacheOffheapUpdateSelfTest.class));
 
         // TODO: GG-7242, GG-7243: Enabled when fixed.
 //        suite.addTest(new TestSuite(GridCacheDhtRemoveFailureTest.class));

Reply via email to