http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicNearEnabledSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicNearEnabledSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicNearEnabledSelfTest.java
new file mode 100644
index 0000000..928d7b7
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicNearEnabledSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.cache.*;
+
+import static org.apache.ignite.cache.GridCacheAtomicityMode.*;
+import static org.apache.ignite.cache.GridCacheDistributionMode.*;
+
+/**
+ *
+ */
+public class GridCacheMultinodeUpdateAtomicNearEnabledSelfTest extends 
GridCacheMultinodeUpdateAbstractSelfTest {
+    /** {@inheritDoc} */
+    @SuppressWarnings("RedundantMethodOverride")
+    @Override protected GridCacheDistributionMode distributionMode() {
+        return NEAR_PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected GridCacheAtomicityMode atomicityMode() {
+        return ATOMIC;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicSelfTest.java
new file mode 100644
index 0000000..068dec0
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateAtomicSelfTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.cache.*;
+
+import static org.apache.ignite.cache.GridCacheAtomicityMode.*;
+import static org.apache.ignite.cache.GridCacheDistributionMode.*;
+
+/**
+ *
+ */
+public class GridCacheMultinodeUpdateAtomicSelfTest extends 
GridCacheMultinodeUpdateAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected GridCacheDistributionMode distributionMode() {
+        return PARTITIONED_ONLY;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected GridCacheAtomicityMode atomicityMode() {
+        return ATOMIC;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
new file mode 100644
index 0000000..a5e816f
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.cache.*;
+
+/**
+ *
+ */
+public class GridCacheMultinodeUpdateNearEnabledNoBackupsSelfTest extends 
GridCacheMultinodeUpdateNearEnabledSelfTest {
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return 2;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheConfiguration cacheConfiguration(String gridName) 
throws Exception {
+        CacheConfiguration ccfg = super.cacheConfiguration(gridName);
+
+        ccfg.setBackups(0);
+
+        return ccfg;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
new file mode 100644
index 0000000..3ff7d42
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateNearEnabledSelfTest.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.cache.*;
+
+import static org.apache.ignite.cache.GridCacheAtomicityMode.*;
+import static org.apache.ignite.cache.GridCacheDistributionMode.*;
+
+/**
+ *
+ */
+public class GridCacheMultinodeUpdateNearEnabledSelfTest extends 
GridCacheMultinodeUpdateAbstractSelfTest {
+    /** {@inheritDoc} */
+    @SuppressWarnings("RedundantMethodOverride")
+    @Override protected GridCacheDistributionMode distributionMode() {
+        return NEAR_PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("RedundantMethodOverride")
+    @Override protected GridCacheAtomicityMode atomicityMode() {
+        return TRANSACTIONAL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateSelfTest.java
new file mode 100644
index 0000000..483b4f9
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMultinodeUpdateSelfTest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.cache.*;
+
+import static org.apache.ignite.cache.GridCacheAtomicityMode.*;
+import static org.apache.ignite.cache.GridCacheDistributionMode.*;
+
+/**
+ *
+ */
+public class GridCacheMultinodeUpdateSelfTest extends 
GridCacheMultinodeUpdateAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected GridCacheDistributionMode distributionMode() {
+        return PARTITIONED_ONLY;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("RedundantMethodOverride")
+    @Override protected GridCacheAtomicityMode atomicityMode() {
+        return TRANSACTIONAL;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManagerSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManagerSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManagerSelfTest.java
new file mode 100644
index 0000000..887ea17
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManagerSelfTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cache.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.processors.cache.*;
+import org.apache.ignite.transactions.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.apache.ignite.testframework.junits.common.*;
+
+import static org.apache.ignite.cache.GridCacheAtomicityMode.*;
+import static org.apache.ignite.cache.GridCacheMode.*;
+
+/**
+ * Tests for {@link GridCacheMvccManager}.
+ */
+public class GridCacheMvccManagerSelfTest extends GridCommonAbstractTest {
+    /** VM ip finder for TCP discovery. */
+    private static TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
+
+    /** Cache mode. */
+    private GridCacheMode mode;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) 
throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setMaxMissedHeartbeats(Integer.MAX_VALUE);
+        disco.setIpFinder(ipFinder);
+
+        cfg.setDiscoverySpi(disco);
+        cfg.setCacheConfiguration(cacheConfiguration());
+
+        return cfg;
+    }
+
+    /** @return Cache configuration. */
+    protected CacheConfiguration cacheConfiguration() {
+        CacheConfiguration cfg = defaultCacheConfiguration();
+
+        cfg.setCacheMode(mode);
+        
cfg.setWriteSynchronizationMode(GridCacheWriteSynchronizationMode.FULL_SYNC);
+        cfg.setAtomicityMode(TRANSACTIONAL);
+
+        return cfg;
+    }
+
+    /** @throws Exception If failed. */
+    public void testLocalCache() throws Exception {
+        mode = LOCAL;
+
+        testCandidates(1);
+    }
+
+    /** @throws Exception If failed. */
+    public void testReplicatedCache() throws Exception {
+        mode = REPLICATED;
+
+        testCandidates(3);
+    }
+
+    /** @throws Exception If failed. */
+    public void testPartitionedCache() throws Exception {
+        mode = PARTITIONED;
+
+        testCandidates(3);
+    }
+
+    /**
+     * @param gridCnt Grid count.
+     * @throws Exception If failed.
+     */
+    private void testCandidates(int gridCnt) throws Exception {
+        try {
+            Ignite ignite = startGridsMultiThreaded(gridCnt);
+
+            GridCache<Integer, Integer> cache = ignite.cache(null);
+
+            IgniteTx tx = cache.txStart();
+
+            cache.put(1, 1);
+
+            tx.commit();
+
+            for (int i = 0; i < gridCnt; i++) {
+                assert 
((GridKernal)grid(i)).internalCache().context().mvcc().localCandidates().isEmpty();
+                assert 
((GridKernal)grid(i)).internalCache().context().mvcc().remoteCandidates().isEmpty();
+            }
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/968c3cf8/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
new file mode 100644
index 0000000..b21b642
--- /dev/null
+++ 
b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheMvccPartitionedSelfTest.java
@@ -0,0 +1,688 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import org.apache.ignite.cache.*;
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.processors.cache.*;
+import org.apache.ignite.spi.discovery.tcp.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
+import org.apache.ignite.testframework.junits.common.*;
+
+import java.util.*;
+
+import static org.apache.ignite.cache.GridCacheAtomicityMode.*;
+import static org.apache.ignite.cache.GridCacheMode.*;
+import static org.apache.ignite.cache.GridCacheDistributionMode.*;
+
+/**
+ * Test cases for multi-threaded tests in partitioned cache.
+ */
+public class GridCacheMvccPartitionedSelfTest extends GridCommonAbstractTest {
+    /** Grid. */
+    private GridKernal grid;
+
+    /** VM ip finder for TCP discovery. */
+    private static TcpDiscoveryIpFinder ipFinder = new 
TcpDiscoveryVmIpFinder(true);
+
+    /**
+     *
+     */
+    public GridCacheMvccPartitionedSelfTest() {
+        super(true /*start grid. */);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        grid = (GridKernal)grid();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        grid = null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration() throws 
Exception {
+        IgniteConfiguration cfg = super.getConfiguration();
+
+        TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+        disco.setIpFinder(ipFinder);
+
+        cfg.setDiscoverySpi(disco);
+
+        CacheConfiguration cacheCfg = defaultCacheConfiguration();
+
+        cacheCfg.setCacheMode(PARTITIONED);
+        cacheCfg.setBackups(1);
+        cacheCfg.setAtomicityMode(TRANSACTIONAL);
+        cacheCfg.setDistributionMode(NEAR_PARTITIONED);
+
+        cfg.setCacheConfiguration(cacheCfg);
+
+        return cfg;
+    }
+
+    /**
+     * Tests remote candidates.
+     */
+    public void testNearLocalsWithPending() {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+
+        GridCacheMvccCandidate<String> c1 = entry.addRemote(node1, 1, ver1, 0, 
false, true);
+        GridCacheMvccCandidate<String> c2 = entry.addNearLocal(node1, 1, ver2, 
0, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(ver2, nearLocCands.iterator().next().version());
+
+        assertEquals(1, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        entry.readyNearLocal(ver2, ver2, empty(), empty(), 
Arrays.asList(ver1));
+
+        checkLocalOwner(c2, ver2, false);
+        checkRemote(c1, ver1, false, false);
+
+        assertNotNull(entry.anyOwner());
+        assertEquals(ver2, entry.anyOwner().version());
+    }
+
+    /**
+     * Tests remote candidates.
+     */
+    public void testNearLocalsWithCommitted() {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+
+        GridCacheMvccCandidate<String> c1 = entry.addNearLocal(node1, 1, ver1, 
0, true);
+        GridCacheMvccCandidate<String> c2 = entry.addRemote(node1, 1, ver2, 0, 
false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(ver1, nearLocCands.iterator().next().version());
+
+        assertEquals(1, rmtCands.size());
+        assertEquals(ver2, rmtCands.iterator().next().version());
+
+        entry.readyNearLocal(ver1, ver1, Arrays.asList(ver2), empty(), 
empty());
+
+        checkLocal(c1, ver1, true, false, false);
+        checkRemote(c2, ver2, true, false);
+
+        assertNull(entry.anyOwner());
+    }
+
+    /**
+     * Tests remote candidates.
+     */
+    public void testNearLocalsWithRolledback() {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+
+        GridCacheMvccCandidate<String> c1 = entry.addNearLocal(node1, 1, ver1, 
0, true);
+        GridCacheMvccCandidate<String> c2 = entry.addRemote(node1, 1, ver2, 0, 
false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(ver1, nearLocCands.iterator().next().version());
+
+        assertEquals(1, rmtCands.size());
+        assertEquals(ver2, rmtCands.iterator().next().version());
+
+        entry.readyNearLocal(ver1, ver1, empty(), Arrays.asList(ver2), 
empty());
+
+        checkLocal(c1, ver1, true, false, false);
+        checkRemote(c2, ver2, true, false);
+
+        assertNull(entry.anyOwner());
+    }
+
+    /**
+     * Tests remote candidates.
+     */
+    public void testNearLocals() {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+
+        GridCacheMvccCandidate<String> c1 = entry.addNearLocal(node1, 1, ver1, 
0, true);
+        GridCacheMvccCandidate<String> c2 = entry.addNearLocal(node1, 1, ver2, 
0, true);
+
+        entry.readyNearLocal(ver2, ver2,  empty(), empty(), empty());
+
+        checkLocalOwner(c2, ver2, false);
+        checkLocal(c1, ver1, false, false, false);
+
+        Collection<GridCacheMvccCandidate<String>> cands = 
entry.localCandidates();
+
+        assert cands.size() == 2;
+        assert cands.iterator().next().version().equals(ver2);
+
+        checkLocalOwner(c2, ver2, false);
+        checkLocal(c1, ver1, false, false, false);
+    }
+
+    /**
+     * Tests remote candidates.
+     */
+    public void testNearLocalsWithOwned() {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+
+        GridCacheMvccCandidate<String> c1 = entry.addRemote(node1, 1, ver1, 0, 
false, true);
+        GridCacheMvccCandidate<String> c2 = entry.addNearLocal(node1, 1, ver2, 
0, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(ver2, nearLocCands.iterator().next().version());
+
+        assertEquals(1, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        entry.orderOwned(ver1, ver2);
+
+        entry.readyNearLocal(ver2, ver2,  empty(), empty(), empty());
+
+        checkRemote(c1, ver1, false, false);
+
+        assertFalse(c1.owner());
+
+        checkLocalOwner(c2, ver2, false);
+
+        assertNotNull(entry.anyOwner());
+        assertEquals(ver2, entry.anyOwner().version());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testAddPendingRemote0() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver0 = version(0);
+        GridCacheVersion ver1 = version(1);
+
+        entry.addNearLocal(node1, 1, ver1, 0, true);
+
+        entry.readyNearLocal(ver1, ver1, empty(), empty(), 
Collections.<GridCacheVersion>singletonList(ver0));
+
+        entry.addRemote(node1, 1, ver0, 0, false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(ver1, nearLocCands.iterator().next().version());
+
+        assertEquals(1, rmtCands.size());
+        assertEquals(ver0, rmtCands.iterator().next().version());
+
+        assertNotNull(entry.anyOwner());
+        assertEquals(ver1, entry.anyOwner().version());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testAddPendingRemote1() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver0 = version(0);
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+        GridCacheVersion ver3 = version(3);
+
+        GridCacheMvccCandidate<String> c3 = entry.addNearLocal(node1, 1, ver3, 
0, true);
+
+        entry.readyNearLocal(ver3, ver3, empty(), empty(), Arrays.asList(ver0, 
ver1, ver2));
+
+        GridCacheMvccCandidate<String> c2 = entry.addRemote(node1, 1, ver2, 0, 
false, true);
+        GridCacheMvccCandidate<String> c1 = entry.addRemote(node1, 1, ver1, 0, 
false, true);
+        GridCacheMvccCandidate<String> c0 = entry.addRemote(node1, 1, ver0, 0, 
false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+
+        assert rmtCands.size() == 3;
+
+        // DHT remote candidates are not reordered and sorted.
+        GridCacheMvccCandidate[] candArr = new GridCacheMvccCandidate[] {c2, 
c1, c0};
+
+        rmtCands = entry.remoteMvccSnapshot();
+
+        int i = 0;
+
+        for (GridCacheMvccCandidate<String> cand : rmtCands) {
+            assert cand == candArr[i] : "Invalid candidate in position " + i;
+
+            i++;
+        }
+
+        assertEquals(c3, entry.anyOwner());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testAddPendingRemote2() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver0 = version(0);
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+        GridCacheVersion ver3 = version(3);
+
+        GridCacheMvccCandidate<String> c3 = entry.addNearLocal(node1, 1, ver3, 
0, true);
+        entry.addNearLocal(node1, 1, ver2, 0, true);
+
+        entry.readyNearLocal(ver3, ver3, empty(), empty(), Arrays.asList(ver0, 
ver1, ver2));
+
+        GridCacheMvccCandidate<String> c1 = entry.addRemote(node1, 1, ver1, 0, 
false, true);
+        GridCacheMvccCandidate<String> c0 = entry.addRemote(node1, 1, ver0, 0, 
false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+
+        assertEquals(2, rmtCands.size());
+
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(2, nearLocCands.size());
+
+        GridCacheMvccCandidate[] candArr = new GridCacheMvccCandidate[] {c1, 
c0};
+
+        int i = 0;
+
+        for (GridCacheMvccCandidate<String> cand : rmtCands) {
+            assert cand == candArr[i] : "Invalid candidate in position " + i;
+
+            i++;
+        }
+
+        assertEquals(c3, entry.anyOwner());
+    }
+
+    /**
+     * Tests salvageRemote method
+     */
+    public void testSalvageRemote() {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(1);
+        GridCacheVersion ver2 = version(2);
+        GridCacheVersion ver3 = version(3);
+        GridCacheVersion ver4 = version(4);
+        GridCacheVersion ver5 = version(5);
+        GridCacheVersion ver6 = version(6);
+
+        entry.addRemote(node1, 1, ver1, 0, false, true);
+        entry.addRemote(node1, 1, ver2, 0, false, true);
+        GridCacheMvccCandidate<String> c3 = entry.addNearLocal(node1, 1, ver3, 
0, true);
+        GridCacheMvccCandidate<String> c4 = entry.addRemote(node1, 1, ver4, 0, 
false, true);
+        entry.addRemote(node1, 1, ver5, 0, false, true);
+        entry.addRemote(node1, 1, ver6, 0, false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+
+        assertEquals(5, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(ver3, nearLocCands.iterator().next().version());
+
+        entry.salvageRemote(ver4);
+
+        rmtCands = entry.remoteMvccSnapshot();
+
+        boolean before = true;
+
+        for (GridCacheMvccCandidate<String> cand : rmtCands) {
+            if (cand == c4) {
+                before = false;
+
+                continue;
+            }
+
+            if (before && cand != c3) {
+                assertTrue(cand.owner());
+                assertTrue(cand.used());
+            }
+            else {
+                assertFalse(cand.owner());
+                assertFalse(cand.used());
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNearRemoteConsistentOrdering0() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(10);
+        GridCacheVersion nearVer2 = version(5);
+        GridCacheVersion ver2 = version(20);
+        GridCacheVersion ver3 = version(30);
+
+        entry.addRemote(node1, 1, ver1, 0, false, true);
+        entry.addNearLocal(node1, 1, nearVer2, 0, true);
+        entry.addRemote(node1, 1, ver3, 0, false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(nearVer2, nearLocCands.iterator().next().version());
+
+        assertEquals(2, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        entry.readyNearLocal(nearVer2, ver2, empty(), empty(), empty());
+
+        assertNull(entry.anyOwner());
+
+        rmtCands = entry.remoteMvccSnapshot();
+
+        assertEquals(ver1, rmtCands.iterator().next().version());
+        assertTrue(rmtCands.iterator().next().owner());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNearRemoteConsistentOrdering1() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(10);
+        GridCacheVersion nearVer2 = version(5);
+        GridCacheVersion ver2 = version(20);
+        GridCacheVersion ver3 = version(30);
+
+        entry.addRemote(node1, 1, ver1, 0, false, true);
+        entry.addNearLocal(node1, 1, nearVer2, 0, true);
+        entry.addRemote(node1, 1, ver3, 0, false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(nearVer2, nearLocCands.iterator().next().version());
+
+        assertEquals(2, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        entry.orderCompleted(nearVer2, Arrays.asList(ver3), empty());
+        entry.readyNearLocal(nearVer2, ver2, empty(), empty(), 
Arrays.asList(ver1));
+
+        nearLocCands = entry.localCandidates();
+        rmtCands = entry.remoteMvccSnapshot();
+
+        assertNull(entry.anyOwner());
+        assertEquals(ver3, rmtCands.iterator().next().version());
+        assertTrue(rmtCands.iterator().next().owner());
+
+        GridCacheMvccCandidate<String> cand = nearLocCands.iterator().next();
+
+        assertTrue(cand.ready());
+        assertFalse(cand.owner());
+        assertFalse(cand.used());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNearRemoteConsistentOrdering2() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(10);
+        GridCacheVersion nearVer2 = version(5);
+        GridCacheVersion ver2 = version(20);
+        GridCacheVersion ver3 = version(30);
+
+        entry.addRemote(node1, 1, ver1, 0, false, true);
+        entry.addNearLocal(node1, 1, nearVer2, 0, true);
+        entry.addRemote(node1, 1, ver3, 0, false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(nearVer2, nearLocCands.iterator().next().version());
+
+        assertEquals(2, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        entry.orderCompleted(nearVer2, empty(), empty());
+        entry.readyNearLocal(nearVer2, ver2, empty(), empty(), empty());
+
+        nearLocCands = entry.localCandidates();
+        rmtCands = entry.remoteMvccSnapshot();
+
+        assertNull(entry.anyOwner());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+        assertTrue(rmtCands.iterator().next().owner());
+
+        GridCacheMvccCandidate<String> cand = nearLocCands.iterator().next();
+
+        assertTrue(cand.ready());
+        assertFalse(cand.used());
+        assertFalse(cand.owner());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNearRemoteConsistentOrdering3() throws Exception {
+        GridCacheAdapter<String, String> cache = grid.internalCache();
+
+        GridCacheTestEntryEx<String, String> entry = new 
GridCacheTestEntryEx<>(cache.context(), "1");
+
+        UUID node1 = UUID.randomUUID();
+
+        GridCacheVersion ver1 = version(10);
+        GridCacheVersion nearVer2 = version(5);
+        GridCacheVersion ver2 = version(20);
+        GridCacheVersion ver3 = version(30);
+
+        entry.addRemote(node1, 1, ver1, 0, false, true);
+        entry.addNearLocal(node1, 1, nearVer2, 0, true);
+        entry.addRemote(node1, 1, ver3, 0, false, true);
+
+        Collection<GridCacheMvccCandidate<String>> rmtCands = 
entry.remoteMvccSnapshot();
+        Collection<GridCacheMvccCandidate<String>> nearLocCands = 
entry.localCandidates();
+
+        assertEquals(1, nearLocCands.size());
+        assertEquals(nearVer2, nearLocCands.iterator().next().version());
+
+        assertEquals(2, rmtCands.size());
+        assertEquals(ver1, rmtCands.iterator().next().version());
+
+        entry.orderCompleted(nearVer2, empty(), empty());
+        entry.readyNearLocal(nearVer2, ver2, empty(), empty(), 
Arrays.asList(ver1));
+
+        rmtCands = entry.remoteMvccSnapshot();
+
+        assertNotNull(entry.anyOwner());
+        checkLocalOwner(entry.anyOwner(), nearVer2, false);
+
+        assertEquals(ver1, rmtCands.iterator().next().version());
+    }
+
+    /**
+     * Gets version based on order.
+     *
+     * @param order Order.
+     * @return Version.
+     */
+    private GridCacheVersion version(int order) {
+        return new GridCacheVersion(1, 0, order, order, 0);
+    }
+
+    /**
+     * Creates an empty list of {@code GridCacheVersion}.
+     *
+     * @return Empty list.
+     */
+    private Collection<GridCacheVersion> empty() {
+        return Collections.emptyList();
+    }
+
+    /**
+     * Checks flags on local owner candidate.
+     *
+     * @param cand Candidate to check.
+     * @param ver Cache version.
+     * @param reentry Reentry flag.
+     */
+    private void checkLocalOwner(GridCacheMvccCandidate<String> cand, 
GridCacheVersion ver, boolean reentry) {
+        assert cand != null;
+
+        info("Done candidate: " + cand);
+
+        assert cand.version().equals(ver);
+
+        // Check flags.
+        assert cand.reentry() == reentry;
+
+        assert !cand.used();
+
+        assert cand.ready();
+        assert cand.owner();
+        assert cand.local();
+    }
+
+    /**
+     * @param cand Candidate to check.
+     * @param ver Version.
+     * @param owner Owner flag.
+     * @param used Done flag.
+     */
+    private void checkRemote(GridCacheMvccCandidate<String> cand, 
GridCacheVersion ver, boolean owner, boolean used) {
+        assert cand != null;
+
+        info("Done candidate: " + cand);
+
+        assert cand.version().equals(ver);
+
+        // Check flags.
+        assert cand.used() == used;
+        assert cand.owner() == owner;
+
+        assert !cand.ready();
+        assert !cand.reentry();
+        assert !cand.local();
+    }
+
+    /**
+     * Checks flags on local candidate.
+     *
+     * @param cand Candidate to check.
+     * @param ver Cache version.
+     * @param ready Ready flag.
+     * @param owner Lock owner.
+     * @param reentry Reentry flag.
+     */
+    private void checkLocal(GridCacheMvccCandidate<String> cand, 
GridCacheVersion ver, boolean ready,
+        boolean owner, boolean reentry) {
+        assert cand != null;
+
+        info("Done candidate: " + cand);
+
+        assert cand.version().equals(ver);
+
+        // Check flags.
+        assert cand.ready() == ready;
+        assert cand.owner() == owner;
+        assert cand.reentry() == reentry;
+
+        assert !cand.used();
+
+        assert cand.local();
+    }
+}

Reply via email to