You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ag...@apache.org on 2015/11/20 12:05:38 UTC

[01/37] ignite git commit: IGNITE-1900: Ignite JXM problem with Spring Boot. This closes #227.

Repository: ignite
Updated Branches:
  refs/heads/ignite-1282 0d56b41ca -> 6d4ecfde7


IGNITE-1900: Ignite JXM problem with Spring Boot. This closes #227.


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

Branch: refs/heads/ignite-1282
Commit: dc32789c270c7d4661178539957b2e27d5dcb91b
Parents: 5a116cb
Author: wmz7year <yd...@gmail.com>
Authored: Mon Nov 16 13:43:23 2015 +0300
Committer: dmagda <ma...@gmail.com>
Committed: Mon Nov 16 13:43:23 2015 +0300

----------------------------------------------------------------------
 .../apache/ignite/internal/IgniteKernal.java    |  9 +++---
 .../org/apache/ignite/mxbean/IgniteMXBean.java  |  8 ++---
 .../ignite/util/mbeans/GridMBeanSelfTest.java   | 33 +++++++++++++++++---
 3 files changed, 37 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/dc32789c/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
index dd129da..f1d67af 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
@@ -564,10 +564,10 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")
-    @Override public Collection<String> getUserAttributesFormatted() {
+    @Override public List<String> getUserAttributesFormatted() {
         assert cfg != null;
 
-        return F.transform(cfg.getUserAttributes().entrySet(), new C1<Map.Entry<String, ?>, String>() {
+        return (List<String>)F.transform(cfg.getUserAttributes().entrySet(), new C1<Map.Entry<String, ?>, String>() {
             @Override public String apply(Map.Entry<String, ?> e) {
                 return e.getKey() + ", " + e.getValue().toString();
             }
@@ -582,10 +582,11 @@ public class IgniteKernal implements IgniteEx, IgniteMXBean, Externalizable {
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<String> getLifecycleBeansFormatted() {
+    @Override public List<String> getLifecycleBeansFormatted() {
         LifecycleBean[] beans = cfg.getLifecycleBeans();
 
-        return F.isEmpty(beans) ? Collections.<String>emptyList() : F.transform(beans, F.<LifecycleBean>string());
+        return F.isEmpty(beans) ? Collections.<String>emptyList() :
+            (List<String>)F.transform(beans, F.<LifecycleBean>string());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/dc32789c/modules/core/src/main/java/org/apache/ignite/mxbean/IgniteMXBean.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/mxbean/IgniteMXBean.java b/modules/core/src/main/java/org/apache/ignite/mxbean/IgniteMXBean.java
index c30e0e5..0754c27 100644
--- a/modules/core/src/main/java/org/apache/ignite/mxbean/IgniteMXBean.java
+++ b/modules/core/src/main/java/org/apache/ignite/mxbean/IgniteMXBean.java
@@ -17,7 +17,7 @@
 
 package org.apache.ignite.mxbean;
 
-import java.util.Collection;
+import java.util.List;
 import java.util.UUID;
 import javax.management.JMException;
 
@@ -75,7 +75,7 @@ public interface IgniteMXBean {
     public long getUpTime();
 
     /**
-     * Gets a collection of formatted user-defined attributes added to this node.
+     * Gets a list of formatted user-defined attributes added to this node.
      * <p>
      * Note that grid will add all System properties and environment properties
      * to grid node attributes also. SPIs may also add node attributes that are
@@ -84,7 +84,7 @@ public interface IgniteMXBean {
      * @return User defined attributes for this node.
      */
     @MXBeanDescription("Collection of formatted user-defined attributes added to this node.")
-    public Collection<String> getUserAttributesFormatted();
+    public List<String> getUserAttributesFormatted();
 
     /**
      * Gets a formatted instance of logger that is in grid.
@@ -149,7 +149,7 @@ public interface IgniteMXBean {
      *      with Ignite.
      */
     @MXBeanDescription("String representation of lifecycle beans.")
-    public Collection<String> getLifecycleBeansFormatted();
+    public List<String> getLifecycleBeansFormatted();
 
     /**
      * This method allows manually remove the checkpoint with given {@code key}.

http://git-wip-us.apache.org/repos/asf/ignite/blob/dc32789c/modules/core/src/test/java/org/apache/ignite/util/mbeans/GridMBeanSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/util/mbeans/GridMBeanSelfTest.java b/modules/core/src/test/java/org/apache/ignite/util/mbeans/GridMBeanSelfTest.java
index da31742..58be549 100644
--- a/modules/core/src/test/java/org/apache/ignite/util/mbeans/GridMBeanSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/util/mbeans/GridMBeanSelfTest.java
@@ -23,6 +23,7 @@ import javax.management.MBeanOperationInfo;
 import javax.management.MBeanParameterInfo;
 import javax.management.StandardMBean;
 import org.apache.ignite.internal.mxbean.IgniteStandardMXBean;
+import org.apache.ignite.mxbean.IgniteMXBean;
 import org.apache.ignite.mxbean.MXBeanDescription;
 import org.apache.ignite.mxbean.MXBeanParametersDescriptions;
 import org.apache.ignite.mxbean.MXBeanParametersNames;
@@ -40,13 +41,13 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
     public void testCorrectMBeanInfo() throws Exception {
         StandardMBean mbean = new IgniteStandardMXBean(new GridMBeanImplementation(), GridMBeanInterface.class);
 
-        MBeanInfo info =  mbean.getMBeanInfo();
+        MBeanInfo info = mbean.getMBeanInfo();
 
         assert info.getDescription().equals("MBeanDescription.") == true;
 
         assert info.getOperations().length == 2;
 
-        for (MBeanOperationInfo opInfo: info.getOperations()) {
+        for (MBeanOperationInfo opInfo : info.getOperations()) {
             if (opInfo.getDescription().equals("MBeanOperation."))
                 assert opInfo.getSignature().length == 2;
             else {
@@ -55,7 +56,7 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
             }
         }
 
-        for (MBeanParameterInfo paramInfo: info.getOperations()[0].getSignature()) {
+        for (MBeanParameterInfo paramInfo : info.getOperations()[0].getSignature()) {
             if (paramInfo.getName().equals("ignored"))
                 assert paramInfo.getDescription().equals("MBeanOperationParameter1.") == true;
             else {
@@ -64,9 +65,9 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
             }
         }
 
-        assert info.getAttributes().length == 4: "Expected 4 attributes but got " + info.getAttributes().length;
+        assert info.getAttributes().length == 4 : "Expected 4 attributes but got " + info.getAttributes().length;
 
-        for (MBeanAttributeInfo attrInfo: info.getAttributes()) {
+        for (MBeanAttributeInfo attrInfo : info.getAttributes()) {
             if (attrInfo.isWritable() == false) {
                 assert (attrInfo.getDescription().equals("MBeanReadonlyGetter.") == true ||
                     attrInfo.getDescription().equals("MBeanROGetter."));
@@ -80,6 +81,7 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
 
     /**
      * Tests correct MBean interface.
+     *
      * @throws Exception Thrown if test fails.
      */
     public void testMissedNameMBeanInfo() throws Exception {
@@ -97,6 +99,7 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
 
     /**
      * Tests correct MBean interface.
+     *
      * @throws Exception Thrown if test fails.
      */
     public void testMissedDescriptionMBeanInfo() throws Exception {
@@ -115,6 +118,7 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
 
     /**
      * Tests correct MBean interface.
+     *
      * @throws Exception Thrown if test fails.
      */
     public void testEmptyDescriptionMBeanInfo() throws Exception {
@@ -133,6 +137,7 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
 
     /**
      * Tests correct MBean interface.
+     *
      * @throws Exception Thrown if test fails.
      */
     public void testEmptyNameMBeanInfo() throws Exception {
@@ -150,6 +155,23 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * Tests correct MBean interface.
+     *
+     * @throws Exception Thrown if test fails.
+     */
+    public void testIgniteKernalReturnsValidMBeanInfo() throws Exception {
+        try {
+            IgniteMXBean ignite = (IgniteMXBean)startGrid();
+
+            assertNotNull(ignite.getUserAttributesFormatted());
+            assertNotNull(ignite.getLifecycleBeansFormatted());
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+
+    /**
      * Super interface for {@link GridMBeanInterface}.
      */
     public static interface GridMBeanSuperInterface {
@@ -211,6 +233,7 @@ public class GridMBeanSelfTest extends GridCommonAbstractTest {
 
         /**
          * Test boolean setter.
+         *
          * @param isWritable Just a boolean.
          */
         public void setWritable(boolean isWritable);


[23/37] ignite git commit: IGNITE-529 Readme fix

Posted by ag...@apache.org.
 IGNITE-529 Readme fix


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

Branch: refs/heads/ignite-1282
Commit: dae3de0b72afd7dc0a0e32db3c5c6015166cb80f
Parents: ba1d563
Author: Anton Vinogradov <av...@apache.org>
Authored: Thu Nov 19 17:42:12 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Thu Nov 19 17:42:12 2015 +0300

----------------------------------------------------------------------
 modules/flume/README.md  | 40 ------------------------
 modules/flume/README.txt | 72 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/dae3de0b/modules/flume/README.md
----------------------------------------------------------------------
diff --git a/modules/flume/README.md b/modules/flume/README.md
deleted file mode 100644
index 2247cf3..0000000
--- a/modules/flume/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-#Flume NG sink
-
-## Setting up and running
-
-1. Create a transformer by implementing EventTransformer interface.
-2. Build it and copy to ${FLUME_HOME}/plugins.d/ignite-sink/lib.
-3. Copy other Ignite-related jar files to ${FLUME_HOME}/plugins.d/ignite-sink/libext to have them as shown below.
-
-```
-plugins.d/
-`-- ignite
-    |-- lib
-    |   `-- ignite-flume-transformer-x.x.x.jar <-- your jar
-    `-- libext
-        |-- cache-api-1.0.0.jar
-        |-- ignite-core-x.x.x.jar
-        |-- ignite-flume-x.x.x.jar
-        |-- ignite-spring-x.x.x.jar
-        |-- spring-aop-4.1.0.RELEASE.jar
-        |-- spring-beans-4.1.0.RELEASE.jar
-        |-- spring-context-4.1.0.RELEASE.jar
-        |-- spring-core-4.1.0.RELEASE.jar
-        `-- spring-expression-4.1.0.RELEASE.jar
-```
-
-4. In Flume configuration file, specify Ignite configuration XML file's location with cache properties
-(see [Apache Ignite](https://apacheignite.readme.io/) with cache name specified for cache creation,
-cache name (same as in Ignite configuration file), your EventTransformer's implementation class,
-and, optionally, batch size (default -- 100).
-
-```
-# Describe the sink
-a1.sinks.k1.type = org.apache.ignite.stream.flume.IgniteSink
-a1.sinks.k1.igniteCfg = /some-path/ignite.xml
-a1.sinks.k1.cacheName = testCache
-a1.sinks.k1.eventTransformer = my.company.MyEventTransformer
-a1.sinks.k1.batchSize = 100
-```
-
-After specifying your source and channel (see Flume's docs), you are ready to run a Flume agent.

http://git-wip-us.apache.org/repos/asf/ignite/blob/dae3de0b/modules/flume/README.txt
----------------------------------------------------------------------
diff --git a/modules/flume/README.txt b/modules/flume/README.txt
new file mode 100644
index 0000000..5b574e3
--- /dev/null
+++ b/modules/flume/README.txt
@@ -0,0 +1,72 @@
+Apache Ignite Flume Streamer Module
+------------------------
+
+Apache Ignite Flume Streamer module provides streaming from Flume to Ignite cache.
+
+To enable Flume Streamer module when starting a standalone node, move 'optional/ignite-Flume' folder to
+'libs' folder before running 'ignite.{sh|bat}' script. The content of the module folder will
+be added to classpath in this case.
+
+Importing Ignite Flume Streamer Module In Maven Project
+-------------------------------------
+
+If you are using Maven to manage dependencies of your project, you can add JCL module
+dependency like this (replace '${ignite.version}' with actual Ignite version you are
+interested in):
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                        http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    ...
+    <dependencies>
+        ...
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-Flume</artifactId>
+            <version>${ignite.version}</version>
+        </dependency>
+        ...
+    </dependencies>
+    ...
+</project>
+
+
+## Setting up and running
+
+1. Create a transformer by implementing EventTransformer interface.
+2. Build it and copy to ${FLUME_HOME}/plugins.d/ignite-sink/lib.
+3. Copy other Ignite-related jar files to ${FLUME_HOME}/plugins.d/ignite-sink/libext to have them as shown below.
+
+```
+plugins.d/
+`-- ignite
+    |-- lib
+    |   `-- ignite-flume-transformer-x.x.x.jar <-- your jar
+    `-- libext
+        |-- cache-api-1.0.0.jar
+        |-- ignite-core-x.x.x.jar
+        |-- ignite-flume-x.x.x.jar
+        |-- ignite-spring-x.x.x.jar
+        |-- spring-aop-4.1.0.RELEASE.jar
+        |-- spring-beans-4.1.0.RELEASE.jar
+        |-- spring-context-4.1.0.RELEASE.jar
+        |-- spring-core-4.1.0.RELEASE.jar
+        `-- spring-expression-4.1.0.RELEASE.jar
+```
+
+4. In Flume configuration file, specify Ignite configuration XML file's location with cache properties
+(see [Apache Ignite](https://apacheignite.readme.io/) with cache name specified for cache creation,
+cache name (same as in Ignite configuration file), your EventTransformer's implementation class,
+and, optionally, batch size (default -- 100).
+
+```
+# Describe the sink
+a1.sinks.k1.type = org.apache.ignite.stream.flume.IgniteSink
+a1.sinks.k1.igniteCfg = /some-path/ignite.xml
+a1.sinks.k1.cacheName = testCache
+a1.sinks.k1.eventTransformer = my.company.MyEventTransformer
+a1.sinks.k1.batchSize = 100
+```
+
+After specifying your source and channel (see Flume's docs), you are ready to run a Flume agent.


[24/37] ignite git commit: Merge remote-tracking branch 'origin/ignite-1.5' into ignite-1.5

Posted by ag...@apache.org.
Merge remote-tracking branch 'origin/ignite-1.5' into ignite-1.5


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

Branch: refs/heads/ignite-1282
Commit: e369e1fe797ac3309cf3eee74a7bacd3c1ad0565
Parents: dae3de0 f0db0d9
Author: Anton Vinogradov <av...@apache.org>
Authored: Thu Nov 19 17:42:40 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Thu Nov 19 17:42:40 2015 +0300

----------------------------------------------------------------------
 .../java/org/apache/ignite/IgniteCache.java     |   3 +-
 .../java/org/apache/ignite/IgniteCompute.java   |   3 +-
 .../org/apache/ignite/compute/ComputeJob.java   |   2 +-
 .../communication/GridIoMessageFactory.java     |  12 +
 .../processors/cache/GridCacheAdapter.java      | 103 ++-
 .../processors/cache/GridCacheAtomicFuture.java |   6 +
 .../processors/cache/GridCacheFuture.java       |  13 -
 .../processors/cache/GridCacheIoManager.java    |  50 +-
 .../processors/cache/GridCacheMessage.java      |  20 +-
 .../processors/cache/GridCacheMvccFuture.java   |   7 +
 .../processors/cache/GridCacheMvccManager.java  | 108 +--
 .../distributed/GridCacheTxRecoveryFuture.java  |  13 +-
 .../dht/CacheDistributedGetFutureAdapter.java   |  27 +-
 .../cache/distributed/dht/CacheGetFuture.java   |  32 +
 .../distributed/dht/GridDhtCacheAdapter.java    | 141 ++++
 .../distributed/dht/GridDhtLockFuture.java      |  16 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |   9 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |  24 +-
 .../cache/distributed/dht/GridDhtTxLocal.java   |   4 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |  17 +-
 .../dht/GridPartitionedGetFuture.java           |  69 +-
 .../dht/GridPartitionedSingleGetFuture.java     | 697 +++++++++++++++++++
 .../dht/atomic/GridDhtAtomicCache.java          | 127 +++-
 .../dht/atomic/GridDhtAtomicUpdateFuture.java   |  84 +--
 .../dht/atomic/GridDhtAtomicUpdateRequest.java  |  11 +
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |   5 -
 .../dht/colocated/GridDhtColocatedCache.java    | 160 ++++-
 .../colocated/GridDhtColocatedLockFuture.java   |  26 +-
 .../distributed/near/CacheVersionedValue.java   |   2 +-
 .../distributed/near/GridNearCacheAdapter.java  |   4 +-
 .../distributed/near/GridNearGetFuture.java     |  57 +-
 .../distributed/near/GridNearGetRequest.java    |   1 -
 .../distributed/near/GridNearGetResponse.java   |   2 -
 .../distributed/near/GridNearLockFuture.java    |  16 +-
 ...arOptimisticSerializableTxPrepareFuture.java |  17 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |  19 +-
 .../GridNearPessimisticTxPrepareFuture.java     |  19 +-
 .../near/GridNearSingleGetRequest.java          | 396 +++++++++++
 .../near/GridNearSingleGetResponse.java         | 321 +++++++++
 .../near/GridNearTransactionalCache.java        |   2 +-
 .../near/GridNearTxFinishFuture.java            |  24 +-
 .../cache/distributed/near/GridNearTxLocal.java | 149 ++--
 .../near/GridNearTxPrepareFutureAdapter.java    |   6 +-
 .../processors/cache/local/GridLocalCache.java  |   4 +-
 .../cache/local/GridLocalLockFuture.java        |   5 -
 .../cache/transactions/IgniteTxHandler.java     |  19 +-
 .../transactions/IgniteTxLocalAdapter.java      |   2 +-
 .../cache/transactions/IgniteTxManager.java     |   2 +-
 .../ignite/marshaller/MarshallerExclusions.java |   4 +-
 .../IgniteClientReconnectCacheTest.java         |  11 +-
 .../cache/GridCacheAbstractFullApiSelfTest.java |  75 ++
 .../GridCacheConcurrentTxMultiNodeTest.java     |  15 -
 .../cache/GridCachePartitionedGetSelfTest.java  |   3 +-
 .../IgniteCacheAbstractStopBusySelfTest.java    |  27 +-
 .../IgniteCacheP2pUnmarshallingErrorTest.java   | 184 +++--
 .../CacheGetFutureHangsSelfTest.java            |   6 +
 .../GridCacheAbstractNodeRestartSelfTest.java   |   2 +
 .../IgniteCacheSingleGetMessageTest.java        | 357 ++++++++++
 .../GridCacheReplicatedMetricsSelfTest.java     |   9 -
 .../testsuites/IgniteCacheTestSuite4.java       |   3 +
 60 files changed, 2915 insertions(+), 637 deletions(-)
----------------------------------------------------------------------



[37/37] ignite git commit: Merge branch 'ignite-1282' of https://git-wip-us.apache.org/repos/asf/ignite into ignite-1282

Posted by ag...@apache.org.
Merge branch 'ignite-1282' of https://git-wip-us.apache.org/repos/asf/ignite into ignite-1282


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

Branch: refs/heads/ignite-1282
Commit: 6d4ecfde78f94dd52834306d14deeaec63a46359
Parents: 9b6adb2 0d56b41
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Fri Nov 20 14:04:57 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Fri Nov 20 14:04:57 2015 +0300

----------------------------------------------------------------------
 .../internal/portable/BinaryWriterExImpl.java   | 101 ++++++++++++-------
 .../portable/PortableClassDescriptor.java       |  45 ++++-----
 .../ignite/internal/portable/PortableUtils.java |  32 +-----
 .../builder/BinaryObjectBuilderImpl.java        |   8 +-
 .../streams/PortableAbstractOutputStream.java   |   7 +-
 .../portable/streams/PortableOutputStream.java  |   7 ++
 .../memory/PlatformOutputStreamImpl.java        |   7 +-
 7 files changed, 107 insertions(+), 100 deletions(-)
----------------------------------------------------------------------



[16/37] ignite git commit: IGNITE-1790 Camel streamer: Add README.txt, license txt and fix Javadoc.

Posted by ag...@apache.org.
IGNITE-1790 Camel streamer: Add README.txt, license txt and fix Javadoc.


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

Branch: refs/heads/ignite-1282
Commit: 480d457a724800c1afa4aadf3fc9ceda7f9a217f
Parents: fee7f86
Author: Raul Kripalani <ra...@apache.org>
Authored: Thu Nov 19 11:47:25 2015 +0000
Committer: Raul Kripalani <ra...@apache.org>
Committed: Thu Nov 19 11:47:34 2015 +0000

----------------------------------------------------------------------
 modules/camel/README.txt                        |  34 ++++
 modules/camel/licenses/apache-2.0.txt           | 202 +++++++++++++++++++
 .../ignite/stream/camel/CamelStreamer.java      |   2 +-
 3 files changed, 237 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/480d457a/modules/camel/README.txt
----------------------------------------------------------------------
diff --git a/modules/camel/README.txt b/modules/camel/README.txt
new file mode 100644
index 0000000..ca119ae
--- /dev/null
+++ b/modules/camel/README.txt
@@ -0,0 +1,34 @@
+Apache Ignite Camel Module
+--------------------------
+
+Apache Ignite Camel provides a streamer to consume cache tuples from a Camel endpoint such as
+HTTP, TCP, File, FTP, AMQP, SNMP, databases, etc. For more information on available components,
+refer to http://camel.apache.org/components.html.
+
+To enable the Camel module when starting a standalone node, move 'optional/ignite-camel' folder
+to 'libs' folder before running 'ignite.{sh|bat}' script. The content of the module folder will
+be added to classpath in this case.
+
+Importing the Camel module in a Maven project
+---------------------------------------------
+
+If you are using Maven to manage dependencies of your project, you can add the Camel module
+dependency like this (replace '${ignite.version}' with actual Ignite version you are
+interested in):
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                        http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    ...
+    <dependencies>
+        ...
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-camel</artifactId>
+            <version>${ignite.version}</version>
+        </dependency>
+        ...
+    </dependencies>
+    ...
+</project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/480d457a/modules/camel/licenses/apache-2.0.txt
----------------------------------------------------------------------
diff --git a/modules/camel/licenses/apache-2.0.txt b/modules/camel/licenses/apache-2.0.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/modules/camel/licenses/apache-2.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.

http://git-wip-us.apache.org/repos/asf/ignite/blob/480d457a/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
----------------------------------------------------------------------
diff --git a/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java b/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
index 40ed6b3..369d2a6 100644
--- a/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
+++ b/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
@@ -40,7 +40,7 @@ import org.apache.ignite.stream.StreamSingleTupleExtractor;
  * This streamer consumes messages from an Apache Camel consumer endpoint and feeds them into an Ignite data streamer.
  *
  * The only mandatory properties are {@link #endpointUri} and the appropriate stream tuple extractor (either {@link
- * StreamSingleTupleExtractor} or {@link StreamMultipleTupleExtractor)}.
+ * StreamSingleTupleExtractor} or {@link StreamMultipleTupleExtractor}.
  *
  * The user can also provide a custom {@link CamelContext} in case they want to attach custom components, a {@link
  * org.apache.camel.component.properties.PropertiesComponent}, set tracers, management strategies, etc.


[27/37] ignite git commit: Merge remote-tracking branch 'apache/ignite-1.5' into ignite-1.5

Posted by ag...@apache.org.
Merge remote-tracking branch 'apache/ignite-1.5' into ignite-1.5


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

Branch: refs/heads/ignite-1282
Commit: c85d1f5fed821d0fa5e354d19d7da3fd7f9ac87c
Parents: 96483be f708c1a
Author: ashutak <as...@gridgain.com>
Authored: Thu Nov 19 19:32:31 2015 +0300
Committer: ashutak <as...@gridgain.com>
Committed: Thu Nov 19 19:32:31 2015 +0300

----------------------------------------------------------------------
 modules/camel/README.txt                        |  34 +
 modules/camel/licenses/apache-2.0.txt           | 202 ++++++
 modules/camel/pom.xml                           | 102 +++
 .../ignite/stream/camel/CamelStreamer.java      | 237 +++++++
 .../stream/camel/IgniteCamelStreamerTest.java   | 420 +++++++++++
 .../camel/IgniteCamelStreamerTestSuite.java     |  48 ++
 .../src/test/resources/camel.test.properties    |  18 +
 .../ignite/codegen/MessageCodeGenerator.java    |  11 +-
 .../java/org/apache/ignite/IgniteCache.java     |   3 +-
 .../java/org/apache/ignite/IgniteCompute.java   |   3 +-
 .../org/apache/ignite/compute/ComputeJob.java   |   2 +-
 .../ignite/internal/GridUpdateNotifier.java     |   2 +-
 .../communication/GridIoMessageFactory.java     |  18 +
 .../discovery/GridDiscoveryManager.java         |   2 +-
 .../processors/cache/GridCacheAdapter.java      | 103 ++-
 .../processors/cache/GridCacheAtomicFuture.java |   6 +
 .../cache/GridCacheDeploymentManager.java       |   2 +-
 .../processors/cache/GridCacheFuture.java       |  13 -
 .../processors/cache/GridCacheGateway.java      |   1 -
 .../processors/cache/GridCacheIoManager.java    |  50 +-
 .../processors/cache/GridCacheMessage.java      |  20 +-
 .../processors/cache/GridCacheMvcc.java         |   7 -
 .../processors/cache/GridCacheMvccFuture.java   |   7 +
 .../processors/cache/GridCacheMvccManager.java  | 150 ++--
 .../GridCachePartitionExchangeManager.java      |  55 +-
 .../cache/GridCacheSharedContext.java           |   7 +-
 .../processors/cache/IgniteCacheProxy.java      |   3 +
 .../distributed/GridCacheTxRecoveryFuture.java  |  54 +-
 .../distributed/GridDistributedBaseMessage.java |  56 --
 .../distributed/GridDistributedLockRequest.java |   6 -
 .../GridDistributedLockResponse.java            |  32 +-
 .../GridDistributedTxPrepareRequest.java        |  67 +-
 .../dht/CacheDistributedGetFutureAdapter.java   |  27 +-
 .../cache/distributed/dht/CacheGetFuture.java   |  32 +
 .../distributed/dht/GridDhtCacheAdapter.java    | 141 ++++
 .../distributed/dht/GridDhtLockFuture.java      |  79 ++-
 .../distributed/dht/GridDhtLockRequest.java     |   2 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |  14 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |  24 +-
 .../cache/distributed/dht/GridDhtTxLocal.java   |   4 +-
 .../distributed/dht/GridDhtTxLocalAdapter.java  |   9 +
 .../distributed/dht/GridDhtTxPrepareFuture.java |  77 +-
 .../dht/GridDhtTxPrepareRequest.java            |  54 +-
 .../dht/GridPartitionedGetFuture.java           |  69 +-
 .../dht/GridPartitionedSingleGetFuture.java     | 697 +++++++++++++++++++
 .../dht/atomic/GridDhtAtomicCache.java          | 127 +++-
 .../dht/atomic/GridDhtAtomicUpdateFuture.java   |  84 +--
 .../dht/atomic/GridDhtAtomicUpdateRequest.java  |  11 +
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |   5 -
 .../dht/colocated/GridDhtColocatedCache.java    | 162 ++++-
 .../colocated/GridDhtColocatedLockFuture.java   |  81 ++-
 .../distributed/near/CacheVersionedValue.java   |   2 +-
 .../distributed/near/GridNearCacheAdapter.java  |   4 +-
 .../distributed/near/GridNearGetFuture.java     |  57 +-
 .../distributed/near/GridNearGetRequest.java    |   1 -
 .../distributed/near/GridNearGetResponse.java   |   2 -
 .../distributed/near/GridNearLockFuture.java    |  72 +-
 .../distributed/near/GridNearLockRequest.java   |   4 +-
 ...arOptimisticSerializableTxPrepareFuture.java | 108 +--
 .../near/GridNearOptimisticTxPrepareFuture.java |  69 +-
 .../GridNearPessimisticTxPrepareFuture.java     |  58 +-
 .../near/GridNearSingleGetRequest.java          | 396 +++++++++++
 .../near/GridNearSingleGetResponse.java         | 321 +++++++++
 .../near/GridNearTransactionalCache.java        |   9 +-
 .../near/GridNearTxFinishFuture.java            |  42 +-
 .../cache/distributed/near/GridNearTxLocal.java | 164 +++--
 .../near/GridNearTxPrepareFutureAdapter.java    |  20 +-
 .../near/GridNearTxPrepareRequest.java          |  52 +-
 .../processors/cache/local/GridLocalCache.java  |   4 +-
 .../cache/local/GridLocalLockFuture.java        |   5 -
 .../cache/transactions/IgniteInternalTx.java    |   1 +
 .../cache/transactions/IgniteTxAdapter.java     |   1 +
 .../cache/transactions/IgniteTxEntry.java       |   9 +-
 .../cache/transactions/IgniteTxHandler.java     |  19 +-
 .../IgniteTxImplicitSingleStateImpl.java        |   7 +
 .../transactions/IgniteTxLocalAdapter.java      |  14 +-
 .../cache/transactions/IgniteTxManager.java     |   3 +-
 .../IgniteTxRemoteStateAdapter.java             |   5 +
 .../cache/transactions/IgniteTxState.java       |   6 +
 .../cache/transactions/IgniteTxStateImpl.java   |  69 +-
 .../clock/GridClockSyncProcessor.java           |  28 +-
 .../internal/util/UUIDCollectionMessage.java    | 114 +++
 .../util/future/GridCompoundFuture.java         |  15 +-
 .../ignite/internal/util/lang/GridFunc.java     |   8 +-
 .../ignite/internal/util/nio/GridNioServer.java |  13 +-
 .../ignite/marshaller/MarshallerExclusions.java |   4 +-
 .../org/apache/ignite/stream/StreamAdapter.java |  19 +-
 .../IgniteClientReconnectCacheTest.java         |  11 +-
 .../cache/GridCacheAbstractFullApiSelfTest.java |  75 ++
 .../GridCacheConcurrentTxMultiNodeTest.java     |  15 -
 .../cache/GridCachePartitionedGetSelfTest.java  |   3 +-
 .../IgniteCacheAbstractStopBusySelfTest.java    |  27 +-
 .../IgniteCacheP2pUnmarshallingErrorTest.java   | 184 +++--
 .../CacheGetFutureHangsSelfTest.java            |   6 +
 .../GridCacheAbstractNodeRestartSelfTest.java   |   2 +
 .../IgniteCacheSingleGetMessageTest.java        | 357 ++++++++++
 .../GridCacheReplicatedMetricsSelfTest.java     |   9 -
 .../IgniteCacheTxStoreSessionTest.java          |   2 +-
 .../testsuites/IgniteCacheTestSuite3.java       |   2 +
 .../testsuites/IgniteCacheTestSuite4.java       |   3 +
 modules/flume/README.md                         |  40 --
 modules/flume/README.txt                        |  72 ++
 modules/flume/licenses/apache-2.0.txt           | 202 ++++++
 modules/twitter/README.txt                      |  32 +
 modules/twitter/licenses/apache-2.0.txt         | 202 ++++++
 modules/twitter/pom.xml                         | 122 ++++
 .../ignite/stream/twitter/OAuthSettings.java    |  86 +++
 .../ignite/stream/twitter/TwitterStreamer.java  | 295 ++++++++
 .../twitter/IgniteTwitterStreamerTest.java      | 234 +++++++
 .../twitter/IgniteTwitterStreamerTestSuite.java |  32 +
 .../stream/twitter/TwitterStreamerImpl.java     |  79 +++
 pom.xml                                         |   2 +
 112 files changed, 6152 insertions(+), 1107 deletions(-)
----------------------------------------------------------------------



[03/37] ignite git commit: Merge remote-tracking branch 'remotes/apache-main/ignite-cont-merge' into ignite-1.5

Posted by ag...@apache.org.
Merge remote-tracking branch 'remotes/apache-main/ignite-cont-merge' into ignite-1.5


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

Branch: refs/heads/ignite-1282
Commit: b382062e02d7e3effca38d5181c47c76c16e24aa
Parents: d54fcbe db221f5
Author: Denis Magda <dm...@gridgain.com>
Authored: Tue Nov 17 16:36:48 2015 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Tue Nov 17 16:36:48 2015 +0300

----------------------------------------------------------------------
 .../apache/ignite/internal/IgniteKernal.java    |   9 +-
 .../org/apache/ignite/mxbean/IgniteMXBean.java  |   8 +-
 .../ignite/util/mbeans/GridMBeanSelfTest.java   |  33 ++++-
 .../GridSpringResourceInjectionSelfTest.java    | 143 +++++++++++++++++++
 .../processors/resource/spring-resource.xml     |  27 ++++
 .../testsuites/IgniteResourceSelfTestSuite.java |   2 +
 6 files changed, 209 insertions(+), 13 deletions(-)
----------------------------------------------------------------------



[36/37] ignite git commit: Merge branch ignite-1.5 into ignite-1282

Posted by ag...@apache.org.
Merge branch ignite-1.5 into ignite-1282


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

Branch: refs/heads/ignite-1282
Commit: 9b6adb2903d69ac6e5cbf6e1677ee2ec9447fb2c
Parents: 3d4ce80
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Fri Nov 20 14:04:22 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Fri Nov 20 14:04:22 2015 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheMapEntry.java     |  4 +-
 .../GridDistributedTxPrepareRequest.java        |  3 +-
 .../dht/GridPartitionedSingleGetFuture.java     |  6 +-
 .../dht/colocated/GridDhtColocatedCache.java    |  2 +-
 .../transactions/IgniteTxLocalAdapter.java      | 71 ++++++++++++--------
 5 files changed, 50 insertions(+), 36 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9b6adb29/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 512a801..2b40351 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
@@ -1986,7 +1986,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                                     (EntryProcessor<Object, Object, ?>)writeObj;
 
                                 CacheInvokeEntry<Object, Object> entry =
-                                    new CacheInvokeEntry<>(cctx, key, prevVal, version());
+                                    new CacheInvokeEntry<>(cctx, key, prevVal, version(), keepPortable);
 
                                 try {
                                     entryProcessor.process(entry, invokeArgs);
@@ -1994,7 +1994,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                                     evtVal = entry.modified() ?
                                         cctx.toCacheObject(cctx.unwrapTemporary(entry.getValue())) : prevVal;
                                 }
-                                catch (Exception e) {
+                                catch (Exception ignore) {
                                     evtVal = prevVal;
                                 }
                             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9b6adb29/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
index 95176ff..e595942 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
@@ -329,8 +329,7 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
         }
 
         // Marshal txNodes only if there is a node in topology with an older version.
-        if (ctx.exchange().minimumNodeVersion(topologyVersion())
-            .compareTo(TX_NODES_DIRECT_MARSHALLABLE_SINCE) < 0) {
+        if (ctx.exchange().minimumNodeVersion(topologyVersion()).compareTo(TX_NODES_DIRECT_MARSHALLABLE_SINCE) < 0) {
             if (txNodes != null && txNodesBytes == null)
                 txNodesBytes = ctx.marshaller().marshal(txNodes);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/9b6adb29/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
index 8f2357b..32f4e80 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
@@ -347,7 +347,8 @@ public class GridPartitionedSingleGetFuture extends GridFutureAdapter<Object> im
                                 subjId,
                                 null,
                                 taskName,
-                                expiryPlc);
+                                expiryPlc,
+                                true);
 
                             if (res != null) {
                                 v = res.get1();
@@ -366,7 +367,8 @@ public class GridPartitionedSingleGetFuture extends GridFutureAdapter<Object> im
                                 subjId,
                                 null,
                                 taskName,
-                                expiryPlc);
+                                expiryPlc,
+                                true);
                         }
 
                         colocated.context().evicts().touch(entry, topVer);

http://git-wip-us.apache.org/repos/asf/ignite/blob/9b6adb29/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
index 72f5cf5..b69b42c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
@@ -239,7 +239,7 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
                         }
                     });
                 }
-            });
+            }, opCtx);
         }
 
         AffinityTopologyVersion topVer = tx == null ?

http://git-wip-us.apache.org/repos/asf/ignite/blob/9b6adb29/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index fae7d8c..7c6a1d4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -67,7 +67,6 @@ import org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
 import org.apache.ignite.internal.util.GridLeanMap;
-import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridEmbeddedFuture;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -2047,7 +2046,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         final CacheEntryPredicate[] filter,
         final GridCacheReturn ret,
         boolean skipStore,
-        final boolean singleRmv) {
+        final boolean singleRmv,
+        boolean keepBinary) {
         try {
             addActiveCache(cacheCtx);
 
@@ -2076,7 +2076,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 singleRmv,
                 hasFilters,
                 needVal,
-                needReadVer);
+                needReadVer,
+                keepBinary);
 
             if (loadMissed) {
                 return loadMissing(cacheCtx,
@@ -2087,7 +2088,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                     singleRmv,
                     hasFilters,
                     skipStore,
-                    retval);
+                    retval,
+                    keepBinary);
             }
 
             return new GridFinishedFuture<>();
@@ -2146,8 +2148,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
         boolean rmv = lookup == null && invokeMap == null;
 
-        Set<KeyCacheObject> missedForLoad = null;
-
         final boolean hasFilters = !F.isEmptyOrNulls(filter) && !F.isAlwaysTrue(filter);
         final boolean needVal = singleRmv || retval || hasFilters;
         final boolean needReadVer = needVal && (serializable() && optimistic());
@@ -2157,6 +2157,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             if (invokeMap != null)
                 transform = true;
 
+            Set<KeyCacheObject> missedForLoad = null;
+
             for (Object key : keys) {
                 if (key == null) {
                     rollback();
@@ -2219,7 +2221,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                     singleRmv,
                     hasFilters,
                     needVal,
-                    needReadVer);
+                    needReadVer,
+                    keepBinary);
 
                 if (loadMissed) {
                     if (missedForLoad == null)
@@ -2238,7 +2241,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                     singleRmv,
                     hasFilters,
                     skipStore,
-                    retval);
+                    retval,
+                    keepBinary);
             }
 
             return new GridFinishedFuture<>();
@@ -2269,7 +2273,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         final boolean singleRmv,
         final boolean hasFilters,
         final boolean skipStore,
-        final boolean retval) {
+        final boolean retval,
+        final boolean keepBinary) {
         GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c =
             new GridInClosure3<KeyCacheObject, Object, GridCacheVersion>() {
                 @Override public void apply(KeyCacheObject key,
@@ -2317,7 +2322,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                         else {
                             boolean success = !hasFilters || isAll(e.context(), key, cacheVal, filter);
 
-                            ret.set(cacheCtx, cacheVal, success);
+                            ret.set(cacheCtx, cacheVal, success, keepBinary);
                         }
                     }
                 }
@@ -2330,6 +2335,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             keys,
             /*skipVals*/singleRmv,
             needReadVer,
+            keepBinary,
             c);
     }
 
@@ -2341,7 +2347,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      * @param invokeArgs Optional arguments for EntryProcessor.
      * @param expiryPlc Explicitly specified expiry policy for entry.
      * @param retval Return value flag.
-     * @param lockOnly
+     * @param lockOnly Lock only flag.
      * @param filter Filter.
      * @param drVer DR version.
      * @param drTtl DR ttl.
@@ -2358,10 +2364,10 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      */
     private boolean enlistWriteEntry(GridCacheContext cacheCtx,
         final KeyCacheObject cacheKey,
-        final @Nullable Object val,
-        final @Nullable EntryProcessor<?, ?, ?> entryProcessor,
-        final @Nullable Object[] invokeArgs,
-        final @Nullable ExpiryPolicy expiryPlc,
+        @Nullable final Object val,
+        @Nullable final EntryProcessor<?, ?, ?> entryProcessor,
+        @Nullable final Object[] invokeArgs,
+        @Nullable final ExpiryPolicy expiryPlc,
         final boolean retval,
         final boolean lockOnly,
         final CacheEntryPredicate[] filter,
@@ -2374,7 +2380,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         boolean singleRmv,
         boolean hasFilters,
         final boolean needVal,
-        boolean needReadVer
+        boolean needReadVer,
+        boolean keepBinary
     ) throws IgniteCheckedException {
         boolean loadMissed = false;
 
@@ -2418,7 +2425,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                         CU.subjectId(this, cctx),
                                         entryProcessor,
                                         resolveTaskName(),
-                                        null) : null;
+                                        null,
+                                        keepBinary) : null;
 
                                 if (res != null) {
                                     old = res.get1();
@@ -2437,7 +2445,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                     CU.subjectId(this, cctx),
                                     entryProcessor,
                                     resolveTaskName(),
-                                    null);
+                                    null,
+                                    keepBinary);
                             }
                         }
                         catch (ClusterTopologyCheckedException e) {
@@ -2450,7 +2459,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                         old = retval ? entry.rawGetOrUnmarshal(false) : entry.rawGet();
 
                     if (old != null && hasFilters && !filter(entry.context(), cacheKey, old, filter)) {
-                        ret.set(cacheCtx, old, false);
+                        ret.set(cacheCtx, old, false, keepBinary);
 
                         if (!readCommitted()) {
                             // Enlist failed filters as reads for non-read-committed mode,
@@ -2466,7 +2475,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                 -1L,
                                 -1L,
                                 null,
-                                skipStore);
+                                skipStore,
+                                keepBinary);
 
                             txEntry.markValid();
 
@@ -2497,7 +2507,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                         drTtl,
                         drExpireTime,
                         drVer,
-                        skipStore);
+                        skipStore,
+                        keepBinary);
 
                     if (!implicit() && readCommitted() && !cacheCtx.offheapTiered())
                         cacheCtx.evicts().touch(entry, topologyVersion());
@@ -2516,7 +2527,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                 assert txEntry.op() != TRANSFORM : txEntry;
 
                                 if (retval)
-                                    ret.set(cacheCtx, null, true);
+                                    ret.set(cacheCtx, null, true, keepBinary);
                                 else
                                     ret.success(true);
                             }
@@ -2529,7 +2540,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                             }
 
                             if (retval && !transform)
-                                ret.set(cacheCtx, old, true);
+                                ret.set(cacheCtx, old, true, keepBinary);
                             else {
                                 if (txEntry.op() == TRANSFORM) {
                                     GridCacheVersion ver;
@@ -2557,7 +2568,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                     // Pessimistic.
                     else {
                         if (retval && !transform)
-                            ret.set(cacheCtx, old, true);
+                            ret.set(cacheCtx, old, true, keepBinary);
                         else
                             ret.success(true);
                     }
@@ -2583,7 +2594,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
             if (!del) {
                 if (hasFilters && !filter(entry.context(), cacheKey, v, filter)) {
-                    ret.set(cacheCtx, v, false);
+                    ret.set(cacheCtx, v, false, keepBinary);
 
                     return loadMissed;
                 }
@@ -2602,7 +2613,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                     drTtl,
                     drExpireTime,
                     drVer,
-                    skipStore);
+                    skipStore,
+                    keepBinary);
 
                 if (enlisted != null)
                     enlisted.add(cacheKey);
@@ -2630,7 +2642,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 txEntry.markValid();
 
                 if (retval && !transform)
-                    ret.set(cacheCtx, v, true);
+                    ret.set(cacheCtx, v, true, keepBinary);
                 else
                     ret.success(true);
             }
@@ -2904,7 +2916,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         final GridCacheContext cacheCtx,
         K key,
         @Nullable V val,
-        @Nullable EntryProcessor entryProcessor,
+        @Nullable EntryProcessor<K, V, Object> entryProcessor,
         @Nullable final Object[] invokeArgs,
         final boolean retval,
         @Nullable final CacheEntryPredicate[] filter
@@ -2932,7 +2944,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 filter,
                 ret,
                 opCtx != null && opCtx.skipStore(),
-                /*singleRmv*/false);
+                /*singleRmv*/false,
+                opCtx != null && opCtx.isKeepBinary());
 
             if (pessimistic()) {
                 assert loadFut == null || loadFut.isDone() : loadFut;


[15/37] ignite git commit: IGNITE-529 License fix

Posted by ag...@apache.org.
 IGNITE-529 License fix


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

Branch: refs/heads/ignite-1282
Commit: fee7f86e2a27c5958ac873bdaece3ef2d97de947
Parents: 33ec73f
Author: Anton Vinogradov <av...@apache.org>
Authored: Thu Nov 19 14:29:40 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Thu Nov 19 14:29:40 2015 +0300

----------------------------------------------------------------------
 modules/flume/licenses/apache-2.0.txt | 202 +++++++++++++++++++++++++++++
 1 file changed, 202 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/fee7f86e/modules/flume/licenses/apache-2.0.txt
----------------------------------------------------------------------
diff --git a/modules/flume/licenses/apache-2.0.txt b/modules/flume/licenses/apache-2.0.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/modules/flume/licenses/apache-2.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.


[08/37] ignite git commit: 'Single' operations optimizations for tx cache.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index db4a4b8..434b6c7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -68,9 +68,7 @@ import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.apache.ignite.transactions.TransactionState;
 import org.jetbrains.annotations.Nullable;
-import org.jsr166.ConcurrentHashMap8;
 
-import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 import static org.apache.ignite.transactions.TransactionState.COMMITTED;
 import static org.apache.ignite.transactions.TransactionState.COMMITTING;
 import static org.apache.ignite.transactions.TransactionState.PREPARING;
@@ -87,7 +85,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     private static final long serialVersionUID = 0L;
 
     /** DHT mappings. */
-    private Map<UUID, GridDistributedTxMapping> mappings = new ConcurrentHashMap8<>();
+    private IgniteTxMappings mappings;
 
     /** Future. */
     @GridToStringExclude
@@ -172,6 +170,8 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
             subjId,
             taskNameHash);
 
+        mappings = implicitSingle ? new IgniteTxMappingsSingleImpl() : new IgniteTxMappingsImpl();
+
         initResult();
     }
 
@@ -208,13 +208,6 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     }
 
     /** {@inheritDoc} */
-    @Override protected IgniteUuid nearMiniId() {
-        assert false : "nearMiniId should not be called for colocated transactions.";
-
-        return null;
-    }
-
-    /** {@inheritDoc} */
     @Override protected IgniteInternalFuture<Boolean> addReader(
         long msgId,
         GridDhtCacheEntry cached,
@@ -280,15 +273,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
      * @return {@code True} if transaction is fully synchronous.
      */
     private boolean sync() {
-        if (super.syncCommit())
-            return true;
-
-        for (int cacheId : activeCacheIds()) {
-            if (cctx.cacheContext(cacheId).config().getWriteSynchronizationMode() == FULL_SYNC)
-                return true;
-        }
-
-        return false;
+        return super.syncCommit() || txState().sync(cctx);
     }
 
     /**
@@ -471,7 +456,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     /**
      * @return DHT map.
      */
-    Map<UUID, GridDistributedTxMapping> mappings() {
+    IgniteTxMappings mappings() {
         return mappings;
     }
 
@@ -518,9 +503,9 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         GridDistributedTxMapping m = mappings.get(node.id());
 
         if (m == null)
-            mappings.put(node.id(), m = new GridDistributedTxMapping(node));
+            mappings.put(m = new GridDistributedTxMapping(node));
 
-        IgniteTxEntry txEntry = txMap.get(key);
+        IgniteTxEntry txEntry = entry(key);
 
         assert txEntry != null;
 
@@ -534,26 +519,10 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     }
 
     /**
-     * Adds keys mapping.
-     *
-     * @param n Mapped node.
-     * @param mappedKeys Mapped keys.
+     * @return Non-null entry if tx has only one write entry.
      */
-    private void addKeyMapping(ClusterNode n, Iterable<IgniteTxKey> mappedKeys) {
-        GridDistributedTxMapping m = mappings.get(n.id());
-
-        if (m == null)
-            mappings.put(n.id(), m = new GridDistributedTxMapping(n));
-
-        for (IgniteTxKey key : mappedKeys) {
-            IgniteTxEntry txEntry = txMap.get(key);
-
-            assert txEntry != null;
-
-            txEntry.nodeId(n.id());
-
-            m.add(txEntry);
-        }
+    @Nullable IgniteTxEntry singleWrite() {
+        return txState.singleWrite();
     }
 
     /**
@@ -567,7 +536,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
                 GridDistributedTxMapping m = mappings.get(n.id());
 
                 if (m == null) {
-                    m = F.addIfAbsent(mappings, n.id(), new GridDistributedTxMapping(n));
+                    mappings.put(m = new GridDistributedTxMapping(n));
 
                     m.near(map.near());
 
@@ -575,8 +544,6 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
                         m.markExplicitLock();
                 }
 
-                assert m != null;
-
                 for (IgniteTxEntry entry : map.entries())
                     m.add(entry);
             }
@@ -588,6 +555,25 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     }
 
     /**
+     * @param map Mapping.
+     * @param entry Entry.
+     */
+    void addSingleEntryMapping(GridDistributedTxMapping map, IgniteTxEntry entry) {
+        ClusterNode n = map.node();
+
+        GridDistributedTxMapping m = new GridDistributedTxMapping(n);
+
+        mappings.put(m);
+
+        m.near(map.near());
+
+        if (map.explicitLock())
+            m.markExplicitLock();
+
+        m.add(entry);
+    }
+
+    /**
      * @param nodeId Node ID to mark with explicit lock.
      * @return {@code True} if mapping was found.
      */
@@ -623,8 +609,23 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         Collection<GridCacheVersion> committedVers,
         Collection<GridCacheVersion> rolledbackVers)
     {
-        Collection<IgniteTxEntry> entries = F.concat(false, mapping.writes(), mapping.reads());
+        readyNearLocks(mapping.writes(), mapping.dhtVersion(), pendingVers, committedVers, rolledbackVers);
+        readyNearLocks(mapping.reads(), mapping.dhtVersion(), pendingVers, committedVers, rolledbackVers);
+    }
 
+    /**
+     * @param entries Entries.
+     * @param dhtVer DHT version.
+     * @param pendingVers Pending versions.
+     * @param committedVers Committed versions.
+     * @param rolledbackVers Rolled back versions.
+     */
+    void readyNearLocks(Collection<IgniteTxEntry> entries,
+        GridCacheVersion dhtVer,
+        Collection<GridCacheVersion> pendingVers,
+        Collection<GridCacheVersion> committedVers,
+        Collection<GridCacheVersion> rolledbackVers)
+    {
         for (IgniteTxEntry txEntry : entries) {
             while (true) {
                 GridCacheContext cacheCtx = txEntry.cached().context();
@@ -637,8 +638,13 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
                     // Handle explicit locks.
                     GridCacheVersion explicit = txEntry.explicitVersion();
 
-                    if (explicit == null)
-                        entry.readyNearLock(xidVer, mapping.dhtVersion(), committedVers, rolledbackVers, pendingVers);
+                    if (explicit == null) {
+                        entry.readyNearLock(xidVer,
+                            dhtVer,
+                            committedVers,
+                            rolledbackVers,
+                            pendingVers);
+                    }
 
                     break;
                 }
@@ -871,7 +877,6 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
      * @param writes Write entries.
      * @param txNodes Transaction nodes mapping.
      * @param last {@code True} if this is last prepare request.
-     * @param lastBackups IDs of backup nodes receiving last prepare request.
      * @return Future that will be completed when locks are acquired.
      */
     @SuppressWarnings("TypeMayBeWeakened")
@@ -879,8 +884,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         @Nullable Collection<IgniteTxEntry> reads,
         @Nullable Collection<IgniteTxEntry> writes,
         Map<UUID, Collection<UUID>> txNodes,
-        boolean last,
-        Collection<UUID> lastBackups
+        boolean last
     ) {
         if (state() != PREPARING) {
             if (timedOut())
@@ -901,8 +905,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
             IgniteUuid.randomUuid(),
             Collections.<IgniteTxKey, GridCacheVersion>emptyMap(),
             last,
-            needReturnValue() && implicit(),
-            lastBackups);
+            needReturnValue() && implicit());
 
         try {
             // At this point all the entries passed in must be enlisted in transaction because this is an
@@ -1274,6 +1277,6 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
 
     /** {@inheritDoc} */
     @Override public String toString() {
-        return S.toString(GridNearTxLocal.class, this, "mappings", mappings.keySet(), "super", super.toString());
+        return S.toString(GridNearTxLocal.class, this, "mappings", mappings, "super", super.toString());
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
index 456d726..798635a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
@@ -99,7 +99,6 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
      * @param near {@code True} if mapping is for near caches.
      * @param txNodes Transaction nodes mapping.
      * @param last {@code True} if this last prepare request for node.
-     * @param lastBackups IDs of backup nodes receiving last prepare request during this prepare.
      * @param onePhaseCommit One phase commit flag.
      * @param retVal Return value flag.
      * @param implicitSingle Implicit single flag.
@@ -118,7 +117,6 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
         boolean near,
         Map<UUID, Collection<UUID>> txNodes,
         boolean last,
-        Collection<UUID> lastBackups,
         boolean onePhaseCommit,
         boolean retVal,
         boolean implicitSingle,
@@ -137,7 +135,6 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
         this.topVer = topVer;
         this.near = near;
         this.last = last;
-        this.lastBackups = lastBackups;
         this.retVal = retVal;
         this.implicitSingle = implicitSingle;
         this.explicitLock = explicitLock;
@@ -153,12 +150,6 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
         return firstClientReq;
     }
 
-    /**
-     * @return IDs of backup nodes receiving last prepare request during this prepare.
-     */
-    public Collection<UUID> lastBackups() {
-        return lastBackups;
-    }
 
     /**
      * @return {@code True} if this last prepare request for node.

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
index 87c68b2..d078df4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
@@ -34,10 +34,12 @@ import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxRemoteAdapter;
 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.IgniteTxRemoteStateImpl;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.GridLeanMap;
 import org.apache.ignite.internal.util.tostring.GridToStringBuilder;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.transactions.TransactionConcurrency;
 import org.apache.ignite.transactions.TransactionIsolation;
 import org.jetbrains.annotations.Nullable;
@@ -74,7 +76,6 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
      * @param ldr Class loader.
      * @param nodeId Node ID.
      * @param nearNodeId Near node ID.
-     * @param rmtThreadId Remote thread ID.
      * @param xidVer XID version.
      * @param commitVer Commit version.
      * @param sys System flag.
@@ -92,7 +93,6 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
         ClassLoader ldr,
         UUID nodeId,
         UUID nearNodeId,
-        long rmtThreadId,
         GridCacheVersion xidVer,
         GridCacheVersion commitVer,
         boolean sys,
@@ -109,8 +109,7 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
         super(
             ctx, 
             nodeId, 
-            rmtThreadId, 
-            xidVer, 
+            xidVer,
             commitVer, 
             sys, 
             plc, 
@@ -127,10 +126,10 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
 
         this.nearNodeId = nearNodeId;
 
-        readMap = Collections.emptyMap();
+        int writeSize = writeEntries != null ? Math.max(txSize, writeEntries.size()) : txSize;
 
-        writeMap = new LinkedHashMap<>(
-            writeEntries != null ? Math.max(txSize, writeEntries.size()) : txSize, 1.0f);
+        txState = new IgniteTxRemoteStateImpl(Collections.<IgniteTxKey, IgniteTxEntry>emptyMap(),
+            U.<IgniteTxKey, IgniteTxEntry>newLinkedHashMap(writeSize));
 
         if (writeEntries != null) {
             for (IgniteTxEntry entry : writeEntries) {
@@ -147,7 +146,6 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
      * @param nodeId Node ID.
      * @param nearNodeId Near node ID.
      * @param nearXidVer Near transaction ID.
-     * @param rmtThreadId Remote thread ID.
      * @param xidVer XID version.
      * @param commitVer Commit version.
      * @param sys System flag.
@@ -163,7 +161,6 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
         UUID nodeId,
         UUID nearNodeId,
         GridCacheVersion nearXidVer,
-        long rmtThreadId,
         GridCacheVersion xidVer,
         GridCacheVersion commitVer,
         boolean sys,
@@ -179,8 +176,7 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
         super(
             ctx, 
             nodeId, 
-            rmtThreadId, 
-            xidVer, 
+            xidVer,
             commitVer,
             sys,
             plc,
@@ -198,8 +194,8 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
         this.nearXidVer = nearXidVer;
         this.nearNodeId = nearNodeId;
 
-        readMap = new LinkedHashMap<>(1, 1.0f);
-        writeMap = new LinkedHashMap<>(txSize, 1.0f);
+        txState = new IgniteTxRemoteStateImpl(U.<IgniteTxKey, IgniteTxEntry>newLinkedHashMap(1),
+            U.<IgniteTxKey, IgniteTxEntry>newLinkedHashMap(txSize));
     }
 
     /** {@inheritDoc} */
@@ -322,7 +318,7 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
                     // Initialize cache entry.
                     entry.cached(cached);
 
-                    writeMap.put(entry.txKey(), entry);
+                    txState.addWriteEntry(entry.txKey(), entry);
 
                     addExplicit(entry);
 
@@ -391,7 +387,7 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
                         drVer,
                         skipStore);
 
-                    writeMap.put(key, txEntry);
+                    txState.addWriteEntry(key, txEntry);
 
                     return true;
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappings.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappings.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappings.java
new file mode 100644
index 0000000..0465510
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappings.java
@@ -0,0 +1,75 @@
+/*
+ * 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.distributed.near;
+
+import java.util.Collection;
+import java.util.UUID;
+import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public interface IgniteTxMappings {
+    /**
+     * Clears this mappings.
+     */
+    public void clear();
+
+    /**
+     * @return {@code True} if there are no mappings.
+     */
+    public boolean empty();
+
+    /**
+     * @param nodeId Node ID.
+     * @return Node mapping.
+     */
+    @Nullable public GridDistributedTxMapping get(UUID nodeId);
+
+    /**
+     * @param mapping Mapping.
+     */
+    public void put(GridDistributedTxMapping mapping);
+
+    /**
+     * @param nodeId Node ID.
+     * @return Removed mapping.
+     */
+    @Nullable public GridDistributedTxMapping remove(UUID nodeId);
+
+    /**
+     * @return Mapping for local node.
+     */
+    @Nullable public GridDistributedTxMapping localMapping();
+
+    /**
+     * @return Non null instance if this mappings contain only one mapping.
+     */
+    @Nullable public GridDistributedTxMapping singleMapping();
+
+    /**
+     * @return All mappings.
+     */
+    public Collection<GridDistributedTxMapping> mappings();
+
+    /**
+     * @return {@code True} if this is single mapping.
+     */
+    public boolean single();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsImpl.java
new file mode 100644
index 0000000..7dec7af
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsImpl.java
@@ -0,0 +1,92 @@
+/*
+ * 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.distributed.near;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+import org.jsr166.ConcurrentHashMap8;
+
+/**
+ *
+ */
+public class IgniteTxMappingsImpl implements IgniteTxMappings {
+    /** */
+    private final Map<UUID, GridDistributedTxMapping> mappings = new ConcurrentHashMap8<>();
+
+    /** {@inheritDoc} */
+    @Override public void clear() {
+        mappings.clear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean empty() {
+        return mappings.isEmpty();
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDistributedTxMapping get(UUID nodeId) {
+        return mappings.get(nodeId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void put(GridDistributedTxMapping mapping) {
+        mappings.put(mapping.node().id(), mapping);
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDistributedTxMapping remove(UUID nodeId) {
+        return mappings.remove(nodeId);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridDistributedTxMapping localMapping() {
+        for (GridDistributedTxMapping m : mappings.values()) {
+            if (m.node().isLocal())
+                return m;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean single() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridDistributedTxMapping singleMapping() {
+        assert mappings.size() == 1 : mappings;
+
+        return F.firstValue(mappings);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridDistributedTxMapping> mappings() {
+        return mappings.values();
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return S.toString(IgniteTxMappingsImpl.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsSingleImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsSingleImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsSingleImpl.java
new file mode 100644
index 0000000..fc15592
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteTxMappingsSingleImpl.java
@@ -0,0 +1,101 @@
+/*
+ * 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.distributed.near;
+
+import java.util.Collection;
+import java.util.UUID;
+import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class IgniteTxMappingsSingleImpl implements IgniteTxMappings {
+    /** */
+    private volatile GridDistributedTxMapping mapping;
+
+    /** {@inheritDoc} */
+    @Override public void clear() {
+        mapping = null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean empty() {
+        return mapping == null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDistributedTxMapping get(UUID nodeId) {
+        GridDistributedTxMapping mapping0 = mapping;
+
+        return (mapping0 != null && mapping0.node().id().equals(nodeId)) ? mapping0 : null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void put(GridDistributedTxMapping mapping) {
+        assert this.mapping == null;
+
+        this.mapping = mapping;
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDistributedTxMapping remove(UUID nodeId) {
+        GridDistributedTxMapping mapping0 = mapping;
+
+        if (mapping0 != null && mapping0.node().id().equals(nodeId)) {
+            this.mapping = null;
+
+            return mapping0;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridDistributedTxMapping localMapping() {
+        GridDistributedTxMapping mapping0 = mapping;
+
+        if (mapping0 != null && mapping0.node().isLocal())
+            return mapping0;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean single() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridDistributedTxMapping singleMapping() {
+        return mapping;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<GridDistributedTxMapping> mappings() {
+        assert false;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return S.toString(IgniteTxMappingsSingleImpl.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
index 94af6bb..f5f99f5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
@@ -275,9 +275,9 @@ public interface IgniteInternalTx extends AutoCloseable, GridTimeoutObject {
     public boolean implicitSingle();
 
     /**
-     * @return Collection of cache IDs involved in this transaction.
+     * @return Transaction state.
      */
-    public Collection<Integer> activeCacheIds();
+    public IgniteTxState txState();
 
     /**
      * @return {@code true} or {@code false} if the deployment is enabled or disabled for all active caches involved
@@ -669,14 +669,6 @@ public interface IgniteInternalTx extends AutoCloseable, GridTimeoutObject {
     public boolean serializable();
 
     /**
-     * Checks whether given key has been removed within transaction.
-     *
-     * @param key Key to check.
-     * @return {@code True} if key has been removed.
-     */
-    public boolean removed(IgniteTxKey key);
-
-    /**
      * Gets allowed remaining time for this transaction.
      *
      * @return Remaining time.

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
index eb2ca2c..6a0f8ab 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
@@ -22,7 +22,6 @@ import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.ObjectStreamException;
-import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -50,7 +49,6 @@ import org.apache.ignite.internal.processors.cache.GridCacheOperation;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry;
-import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
 import org.apache.ignite.internal.processors.cache.version.GridCachePlainVersionedEntry;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext;
@@ -120,10 +118,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
     @GridToStringInclude
     protected boolean implicit;
 
-    /** Implicit with one key flag. */
-    @GridToStringInclude
-    protected boolean implicitSingle;
-
     /** Local flag. */
     @GridToStringInclude
     protected boolean loc;
@@ -262,7 +256,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
      * @param cctx Cache registry.
      * @param xidVer Transaction ID.
      * @param implicit Implicit flag.
-     * @param implicitSingle Implicit with one key flag.
      * @param loc Local flag.
      * @param sys System transaction flag.
      * @param plc IO policy.
@@ -275,7 +268,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
         GridCacheSharedContext<?, ?> cctx,
         GridCacheVersion xidVer,
         boolean implicit,
-        boolean implicitSingle,
         boolean loc,
         boolean sys,
         byte plc,
@@ -295,7 +287,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
         this.cctx = cctx;
         this.xidVer = xidVer;
         this.implicit = implicit;
-        this.implicitSingle = implicitSingle;
         this.loc = loc;
         this.sys = sys;
         this.plc = plc;
@@ -362,7 +353,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
         this.taskNameHash = taskNameHash;
 
         implicit = false;
-        implicitSingle = false;
         loc = false;
 
         if (log == null)
@@ -421,45 +411,7 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
 
     /** {@inheritDoc} */
     @Override public boolean storeUsed() {
-        if (!storeEnabled())
-            return false;
-
-        Collection<Integer> cacheIds = activeCacheIds();
-
-        if (!cacheIds.isEmpty()) {
-            for (int cacheId : cacheIds) {
-                CacheStoreManager store = cctx.cacheContext(cacheId).store();
-
-                if (store.configured())
-                    return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Store manager for current transaction.
-     *
-     * @return Store manager.
-     */
-    protected Collection<CacheStoreManager> stores() {
-        Collection<Integer> cacheIds = activeCacheIds();
-
-        if (!cacheIds.isEmpty()) {
-            Collection<CacheStoreManager> stores = new ArrayList<>(cacheIds.size());
-
-            for (int cacheId : cacheIds) {
-                CacheStoreManager store = cctx.cacheContext(cacheId).store();
-
-                if (store.configured())
-                    stores.add(store);
-            }
-
-            return stores;
-        }
-
-        return null;
+        return storeEnabled() && txState().storeUsed(cctx);
     }
 
     /**
@@ -645,7 +597,7 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
 
     /** {@inheritDoc} */
     @Override public boolean implicitSingle() {
-        return implicitSingle;
+        return txState().implicitSingle();
     }
 
     /** {@inheritDoc} */
@@ -1758,11 +1710,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
         }
 
         /** {@inheritDoc} */
-        @Override public Collection<Integer> activeCacheIds() {
-            throw new IllegalStateException("Deserialized transaction can only be used as read-only.");
-        }
-
-        /** {@inheritDoc} */
         @Override public boolean activeCachesDeploymentEnabled() {
             return false;
         }
@@ -1877,6 +1824,11 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
         }
 
         /** {@inheritDoc} */
+        @Override public IgniteTxState txState() {
+            return null;
+        }
+
+        /** {@inheritDoc} */
         @Override public Collection<UUID> masterNodeIds() {
             return null;
         }
@@ -2150,11 +2102,6 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter
         }
 
         /** {@inheritDoc} */
-        @Override public boolean removed(IgniteTxKey key) {
-            return false;
-        }
-
-        /** {@inheritDoc} */
         @Override public long remainingTime() throws IgniteTxTimeoutCheckedException {
             return 0;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
index 570aa48..0e5657b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
@@ -216,8 +216,7 @@ public class IgniteTxHandler {
             req.reads(),
             req.writes(),
             req.transactionNodes(),
-            req.last(),
-            req.lastBackups());
+            req.last());
 
         if (locTx.isRollbackOnly())
             locTx.rollbackAsync();
@@ -398,7 +397,6 @@ public class IgniteTxHandler {
 
             if (req.onePhaseCommit()) {
                 assert req.last();
-                assert F.isEmpty(req.lastBackups()) || req.lastBackups().size() <= 1;
 
                 tx.onePhaseCommit(true);
             }
@@ -413,8 +411,7 @@ public class IgniteTxHandler {
                 req.messageId(),
                 req.miniId(),
                 req.transactionNodes(),
-                req.last(),
-                req.lastBackups());
+                req.last());
 
             if (tx.isRollbackOnly()) {
                 try {
@@ -1091,12 +1088,13 @@ public class IgniteTxHandler {
             GridDhtTxRemote tx = ctx.tm().tx(req.version());
 
             if (tx == null) {
+                boolean single = req.last() && req.writes().size() == 1;
+
                 tx = new GridDhtTxRemote(
                     ctx,
                     req.nearNodeId(),
                     req.futureId(),
                     nodeId,
-                    req.threadId(),
                     req.topologyVersion(),
                     req.version(),
                     null,
@@ -1110,7 +1108,8 @@ public class IgniteTxHandler {
                     req.nearXidVersion(),
                     req.transactionNodes(),
                     req.subjectId(),
-                    req.taskNameHash());
+                    req.taskNameHash(),
+                    single);
 
                 tx.writeVersion(req.writeVersion());
 
@@ -1138,7 +1137,7 @@ public class IgniteTxHandler {
                 tx.transactionNodes(req.transactionNodes());
             }
 
-            if (!tx.isSystemInvalidate() && !F.isEmpty(req.writes())) {
+            if (!tx.isSystemInvalidate()) {
                 int idx = 0;
 
                 for (IgniteTxEntry entry : req.writes()) {
@@ -1236,7 +1235,6 @@ public class IgniteTxHandler {
                     ldr,
                     nodeId,
                     req.nearNodeId(),
-                    req.threadId(),
                     req.version(),
                     null,
                     req.system(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
new file mode 100644
index 0000000..5f48469
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
@@ -0,0 +1,259 @@
+/*
+ * 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.transactions;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
+import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteTxImplicitSingleStateImpl extends IgniteTxLocalStateAdapter {
+    /** */
+    private GridCacheContext cacheCtx;
+
+    /** */
+    private IgniteTxEntry entry;
+
+    /** */
+    private boolean init;
+
+    /** {@inheritDoc} */
+    @Override public void addActiveCache(GridCacheContext ctx, IgniteTxLocalAdapter tx)
+        throws IgniteCheckedException {
+        assert cacheCtx == null : "Cache already set [cur=" + cacheCtx.name() + ", new=" + ctx.name() + ']';
+
+        this.cacheCtx = ctx;
+
+        tx.activeCachesDeploymentEnabled(cacheCtx.deploymentEnabled());
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridCacheContext singleCacheContext(GridCacheSharedContext cctx) {
+        return cacheCtx;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Integer firstCacheId() {
+        return cacheCtx != null ? cacheCtx.cacheId() : null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void awaitLastFut(GridCacheSharedContext ctx) {
+        if (cacheCtx == null)
+            return;
+
+        cacheCtx.cache().awaitLastFut();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean implicitSingle() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCheckedException validateTopology(GridCacheSharedContext cctx, GridDhtTopologyFuture topFut) {
+        if (cacheCtx == null)
+            return null;
+
+        Throwable err = topFut.validateCache(cacheCtx);
+
+        if (err != null) {
+            return new IgniteCheckedException("Failed to perform cache operation (cache topology is not valid): " +
+                U.maskName(cacheCtx.name()));
+        }
+
+        if (CU.affinityNodes(cacheCtx, topFut.topologyVersion()).isEmpty()) {
+            return new ClusterTopologyServerNotFoundException("Failed to map keys for cache (all " +
+                "partition nodes left the grid): " + cacheCtx.name());
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean sync(GridCacheSharedContext cctx) {
+        return cacheCtx != null && cacheCtx.config().getWriteSynchronizationMode() == FULL_SYNC;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasNearCache(GridCacheSharedContext cctx) {
+        return cacheCtx != null && cacheCtx.isNear();
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDhtTopologyFuture topologyReadLock(GridCacheSharedContext cctx, GridFutureAdapter<?> fut) {
+        if (cacheCtx == null || cacheCtx.isLocal())
+            return cctx.exchange().lastTopologyFuture();
+
+        cacheCtx.topology().readLock();
+
+        if (cacheCtx.topology().stopping()) {
+            fut.onDone(new IgniteCheckedException("Failed to perform cache operation (cache is stopped): " +
+                cacheCtx.name()));
+
+            return null;
+        }
+
+        return cacheCtx.topology().topologyVersionFuture();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void topologyReadUnlock(GridCacheSharedContext cctx) {
+        if (cacheCtx == null || cacheCtx.isLocal())
+            return;
+
+        cacheCtx.topology().readUnlock();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean storeUsed(GridCacheSharedContext cctx) {
+        if (cacheCtx == null)
+            return false;
+
+        CacheStoreManager store = cacheCtx.store();
+
+        return store.configured();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
+        if (cacheCtx == null)
+            return null;
+
+        CacheStoreManager store = cacheCtx.store();
+
+        if (store.configured())
+            return Collections.singleton(store);
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onTxEnd(GridCacheSharedContext cctx, IgniteInternalTx tx, boolean commit) {
+        if (cacheCtx != null)
+            onTxEnd(cacheCtx, tx, commit);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry entry(IgniteTxKey key) {
+        if (entry != null && entry.txKey().equals(key))
+            return entry;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasWriteKey(IgniteTxKey key) {
+        return entry != null && entry.txKey().equals(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> readSet() {
+        return Collections.emptySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> writeSet() {
+        return entry != null ? Collections.singleton(entry.txKey()) : Collections.<IgniteTxKey>emptySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> writeEntries() {
+        return entry != null ? Collections.singletonList(entry) : Collections.<IgniteTxEntry>emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> readEntries() {
+        return Collections.emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
+        return entry != null ? Collections.singletonMap(entry.txKey(), entry) :
+            Collections.<IgniteTxKey, IgniteTxEntry>emptyMap();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
+        return Collections.emptyMap();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean empty() {
+        return entry == null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> allEntries() {
+        return entry != null ? Collections.singletonList(entry) : Collections.<IgniteTxEntry>emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean init(int txSize) {
+        if (!init) {
+            init = true;
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean initialized() {
+        return init;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addEntry(IgniteTxEntry entry) {
+        assert this.entry == null : "Entry already set [cur=" + this.entry + ", new=" + entry + ']';
+
+        this.entry = entry;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void seal() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry singleWrite() {
+        return entry;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return S.toString(IgniteTxImplicitSingleStateImpl.class, this);
+    }
+}


[32/37] ignite git commit: IGNITE-426 Implemented failover for Continuous query.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
index 1219f2f..72a60d2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
@@ -78,6 +78,11 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
     @GridDirectCollection(CacheObject.class)
     private List<CacheObject> vals;
 
+    /** Previous values. */
+    @GridToStringInclude
+    @GridDirectCollection(CacheObject.class)
+    private List<CacheObject> prevVals;
+
     /** Conflict versions. */
     @GridDirectCollection(GridCacheVersion.class)
     private List<GridCacheVersion> conflictVers;
@@ -139,10 +144,19 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
     /** Task name hash. */
     private int taskNameHash;
 
+    /** Partition. */
+    private GridLongList updateCntrs;
+
     /** On response flag. Access should be synced on future. */
     @GridDirectTransient
     private boolean onRes;
 
+    @GridDirectTransient
+    private List<Integer> partIds;
+
+    @GridDirectTransient
+    private List<CacheObject> localPrevVals;
+
     /**
      * Empty constructor required by {@link Externalizable}.
      */
@@ -193,6 +207,8 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
         this.addDepInfo = addDepInfo;
 
         keys = new ArrayList<>();
+        partIds = new ArrayList<>();
+        localPrevVals = new ArrayList<>();
 
         if (forceTransformBackups) {
             entryProcessors = new ArrayList<>();
@@ -216,15 +232,25 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
      * @param ttl TTL (optional).
      * @param conflictExpireTime Conflict expire time (optional).
      * @param conflictVer Conflict version (optional).
+     * @param addPrevVal If {@code true} adds previous value.
+     * @param prevVal Previous value.
      */
     public void addWriteValue(KeyCacheObject key,
         @Nullable CacheObject val,
         EntryProcessor<Object, Object, Object> entryProcessor,
         long ttl,
         long conflictExpireTime,
-        @Nullable GridCacheVersion conflictVer) {
+        @Nullable GridCacheVersion conflictVer,
+        boolean addPrevVal,
+        int partId,
+        @Nullable CacheObject prevVal,
+        @Nullable Long updateIdx) {
         keys.add(key);
 
+        partIds.add(partId);
+
+        localPrevVals.add(prevVal);
+
         if (forceTransformBackups) {
             assert entryProcessor != null;
 
@@ -233,6 +259,20 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
         else
             vals.add(val);
 
+        if (addPrevVal) {
+            if (prevVals == null)
+                prevVals = new ArrayList<>();
+
+            prevVals.add(prevVal);
+        }
+
+        if (updateIdx != null) {
+            if (updateCntrs == null)
+                updateCntrs = new GridLongList();
+
+            updateCntrs.add(updateIdx);
+        }
+
         // In case there is no conflict, do not create the list.
         if (conflictVer != null) {
             if (conflictVers == null) {
@@ -283,8 +323,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
         @Nullable CacheObject val,
         EntryProcessor<Object, Object, Object> entryProcessor,
         long ttl,
-        long expireTime)
-    {
+        long expireTime) {
         if (nearKeys == null) {
             nearKeys = new ArrayList<>();
 
@@ -415,6 +454,25 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
     }
 
     /**
+     * @param idx Partition index.
+     * @return Partition id.
+     */
+    public int partitionId(int idx) {
+        return partIds.get(idx);
+    }
+
+    /**
+     * @param updCntr Update counter.
+     * @return Update counter.
+     */
+    public Long updateCounter(int updCntr) {
+        if (updateCntrs != null && updCntr < updateCntrs.size())
+            return updateCntrs.get(updCntr);
+
+        return null;
+    }
+
+    /**
      * @param idx Near key index.
      * @return Key.
      */
@@ -435,6 +493,25 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
     /**
      * @param idx Key index.
+     * @return Value.
+     */
+    @Nullable public CacheObject previousValue(int idx) {
+        if (prevVals != null)
+            return prevVals.get(idx);
+
+        return null;
+    }
+
+    /**
+     * @param idx Key index.
+     * @return Value.
+     */
+    @Nullable public CacheObject localPreviousValue(int idx) {
+        return localPrevVals.get(idx);
+    }
+
+    /**
+     * @param idx Key index.
      * @return Entry processor.
      */
     @Nullable public EntryProcessor<Object, Object, Object> entryProcessor(int idx) {
@@ -544,8 +621,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
         return invokeArgs;
     }
 
-    /** {@inheritDoc}
-     * @param ctx*/
+    /** {@inheritDoc} */
     @Override public void prepareMarshal(GridCacheSharedContext ctx) throws IgniteCheckedException {
         super.prepareMarshal(ctx);
 
@@ -695,42 +771,54 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
                 writer.incrementState();
 
             case 16:
-                if (!writer.writeUuid("subjId", subjId))
+                if (!writer.writeCollection("prevVals", prevVals, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
             case 17:
-                if (!writer.writeByte("syncMode", syncMode != null ? (byte)syncMode.ordinal() : -1))
+                if (!writer.writeUuid("subjId", subjId))
                     return false;
 
                 writer.incrementState();
 
             case 18:
-                if (!writer.writeInt("taskNameHash", taskNameHash))
+                if (!writer.writeByte("syncMode", syncMode != null ? (byte)syncMode.ordinal() : -1))
                     return false;
 
                 writer.incrementState();
 
             case 19:
-                if (!writer.writeMessage("topVer", topVer))
+                if (!writer.writeInt("taskNameHash", taskNameHash))
                     return false;
 
                 writer.incrementState();
 
             case 20:
-                if (!writer.writeMessage("ttls", ttls))
+                if (!writer.writeMessage("topVer", topVer))
                     return false;
 
                 writer.incrementState();
 
             case 21:
-                if (!writer.writeCollection("vals", vals, MessageCollectionItemType.MSG))
+                if (!writer.writeMessage("ttls", ttls))
                     return false;
 
                 writer.incrementState();
 
             case 22:
+                if (!writer.writeMessage("updateCntrs", updateCntrs))
+                    return false;
+
+                writer.incrementState();
+
+            case 23:
+                if (!writer.writeCollection("vals", vals, MessageCollectionItemType.MSG))
+                    return false;
+
+                writer.incrementState();
+
+            case 24:
                 if (!writer.writeMessage("writeVer", writeVer))
                     return false;
 
@@ -857,7 +945,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
                 reader.incrementState();
 
             case 16:
-                subjId = reader.readUuid("subjId");
+                prevVals = reader.readCollection("prevVals", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
                     return false;
@@ -865,6 +953,14 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
                 reader.incrementState();
 
             case 17:
+                subjId = reader.readUuid("subjId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 18:
                 byte syncModeOrd;
 
                 syncModeOrd = reader.readByte("syncMode");
@@ -876,7 +972,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
                 reader.incrementState();
 
-            case 18:
+            case 19:
                 taskNameHash = reader.readInt("taskNameHash");
 
                 if (!reader.isLastRead())
@@ -884,7 +980,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
                 reader.incrementState();
 
-            case 19:
+            case 20:
                 topVer = reader.readMessage("topVer");
 
                 if (!reader.isLastRead())
@@ -892,7 +988,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
                 reader.incrementState();
 
-            case 20:
+            case 21:
                 ttls = reader.readMessage("ttls");
 
                 if (!reader.isLastRead())
@@ -900,7 +996,15 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
                 reader.incrementState();
 
-            case 21:
+            case 22:
+                updateCntrs = reader.readMessage("updateCntrs");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 23:
                 vals = reader.readCollection("vals", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
@@ -908,7 +1012,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
                 reader.incrementState();
 
-            case 22:
+            case 24:
                 writeVer = reader.readMessage("writeVer");
 
                 if (!reader.isLastRead())
@@ -928,7 +1032,7 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 23;
+        return 25;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
index 2f2944d..43f34c9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsExchangeFuture.java
@@ -613,7 +613,9 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
                                 if (updateTop) {
                                     for (GridClientPartitionTopology top : cctx.exchange().clientTopologies()) {
                                         if (top.cacheId() == cacheCtx.cacheId()) {
-                                            cacheCtx.topology().update(exchId, top.partitionMap(true));
+                                            cacheCtx.topology().update(exchId,
+                                                top.partitionMap(true),
+                                                top.updateCounters());
 
                                             break;
                                         }
@@ -813,6 +815,8 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
                     }
                 }
 
+                boolean topChanged = discoEvt.type() != EVT_DISCOVERY_CUSTOM_EVT;
+
                 for (GridCacheContext cacheCtx : cctx.cacheContexts()) {
                     if (cacheCtx.isLocal())
                         continue;
@@ -823,6 +827,9 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
                     if (drCacheCtx.isDrEnabled())
                         drCacheCtx.dr().beforeExchange(topVer, exchId.isLeft());
 
+                    if (topChanged)
+                        cacheCtx.continuousQueries().beforeExchange(exchId.topologyVersion());
+
                     // Partition release future is done so we can flush the write-behind store.
                     cacheCtx.store().forceFlush();
 
@@ -956,14 +963,18 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
      * @param id ID.
      * @throws IgniteCheckedException If failed.
      */
-    private void sendLocalPartitions(ClusterNode node, @Nullable GridDhtPartitionExchangeId id) throws IgniteCheckedException {
+    private void sendLocalPartitions(ClusterNode node, @Nullable GridDhtPartitionExchangeId id)
+        throws IgniteCheckedException {
         GridDhtPartitionsSingleMessage m = new GridDhtPartitionsSingleMessage(id,
             clientOnlyExchange,
             cctx.versions().last());
 
         for (GridCacheContext cacheCtx : cctx.cacheContexts()) {
-            if (!cacheCtx.isLocal())
+            if (!cacheCtx.isLocal()) {
                 m.addLocalPartitionMap(cacheCtx.cacheId(), cacheCtx.topology().localPartitionMap());
+
+                m.partitionUpdateCounters(cacheCtx.cacheId(), cacheCtx.topology().updateCounters());
+            }
         }
 
         if (log.isDebugEnabled())
@@ -989,15 +1000,21 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
 
                 boolean ready = startTopVer == null || startTopVer.compareTo(id.topologyVersion()) <= 0;
 
-                if (ready)
+                if (ready) {
                     m.addFullPartitionsMap(cacheCtx.cacheId(), cacheCtx.topology().partitionMap(true));
+
+                    m.addPartitionUpdateCounters(cacheCtx.cacheId(), cacheCtx.topology().updateCounters());
+                }
             }
         }
 
         // It is important that client topologies be added after contexts.
-        for (GridClientPartitionTopology top : cctx.exchange().clientTopologies())
+        for (GridClientPartitionTopology top : cctx.exchange().clientTopologies()) {
             m.addFullPartitionsMap(top.cacheId(), top.partitionMap(true));
 
+            m.addPartitionUpdateCounters(top.cacheId(), top.updateCounters());
+        }
+
         if (log.isDebugEnabled())
             log.debug("Sending full partition map [nodeIds=" + F.viewReadOnly(nodes, F.node2id()) +
                 ", exchId=" + exchId + ", msg=" + m + ']');
@@ -1334,15 +1351,17 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
         for (Map.Entry<Integer, GridDhtPartitionFullMap> entry : msg.partitions().entrySet()) {
             Integer cacheId = entry.getKey();
 
+            Map<Integer, Long> cntrMap = msg.partitionUpdateCounters(cacheId);
+
             GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
 
             if (cacheCtx != null)
-                cacheCtx.topology().update(exchId, entry.getValue());
+                cacheCtx.topology().update(exchId, entry.getValue(), cntrMap);
             else {
                 ClusterNode oldest = CU.oldestAliveCacheServerNode(cctx, AffinityTopologyVersion.NONE);
 
                 if (oldest != null && oldest.isLocal())
-                    cctx.exchange().clientTopology(cacheId, this).update(exchId, entry.getValue());
+                    cctx.exchange().clientTopology(cacheId, this).update(exchId, entry.getValue(), cntrMap);
             }
         }
     }
@@ -1360,7 +1379,7 @@ public class GridDhtPartitionsExchangeFuture extends GridFutureAdapter<AffinityT
             GridDhtPartitionTopology top = cacheCtx != null ? cacheCtx.topology() :
                 cctx.exchange().clientTopology(cacheId, this);
 
-            top.update(exchId, entry.getValue());
+            top.update(exchId, entry.getValue(), msg.partitionUpdateCounters(cacheId));
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
index c06d773..3f4f9bc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsFullMessage.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.distributed.dht.preloader;
 
 import java.io.Externalizable;
 import java.nio.ByteBuffer;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.ignite.IgniteCheckedException;
@@ -48,6 +49,14 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
     /** */
     private byte[] partsBytes;
 
+    /** Partitions update counters. */
+    @GridToStringInclude
+    @GridDirectTransient
+    private Map<Integer, Map<Integer, Long>> partCntrs;
+
+    /** Serialized partitions counters. */
+    private byte[] partCntrsBytes;
+
     /** Topology version. */
     private AffinityTopologyVersion topVer;
 
@@ -92,13 +101,41 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
             parts.put(cacheId, fullMap);
     }
 
-    /** {@inheritDoc}
-     * @param ctx*/
+    /**
+     * @param cacheId Cache ID.
+     * @param cntrMap Partition update counters.
+     */
+    public void addPartitionUpdateCounters(int cacheId, Map<Integer, Long> cntrMap) {
+        if (partCntrs == null)
+            partCntrs = new HashMap<>();
+
+        if (!partCntrs.containsKey(cacheId))
+            partCntrs.put(cacheId, cntrMap);
+    }
+
+    /**
+     * @param cacheId Cache ID.
+     * @return Partition update counters.
+     */
+    public Map<Integer, Long> partitionUpdateCounters(int cacheId) {
+        if (partCntrs != null) {
+            Map<Integer, Long> res = partCntrs.get(cacheId);
+
+            return res != null ? res : Collections.<Integer, Long>emptyMap();
+        }
+
+        return Collections.emptyMap();
+    }
+
+    /** {@inheritDoc} */
     @Override public void prepareMarshal(GridCacheSharedContext ctx) throws IgniteCheckedException {
         super.prepareMarshal(ctx);
 
         if (parts != null && partsBytes == null)
             partsBytes = ctx.marshaller().marshal(parts);
+
+        if (partCntrs != null)
+            partCntrsBytes = ctx.marshaller().marshal(partCntrs);
     }
 
     /**
@@ -121,6 +158,9 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
 
         if (partsBytes != null && parts == null)
             parts = ctx.marshaller().unmarshal(partsBytes, ldr);
+
+        if (partCntrsBytes != null)
+            partCntrs = ctx.marshaller().unmarshal(partCntrsBytes, ldr);
     }
 
     /** {@inheritDoc} */
@@ -139,12 +179,18 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
 
         switch (writer.state()) {
             case 5:
-                if (!writer.writeByteArray("partsBytes", partsBytes))
+                if (!writer.writeByteArray("partCntrsBytes", partCntrsBytes))
                     return false;
 
                 writer.incrementState();
 
             case 6:
+                if (!writer.writeByteArray("partsBytes", partsBytes))
+                    return false;
+
+                writer.incrementState();
+
+            case 7:
                 if (!writer.writeMessage("topVer", topVer))
                     return false;
 
@@ -167,7 +213,7 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
 
         switch (reader.state()) {
             case 5:
-                partsBytes = reader.readByteArray("partsBytes");
+                partCntrsBytes = reader.readByteArray("partCntrsBytes");
 
                 if (!reader.isLastRead())
                     return false;
@@ -175,6 +221,14 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
                 reader.incrementState();
 
             case 6:
+                partsBytes = reader.readByteArray("partsBytes");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 7:
                 topVer = reader.readMessage("topVer");
 
                 if (!reader.isLastRead())
@@ -194,7 +248,7 @@ public class GridDhtPartitionsFullMessage extends GridDhtPartitionsAbstractMessa
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 7;
+        return 8;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
index 83fbb1a..a2366bf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/preloader/GridDhtPartitionsSingleMessage.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.distributed.dht.preloader;
 
 import java.io.Externalizable;
 import java.nio.ByteBuffer;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import org.apache.ignite.IgniteCheckedException;
@@ -46,6 +47,14 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
     /** Serialized partitions. */
     private byte[] partsBytes;
 
+    /** Partitions update counters. */
+    @GridToStringInclude
+    @GridDirectTransient
+    private Map<Integer, Map<Integer, Long>> partCntrs;
+
+    /** Serialized partitions counters. */
+    private byte[] partCntrsBytes;
+
     /** */
     private boolean client;
 
@@ -90,6 +99,31 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
     }
 
     /**
+     * @param cacheId Cache ID.
+     * @param cntrMap Partition update counters.
+     */
+    public void partitionUpdateCounters(int cacheId, Map<Integer, Long> cntrMap) {
+        if (partCntrs == null)
+            partCntrs = new HashMap<>();
+
+        partCntrs.put(cacheId, cntrMap);
+    }
+
+    /**
+     * @param cacheId Cache ID.
+     * @return Partition update counters.
+     */
+    public Map<Integer, Long> partitionUpdateCounters(int cacheId) {
+        if (partCntrs != null) {
+            Map<Integer, Long> res = partCntrs.get(cacheId);
+
+            return res != null ? res : Collections.<Integer, Long>emptyMap();
+        }
+
+        return Collections.emptyMap();
+    }
+
+    /**
      * @return Local partitions.
      */
     public Map<Integer, GridDhtPartitionMap> partitions() {
@@ -103,6 +137,9 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
 
         if (partsBytes == null && parts != null)
             partsBytes = ctx.marshaller().marshal(parts);
+
+        if (partCntrs != null)
+            partCntrsBytes = ctx.marshaller().marshal(partCntrs);
     }
 
     /** {@inheritDoc} */
@@ -111,6 +148,9 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
 
         if (partsBytes != null && parts == null)
             parts = ctx.marshaller().unmarshal(partsBytes, ldr);
+
+        if (partCntrsBytes != null)
+            partCntrs = ctx.marshaller().unmarshal(partCntrsBytes, ldr);
     }
 
     /** {@inheritDoc} */
@@ -135,6 +175,12 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
                 writer.incrementState();
 
             case 6:
+                if (!writer.writeByteArray("partCntrsBytes", partCntrsBytes))
+                    return false;
+
+                writer.incrementState();
+
+            case 7:
                 if (!writer.writeByteArray("partsBytes", partsBytes))
                     return false;
 
@@ -165,6 +211,14 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
                 reader.incrementState();
 
             case 6:
+                partCntrsBytes = reader.readByteArray("partCntrsBytes");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 7:
                 partsBytes = reader.readByteArray("partsBytes");
 
                 if (!reader.isLastRead())
@@ -184,7 +238,7 @@ public class GridDhtPartitionsSingleMessage extends GridDhtPartitionsAbstractMes
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 7;
+        return 8;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
index 1bf03a9..706655b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
@@ -249,7 +249,7 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
                         /*write-through*/false,
                         /*read-through*/false,
                         /*retval*/false,
-                        /**expiry policy*/null,
+                        /*expiry policy*/null,
                         /*event*/true,
                         /*metrics*/true,
                         /*primary*/false,
@@ -263,7 +263,9 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
                         false,
                         false,
                         subjId,
-                        taskName);
+                        taskName,
+                        null,
+                        null);
 
                     if (updRes.removeVersion() != null)
                         ctx.onDeferredDelete(entry, updRes.removeVersion());
@@ -361,7 +363,9 @@ public class GridNearAtomicCache<K, V> extends GridNearCacheAdapter<K, V> {
                             false,
                             intercept,
                             req.subjectId(),
-                            taskName);
+                            taskName,
+                            null,
+                            null);
 
                         if (updRes.removeVersion() != null)
                             ctx.onDeferredDelete(entry, updRes.removeVersion());

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
index d078df4..ba58f57 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
@@ -226,6 +226,13 @@ public class GridNearTxRemote extends GridDistributedTxRemoteAdapter {
     }
 
     /**
+     * @param cntrs Partition indexes.
+     */
+    @Override public void setPartitionUpdateCounters(long[] cntrs) {
+        // No-op.
+    }
+
+    /**
      * Adds owned versions to map.
      *
      * @param vers Map of owned versions.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryBatchAck.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryBatchAck.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryBatchAck.java
new file mode 100644
index 0000000..7db9026
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryBatchAck.java
@@ -0,0 +1,163 @@
+/*
+ * 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.query.continuous;
+
+import java.nio.ByteBuffer;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.internal.GridDirectMap;
+import org.apache.ignite.internal.processors.cache.GridCacheMessage;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Batch acknowledgement.
+ */
+public class CacheContinuousQueryBatchAck extends GridCacheMessage {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Routine ID. */
+    private UUID routineId;
+
+    /** Update counters. */
+    @GridToStringInclude
+    @GridDirectMap(keyType = Integer.class, valueType = Long.class)
+    private Map<Integer, Long> updateCntrs;
+
+    /**
+     * Default constructor.
+     */
+    public CacheContinuousQueryBatchAck() {
+        // No-op.
+    }
+
+    /**
+     * @param cacheId Cache ID.
+     * @param routineId Routine ID.
+     * @param updateCntrs Update counters.
+     */
+    CacheContinuousQueryBatchAck(int cacheId, UUID routineId, Map<Integer, Long> updateCntrs) {
+        this.cacheId = cacheId;
+        this.routineId = routineId;
+        this.updateCntrs = updateCntrs;
+    }
+
+    /**
+     * @return Routine ID.
+     */
+    UUID routineId() {
+        return routineId;
+    }
+
+    /**
+     * @return Update counters.
+     */
+    Map<Integer, Long> updateCntrs() {
+        return updateCntrs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!super.writeTo(buf, writer))
+            return false;
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 3:
+                if (!writer.writeUuid("routineId", routineId))
+                    return false;
+
+                writer.incrementState();
+
+            case 4:
+                if (!writer.writeMap("updateCntrs", updateCntrs, MessageCollectionItemType.INT,
+                    MessageCollectionItemType.LONG))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        if (!super.readFrom(buf, reader))
+            return false;
+
+        switch (reader.state()) {
+            case 3:
+                routineId = reader.readUuid("routineId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 4:
+                updateCntrs = reader.readMap("updateCntrs", MessageCollectionItemType.INT,
+                    MessageCollectionItemType.LONG, false);
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(CacheContinuousQueryBatchAck.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean addDeploymentInfo() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte directType() {
+        return 118;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 5;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(CacheContinuousQueryBatchAck.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java
index a4b35eb..0495e6d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEntry.java
@@ -22,10 +22,12 @@ import javax.cache.event.EventType;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.managers.deployment.GridDeploymentInfo;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheDeployable;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -42,6 +44,12 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
     private static final long serialVersionUID = 0L;
 
     /** */
+    private static final byte BACKUP_ENTRY = 0b0001;
+
+    /** */
+    private static final byte FILTERED_ENTRY = 0b0010;
+
+    /** */
     private static final EventType[] EVT_TYPE_VALS = EventType.values();
 
     /**
@@ -75,8 +83,24 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
     @GridDirectTransient
     private GridDeploymentInfo depInfo;
 
+    /** Partition. */
+    private int part;
+
+    /** Update counter. */
+    private long updateCntr;
+
+    /** Flags. */
+    private byte flags;
+
+    /** */
+    @GridToStringInclude
+    private AffinityTopologyVersion topVer;
+
+    /** Filtered events. */
+    private GridLongList filteredEvts;
+
     /**
-     * Required by {@link org.apache.ignite.plugin.extensions.communication.Message}.
+     * Required by {@link Message}.
      */
     public CacheContinuousQueryEntry() {
         // No-op.
@@ -88,18 +112,34 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
      * @param key Key.
      * @param newVal New value.
      * @param oldVal Old value.
+     * @param part Partition.
+     * @param updateCntr Update partition counter.
+     * @param topVer Topology version if applicable.
      */
     CacheContinuousQueryEntry(
         int cacheId,
         EventType evtType,
         KeyCacheObject key,
         @Nullable CacheObject newVal,
-        @Nullable CacheObject oldVal) {
+        @Nullable CacheObject oldVal,
+        int part,
+        long updateCntr,
+        @Nullable AffinityTopologyVersion topVer) {
         this.cacheId = cacheId;
         this.evtType = evtType;
         this.key = key;
         this.newVal = newVal;
         this.oldVal = oldVal;
+        this.part = part;
+        this.updateCntr = updateCntr;
+        this.topVer = topVer;
+    }
+
+    /**
+     * @return Topology version if applicable.
+     */
+    @Nullable AffinityTopologyVersion topologyVersion() {
+        return topVer;
     }
 
     /**
@@ -117,6 +157,66 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
     }
 
     /**
+     * @return Partition.
+     */
+    int partition() {
+        return part;
+    }
+
+    /**
+     * @return Update counter.
+     */
+    long updateCounter() {
+        return updateCntr;
+    }
+
+    /**
+     * Mark that entry create on backup.
+     */
+    void markBackup() {
+        flags |= BACKUP_ENTRY;
+    }
+
+    /**
+     * Mark that entry filtered.
+     */
+    void markFiltered() {
+        flags |= FILTERED_ENTRY;
+        newVal = null;
+        oldVal = null;
+        key = null;
+        depInfo = null;
+    }
+
+    /**
+     * @return {@code True} if entry sent by backup node.
+     */
+    boolean isBackup() {
+        return (flags & BACKUP_ENTRY) != 0;
+    }
+
+    /**
+     * @return {@code True} if entry was filtered.
+     */
+    boolean isFiltered() {
+        return (flags & FILTERED_ENTRY) != 0;
+    }
+
+    /**
+     * @param cntrs Filtered events.
+     */
+    void filteredEvents(GridLongList cntrs) {
+        filteredEvts = cntrs;
+    }
+
+    /**
+     * @return previous filtered events.
+     */
+    long[] filteredEvents() {
+        return filteredEvts == null ? null : filteredEvts.array();
+    }
+
+    /**
      * @param cctx Cache context.
      * @throws IgniteCheckedException In case of error.
      */
@@ -138,13 +238,15 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
      * @throws IgniteCheckedException In case of error.
      */
     void unmarshal(GridCacheContext cctx, @Nullable ClassLoader ldr) throws IgniteCheckedException {
-        key.finishUnmarshal(cctx.cacheObjectContext(), ldr);
+        if (!isFiltered()) {
+            key.finishUnmarshal(cctx.cacheObjectContext(), ldr);
 
-        if (newVal != null)
-            newVal.finishUnmarshal(cctx.cacheObjectContext(), ldr);
+            if (newVal != null)
+                newVal.finishUnmarshal(cctx.cacheObjectContext(), ldr);
 
-        if (oldVal != null)
-            oldVal.finishUnmarshal(cctx.cacheObjectContext(), ldr);
+            if (oldVal != null)
+                oldVal.finishUnmarshal(cctx.cacheObjectContext(), ldr);
+        }
     }
 
     /**
@@ -208,23 +310,53 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
                 writer.incrementState();
 
             case 2:
-                if (!writer.writeMessage("key", key))
+                if (!writer.writeMessage("filteredEvts", filteredEvts))
                     return false;
 
                 writer.incrementState();
 
             case 3:
-                if (!writer.writeMessage("newVal", newVal))
+                if (!writer.writeByte("flags", flags))
                     return false;
 
                 writer.incrementState();
 
             case 4:
+                if (!writer.writeMessage("key", key))
+                    return false;
+
+                writer.incrementState();
+
+            case 5:
+                if (!writer.writeMessage("newVal", newVal))
+                    return false;
+
+                writer.incrementState();
+
+            case 6:
                 if (!writer.writeMessage("oldVal", oldVal))
                     return false;
 
                 writer.incrementState();
 
+            case 7:
+                if (!writer.writeInt("part", part))
+                    return false;
+
+                writer.incrementState();
+
+            case 8:
+                if (!writer.writeMessage("topVer", topVer))
+                    return false;
+
+                writer.incrementState();
+
+            case 9:
+                if (!writer.writeLong("updateCntr", updateCntr))
+                    return false;
+
+                writer.incrementState();
+
         }
 
         return true;
@@ -259,7 +391,7 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
                 reader.incrementState();
 
             case 2:
-                key = reader.readMessage("key");
+                filteredEvts = reader.readMessage("filteredEvts");
 
                 if (!reader.isLastRead())
                     return false;
@@ -267,7 +399,7 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
                 reader.incrementState();
 
             case 3:
-                newVal = reader.readMessage("newVal");
+                flags = reader.readByte("flags");
 
                 if (!reader.isLastRead())
                     return false;
@@ -275,6 +407,22 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
                 reader.incrementState();
 
             case 4:
+                key = reader.readMessage("key");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 5:
+                newVal = reader.readMessage("newVal");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 6:
                 oldVal = reader.readMessage("oldVal");
 
                 if (!reader.isLastRead())
@@ -282,6 +430,30 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
 
                 reader.incrementState();
 
+            case 7:
+                part = reader.readInt("part");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 8:
+                topVer = reader.readMessage("topVer");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 9:
+                updateCntr = reader.readLong("updateCntr");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
         }
 
         return reader.afterMessageRead(CacheContinuousQueryEntry.class);
@@ -289,7 +461,7 @@ public class CacheContinuousQueryEntry implements GridCacheDeployable, Message {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 5;
+        return 10;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
index 7417138..a1ebe39 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryEvent.java
@@ -58,8 +58,7 @@ class CacheContinuousQueryEvent<K, V> extends CacheEntryEvent<K, V> {
     }
 
     /** {@inheritDoc} */
-    @Override
-    public K getKey() {
+    @Override public K getKey() {
         return e.key().value(cctx.cacheObjectContext(), false);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
index e517c70..b69d4cd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryHandler.java
@@ -21,8 +21,21 @@ import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.TreeMap;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
 import javax.cache.event.CacheEntryEvent;
 import javax.cache.event.CacheEntryUpdatedListener;
 import javax.cache.event.EventType;
@@ -30,26 +43,37 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.events.CacheQueryExecutedEvent;
 import org.apache.ignite.events.CacheQueryReadEvent;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteDeploymentCheckedException;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import org.apache.ignite.internal.managers.communication.GridIoPolicy;
 import org.apache.ignite.internal.managers.deployment.GridDeployment;
 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.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager;
 import org.apache.ignite.internal.processors.cache.query.CacheQueryType;
+import org.apache.ignite.internal.processors.continuous.GridContinuousBatch;
+import org.apache.ignite.internal.processors.continuous.GridContinuousBatchAdapter;
 import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
 import org.apache.ignite.internal.processors.platform.cache.query.PlatformContinuousQueryFilter;
+import org.apache.ignite.internal.util.GridConcurrentSkipListSet;
+import org.apache.ignite.internal.util.GridLongList;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.lang.IgnitePredicate;
 import org.jetbrains.annotations.Nullable;
+import org.jsr166.ConcurrentLinkedDeque8;
 
 import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_EXECUTED;
 import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_OBJECT_READ;
@@ -61,6 +85,9 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** */
+    private static final int BACKUP_ACK_THRESHOLD = 100;
+
     /** Cache name. */
     private String cacheName;
 
@@ -97,9 +124,27 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
     /** Whether to skip primary check for REPLICATED cache. */
     private transient boolean skipPrimaryCheck;
 
+    /** Backup queue. */
+    private transient Collection<CacheContinuousQueryEntry> backupQueue;
+
+    /** */
+    private boolean localCache;
+
+    /** */
+    private transient ConcurrentMap<Integer, PartitionRecovery> rcvs;
+
+    /** */
+    private transient ConcurrentMap<Integer, EntryBuffer> entryBufs;
+
+    /** */
+    private transient AcknowledgeBuffer ackBuf;
+
     /** */
     private transient int cacheId;
 
+    /** */
+    private Map<Integer, Long> initUpdCntrs;
+
     /**
      * Required by {@link Externalizable}.
      */
@@ -121,6 +166,7 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
      * @param ignoreExpired Ignore expired events flag.
      * @param skipPrimaryCheck Whether to skip primary check for REPLICATED cache.
      * @param taskHash Task name hash code.
+     * @param locCache {@code True} if local cache.
      */
     public CacheContinuousQueryHandler(
         String cacheName,
@@ -133,7 +179,8 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
         boolean sync,
         boolean ignoreExpired,
         int taskHash,
-        boolean skipPrimaryCheck) {
+        boolean skipPrimaryCheck,
+        boolean locCache) {
         assert topic != null;
         assert locLsnr != null;
 
@@ -148,6 +195,7 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
         this.ignoreExpired = ignoreExpired;
         this.taskHash = taskHash;
         this.skipPrimaryCheck = skipPrimaryCheck;
+        this.localCache = locCache;
 
         cacheId = CU.cacheId(cacheName);
     }
@@ -173,6 +221,11 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public void updateCounters(Map<Integer, Long> cntrs) {
+        this.initUpdCntrs = cntrs;
+    }
+
+    /** {@inheritDoc} */
     @Override public RegisterStatus register(final UUID nodeId, final UUID routineId, final GridKernalContext ctx)
         throws IgniteCheckedException {
         assert nodeId != null;
@@ -185,8 +238,32 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
         if (rmtFilter != null)
             ctx.resource().injectGeneric(rmtFilter);
 
+        entryBufs = new ConcurrentHashMap<>();
+
+        backupQueue = new ConcurrentLinkedDeque8<>();
+
+        ackBuf = new AcknowledgeBuffer();
+
+        rcvs = new ConcurrentHashMap<>();
+
         final boolean loc = nodeId.equals(ctx.localNodeId());
 
+        assert !skipPrimaryCheck || loc;
+
+        final GridCacheContext<K, V> cctx = cacheContext(ctx);
+
+        if (!internal && cctx != null && initUpdCntrs != null) {
+            Map<Integer, Long> map = cctx.topology().updateCounters();
+
+            for (Map.Entry<Integer, Long> e : map.entrySet()) {
+                Long cntr0 = initUpdCntrs.get(e.getKey());
+                Long cntr1 = e.getValue();
+
+                if (cntr0 == null || cntr1 > cntr0)
+                    initUpdCntrs.put(e.getKey(), cntr1);
+            }
+        }
+
         CacheContinuousQueryListener<K, V> lsnr = new CacheContinuousQueryListener<K, V>() {
             @Override public void onExecution() {
                 if (ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
@@ -212,11 +289,15 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
                 if (ignoreExpired && evt.getEventType() == EventType.EXPIRED)
                     return;
 
-                GridCacheContext<K, V> cctx = cacheContext(ctx);
+                final GridCacheContext<K, V> cctx = cacheContext(ctx);
 
-                if (cctx.isReplicated() && !skipPrimaryCheck && !primary)
+                // Check that cache stopped.
+                if (cctx == null)
                     return;
 
+                // skipPrimaryCheck is set only when listen locally for replicated cache events.
+                assert !skipPrimaryCheck || (cctx.isReplicated() && ctx.localNodeId().equals(nodeId));
+
                 boolean notify = true;
 
                 if (rmtFilter != null) {
@@ -228,54 +309,94 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
                     }
                 }
 
-                if (notify) {
-                    if (loc)
-                        locLsnr.onUpdated(F.<CacheEntryEvent<? extends K, ? extends V>>asList(evt));
-                    else {
-                        try {
-                            if (cctx.deploymentEnabled() && ctx.discovery().node(nodeId) != null) {
-                                evt.entry().prepareMarshal(cctx);
-
-                                cctx.deploy().prepare(evt.entry());
+                try {
+                    final CacheContinuousQueryEntry entry = evt.entry();
+
+                    if (!notify)
+                        entry.markFiltered();
+
+                    if (primary || skipPrimaryCheck) {
+                        if (loc) {
+                            if (!localCache) {
+                                Collection<CacheContinuousQueryEntry> entries = handleEvent(ctx, entry);
+
+                                if (!entries.isEmpty()) {
+                                    final IgniteCache cache = cctx.kernalContext().cache().jcache(cctx.name());
+
+                                    Iterable<CacheEntryEvent<? extends K, ? extends V>> evts = F.viewReadOnly(entries,
+                                        new C1<CacheContinuousQueryEntry, CacheEntryEvent<? extends K, ? extends V>>() {
+                                            @Override public CacheEntryEvent<? extends K, ? extends V> apply(
+                                                CacheContinuousQueryEntry e) {
+                                                return new CacheContinuousQueryEvent<>(cache, cctx, e);
+                                            }
+                                        },
+                                        new IgnitePredicate<CacheContinuousQueryEntry>() {
+                                            @Override public boolean apply(CacheContinuousQueryEntry entry) {
+                                                return !entry.isFiltered();
+                                            }
+                                        }
+                                    );
+
+                                    locLsnr.onUpdated(evts);
+
+                                    if (!internal && !skipPrimaryCheck)
+                                        sendBackupAcknowledge(ackBuf.onAcknowledged(entry), routineId, ctx);
+                                }
+                            }
+                            else {
+                                if (!entry.isFiltered())
+                                    locLsnr.onUpdated(F.<CacheEntryEvent<? extends K, ? extends V>>asList(evt));
                             }
-                            else
-                                evt.entry().prepareMarshal(cctx);
-
-                            ctx.continuous().addNotification(nodeId, routineId, evt.entry(), topic, sync, true);
                         }
-                        catch (ClusterTopologyCheckedException ex) {
-                            IgniteLogger log = ctx.log(getClass());
+                        else {
+                            if (!entry.isFiltered())
+                                prepareEntry(cctx, nodeId, entry);
 
-                            if (log.isDebugEnabled())
-                                log.debug("Failed to send event notification to node, node left cluster " +
-                                    "[node=" + nodeId + ", err=" + ex + ']');
-                        }
-                        catch (IgniteCheckedException ex) {
-                            U.error(ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex);
+                            CacheContinuousQueryEntry e = handleEntry(entry);
+
+                            if (e != null)
+                                ctx.continuous().addNotification(nodeId, routineId, entry, topic, sync, true);
                         }
                     }
+                    else {
+                        if (!internal) {
+                            entry.markBackup();
 
-                    if (recordIgniteEvt) {
-                        ctx.event().record(new CacheQueryReadEvent<>(
-                            ctx.discovery().localNode(),
-                            "Continuous query executed.",
-                            EVT_CACHE_QUERY_OBJECT_READ,
-                            CacheQueryType.CONTINUOUS.name(),
-                            cacheName,
-                            null,
-                            null,
-                            null,
-                            rmtFilter,
-                            null,
-                            nodeId,
-                            taskName(),
-                            evt.getKey(),
-                            evt.getValue(),
-                            evt.getOldValue(),
-                            null
-                        ));
+                            backupQueue.add(entry);
+                        }
                     }
                 }
+                catch (ClusterTopologyCheckedException ex) {
+                    IgniteLogger log = ctx.log(getClass());
+
+                    if (log.isDebugEnabled())
+                        log.debug("Failed to send event notification to node, node left cluster " +
+                            "[node=" + nodeId + ", err=" + ex + ']');
+                }
+                catch (IgniteCheckedException ex) {
+                    U.error(ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex);
+                }
+
+                if (recordIgniteEvt && notify) {
+                    ctx.event().record(new CacheQueryReadEvent<>(
+                        ctx.discovery().localNode(),
+                        "Continuous query executed.",
+                        EVT_CACHE_QUERY_OBJECT_READ,
+                        CacheQueryType.CONTINUOUS.name(),
+                        cacheName,
+                        null,
+                        null,
+                        null,
+                        rmtFilter,
+                        null,
+                        nodeId,
+                        taskName(),
+                        evt.getKey(),
+                        evt.getValue(),
+                        evt.getOldValue(),
+                        null
+                    ));
+                }
             }
 
             @Override public void onUnregister() {
@@ -283,6 +404,85 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
                     ((PlatformContinuousQueryFilter)rmtFilter).onQueryUnregister();
             }
 
+            @Override public void cleanupBackupQueue(Map<Integer, Long> updateCntrs) {
+                Iterator<CacheContinuousQueryEntry> it = backupQueue.iterator();
+
+                while (it.hasNext()) {
+                    CacheContinuousQueryEntry backupEntry = it.next();
+
+                    Long updateCntr = updateCntrs.get(backupEntry.partition());
+
+                    if (updateCntr != null && backupEntry.updateCounter() <= updateCntr)
+                        it.remove();
+                }
+            }
+
+            @Override public void flushBackupQueue(GridKernalContext ctx, AffinityTopologyVersion topVer) {
+                if (backupQueue.isEmpty())
+                    return;
+
+                try {
+                    GridCacheContext<K, V> cctx = cacheContext(ctx);
+
+                    for (CacheContinuousQueryEntry e : backupQueue) {
+                        if (!e.isFiltered())
+                            prepareEntry(cctx, nodeId, e);
+                    }
+
+                    ctx.continuous().addBackupNotification(nodeId, routineId, backupQueue, topic);
+
+                    backupQueue.clear();
+                }
+                catch (IgniteCheckedException e) {
+                    U.error(ctx.log(getClass()), "Failed to send backup event notification to node: " + nodeId, e);
+                }
+            }
+
+            @Override public void acknowledgeBackupOnTimeout(GridKernalContext ctx) {
+                sendBackupAcknowledge(ackBuf.acknowledgeOnTimeout(), routineId, ctx);
+            }
+
+            @Override public void skipUpdateEvent(CacheContinuousQueryEvent<K, V> evt, AffinityTopologyVersion topVer) {
+                try {
+                    assert evt != null;
+
+                    CacheContinuousQueryEntry e = evt.entry();
+
+                    EntryBuffer buf = entryBufs.get(e.partition());
+
+                    if (buf == null) {
+                        buf = new EntryBuffer();
+
+                        EntryBuffer oldRec = entryBufs.putIfAbsent(e.partition(), buf);
+
+                        if (oldRec != null)
+                            buf = oldRec;
+                    }
+
+                    e = buf.skipEntry(e);
+
+                    if (e != null)
+                        ctx.continuous().addNotification(nodeId, routineId, e, topic, sync, true);
+                }
+                catch (ClusterTopologyCheckedException ex) {
+                    IgniteLogger log = ctx.log(getClass());
+
+                    if (log.isDebugEnabled())
+                        log.debug("Failed to send event notification to node, node left cluster " +
+                                "[node=" + nodeId + ", err=" + ex + ']');
+                }
+                catch (IgniteCheckedException ex) {
+                    U.error(ctx.log(getClass()), "Failed to send event notification to node: " + nodeId, ex);
+                }
+            }
+
+            @Override public void onPartitionEvicted(int part) {
+                for (Iterator<CacheContinuousQueryEntry> it = backupQueue.iterator(); it.hasNext();) {
+                    if (it.next().partition() == part)
+                        it.remove();
+                }
+            }
+
             @Override public boolean oldValueRequired() {
                 return oldValRequired;
             }
@@ -304,6 +504,23 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
         return mgr.registerListener(routineId, lsnr, internal);
     }
 
+    /**
+     * @param cctx Context.
+     * @param nodeId ID of the node that started routine.
+     * @param entry Entry.
+     * @throws IgniteCheckedException In case of error.
+     */
+    private void prepareEntry(GridCacheContext cctx, UUID nodeId, CacheContinuousQueryEntry entry)
+        throws IgniteCheckedException {
+        if (cctx.kernalContext().config().isPeerClassLoadingEnabled() && cctx.discovery().node(nodeId) != null) {
+            entry.prepareMarshal(cctx);
+
+            cctx.deploy().prepare(entry);
+        }
+        else
+            entry.prepareMarshal(cctx);
+    }
+
     /** {@inheritDoc} */
     @Override public void onListenerRegistered(UUID routineId, GridKernalContext ctx) {
         // No-op.
@@ -366,17 +583,377 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
 
         final IgniteCache cache = cctx.kernalContext().cache().jcache(cctx.name());
 
-        Iterable<CacheEntryEvent<? extends K, ? extends V>> evts = F.viewReadOnly(entries,
+        Collection<CacheContinuousQueryEntry> entries0 = new ArrayList<>();
+
+        for (CacheContinuousQueryEntry e : entries)
+            entries0.addAll(handleEvent(ctx, e));
+
+        Iterable<CacheEntryEvent<? extends K, ? extends V>> evts = F.viewReadOnly(entries0,
             new C1<CacheContinuousQueryEntry, CacheEntryEvent<? extends K, ? extends V>>() {
                 @Override public CacheEntryEvent<? extends K, ? extends V> apply(CacheContinuousQueryEntry e) {
                     return new CacheContinuousQueryEvent<>(cache, cctx, e);
                 }
+            },
+            new IgnitePredicate<CacheContinuousQueryEntry>() {
+                @Override public boolean apply(CacheContinuousQueryEntry entry) {
+                    return !entry.isFiltered();
+                }
             }
         );
 
         locLsnr.onUpdated(evts);
     }
 
+    /**
+     * @param ctx Context.
+     * @param e entry.
+     * @return Entry collection.
+     */
+    private Collection<CacheContinuousQueryEntry> handleEvent(GridKernalContext ctx,
+        CacheContinuousQueryEntry e) {
+        assert e != null;
+
+        if (internal) {
+            if (e.isFiltered())
+                return Collections.emptyList();
+            else
+                return F.asList(e);
+        }
+
+        // Initial query entry or evicted entry.
+        // This events should be fired immediately.
+        if (e.updateCounter() == -1)
+            return F.asList(e);
+
+        PartitionRecovery rec = rcvs.get(e.partition());
+
+        if (rec == null) {
+            rec = new PartitionRecovery(ctx.log(getClass()), cacheContext(ctx).topology().topologyVersion(),
+                initUpdCntrs == null ? null : initUpdCntrs.get(e.partition()));
+
+            PartitionRecovery oldRec = rcvs.putIfAbsent(e.partition(), rec);
+
+            if (oldRec != null)
+                rec = oldRec;
+        }
+
+        return rec.collectEntries(e);
+    }
+
+    /**
+     * @param e Entry.
+     * @return Entry.
+     */
+    private CacheContinuousQueryEntry handleEntry(CacheContinuousQueryEntry e) {
+        assert e != null;
+        assert entryBufs != null;
+
+        if (internal) {
+            if (e.isFiltered())
+                return null;
+            else
+                return e;
+        }
+
+        // Initial query entry.
+        // This events should be fired immediately.
+        if (e.updateCounter() == -1)
+            return e;
+
+        EntryBuffer buf = entryBufs.get(e.partition());
+
+        if (buf == null) {
+            buf = new EntryBuffer();
+
+            EntryBuffer oldRec = entryBufs.putIfAbsent(e.partition(), buf);
+
+            if (oldRec != null)
+                buf = oldRec;
+        }
+
+        return buf.handle(e);
+    }
+
+    /**
+     *
+     */
+    private static class PartitionRecovery {
+        /** Event which means hole in sequence. */
+        private static final CacheContinuousQueryEntry HOLE = new CacheContinuousQueryEntry();
+
+        /** */
+        private final static int MAX_BUFF_SIZE = 100;
+
+        /** */
+        private IgniteLogger log;
+
+        /** */
+        private long lastFiredEvt;
+
+        /** */
+        private AffinityTopologyVersion curTop = AffinityTopologyVersion.NONE;
+
+        /** */
+        private final Map<Long, CacheContinuousQueryEntry> pendingEvts = new TreeMap<>();
+
+        /**
+         * @param log Logger.
+         * @param topVer Topology version.
+         * @param initCntr Update counters.
+         */
+        public PartitionRecovery(IgniteLogger log, AffinityTopologyVersion topVer, @Nullable Long initCntr) {
+            this.log = log;
+
+            if (initCntr != null) {
+                this.lastFiredEvt = initCntr;
+
+                curTop = topVer;
+            }
+        }
+
+        /**
+         * Add continuous entry.
+         *
+         * @param entry Cache continuous query entry.
+         * @return Collection entries which will be fired.
+         */
+        public Collection<CacheContinuousQueryEntry> collectEntries(CacheContinuousQueryEntry entry) {
+            assert entry != null;
+
+            List<CacheContinuousQueryEntry> entries;
+
+            synchronized (pendingEvts) {
+                // Received first event.
+                if (curTop == AffinityTopologyVersion.NONE) {
+                    lastFiredEvt = entry.updateCounter();
+
+                    curTop = entry.topologyVersion();
+
+                    return F.asList(entry);
+                }
+
+                if (curTop.compareTo(entry.topologyVersion()) < 0) {
+                    if (entry.updateCounter() == 1 && !entry.isBackup()) {
+                        entries = new ArrayList<>(pendingEvts.size());
+
+                        for (CacheContinuousQueryEntry evt : pendingEvts.values()) {
+                            if (evt != HOLE && !evt.isFiltered())
+                                entries.add(evt);
+                        }
+
+                        pendingEvts.clear();
+
+                        curTop = entry.topologyVersion();
+
+                        lastFiredEvt = entry.updateCounter();
+
+                        entries.add(entry);
+
+                        return entries;
+                    }
+
+                    curTop = entry.topologyVersion();
+                }
+
+                // Check duplicate.
+                if (entry.updateCounter() > lastFiredEvt) {
+                    pendingEvts.put(entry.updateCounter(), entry);
+
+                    // Put filtered events.
+                    if (entry.filteredEvents() != null) {
+                        for (long cnrt : entry.filteredEvents()) {
+                            if (cnrt > lastFiredEvt)
+                                pendingEvts.put(cnrt, HOLE);
+                        }
+                    }
+                }
+                else {
+                    if (log.isDebugEnabled())
+                        log.debug("Skip duplicate continuous query message: " + entry);
+
+                    return Collections.emptyList();
+                }
+
+                if (pendingEvts.isEmpty())
+                    return Collections.emptyList();
+
+                Iterator<Map.Entry<Long, CacheContinuousQueryEntry>> iter = pendingEvts.entrySet().iterator();
+
+                entries = new ArrayList<>();
+
+                if (pendingEvts.size() >= MAX_BUFF_SIZE) {
+                    for (int i = 0; i < MAX_BUFF_SIZE - (MAX_BUFF_SIZE / 10); i++) {
+                        Map.Entry<Long, CacheContinuousQueryEntry> e = iter.next();
+
+                        if (e.getValue() != HOLE && !e.getValue().isFiltered())
+                            entries.add(e.getValue());
+
+                        lastFiredEvt = e.getKey();
+
+                        iter.remove();
+                    }
+                }
+                else {
+                    // Elements are consistently.
+                    while (iter.hasNext()) {
+                        Map.Entry<Long, CacheContinuousQueryEntry> e = iter.next();
+
+                        if (e.getKey() == lastFiredEvt + 1) {
+                            ++lastFiredEvt;
+
+                            if (e.getValue() != HOLE && !e.getValue().isFiltered())
+                                entries.add(e.getValue());
+
+                            iter.remove();
+                        }
+                        else
+                            break;
+                    }
+                }
+            }
+
+            return entries;
+        }
+    }
+
+    /**
+     *
+     */
+    private static class EntryBuffer {
+        /** */
+        private final static int MAX_BUFF_SIZE = 100;
+
+        /** */
+        private final GridConcurrentSkipListSet<Long> buf = new GridConcurrentSkipListSet<>();
+
+        /** */
+        private AtomicLong lastFiredCntr = new AtomicLong();
+
+        /**
+         * @param newVal New value.
+         * @return Old value if previous value less than new value otherwise {@code -1}.
+         */
+        private long updateFiredCounter(long newVal) {
+            long prevVal = lastFiredCntr.get();
+
+            while (prevVal < newVal) {
+                if (lastFiredCntr.compareAndSet(prevVal, newVal))
+                    return prevVal;
+                else
+                    prevVal = lastFiredCntr.get();
+            }
+
+            return prevVal >= newVal ? -1 : prevVal;
+        }
+
+        /**
+         * @param e Entry.
+         * @param topVer Topology version.
+         * @return Continuous query entry.
+         */
+        private CacheContinuousQueryEntry skipEntry(CacheContinuousQueryEntry e) {
+            if (lastFiredCntr.get() > e.updateCounter() || e.updateCounter() == 1) {
+
+                e.markFiltered();
+
+                return e;
+            }
+            else {
+                buf.add(e.updateCounter());
+
+                // Double check. If another thread sent a event with counter higher than this event.
+                if (lastFiredCntr.get() > e.updateCounter() && buf.contains(e.updateCounter())) {
+                    buf.remove(e.updateCounter());
+
+                    e.markFiltered();
+
+                    return e;
+                }
+                else
+                    return null;
+            }
+        }
+
+        /**
+         * Add continuous entry.
+         *
+         * @param e Cache continuous query entry.
+         * @return Collection entries which will be fired.
+         */
+        public CacheContinuousQueryEntry handle(CacheContinuousQueryEntry e) {
+            assert e != null;
+
+            if (e.isFiltered()) {
+                Long last = buf.lastx();
+                Long first = buf.firstx();
+
+                if (last != null && first != null && last - first >= MAX_BUFF_SIZE) {
+                    NavigableSet<Long> prevHoles = buf.subSet(first, true, last, true);
+
+                    GridLongList filteredEvts = new GridLongList((int)(last - first));
+
+                    int size = 0;
+
+                    Long cntr;
+
+                    while ((cntr = prevHoles.pollFirst()) != null) {
+                        filteredEvts.add(cntr);
+
+                        ++size;
+                    }
+
+                    filteredEvts.truncate(size, true);
+
+                    e.filteredEvents(filteredEvts);
+
+                    return e;
+                }
+
+                if (lastFiredCntr.get() > e.updateCounter() || e.updateCounter() == 1)
+                    return e;
+                else {
+                    buf.add(e.updateCounter());
+
+                    // Double check. If another thread sent a event with counter higher than this event.
+                    if (lastFiredCntr.get() > e.updateCounter() && buf.contains(e.updateCounter())) {
+                        buf.remove(e.updateCounter());
+
+                        return e;
+                    }
+                    else
+                        return null;
+                }
+            }
+            else {
+                long prevVal = updateFiredCounter(e.updateCounter());
+
+                if (prevVal == -1)
+                    return e;
+                else {
+                    NavigableSet<Long> prevHoles = buf.subSet(prevVal, true, e.updateCounter(), true);
+
+                    GridLongList filteredEvts = new GridLongList((int)(e.updateCounter() - prevVal));
+
+                    int size = 0;
+
+                    Long cntr;
+
+                    while ((cntr = prevHoles.pollFirst()) != null) {
+                        filteredEvts.add(cntr);
+
+                        ++size;
+                    }
+
+                    filteredEvts.truncate(size, true);
+
+                    e.filteredEvents(filteredEvts);
+
+                    return e;
+                }
+            }
+        }
+    }
+
     /** {@inheritDoc} */
     @Override public void p2pMarshal(GridKernalContext ctx) throws IgniteCheckedException {
         assert ctx != null;
@@ -397,6 +974,65 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public GridContinuousBatch createBatch() {
+        return new GridContinuousBatchAdapter();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBatchAcknowledged(final UUID routineId,
+        GridContinuousBatch batch,
+        final GridKernalContext ctx) {
+        sendBackupAcknowledge(ackBuf.onAcknowledged(batch), routineId, ctx);
+    }
+
+    /**
+     * @param t Acknowledge information.
+     * @param routineId Routine ID.
+     * @param ctx Context.
+     */
+    private void sendBackupAcknowledge(final IgniteBiTuple<Map<Integer, Long>, Set<AffinityTopologyVersion>> t,
+        final UUID routineId,
+        final GridKernalContext ctx) {
+        if (t != null) {
+            ctx.closure().runLocalSafe(new Runnable() {
+                @Override public void run() {
+                    GridCacheContext<K, V> cctx = cacheContext(ctx);
+
+                    CacheContinuousQueryBatchAck msg = new CacheContinuousQueryBatchAck(cctx.cacheId(),
+                        routineId,
+                        t.get1());
+
+                    Collection<ClusterNode> nodes = new HashSet<>();
+
+                    for (AffinityTopologyVersion topVer : t.get2())
+                        nodes.addAll(ctx.discovery().cacheNodes(topVer));
+
+                    for (ClusterNode node : nodes) {
+                        if (!node.id().equals(ctx.localNodeId())) {
+                            try {
+                                cctx.io().send(node, msg, GridIoPolicy.SYSTEM_POOL);
+                            }
+                            catch (ClusterTopologyCheckedException e) {
+                                IgniteLogger log = ctx.log(getClass());
+
+                                if (log.isDebugEnabled())
+                                    log.debug("Failed to send acknowledge message, node left " +
+                                        "[msg=" + msg + ", node=" + node + ']');
+                            }
+                            catch (IgniteCheckedException e) {
+                                IgniteLogger log = ctx.log(getClass());
+
+                                U.error(log, "Failed to send acknowledge message " +
+                                    "[msg=" + msg + ", node=" + node + ']', e);
+                            }
+                        }
+                    }
+                }
+            });
+        }
+    }
+
+    /** {@inheritDoc} */
     @Nullable @Override public Object orderedTopic() {
         return topic;
     }
@@ -471,6 +1107,93 @@ class CacheContinuousQueryHandler<K, V> implements GridContinuousHandler {
         return ctx.cache().<K, V>context().cacheContext(cacheId);
     }
 
+    /** */
+    private static class AcknowledgeBuffer {
+        /** */
+        private int size;
+
+        /** */
+        @GridToStringInclude
+        private Map<Integer, Long> updateCntrs = new HashMap<>();
+
+        /** */
+        @GridToStringInclude
+        private Set<AffinityTopologyVersion> topVers = U.newHashSet(1);
+
+        /**
+         * @param batch Batch.
+         * @return Non-null tuple if acknowledge should be sent to backups.
+         */
+        @SuppressWarnings("unchecked")
+        @Nullable synchronized IgniteBiTuple<Map<Integer, Long>, Set<AffinityTopologyVersion>>
+        onAcknowledged(GridContinuousBatch batch) {
+            size += batch.size();
+
+            Collection<CacheContinuousQueryEntry> entries = (Collection)batch.collect();
+
+            for (CacheContinuousQueryEntry e : entries)
+                addEntry(e);
+
+            return size >= BACKUP_ACK_THRESHOLD ? acknowledgeData() : null;
+        }
+
+        /**
+         * @param e Entry.
+         * @return Non-null tuple if acknowledge should be sent to backups.
+         */
+        @Nullable synchronized IgniteBiTuple<Map<Integer, Long>, Set<AffinityTopologyVersion>>
+        onAcknowledged(CacheContinuousQueryEntry e) {
+            size++;
+
+            addEntry(e);
+
+            return size >= BACKUP_ACK_THRESHOLD ? acknowledgeData() : null;
+        }
+
+        /**
+         * @param e Entry.
+         */
+        private void addEntry(CacheContinuousQueryEntry e) {
+            topVers.add(e.topologyVersion());
+
+            Long cntr0 = updateCntrs.get(e.partition());
+
+            if (cntr0 == null || e.updateCounter() > cntr0)
+                updateCntrs.put(e.partition(), e.updateCounter());
+        }
+
+        /**
+         * @return Non-null tuple if acknowledge should be sent to backups.
+         */
+        @Nullable synchronized IgniteBiTuple<Map<Integer, Long>, Set<AffinityTopologyVersion>>
+            acknowledgeOnTimeout() {
+            return size > 0 ? acknowledgeData() : null;
+        }
+
+        /**
+         * @return Tuple with acknowledge information.
+         */
+        private IgniteBiTuple<Map<Integer, Long>, Set<AffinityTopologyVersion>> acknowledgeData() {
+            assert size > 0;
+
+            Map<Integer, Long> cntrs = new HashMap<>(updateCntrs);
+
+            IgniteBiTuple<Map<Integer, Long>, Set<AffinityTopologyVersion>> res =
+                new IgniteBiTuple<>(cntrs, topVers);
+
+            topVers = U.newHashSet(1);
+
+            size = 0;
+
+            return res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(AcknowledgeBuffer.class, this);
+        }
+    }
+
     /**
      * Deployable object.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
index a3c19a9..8342acf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryListener.java
@@ -17,6 +17,10 @@
 
 package org.apache.ignite.internal.processors.cache.query.continuous;
 
+import java.util.Map;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+
 /**
  * Continuous query listener.
  */
@@ -41,6 +45,37 @@ interface CacheContinuousQueryListener<K, V> {
     public void onUnregister();
 
     /**
+     * Cleans backup queue.
+     *
+     * @param updateCntrs Update indexes map.
+     */
+    public void cleanupBackupQueue(Map<Integer, Long> updateCntrs);
+
+    /**
+     * Flushes backup queue.
+     *
+     * @param ctx Context.
+     * @param topVer Topology version.
+     */
+    public void flushBackupQueue(GridKernalContext ctx, AffinityTopologyVersion topVer);
+
+    /**
+     * @param ctx Context.
+     */
+    public void acknowledgeBackupOnTimeout(GridKernalContext ctx);
+
+    /**
+     * @param evt Event
+     * @param topVer Topology version.
+     */
+    public void skipUpdateEvent(CacheContinuousQueryEvent<K, V> evt, AffinityTopologyVersion topVer);
+
+    /**
+     * @param part Partition.
+     */
+    public void onPartitionEvicted(int part);
+
+    /**
      * @return Whether old value is required.
      */
     public boolean oldValueRequired();


[14/37] ignite git commit: ignite-1.5 Changed update version url.

Posted by ag...@apache.org.
ignite-1.5 Changed update version url.


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

Branch: refs/heads/ignite-1282
Commit: 33ec73f901ca5dba441c6ca4e118d55165f3d25e
Parents: c490de3
Author: Andrey <an...@gridgain.com>
Authored: Thu Nov 19 15:43:51 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Thu Nov 19 15:43:51 2015 +0700

----------------------------------------------------------------------
 .../main/java/org/apache/ignite/internal/GridUpdateNotifier.java   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/33ec73f9/modules/core/src/main/java/org/apache/ignite/internal/GridUpdateNotifier.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridUpdateNotifier.java b/modules/core/src/main/java/org/apache/ignite/internal/GridUpdateNotifier.java
index b6162ed..5d2cf35 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridUpdateNotifier.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridUpdateNotifier.java
@@ -141,7 +141,7 @@ class GridUpdateNotifier {
 
             this.ver = ver;
 
-            url = "http://tiny.cc/updater/update_status_ignite.php";
+            url = "http://ignite.run/update_status_ignite.php";
 
             this.gridName = gridName == null ? "null" : gridName;
             this.gw = gw;


[26/37] ignite git commit: Added benchmark: IgniteSqlQueryPutSeparatedBenchmark

Posted by ag...@apache.org.
Added benchmark: IgniteSqlQueryPutSeparatedBenchmark


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

Branch: refs/heads/ignite-1282
Commit: 96483be6543e223282eaf8d5c8dbabbab1715baf
Parents: 4c9ea58
Author: ashutak <as...@gridgain.com>
Authored: Thu Nov 19 19:31:28 2015 +0300
Committer: ashutak <as...@gridgain.com>
Committed: Thu Nov 19 19:31:28 2015 +0300

----------------------------------------------------------------------
 .../config/benchmark-multicast.properties       |  6 +-
 .../benchmark-query-put-separated.properties    | 88 ++++++++++++++++++++
 .../IgniteSqlQueryPutSeparatedBenchmark.java    | 84 +++++++++++++++++++
 3 files changed, 175 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/96483be6/modules/yardstick/config/benchmark-multicast.properties
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/benchmark-multicast.properties b/modules/yardstick/config/benchmark-multicast.properties
index 85f6c11..03cfddb 100644
--- a/modules/yardstick/config/benchmark-multicast.properties
+++ b/modules/yardstick/config/benchmark-multicast.properties
@@ -113,7 +113,7 @@ CONFIGS="\
 -cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgnitePutAllBenchmark -sn IgniteNode -ds ${ver}atomic-putAll-1-backup,\
 -cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgnitePutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-putAll-1-backup,\
 -cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 100 -dn IgnitePutAllSerializableTxBenchmark -sn IgniteNode -ds ${ver}tx-putAllSerializable-1-backup,\
--cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC  -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds tx-optimistic-getAllPutAll-1-backup,\
--cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc PESSIMISTIC -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds tx-pessimistic-getAllPutAll-1-backup,\
--cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC -txi SERIALIZABLE -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds tx-opt-serializable-getAllPutAll-1-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC  -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-optimistic-getAllPutAll-1-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc PESSIMISTIC -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-pessimistic-getAllPutAll-1-backup,\
+-cfg ${SCRIPT_DIR}/../config/ignite-multicast-config.xml -nn ${nodesNum} -b ${b} -w ${w} -d ${d} -t ${t} -sm ${sm} -bs 10 -txc OPTIMISTIC -txi SERIALIZABLE -dn IgniteGetAllPutAllTxBenchmark -sn IgniteNode -ds ${ver}tx-opt-serializable-getAllPutAll-1-backup,\
 "

http://git-wip-us.apache.org/repos/asf/ignite/blob/96483be6/modules/yardstick/config/benchmark-query-put-separated.properties
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/benchmark-query-put-separated.properties b/modules/yardstick/config/benchmark-query-put-separated.properties
new file mode 100644
index 0000000..b1b2942
--- /dev/null
+++ b/modules/yardstick/config/benchmark-query-put-separated.properties
@@ -0,0 +1,88 @@
+# 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.
+
+#
+# Contains all multicast benchmarks
+#
+
+now0=`date +'%H%M%S'`
+
+# JVM options.
+JVM_OPTS=${JVM_OPTS}" -DIGNITE_QUIET=false"
+
+# Uncomment to enable concurrent garbage collection (GC) if you encounter long GC pauses.
+JVM_OPTS=${JVM_OPTS}" \
+-Xloggc:./gc${now0}.log \
+-XX:+PrintGCDetails \
+-verbose:gc \
+-XX:+UseParNewGC \
+-XX:+UseConcMarkSweepGC \
+-XX:+UseTLAB \
+-XX:NewSize=128m \
+-XX:MaxNewSize=128m \
+-XX:MaxTenuringThreshold=0 \
+-XX:SurvivorRatio=1024 \
+-XX:+UseCMSInitiatingOccupancyOnly \
+-XX:CMSInitiatingOccupancyFraction=60 \
+"
+
+#Ignite version
+ver="RELEASE-"
+
+# List of default probes.
+# Add DStatProbe or VmStatProbe if your OS supports it (e.g. if running on Linux).
+BENCHMARK_DEFAULT_PROBES=ThroughputLatencyProbe,PercentileProbe,DStatProbe
+
+# Packages where the specified benchmark is searched by reflection mechanism.
+BENCHMARK_PACKAGES=org.yardstickframework,org.apache.ignite.yardstick
+
+# Restart servers for each benchmark.
+RESTART_SERVERS=true
+
+# Probe point writer class name.
+# BENCHMARK_WRITER=
+
+# Comma-separated list of the hosts to run BenchmarkServers on.
+SERVER_HOSTS=localhost,localhost,localhost
+
+# Comma-separated list of the hosts to run BenchmarkDrivers on.
+DRIVER_HOSTS=localhost,localhost
+
+# Remote username.
+# REMOTE_USER=
+
+# Number of nodes, used to wait for the specified number of nodes to start.
+nodesNum=$((`echo ${SERVER_HOSTS} | tr ',' '\n' | wc -l` + `echo ${DRIVER_HOSTS} | tr ',' '\n' | wc -l`))
+
+# Backups count.
+b=1
+
+# Warmup.
+w=10
+
+# Duration.
+d=30
+
+# Threads count.
+t=64
+
+# Sync mode.
+sm=PRIMARY_SYNC
+
+# Run configuration which contains all benchmarks.
+# Note that each benchmark is set to run for 300 seconds (5 mins) with warm-up set to 60 seconds (1 minute).
+CONFIGS="\
+-cfg ${SCRIPT_DIR}/../config/ignite-localhost-config.xml -nn ${nodesNum} -b 1 -w ${w} -d ${d} -t ${t} -sm PRIMARY_SYNC -dn IgniteSqlQueryPutSeparatedBenchmark -sn IgniteNode -ds query-put-1b,\
+"

http://git-wip-us.apache.org/repos/asf/ignite/blob/96483be6/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutSeparatedBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutSeparatedBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutSeparatedBenchmark.java
new file mode 100644
index 0000000..b74978e
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutSeparatedBenchmark.java
@@ -0,0 +1,84 @@
+/*
+ * 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.yardstick.cache;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+import javax.cache.Cache;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.yardstick.cache.model.Person;
+import org.yardstickframework.BenchmarkConfiguration;
+
+/**
+ * Ignite benchmark that performs put and query operations.
+ */
+public class IgniteSqlQueryPutSeparatedBenchmark extends IgniteCacheAbstractBenchmark<Integer, Object> {
+    /** {@inheritDoc} */
+    @Override public void setUp(BenchmarkConfiguration cfg) throws Exception {
+        super.setUp(cfg);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean test(Map<Object, Object> ctx) throws Exception {
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+        if (cfg.memberId() % 2 == 0) {
+            double salary = rnd.nextDouble() * args.range() * 1000;
+
+            double maxSalary = salary + 1000;
+
+            Collection<Cache.Entry<Integer, Object>> entries = executeQuery(salary, maxSalary);
+
+            for (Cache.Entry<Integer, Object> entry : entries) {
+                Person p = (Person)entry.getValue();
+
+                if (p.getSalary() < salary || p.getSalary() > maxSalary)
+                    throw new Exception("Invalid person retrieved [min=" + salary + ", max=" + maxSalary +
+                            ", person=" + p + ']');
+            }
+        }
+        else {
+            int i = rnd.nextInt(args.range());
+
+            cache.put(i, new Person(i, "firstName" + i, "lastName" + i, i * 1000));
+        }
+
+        return true;
+    }
+
+    /**
+     * @param minSalary Min salary.
+     * @param maxSalary Max salary.
+     * @return Query result.
+     * @throws Exception If failed.
+     */
+    private Collection<Cache.Entry<Integer, Object>> executeQuery(double minSalary, double maxSalary) throws Exception {
+        SqlQuery qry = new SqlQuery(Person.class, "salary >= ? and salary <= ?");
+
+        qry.setArgs(minSalary, maxSalary);
+
+        return cache.query(qry).getAll();
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteCache<Integer, Object> cache() {
+        return ignite().cache("query");
+    }
+}


[07/37] ignite git commit: 'Single' operations optimizations for tx cache.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index 2c7bf8a..758f82c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -66,9 +66,7 @@ import org.apache.ignite.internal.processors.dr.GridDrType;
 import org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
-import org.apache.ignite.internal.util.F0;
 import org.apache.ignite.internal.util.GridLeanMap;
-import org.apache.ignite.internal.util.GridLeanSet;
 import org.apache.ignite.internal.util.future.GridEmbeddedFuture;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -123,18 +121,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     /** */
     private static final long serialVersionUID = 0L;
 
-    /** Per-transaction read map. */
-    @GridToStringInclude
-    protected Map<IgniteTxKey, IgniteTxEntry> txMap;
-
-    /** Read view on transaction map. */
-    @GridToStringExclude
-    protected IgniteTxMap readView;
-
-    /** Write view on transaction map. */
-    @GridToStringExclude
-    protected IgniteTxMap writeView;
-
     /** Minimal version encountered (either explicit lock or XID of this transaction). */
     protected GridCacheVersion minVer;
 
@@ -156,9 +142,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     /** Commit error. */
     protected AtomicReference<Throwable> commitErr = new AtomicReference<>();
 
-    /** Active cache IDs. */
-    protected Set<Integer> activeCacheIds = new HashSet<>();
-
     /** Need return value. */
     protected boolean needRetVal;
 
@@ -168,6 +151,10 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     /** Flag indicating whether deployment is enabled for caches from this transaction or not. */
     private boolean depEnabled;
 
+    /** */
+    @GridToStringInclude
+    protected IgniteTxLocalState txState;
+
     /**
      * Empty constructor required for {@link Externalizable}.
      */
@@ -209,7 +196,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             cctx,
             xidVer,
             implicit,
-            implicitSingle,
             /*local*/true,
             sys,
             plc,
@@ -225,6 +211,13 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         );
 
         minVer = xidVer;
+
+        txState = implicitSingle ? new IgniteTxImplicitSingleStateImpl() : new IgniteTxStateImpl();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxState txState() {
+        return txState;
     }
 
     /**
@@ -246,7 +239,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
     /** {@inheritDoc} */
     @Override public boolean empty() {
-        return txMap.isEmpty();
+        return txState.empty();
     }
 
     /** {@inheritDoc} */
@@ -267,16 +260,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     /** {@inheritDoc} */
     @Override public boolean onOwnerChanged(GridCacheEntryEx entry, GridCacheMvccCandidate owner) {
         assert false;
-        return false;
-    }
 
-    /**
-     * Gets collection of active cache IDs for this transaction.
-     *
-     * @return Collection of active cache IDs.
-     */
-    @Override public Collection<Integer> activeCacheIds() {
-        return activeCacheIds;
+        return false;
     }
 
     /** {@inheritDoc} */
@@ -284,77 +269,70 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         return depEnabled;
     }
 
+    /**
+     * @param depEnabled Flag indicating whether deployment is enabled for caches from this transaction or not.
+     */
+    public void activeCachesDeploymentEnabled(boolean depEnabled) {
+        this.depEnabled = depEnabled;
+    }
+
     /** {@inheritDoc} */
     @Override public boolean isStarted() {
-        return txMap != null;
+        return txState.initialized();
     }
 
     /** {@inheritDoc} */
     @Override public boolean hasWriteKey(IgniteTxKey key) {
-        return writeView.containsKey(key);
+        return txState.hasWriteKey(key);
     }
 
     /**
      * @return Transaction read set.
      */
     @Override public Set<IgniteTxKey> readSet() {
-        return txMap == null ? Collections.<IgniteTxKey>emptySet() : readView.keySet();
+        return txState.readSet();
     }
 
     /**
      * @return Transaction write set.
      */
     @Override public Set<IgniteTxKey> writeSet() {
-        return txMap == null ? Collections.<IgniteTxKey>emptySet() : writeView.keySet();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean removed(IgniteTxKey key) {
-        if (txMap == null)
-            return false;
-
-        IgniteTxEntry e = txMap.get(key);
-
-        return e != null && e.op() == DELETE;
+        return txState.writeSet();
     }
 
     /** {@inheritDoc} */
     @Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
-        return readView == null ? Collections.<IgniteTxKey, IgniteTxEntry>emptyMap() : readView;
+        return txState.readMap();
     }
 
     /** {@inheritDoc} */
     @Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
-        return writeView == null ? Collections.<IgniteTxKey, IgniteTxEntry>emptyMap() : writeView;
+        return txState.writeMap();
     }
 
     /** {@inheritDoc} */
     @Override public Collection<IgniteTxEntry> allEntries() {
-        return txMap == null ? Collections.<IgniteTxEntry>emptySet() : txMap.values();
+        return txState.allEntries();
     }
 
     /** {@inheritDoc} */
     @Override public Collection<IgniteTxEntry> readEntries() {
-        return readView == null ? Collections.<IgniteTxEntry>emptyList() : readView.values();
+        return txState.readEntries();
     }
 
     /** {@inheritDoc} */
     @Override public Collection<IgniteTxEntry> writeEntries() {
-        return writeView == null ? Collections.<IgniteTxEntry>emptyList() : writeView.values();
+        return txState.writeEntries();
     }
 
     /** {@inheritDoc} */
     @Nullable @Override public IgniteTxEntry entry(IgniteTxKey key) {
-        return txMap == null ? null : txMap.get(key);
+        return txState.entry(key);
     }
 
     /** {@inheritDoc} */
     @Override public void seal() {
-        if (readView != null)
-            readView.seal();
-
-        if (writeView != null)
-            writeView.seal();
+        txState.seal();
     }
 
     /** {@inheritDoc} */
@@ -409,7 +387,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         KeyCacheObject key,
         CacheEntryPredicate[] filter
     ) throws GridCacheFilterFailedException {
-        IgniteTxEntry e = txMap == null ? null : txMap.get(cacheCtx.txKey(key));
+        IgniteTxEntry e = entry(cacheCtx.txKey(key));
 
         if (e != null) {
             // We should look at tx entry previous value. If this is a user peek then previous
@@ -652,7 +630,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         if (!storeEnabled() || internal())
             return;
 
-        Collection<CacheStoreManager> stores = stores();
+        Collection<CacheStoreManager> stores = txState.stores(cctx);
 
         if (stores == null || stores.isEmpty())
             return;
@@ -854,7 +832,9 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
         checkValid();
 
-        boolean empty = F.isEmpty(near() ? txMap : writeMap());
+        Collection<IgniteTxEntry> commitEntries = near() ? allEntries() : writeEntries();
+
+        boolean empty = F.isEmpty(commitEntries);
 
         // Register this transaction as completed prior to write-phase to
         // ensure proper lock ordering for removed entries.
@@ -874,7 +854,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 /*
                  * Commit to cache. Note that for 'near' transaction we loop through all the entries.
                  */
-                for (IgniteTxEntry txEntry : (near() ? allEntries() : writeEntries())) {
+                for (IgniteTxEntry txEntry : commitEntries) {
                     GridCacheContext cacheCtx = txEntry.context();
 
                     GridDrType drType = cacheCtx.isDrEnabled() ? DR_PRIMARY : DR_NONE;
@@ -1282,7 +1262,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 cctx.tm().rollbackTx(this);
 
                 if (!internal()) {
-                    Collection<CacheStoreManager> stores = stores();
+                    Collection<CacheStoreManager> stores = txState.stores(cctx);
 
                     if (stores != null && !stores.isEmpty()) {
                         assert isWriteToStoreFromDhtValid(stores) :
@@ -1582,25 +1562,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     }
 
     /**
-     * Adds skipped key.
-     *
-     * @param skipped Skipped set (possibly {@code null}).
-     * @param key Key to add.
-     * @return Skipped set.
-     */
-    private Set<KeyCacheObject> skip(Set<KeyCacheObject> skipped, KeyCacheObject key) {
-        if (skipped == null)
-            skipped = new GridLeanSet<>();
-
-        skipped.add(key);
-
-        if (log.isDebugEnabled())
-            log.debug("Added key to skipped set: " + key);
-
-        return skipped;
-    }
-
-    /**
      * Loads all missed keys for
      * {@link #getAllAsync(GridCacheContext, Collection, boolean, boolean, boolean, boolean)} method.
      *
@@ -1954,6 +1915,24 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     }
 
     /** {@inheritDoc} */
+    @Override public <K, V> IgniteInternalFuture<GridCacheReturn> putAsync(
+        GridCacheContext cacheCtx,
+        K key,
+        V val,
+        boolean retval,
+        CacheEntryPredicate[] filter) {
+        return putAsync0(cacheCtx, key, val, null, null, retval, filter);
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteInternalFuture<GridCacheReturn> invokeAsync(GridCacheContext cacheCtx,
+        K key,
+        EntryProcessor<K, V, Object> entryProcessor,
+        Object... invokeArgs) {
+        return (IgniteInternalFuture)putAsync0(cacheCtx, key, null, entryProcessor, invokeArgs, true, null);
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteInternalFuture<?> putAllDrAsync(
         GridCacheContext cacheCtx,
         Map<KeyCacheObject, GridCacheDrInfo> drMap
@@ -2009,12 +1988,88 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     }
 
     /**
+     * @param cacheCtx Cache context.
+     * @param cacheKey Key to enlist.
+     * @param val Value.
+     * @param expiryPlc Explicitly specified expiry policy for entry.
+     * @param entryProcessor Entry processor (for invoke operation).
+     * @param invokeArgs Optional arguments for EntryProcessor.
+     * @param retval Flag indicating whether a value should be returned.
+     * @param lockOnly If {@code true}, then entry will be enlisted as noop.
+     * @param filter User filters.
+     * @param ret Return value.
+     * @param skipStore Skip store flag.
+     * @param singleRmv {@code True} for single key remove operation ({@link Cache#remove(Object)}.
+     * @return Future for entry values loading.
+     */
+    private <K, V> IgniteInternalFuture<Void> enlistWrite(
+        final GridCacheContext cacheCtx,
+        KeyCacheObject cacheKey,
+        Object val,
+        @Nullable ExpiryPolicy expiryPlc,
+        @Nullable EntryProcessor<K, V, Object> entryProcessor,
+        @Nullable Object[] invokeArgs,
+        final boolean retval,
+        boolean lockOnly,
+        final CacheEntryPredicate[] filter,
+        final GridCacheReturn ret,
+        boolean skipStore,
+        final boolean singleRmv) {
+        try {
+            addActiveCache(cacheCtx);
+
+            final boolean hasFilters = !F.isEmptyOrNulls(filter) && !F.isAlwaysTrue(filter);
+            final boolean needVal = singleRmv || retval || hasFilters;
+            final boolean needReadVer = needVal && (serializable() && optimistic());
+
+            if (entryProcessor != null)
+                transform = true;
+
+            boolean loadMissed = enlistWriteEntry(cacheCtx,
+                cacheKey,
+                val,
+                entryProcessor,
+                invokeArgs,
+                expiryPlc,
+                retval,
+                lockOnly,
+                filter,
+                /*drVer*/null,
+                /*drTtl*/-1L,
+                /*drExpireTime*/-1L,
+                ret,
+                /*enlisted*/null,
+                skipStore,
+                singleRmv,
+                hasFilters,
+                needVal,
+                needReadVer);
+
+            if (loadMissed) {
+                return loadMissing(cacheCtx,
+                    Collections.singleton(cacheKey),
+                    filter,
+                    ret,
+                    needReadVer,
+                    singleRmv,
+                    hasFilters,
+                    skipStore,
+                    retval);
+            }
+
+            return new GridFinishedFuture<>();
+        }
+        catch (IgniteCheckedException e) {
+            return new GridFinishedFuture<>(e);
+        }
+    }
+
+    /**
      * Internal routine for <tt>putAll(..)</tt>
      *
      * @param cacheCtx Cache context.
      * @param keys Keys to enlist.
      * @param expiryPlc Explicitly specified expiry policy for entry.
-     * @param implicit Implicit flag.
      * @param lookup Value lookup map ({@code null} for remove).
      * @param invokeMap Map with entry processors for invoke operation.
      * @param invokeArgs Optional arguments for EntryProcessor.
@@ -2027,13 +2082,12 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      * @param drRmvMap DR remove map (optional).
      * @param skipStore Skip store flag.
      * @param singleRmv {@code True} for single key remove operation ({@link Cache#remove(Object)}.
-     * @return Future with skipped keys (the ones that didn't pass filter for pessimistic transactions).
+     * @return Future for missing values loading.
      */
-    private <K, V> IgniteInternalFuture<Set<KeyCacheObject>> enlistWrite(
+    private <K, V> IgniteInternalFuture<Void> enlistWrite(
         final GridCacheContext cacheCtx,
         Collection<?> keys,
         @Nullable ExpiryPolicy expiryPlc,
-        boolean implicit,
         @Nullable Map<?, ?> lookup,
         @Nullable Map<?, EntryProcessor<K, V, Object>> invokeMap,
         @Nullable Object[] invokeArgs,
@@ -2056,8 +2110,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             return new GridFinishedFuture<>(e);
         }
 
-        Set<KeyCacheObject> skipped = null;
-
         boolean rmv = lookup == null && invokeMap == null;
 
         Set<KeyCacheObject> missedForLoad = null;
@@ -2115,345 +2167,441 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
                 KeyCacheObject cacheKey = cacheCtx.toCacheKeyObject(key);
 
-                IgniteTxKey txKey = cacheCtx.txKey(cacheKey);
-
-                IgniteTxEntry txEntry = entry(txKey);
-
-                // First time access.
-                if (txEntry == null) {
-                    while (true) {
-                        GridCacheEntryEx entry = entryEx(cacheCtx, txKey, topologyVersion());
-
-                        try {
-                            entry.unswap(false);
-
-                            // Check if lock is being explicitly acquired by the same thread.
-                            if (!implicit && cctx.kernalContext().config().isCacheSanityCheckEnabled() &&
-                                entry.lockedByThread(threadId, xidVer))
-                                throw new IgniteCheckedException("Cannot access key within transaction if lock is " +
-                                    "externally held [key=" + key + ", entry=" + entry + ", xidVer=" + xidVer +
-                                    ", threadId=" + threadId +
-                                    ", locNodeId=" + cctx.localNodeId() + ']');
-
-                            CacheObject old = null;
-                            GridCacheVersion readVer = null;
+                boolean loadMissed = enlistWriteEntry(cacheCtx,
+                    cacheKey,
+                    val,
+                    entryProcessor,
+                    invokeArgs,
+                    expiryPlc,
+                    retval,
+                    lockOnly,
+                    filter,
+                    drVer,
+                    drTtl,
+                    drExpireTime,
+                    ret,
+                    enlisted,
+                    skipStore,
+                    singleRmv,
+                    hasFilters,
+                    needVal,
+                    needReadVer);
+
+                if (loadMissed) {
+                    if (missedForLoad == null)
+                        missedForLoad = new HashSet<>();
+
+                    missedForLoad.add(cacheKey);
+                }
+            }
 
-                            if (optimistic() && !implicit()) {
-                                try {
-                                    if (needReadVer) {
-                                        T2<CacheObject, GridCacheVersion> res = primaryLocal(entry) ?
-                                            entry.innerGetVersioned(this,
-                                                /*swap*/false,
-                                                /*unmarshal*/retval,
-                                                /*metrics*/retval,
-                                                /*events*/retval,
-                                                CU.subjectId(this, cctx),
-                                                entryProcessor,
-                                                resolveTaskName(),
-                                                null) : null;
+            if (missedForLoad != null) {
+                return loadMissing(cacheCtx,
+                    missedForLoad,
+                    filter,
+                    ret,
+                    needReadVer,
+                    singleRmv,
+                    hasFilters,
+                    skipStore,
+                    retval);
+            }
 
-                                        if (res != null) {
-                                            old = res.get1();
-                                            readVer = res.get2();
-                                        }
-                                    }
-                                    else {
-                                        old = entry.innerGet(this,
-                                            /*swap*/false,
-                                            /*read-through*/false,
-                                            /*fail-fast*/false,
-                                            /*unmarshal*/retval,
-                                            /*metrics*/retval,
-                                            /*events*/retval,
-                                            /*temporary*/false,
-                                            CU.subjectId(this, cctx),
-                                            entryProcessor,
-                                            resolveTaskName(),
-                                            null);
-                                    }
-                                }
-                                catch (ClusterTopologyCheckedException e) {
-                                    entry.context().evicts().touch(entry, topologyVersion());
+            return new GridFinishedFuture<>();
+        }
+        catch (IgniteCheckedException e) {
+            return new GridFinishedFuture<>(e);
+        }
+    }
 
-                                    throw e;
-                                }
-                            }
-                            else
-                                old = retval ? entry.rawGetOrUnmarshal(false) : entry.rawGet();
+    /**
+     * @param cacheCtx Cache context.
+     * @param keys Keys to load.
+     * @param ret Return value.
+     * @param needReadVer Read version flag.
+     * @param singleRmv {@code True} for single remove operation.
+     * @param hasFilters {@code True} if filters not empty.
+     * @param skipStore Skip store flag.
+     * @param retval Return value flag.
+     * @return Load future.
+     */
+    private IgniteInternalFuture<Void> loadMissing(
+        final GridCacheContext cacheCtx,
+        final Set<KeyCacheObject> keys,
+        final CacheEntryPredicate[] filter,
+        final GridCacheReturn ret,
+        final boolean needReadVer,
+        final boolean singleRmv,
+        final boolean hasFilters,
+        final boolean skipStore,
+        final boolean retval) {
+        GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c =
+            new GridInClosure3<KeyCacheObject, Object, GridCacheVersion>() {
+                @Override public void apply(KeyCacheObject key,
+                    @Nullable Object val,
+                    @Nullable GridCacheVersion loadVer) {
+                    if (log.isDebugEnabled())
+                        log.debug("Loaded value from remote node [key=" + key + ", val=" + val + ']');
 
-                            if (old != null && hasFilters && !filter(entry.context(), cacheKey, old, filter)) {
-                                skipped = skip(skipped, cacheKey);
+                    IgniteTxEntry e = entry(new IgniteTxKey(key, cacheCtx.cacheId()));
 
-                                ret.set(cacheCtx, old, false);
+                    assert e != null;
 
-                                if (!readCommitted()) {
-                                    // Enlist failed filters as reads for non-read-committed mode,
-                                    // so future ops will get the same values.
-                                    txEntry = addEntry(READ,
-                                        old,
-                                        null,
-                                        null,
-                                        entry,
-                                        null,
-                                        CU.empty0(),
-                                        false,
-                                        -1L,
-                                        -1L,
-                                        null,
-                                        skipStore);
+                    if (needReadVer) {
+                        assert loadVer != null;
 
-                                    txEntry.markValid();
+                        e.serializableReadVersion(singleRmv && val != null ? SER_READ_NOT_EMPTY_VER : loadVer);
+                    }
 
-                                    if (needReadVer) {
-                                        assert readVer != null;
+                    if (singleRmv) {
+                        assert !hasFilters && !retval;
+                        assert val == null || Boolean.TRUE.equals(val) : val;
 
-                                        txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
-                                    }
-                                }
+                        ret.set(cacheCtx, null, val != null);
+                    }
+                    else {
+                        CacheObject cacheVal = cacheCtx.toCacheObject(val);
 
-                                if (readCommitted())
-                                    cacheCtx.evicts().touch(entry, topologyVersion());
+                        if (e.op() == TRANSFORM) {
+                            GridCacheVersion ver;
 
-                                break; // While.
+                            try {
+                                ver = e.cached().version();
                             }
+                            catch (GridCacheEntryRemovedException ex) {
+                                assert optimistic() : e;
 
-                            final GridCacheOperation op = lockOnly ? NOOP : rmv ? DELETE :
-                                entryProcessor != null ? TRANSFORM : old != null ? UPDATE : CREATE;
+                                if (log.isDebugEnabled())
+                                    log.debug("Failed to get entry version: [msg=" + ex.getMessage() + ']');
 
-                            txEntry = addEntry(op,
-                                cacheCtx.toCacheObject(val),
-                                entryProcessor,
-                                invokeArgs,
-                                entry,
-                                expiryPlc,
-                                filter,
-                                true,
-                                drTtl,
-                                drExpireTime,
-                                drVer,
-                                skipStore);
+                                ver = null;
+                            }
 
-                            if (!implicit() && readCommitted() && !cacheCtx.offheapTiered())
-                                cacheCtx.evicts().touch(entry, topologyVersion());
+                            addInvokeResult(e, cacheVal, ret, ver);
+                        }
+                        else {
+                            boolean success = !hasFilters || isAll(e.context(), key, cacheVal, filter);
 
-                            enlisted.add(cacheKey);
+                            ret.set(cacheCtx, cacheVal, success);
+                        }
+                    }
+                }
+            };
 
-                            if (!pessimistic() && !implicit()) {
-                                txEntry.markValid();
+        return loadMissing(
+            cacheCtx,
+            /*read through*/cacheCtx.config().isLoadPreviousValue() && !skipStore,
+            /*async*/true,
+            keys,
+            /*skipVals*/singleRmv,
+            needReadVer,
+            c);
+    }
 
-                                if (old == null) {
-                                    if (needVal) {
-                                        if (missedForLoad == null)
-                                            missedForLoad = new HashSet<>();
+    /**
+     * @param cacheCtx Cache context.
+     * @param cacheKey Key.
+     * @param val Value.
+     * @param entryProcessor Entry processor.
+     * @param invokeArgs Optional arguments for EntryProcessor.
+     * @param expiryPlc Explicitly specified expiry policy for entry.
+     * @param retval Return value flag.
+     * @param lockOnly
+     * @param filter Filter.
+     * @param drVer DR version.
+     * @param drTtl DR ttl.
+     * @param drExpireTime DR expire time.
+     * @param ret Return value.
+     * @param enlisted Enlisted keys collection.
+     * @param skipStore Skip store flag.
+     * @param singleRmv {@code True} for single remove operation.
+     * @param hasFilters {@code True} if filters not empty.
+     * @param needVal {@code True} if value is needed.
+     * @param needReadVer {@code True} if need read entry version.
+     * @return {@code True} if entry value should be loaded.
+     * @throws IgniteCheckedException If failed.
+     */
+    private boolean enlistWriteEntry(GridCacheContext cacheCtx,
+        final KeyCacheObject cacheKey,
+        final @Nullable Object val,
+        final @Nullable EntryProcessor<?, ?, ?> entryProcessor,
+        final @Nullable Object[] invokeArgs,
+        final @Nullable ExpiryPolicy expiryPlc,
+        final boolean retval,
+        final boolean lockOnly,
+        final CacheEntryPredicate[] filter,
+        final GridCacheVersion drVer,
+        final long drTtl,
+        long drExpireTime,
+        final GridCacheReturn ret,
+        @Nullable final Collection<KeyCacheObject> enlisted,
+        boolean skipStore,
+        boolean singleRmv,
+        boolean hasFilters,
+        final boolean needVal,
+        boolean needReadVer
+    ) throws IgniteCheckedException {
+        boolean loadMissed = false;
 
-                                        missedForLoad.add(cacheKey);
-                                    }
-                                    else {
-                                        assert !implicit() || !transform : this;
-                                        assert txEntry.op() != TRANSFORM : txEntry;
+        final boolean rmv = val == null && entryProcessor == null;
 
-                                        if (retval)
-                                            ret.set(cacheCtx, null, true);
-                                        else
-                                            ret.success(true);
-                                    }
-                                }
-                                else {
-                                    if (needReadVer) {
-                                        assert readVer != null;
+        IgniteTxKey txKey = cacheCtx.txKey(cacheKey);
 
-                                        txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
-                                    }
+        IgniteTxEntry txEntry = entry(txKey);
 
-                                    if (retval && !transform)
-                                        ret.set(cacheCtx, old, true);
-                                    else {
-                                        if (txEntry.op() == TRANSFORM) {
-                                            GridCacheVersion ver;
+        // First time access.
+        if (txEntry == null) {
+            while (true) {
+                GridCacheEntryEx entry = entryEx(cacheCtx, txKey, topologyVersion());
 
-                                            try {
-                                                ver = entry.version();
-                                            }
-                                            catch (GridCacheEntryRemovedException ex) {
-                                                assert optimistic() : txEntry;
+                try {
+                    entry.unswap(false);
+
+                    // Check if lock is being explicitly acquired by the same thread.
+                    if (!implicit && cctx.kernalContext().config().isCacheSanityCheckEnabled() &&
+                        entry.lockedByThread(threadId, xidVer)) {
+                        throw new IgniteCheckedException("Cannot access key within transaction if lock is " +
+                            "externally held [key=" + CU.value(cacheKey, cacheCtx, false) +
+                            ", entry=" + entry +
+                            ", xidVer=" + xidVer +
+                            ", threadId=" + threadId +
+                            ", locNodeId=" + cctx.localNodeId() + ']');
+                    }
 
-                                                if (log.isDebugEnabled())
-                                                    log.debug("Failed to get entry version " +
-                                                        "[err=" + ex.getMessage() + ']');
+                    CacheObject old = null;
+                    GridCacheVersion readVer = null;
 
-                                                ver = null;
-                                            }
+                    if (optimistic() && !implicit()) {
+                        try {
+                            if (needReadVer) {
+                                T2<CacheObject, GridCacheVersion> res = primaryLocal(entry) ?
+                                    entry.innerGetVersioned(this,
+                                        /*swap*/false,
+                                        /*unmarshal*/retval,
+                                        /*metrics*/retval,
+                                        /*events*/retval,
+                                        CU.subjectId(this, cctx),
+                                        entryProcessor,
+                                        resolveTaskName(),
+                                        null) : null;
 
-                                            addInvokeResult(txEntry, old, ret, ver);
-                                        }
-                                        else
-                                            ret.success(true);
-                                    }
+                                if (res != null) {
+                                    old = res.get1();
+                                    readVer = res.get2();
                                 }
                             }
-                            // Pessimistic.
                             else {
-                                if (retval && !transform)
-                                    ret.set(cacheCtx, old, true);
-                                else
-                                    ret.success(true);
+                                old = entry.innerGet(this,
+                                    /*swap*/false,
+                                    /*read-through*/false,
+                                    /*fail-fast*/false,
+                                    /*unmarshal*/retval,
+                                    /*metrics*/retval,
+                                    /*events*/retval,
+                                    /*temporary*/false,
+                                    CU.subjectId(this, cctx),
+                                    entryProcessor,
+                                    resolveTaskName(),
+                                    null);
                             }
-
-                            break; // While.
                         }
-                        catch (GridCacheEntryRemovedException ignore) {
-                            if (log.isDebugEnabled())
-                                log.debug("Got removed entry in transaction putAll0 method: " + entry);
+                        catch (ClusterTopologyCheckedException e) {
+                            entry.context().evicts().touch(entry, topologyVersion());
+
+                            throw e;
                         }
                     }
-                }
-                else {
-                    if (entryProcessor == null && txEntry.op() == TRANSFORM)
-                        throw new IgniteCheckedException("Failed to enlist write value for key (cannot have update value in " +
-                            "transaction after EntryProcessor is applied): " + key);
+                    else
+                        old = retval ? entry.rawGetOrUnmarshal(false) : entry.rawGet();
 
-                    GridCacheEntryEx entry = txEntry.cached();
+                    if (old != null && hasFilters && !filter(entry.context(), cacheKey, old, filter)) {
+                        ret.set(cacheCtx, old, false);
 
-                    CacheObject v = txEntry.value();
-
-                    boolean del = txEntry.op() == DELETE && rmv;
+                        if (!readCommitted()) {
+                            // Enlist failed filters as reads for non-read-committed mode,
+                            // so future ops will get the same values.
+                            txEntry = addEntry(READ,
+                                old,
+                                null,
+                                null,
+                                entry,
+                                null,
+                                CU.empty0(),
+                                false,
+                                -1L,
+                                -1L,
+                                null,
+                                skipStore);
 
-                    if (!del) {
-                        if (hasFilters && !filter(entry.context(), cacheKey, v, filter)) {
-                            skipped = skip(skipped, cacheKey);
+                            txEntry.markValid();
 
-                            ret.set(cacheCtx, v, false);
+                            if (needReadVer) {
+                                assert readVer != null;
 
-                            continue;
+                                txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
+                            }
                         }
 
-                        GridCacheOperation op = rmv ? DELETE : entryProcessor != null ? TRANSFORM :
-                            v != null ? UPDATE : CREATE;
+                        if (readCommitted())
+                            cacheCtx.evicts().touch(entry, topologyVersion());
 
-                        txEntry = addEntry(op,
-                            cacheCtx.toCacheObject(val),
-                            entryProcessor,
-                            invokeArgs,
-                            entry,
-                            expiryPlc,
-                            filter,
-                            true,
-                            drTtl,
-                            drExpireTime,
-                            drVer,
-                            skipStore);
+                        break; // While.
+                    }
+
+                    final GridCacheOperation op = lockOnly ? NOOP : rmv ? DELETE :
+                        entryProcessor != null ? TRANSFORM : old != null ? UPDATE : CREATE;
+
+                    txEntry = addEntry(op,
+                        cacheCtx.toCacheObject(val),
+                        entryProcessor,
+                        invokeArgs,
+                        entry,
+                        expiryPlc,
+                        filter,
+                        true,
+                        drTtl,
+                        drExpireTime,
+                        drVer,
+                        skipStore);
 
+                    if (!implicit() && readCommitted() && !cacheCtx.offheapTiered())
+                        cacheCtx.evicts().touch(entry, topologyVersion());
+
+                    if (enlisted != null)
                         enlisted.add(cacheKey);
 
-                        if (txEntry.op() == TRANSFORM) {
-                            GridCacheVersion ver;
+                    if (!pessimistic() && !implicit()) {
+                        txEntry.markValid();
 
-                            try {
-                                ver = entry.version();
-                            }
-                            catch (GridCacheEntryRemovedException e) {
-                                assert optimistic() : txEntry;
+                        if (old == null) {
+                            if (needVal)
+                                loadMissed = true;
+                            else {
+                                assert !implicit() || !transform : this;
+                                assert txEntry.op() != TRANSFORM : txEntry;
 
-                                if (log.isDebugEnabled())
-                                    log.debug("Failed to get entry version: [msg=" + e.getMessage() + ']');
+                                if (retval)
+                                    ret.set(cacheCtx, null, true);
+                                else
+                                    ret.success(true);
+                            }
+                        }
+                        else {
+                            if (needReadVer) {
+                                assert readVer != null;
 
-                                ver = null;
+                                txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
                             }
 
-                            addInvokeResult(txEntry, txEntry.value(), ret, ver);
-                        }
-                    }
+                            if (retval && !transform)
+                                ret.set(cacheCtx, old, true);
+                            else {
+                                if (txEntry.op() == TRANSFORM) {
+                                    GridCacheVersion ver;
 
-                    if (!pessimistic()) {
-                        txEntry.markValid();
+                                    try {
+                                        ver = entry.version();
+                                    }
+                                    catch (GridCacheEntryRemovedException ex) {
+                                        assert optimistic() : txEntry;
+
+                                        if (log.isDebugEnabled())
+                                            log.debug("Failed to get entry version " +
+                                                "[err=" + ex.getMessage() + ']');
+
+                                        ver = null;
+                                    }
 
+                                    addInvokeResult(txEntry, old, ret, ver);
+                                }
+                                else
+                                    ret.success(true);
+                            }
+                        }
+                    }
+                    // Pessimistic.
+                    else {
                         if (retval && !transform)
-                            ret.set(cacheCtx, v, true);
+                            ret.set(cacheCtx, old, true);
                         else
                             ret.success(true);
                     }
-                }
+
+                    break; // While.
+                }
+                catch (GridCacheEntryRemovedException ignore) {
+                    if (log.isDebugEnabled())
+                        log.debug("Got removed entry in transaction putAll0 method: " + entry);
+                }
             }
         }
-        catch (IgniteCheckedException e) {
-            return new GridFinishedFuture<>(e);
-        }
-
-        if (missedForLoad != null) {
-            final boolean skipVals = singleRmv;
-
-            IgniteInternalFuture<Void> fut = loadMissing(
-                cacheCtx,
-                /*read through*/cacheCtx.config().isLoadPreviousValue() && !skipStore,
-                /*async*/true,
-                missedForLoad,
-                skipVals,
-                needReadVer,
-                new GridInClosure3<KeyCacheObject, Object, GridCacheVersion>() {
-                    @Override public void apply(KeyCacheObject key,
-                        @Nullable Object val,
-                        @Nullable GridCacheVersion loadVer) {
-                        if (log.isDebugEnabled())
-                            log.debug("Loaded value from remote node [key=" + key + ", val=" + val + ']');
+        else {
+            if (entryProcessor == null && txEntry.op() == TRANSFORM)
+                throw new IgniteCheckedException("Failed to enlist write value for key (cannot have update value in " +
+                    "transaction after EntryProcessor is applied): " + CU.value(cacheKey, cacheCtx, false));
 
-                        IgniteTxEntry e = entry(new IgniteTxKey(key, cacheCtx.cacheId()));
+            GridCacheEntryEx entry = txEntry.cached();
 
-                        assert e != null;
+            CacheObject v = txEntry.value();
 
-                        if (needReadVer) {
-                            assert loadVer != null;
+            boolean del = txEntry.op() == DELETE && rmv;
 
-                            e.serializableReadVersion(singleRmv && val != null ? SER_READ_NOT_EMPTY_VER : loadVer);
-                        }
+            if (!del) {
+                if (hasFilters && !filter(entry.context(), cacheKey, v, filter)) {
+                    ret.set(cacheCtx, v, false);
 
-                        if (singleRmv) {
-                            assert !hasFilters && !retval;
-                            assert val == null || Boolean.TRUE.equals(val) : val;
+                    return loadMissed;
+                }
 
-                            ret.set(cacheCtx, null, val != null);
-                        }
-                        else {
-                            CacheObject cacheVal = cacheCtx.toCacheObject(val);
+                GridCacheOperation op = rmv ? DELETE : entryProcessor != null ? TRANSFORM :
+                    v != null ? UPDATE : CREATE;
 
-                            if (e.op() == TRANSFORM) {
-                                GridCacheVersion ver;
+                txEntry = addEntry(op,
+                    cacheCtx.toCacheObject(val),
+                    entryProcessor,
+                    invokeArgs,
+                    entry,
+                    expiryPlc,
+                    filter,
+                    true,
+                    drTtl,
+                    drExpireTime,
+                    drVer,
+                    skipStore);
 
-                                try {
-                                    ver = e.cached().version();
-                                }
-                                catch (GridCacheEntryRemovedException ex) {
-                                    assert optimistic() : e;
+                if (enlisted != null)
+                    enlisted.add(cacheKey);
 
-                                    if (log.isDebugEnabled())
-                                        log.debug("Failed to get entry version: [msg=" + ex.getMessage() + ']');
+                if (txEntry.op() == TRANSFORM) {
+                    GridCacheVersion ver;
 
-                                    ver = null;
-                                }
+                    try {
+                        ver = entry.version();
+                    }
+                    catch (GridCacheEntryRemovedException e) {
+                        assert optimistic() : txEntry;
 
-                                addInvokeResult(e, cacheVal, ret, ver);
-                            }
-                            else {
-                                boolean success = !hasFilters || isAll(e.context(), key, cacheVal, filter);
+                        if (log.isDebugEnabled())
+                            log.debug("Failed to get entry version: [msg=" + e.getMessage() + ']');
 
-                                ret.set(cacheCtx, cacheVal, success);
-                            }
-                        }
+                        ver = null;
                     }
-                });
 
-            return new GridEmbeddedFuture<>(
-                new C2<Void, Exception, Set<KeyCacheObject>>() {
-                    @Override public Set<KeyCacheObject> apply(Void b, Exception e) {
-                        if (e != null)
-                            throw new GridClosureException(e);
+                    addInvokeResult(txEntry, txEntry.value(), ret, ver);
+                }
+            }
 
-                        return Collections.emptySet();
-                    }
-                }, fut
-            );
+            if (!pessimistic()) {
+                txEntry.markValid();
+
+                if (retval && !transform)
+                    ret.set(cacheCtx, v, true);
+                else
+                    ret.success(true);
+            }
         }
 
-        return new GridFinishedFuture<>(skipped);
+        return loadMissed;
     }
 
     /**
@@ -2486,22 +2634,19 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      *
      * @param cacheCtx Context.
      * @param keys Keys.
-     * @param failed Collection of potentially failed keys (need to populate in this method).
      * @param ret Return value.
      * @param rmv {@code True} if remove.
      * @param retval Flag to return value or not.
      * @param read {@code True} if read.
      * @param accessTtl TTL for read operation.
      * @param filter Filter to check entries.
-     * @return Failed keys.
      * @throws IgniteCheckedException If error.
      * @param computeInvoke If {@code true} computes return value for invoke operation.
      */
     @SuppressWarnings("unchecked")
-    protected Set<KeyCacheObject> postLockWrite(
+    protected final void postLockWrite(
         GridCacheContext cacheCtx,
         Iterable<KeyCacheObject> keys,
-        Set<KeyCacheObject> failed,
         GridCacheReturn ret,
         boolean rmv,
         boolean retval,
@@ -2606,8 +2751,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                             log.debug("Filter passed in post lock for key: " + k);
                     }
                     else {
-                        failed = skip(failed, k);
-
                         // Revert operation to previous. (if no - NOOP, so entry will be unlocked).
                         txEntry.setAndMarkValid(txEntry.previousOperation(), cacheCtx.toCacheObject(ret.value()));
                         txEntry.filters(CU.empty0());
@@ -2638,11 +2781,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 }
             }
         }
-
-        if (log.isDebugEnabled())
-            log.debug("Entries that failed after lock filter check: " + failed);
-
-        return failed;
     }
 
     /**
@@ -2696,6 +2834,144 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     }
 
     /**
+     * @param cacheCtx Cache context.
+     * @param retval Return value flag.
+     * @throws IgniteCheckedException If failed.
+     */
+    private void beforePut(GridCacheContext cacheCtx, boolean retval) throws IgniteCheckedException {
+        checkUpdatesAllowed(cacheCtx);
+
+        cacheCtx.checkSecurity(SecurityPermission.CACHE_PUT);
+
+        if (retval)
+            needReturnValue(true);
+
+        checkValid();
+
+        init();
+    }
+
+    /**
+     * Internal method for single update operation.
+     *
+     * @param cacheCtx Cache context.
+     * @param key Key.
+     * @param val Value.
+     * @param entryProcessor Entry processor.
+     * @param invokeArgs Optional arguments for EntryProcessor.
+     * @param retval Return value flag.
+     * @param filter Filter.
+     * @return Operation future.
+     */
+    private <K, V> IgniteInternalFuture putAsync0(
+        final GridCacheContext cacheCtx,
+        K key,
+        @Nullable V val,
+        @Nullable EntryProcessor entryProcessor,
+        @Nullable final Object[] invokeArgs,
+        final boolean retval,
+        @Nullable final CacheEntryPredicate[] filter
+    ) {
+        assert key != null;
+
+        try {
+            beforePut(cacheCtx, retval);
+
+            final GridCacheReturn ret = new GridCacheReturn(localResult(), false);
+
+            CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
+
+            KeyCacheObject cacheKey = cacheCtx.toCacheKeyObject(key);
+
+            final IgniteInternalFuture<Void> loadFut = enlistWrite(
+                cacheCtx,
+                cacheKey,
+                val,
+                opCtx != null ? opCtx.expiry() : null,
+                entryProcessor,
+                invokeArgs,
+                retval,
+                /*lockOnly*/false,
+                filter,
+                ret,
+                opCtx != null && opCtx.skipStore(),
+                /*singleRmv*/false);
+
+            if (pessimistic()) {
+                assert loadFut == null || loadFut.isDone() : loadFut;
+
+                final Collection<KeyCacheObject> enlisted = Collections.singleton(cacheKey);
+
+                if (log.isDebugEnabled())
+                    log.debug("Before acquiring transaction lock for put on key: " + enlisted);
+
+                IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(enlisted,
+                    lockTimeout(),
+                    this,
+                    false,
+                    retval,
+                    isolation,
+                    isInvalidate(),
+                    -1L);
+
+                PLC1<GridCacheReturn> plc1 = new PLC1<GridCacheReturn>(ret) {
+                    @Override public GridCacheReturn postLock(GridCacheReturn ret)
+                        throws IgniteCheckedException
+                    {
+                        if (log.isDebugEnabled())
+                            log.debug("Acquired transaction lock for put on keys: " + enlisted);
+
+                        postLockWrite(cacheCtx,
+                            enlisted,
+                            ret,
+                            /*remove*/false,
+                            retval,
+                            /*read*/false,
+                            -1L,
+                            filter,
+                            /*computeInvoke*/true);
+
+                        return ret;
+                    }
+                };
+
+                if (fut.isDone()) {
+                    try {
+                        return nonInterruptable(plc1.apply(fut.get(), null));
+                    }
+                    catch (GridClosureException e) {
+                        return new GridFinishedFuture<>(e.unwrap());
+                    }
+                    catch (IgniteCheckedException e) {
+                        try {
+                            return nonInterruptable(plc1.apply(false, e));
+                        }
+                        catch (Exception e1) {
+                            return new GridFinishedFuture<>(e1);
+                        }
+                    }
+                }
+                else {
+                    return nonInterruptable(new GridEmbeddedFuture<>(
+                        fut,
+                        plc1
+                    ));
+                }
+            }
+            else
+                return optimisticPutFuture(loadFut, ret);
+        }
+        catch (IgniteCheckedException e) {
+            return new GridFinishedFuture(e);
+        }
+        catch (RuntimeException e) {
+            onException();
+
+            throw e;
+        }
+    }
+
+    /**
      * Internal method for all put and transform operations. Only one of {@code map}, {@code transformMap}
      * maps must be non-null.
      *
@@ -2721,17 +2997,12 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         assert filter == null || invokeMap == null;
 
         try {
-            checkUpdatesAllowed(cacheCtx);
+            beforePut(cacheCtx, retval);
         }
         catch (IgniteCheckedException e) {
             return new GridFinishedFuture(e);
         }
 
-        cacheCtx.checkSecurity(SecurityPermission.CACHE_PUT);
-
-        if (retval)
-            needReturnValue(true);
-
         // Cached entry may be passed only from entry wrapper.
         final Map<?, ?> map0;
         final Map<?, EntryProcessor<K, V, Object>> invokeMap0;
@@ -2757,15 +3028,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
         assert map0 != null || invokeMap0 != null;
 
-        try {
-            checkValid();
-        }
-        catch (IgniteCheckedException e) {
-            return new GridFinishedFuture<>(e);
-        }
-
-        init();
-
         final GridCacheReturn ret = new GridCacheReturn(localResult(), false);
 
         if (F.isEmpty(map0) && F.isEmpty(invokeMap0)) {
@@ -2783,15 +3045,14 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         try {
             Set<?> keySet = map0 != null ? map0.keySet() : invokeMap0.keySet();
 
-            Collection<KeyCacheObject> enlisted = new ArrayList<>();
+            final Collection<KeyCacheObject> enlisted = new ArrayList<>();
 
             CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
 
-            final IgniteInternalFuture<Set<KeyCacheObject>> loadFut = enlistWrite(
+            final IgniteInternalFuture<Void> loadFut = enlistWrite(
                 cacheCtx,
                 keySet,
                 opCtx != null ? opCtx.expiry() : null,
-                implicit,
                 map0,
                 invokeMap0,
                 invokeArgs,
@@ -2806,15 +3067,12 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                 false);
 
             if (pessimistic()) {
-                // Loose all skipped.
-                final Set<KeyCacheObject> loaded = loadFut.get();
-
-                final Collection<KeyCacheObject> keys = F.view(enlisted, F0.notIn(loaded));
+                assert loadFut == null || loadFut.isDone() : loadFut;
 
                 if (log.isDebugEnabled())
-                    log.debug("Before acquiring transaction lock for put on keys: " + keys);
+                    log.debug("Before acquiring transaction lock for put on keys: " + enlisted);
 
-                IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(keys,
+                IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(enlisted,
                     lockTimeout(),
                     this,
                     false,
@@ -2828,11 +3086,10 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                         throws IgniteCheckedException
                     {
                         if (log.isDebugEnabled())
-                            log.debug("Acquired transaction lock for put on keys: " + keys);
+                            log.debug("Acquired transaction lock for put on keys: " + enlisted);
 
                         postLockWrite(cacheCtx,
-                            keys,
-                            loaded,
+                            enlisted,
                             ret,
                             /*remove*/false,
                             retval,
@@ -2861,64 +3118,79 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                         }
                     }
                 }
-                else
+                else {
                     return nonInterruptable(new GridEmbeddedFuture<>(
                         fut,
                         plc1
                     ));
+                }
             }
-            else {
-                if (implicit()) {
-                    // Should never load missing values for implicit transaction as values will be returned
-                    // with prepare response, if required.
-                    assert loadFut.isDone();
+            else
+                return optimisticPutFuture(loadFut, ret);
+        }
+        catch (RuntimeException e) {
+            onException();
 
-                    try {
-                        loadFut.get();
-                    }
-                    catch (IgniteCheckedException e) {
-                        return new GridFinishedFuture<>(e);
-                    }
+            throw e;
+        }
+    }
 
-                    return nonInterruptable(commitAsync().chain(new CX1<IgniteInternalFuture<IgniteInternalTx>, GridCacheReturn>() {
-                        @Override public GridCacheReturn applyx(IgniteInternalFuture<IgniteInternalTx> txFut) throws IgniteCheckedException {
-                            try {
-                                txFut.get();
+    /**
+     * @param loadFut Missing keys load future.
+     * @param ret Future result.
+     * @return Future.
+     */
+    private IgniteInternalFuture optimisticPutFuture(IgniteInternalFuture<Void> loadFut, final GridCacheReturn ret) {
+        if (implicit()) {
+            // Should never load missing values for implicit transaction as values will be returned
+            // with prepare response, if required.
+            assert loadFut.isDone();
 
-                                return implicitRes;
-                            }
-                            catch (IgniteCheckedException | RuntimeException e) {
-                                rollbackAsync();
+            try {
+                loadFut.get();
+            }
+            catch (IgniteCheckedException e) {
+                return new GridFinishedFuture<>(e);
+            }
 
-                                throw e;
-                            }
+            return nonInterruptable(commitAsync().chain(
+                new CX1<IgniteInternalFuture<IgniteInternalTx>, GridCacheReturn>() {
+                    @Override public GridCacheReturn applyx(IgniteInternalFuture<IgniteInternalTx> txFut)
+                        throws IgniteCheckedException {
+                        try {
+                            txFut.get();
+
+                            return implicitRes;
                         }
-                    }));
-                }
-                else
-                    return nonInterruptable(loadFut.chain(new CX1<IgniteInternalFuture<Set<KeyCacheObject>>, GridCacheReturn>() {
-                        @Override public GridCacheReturn applyx(IgniteInternalFuture<Set<KeyCacheObject>> f) throws IgniteCheckedException {
-                            f.get();
+                        catch (IgniteCheckedException | RuntimeException e) {
+                            rollbackAsync();
 
-                            return ret;
+                            throw e;
                         }
-                    }));
-            }
+                    }
+                }
+            ));
         }
-        catch (RuntimeException e) {
-            for (IgniteTxEntry txEntry : txMap.values()) {
-                GridCacheEntryEx cached0 = txEntry.cached();
-
-                if (cached0 != null)
-                    txEntry.context().evicts().touch(cached0, topologyVersion());
-            }
+        else {
+            return nonInterruptable(loadFut.chain(new CX1<IgniteInternalFuture<Void>, GridCacheReturn>() {
+                @Override public GridCacheReturn applyx(IgniteInternalFuture<Void> f) throws IgniteCheckedException {
+                    f.get();
 
-            throw e;
+                    return ret;
+                }
+            }));
         }
-        catch (IgniteCheckedException e) {
-            setRollbackOnly();
+    }
 
-            return new GridFinishedFuture<>(e);
+    /**
+     *
+     */
+    private void onException() {
+        for (IgniteTxEntry txEntry : allEntries()) {
+            GridCacheEntryEx cached0 = txEntry.cached();
+
+            if (cached0 != null)
+                txEntry.context().evicts().touch(cached0, topologyVersion());
         }
     }
 
@@ -2974,9 +3246,10 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
         assert keys0 != null;
 
-        if (log.isDebugEnabled())
+        if (log.isDebugEnabled()) {
             log.debug("Called removeAllAsync(...) [tx=" + this + ", keys=" + keys0 + ", implicit=" + implicit +
                 ", retval=" + retval + "]");
+        }
 
         try {
             checkValid();
@@ -3002,140 +3275,131 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
 
         init();
 
-        try {
-            Collection<KeyCacheObject> enlisted = new ArrayList<>();
-
-            CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
+        final Collection<KeyCacheObject> enlisted = new ArrayList<>();
 
-            ExpiryPolicy plc;
+        CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
 
-            if (!F.isEmpty(filter))
-                plc = opCtx != null ? opCtx.expiry() : null;
-            else
-                plc = null;
+        ExpiryPolicy plc;
 
-            final IgniteInternalFuture<Set<KeyCacheObject>> loadFut = enlistWrite(
-                cacheCtx,
-                keys0,
-                plc,
-                implicit,
-                /** lookup map */null,
-                /** invoke map */null,
-                /** invoke arguments */null,
-                retval,
-                /** lock only */false,
-                filter,
-                ret,
-                enlisted,
-                null,
-                drMap,
-                opCtx != null && opCtx.skipStore(),
-                singleRmv
-            );
+        if (!F.isEmpty(filter))
+            plc = opCtx != null ? opCtx.expiry() : null;
+        else
+            plc = null;
 
-            if (log.isDebugEnabled())
-                log.debug("Remove keys: " + enlisted);
+        final IgniteInternalFuture<Void> loadFut = enlistWrite(
+            cacheCtx,
+            keys0,
+            plc,
+            /** lookup map */null,
+            /** invoke map */null,
+            /** invoke arguments */null,
+            retval,
+            /** lock only */false,
+            filter,
+            ret,
+            enlisted,
+            null,
+            drMap,
+            opCtx != null && opCtx.skipStore(),
+            singleRmv
+        );
 
-            // Acquire locks only after having added operation to the write set.
-            // Otherwise, during rollback we will not know whether locks need
-            // to be rolled back.
-            if (pessimistic()) {
-                // Loose all skipped.
-                final Collection<KeyCacheObject> passedKeys = F.view(enlisted, F0.notIn(loadFut.get()));
+        if (log.isDebugEnabled())
+            log.debug("Remove keys: " + enlisted);
 
-                if (log.isDebugEnabled())
-                    log.debug("Before acquiring transaction lock for remove on keys: " + passedKeys);
+        // Acquire locks only after having added operation to the write set.
+        // Otherwise, during rollback we will not know whether locks need
+        // to be rolled back.
+        if (pessimistic()) {
+            assert loadFut.isDone() : loadFut;
 
-                IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(passedKeys,
-                    lockTimeout(),
-                    this,
-                    false,
-                    retval,
-                    isolation,
-                    isInvalidate(),
-                    -1L);
+            if (log.isDebugEnabled())
+                log.debug("Before acquiring transaction lock for remove on keys: " + enlisted);
 
-                PLC1<GridCacheReturn> plc1 = new PLC1<GridCacheReturn>(ret) {
-                    @Override protected GridCacheReturn postLock(GridCacheReturn ret)
-                        throws IgniteCheckedException
-                    {
-                        if (log.isDebugEnabled())
-                            log.debug("Acquired transaction lock for remove on keys: " + passedKeys);
+            IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(enlisted,
+                lockTimeout(),
+                this,
+                false,
+                retval,
+                isolation,
+                isInvalidate(),
+                -1L);
+
+            PLC1<GridCacheReturn> plc1 = new PLC1<GridCacheReturn>(ret) {
+                @Override protected GridCacheReturn postLock(GridCacheReturn ret)
+                    throws IgniteCheckedException
+                {
+                    if (log.isDebugEnabled())
+                        log.debug("Acquired transaction lock for remove on keys: " + enlisted);
 
-                        postLockWrite(cacheCtx,
-                            passedKeys,
-                            loadFut.get(),
-                            ret,
+                    postLockWrite(cacheCtx,
+                        enlisted,
+                        ret,
                             /*remove*/true,
-                            retval,
+                        retval,
                             /*read*/false,
-                            -1L,
-                            filter,
+                        -1L,
+                        filter,
                             /*computeInvoke*/false);
 
-                        return ret;
-                    }
-                };
+                    return ret;
+                }
+            };
 
-                if (fut.isDone()) {
+            if (fut.isDone()) {
+                try {
+                    return nonInterruptable(plc1.apply(fut.get(), null));
+                }
+                catch (GridClosureException e) {
+                    return new GridFinishedFuture<>(e.unwrap());
+                }
+                catch (IgniteCheckedException e) {
                     try {
-                        return nonInterruptable(plc1.apply(fut.get(), null));
+                        return nonInterruptable(plc1.apply(false, e));
                     }
-                    catch (GridClosureException e) {
-                        return new GridFinishedFuture<>(e.unwrap());
-                    }
-                    catch (IgniteCheckedException e) {
-                        try {
-                            return nonInterruptable(plc1.apply(false, e));
-                        }
-                        catch (Exception e1) {
-                            return new GridFinishedFuture<>(e1);
-                        }
+                    catch (Exception e1) {
+                        return new GridFinishedFuture<>(e1);
                     }
                 }
-                else
-                    return nonInterruptable(new GridEmbeddedFuture<>(
-                        fut,
-                        plc1
-                    ));
             }
-            else {
-                if (implicit()) {
-                    // Should never load missing values for implicit transaction as values will be returned
-                    // with prepare response, if required.
-                    assert loadFut.isDone();
-
-                    return nonInterruptable(commitAsync().chain(new CX1<IgniteInternalFuture<IgniteInternalTx>, GridCacheReturn>() {
-                        @Override public GridCacheReturn applyx(IgniteInternalFuture<IgniteInternalTx> txFut)
-                            throws IgniteCheckedException {
-                            try {
-                                txFut.get();
+            else
+                return nonInterruptable(new GridEmbeddedFuture<>(
+                    fut,
+                    plc1
+                ));
+        }
+        else {
+            if (implicit()) {
+                // Should never load missing values for implicit transaction as values will be returned
+                // with prepare response, if required.
+                assert loadFut.isDone();
 
-                                return implicitRes;
-                            }
-                            catch (IgniteCheckedException | RuntimeException e) {
-                                rollbackAsync();
+                return nonInterruptable(commitAsync().chain(new CX1<IgniteInternalFuture<IgniteInternalTx>, GridCacheReturn>() {
+                    @Override public GridCacheReturn applyx(IgniteInternalFuture<IgniteInternalTx> txFut)
+                        throws IgniteCheckedException {
+                        try {
+                            txFut.get();
 
-                                throw e;
-                            }
+                            return implicitRes;
                         }
-                    }));
-                }
-                else
-                    return nonInterruptable(loadFut.chain(new CX1<IgniteInternalFuture<Set<KeyCacheObject>>, GridCacheReturn>() {
-                        @Override public GridCacheReturn applyx(IgniteInternalFuture<Set<KeyCacheObject>> f)
-                            throws IgniteCheckedException {
-                            f.get();
+                        catch (IgniteCheckedException | RuntimeException e) {
+                            rollbackAsync();
 
-                            return ret;
+                            throw e;
                         }
-                    }));
+                    }
+                }));
             }
-        }
-        catch (IgniteCheckedException e) {
-            setRollbackOnly();
+            else {
+                return nonInterruptable(loadFut.chain(new CX1<IgniteInternalFuture<Void>, GridCacheReturn>() {
+                    @Override public GridCacheReturn applyx(IgniteInternalFuture<Void> f)
+                        throws IgniteCheckedException {
+                        f.get();
 
-            return new GridFinishedFuture<>(e);
+                        return ret;
+                    }
+                }));
+            }
         }
     }
 
@@ -3169,16 +3433,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      * @return {@code True} if transaction was successfully  started.
      */
     public boolean init() {
-        if (txMap == null) {
-            txMap = new LinkedHashMap<>(txSize > 0 ? txSize : 16, 1.0f);
+        return !txState.init(txSize) || cctx.tm().onStarted(this);
 
-            readView = new IgniteTxMap(txMap, CU.reads());
-            writeView = new IgniteTxMap(txMap, CU.writes());
-
-            return cctx.tm().onStarted(this);
-        }
-
-        return true;
     }
 
     /**
@@ -3188,38 +3444,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      * @throws IgniteCheckedException If caches already enlisted in this transaction are not compatible with given
      *      cache (e.g. they have different stores).
      */
-    protected void addActiveCache(GridCacheContext cacheCtx) throws IgniteCheckedException {
-        int cacheId = cacheCtx.cacheId();
-
-        // Check if we can enlist new cache to transaction.
-        if (!activeCacheIds.contains(cacheId)) {
-            String err = cctx.verifyTxCompatibility(this, activeCacheIds, cacheCtx);
-
-            if (err != null) {
-                StringBuilder cacheNames = new StringBuilder();
-
-                int idx = 0;
-
-                for (Integer activeCacheId : activeCacheIds) {
-                    cacheNames.append(cctx.cacheContext(activeCacheId).name());
-
-                    if (idx++ < activeCacheIds.size() - 1)
-                        cacheNames.append(", ");
-                }
-
-                throw new IgniteCheckedException("Failed to enlist new cache to existing transaction (" +
-                    err +
-                    ") [activeCaches=[" + cacheNames + "]" +
-                    ", cacheName=" + cacheCtx.name() +
-                    ", cacheSystem=" + cacheCtx.systemTx() +
-                    ", txSystem=" + system() + ']');
-            }
-            else
-                activeCacheIds.add(cacheId);
-
-            if (activeCacheIds.size() == 1)
-                depEnabled = cacheCtx.deploymentEnabled();
-        }
+    protected final void addActiveCache(GridCacheContext cacheCtx) throws IgniteCheckedException {
+        txState.addActiveCache(cacheCtx, this);
     }
 
     /**
@@ -3294,7 +3520,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             "Invalid tx state for adding entry [op=" + op + ", val=" + val + ", entry=" + entry + ", filter=" +
                 Arrays.toString(filter) + ", txCtx=" + cctx.tm().txContextVersion() + ", tx=" + this + ']';
 
-        IgniteTxEntry old = txMap.get(key);
+        IgniteTxEntry old = entry(key);
 
         // Keep old filter if already have one (empty filter is always overridden).
         if (!filtersSet || !F.isEmptyOrNulls(filter)) {
@@ -3358,7 +3584,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             if (!hasDrTtl)
                 txEntry.expiry(expiryPlc);
 
-            txMap.put(key, txEntry);
+            txState.addEntry(txEntry);
 
             if (log.isDebugEnabled())
                 log.debug("Created transaction entry: " + txEntry);
@@ -3420,7 +3646,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     /** {@inheritDoc} */
     @Override public String toString() {
         return GridToStringBuilder.toString(IgniteTxLocalAdapter.class, this, "super", super.toString(),
-            "size", (txMap == null ? 0 : txMap.size()));
+            "size", allEntries().size());
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalEx.java
index 0d83338..5dc3338 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalEx.java
@@ -93,9 +93,37 @@ public interface IgniteTxLocalEx extends IgniteInternalTx {
 
     /**
      * @param cacheCtx Cache context.
+     * @param key Key.
+     * @param val Value.
+     * @param retval Return value flag.
+     * @param filter Filter.
+     * @return Future for put operation.
+     */
+    public <K, V> IgniteInternalFuture<GridCacheReturn> putAsync(
+        GridCacheContext cacheCtx,
+        K key,
+        V val,
+        boolean retval,
+        CacheEntryPredicate[] filter);
+
+    /**
+     * @param cacheCtx Cache context.
+     * @param key Key.
+     * @param entryProcessor Entry processor.
+     * @param invokeArgs Optional arguments for entry processor.
+     * @return Operation future.
+     */
+    public <K, V> IgniteInternalFuture<GridCacheReturn> invokeAsync(
+        GridCacheContext cacheCtx,
+        K key,
+        EntryProcessor<K, V, Object> entryProcessor,
+        Object... invokeArgs);
+
+    /**
+     * @param cacheCtx Cache context.
      * @param map Entry processors map.
      * @param invokeArgs Optional arguments for entry processor.
-     * @return Transform operation future.
+     * @return Operation future.
      */
     public <K, V, T> IgniteInternalFuture<GridCacheReturn> invokeAsync(
         GridCacheContext cacheCtx,

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalState.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalState.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalState.java
new file mode 100644
index 0000000..123d396
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalState.java
@@ -0,0 +1,44 @@
+/*
+ * 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.transactions;
+
+/**
+ *
+ */
+public interface IgniteTxLocalState extends IgniteTxState {
+    /**
+     * @param entry Entry.
+     */
+    public void addEntry(IgniteTxEntry entry);
+
+    /**
+     * @param txSize Transaction size.
+     * @return {@code True} if transaction was successfully  started.
+     */
+    public boolean init(int txSize);
+
+    /**
+     * @return {@code True} if init method was called.
+     */
+    public boolean initialized();
+
+    /**
+     *
+     */
+    public void seal();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalStateAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalStateAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalStateAdapter.java
new file mode 100644
index 0000000..cde5203
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalStateAdapter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.transactions;
+
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+/**
+ *
+ */
+public abstract class IgniteTxLocalStateAdapter implements IgniteTxLocalState {
+    /**
+     * @param cacheCtx Cache context.
+     * @param tx Transaction.
+     * @param commit {@code False} if transaction rolled back.
+     */
+    protected final void onTxEnd(GridCacheContext cacheCtx, IgniteInternalTx tx, boolean commit) {
+        if (cacheCtx.cache().configuration().isStatisticsEnabled()) {
+            // Convert start time from ms to ns.
+            if (commit)
+                cacheCtx.cache().metrics0().onTxCommit((U.currentTimeMillis() - tx.startTime()) * 1000);
+            else
+                cacheCtx.cache().metrics0().onTxRollback((U.currentTimeMillis() - tx.startTime()) * 1000);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
index c2e7dea..ccccca0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
@@ -1092,13 +1092,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
                 if (!tx.system())
                     cctx.txMetrics().onTxCommit();
 
-                for (int cacheId : tx.activeCacheIds()) {
-                    GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
-
-                    if (cacheCtx.cache().configuration().isStatisticsEnabled())
-                        // Convert start time from ms to ns.
-                        cacheCtx.cache().metrics0().onTxCommit((U.currentTimeMillis() - tx.startTime()) * 1000);
-                }
+                tx.txState().onTxEnd(cctx, tx, true);
             }
 
             if (slowTxWarnTimeout > 0 && tx.local() &&
@@ -1163,13 +1157,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
                 if (!tx.system())
                     cctx.txMetrics().onTxRollback();
 
-                for (int cacheId : tx.activeCacheIds()) {
-                    GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
-
-                    if (cacheCtx.cache().configuration().isStatisticsEnabled())
-                        // Convert start time from ms to ns.
-                        cacheCtx.cache().metrics0().onTxRollback((U.currentTimeMillis() - tx.startTime()) * 1000);
-                }
+                tx.txState().onTxEnd(cctx, tx, false);
             }
 
             if (log.isDebugEnabled())
@@ -1233,7 +1221,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
             if (!tx.system())
                 threadMap.remove(tx.threadId(), tx);
             else {
-                Integer cacheId = F.first(tx.activeCacheIds());
+                Integer cacheId = tx.txState().firstCacheId();
 
                 if (cacheId != null)
                     sysThreadMap.remove(new TxThreadKey(tx.threadId(), cacheId), tx);

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxMap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxMap.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxMap.java
index 6408573..429c995 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxMap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxMap.java
@@ -170,8 +170,7 @@ public class IgniteTxMap extends AbstractMap<IgniteTxKey, IgniteTxEntry> impleme
     }
 
     /** {@inheritDoc} */
-    @Nullable
-    @Override public IgniteTxEntry get(Object key) {
+    @Nullable @Override public IgniteTxEntry get(Object key) {
         IgniteTxEntry e = txMap.get(key);
 
         return e == null ? null : filter.apply(e) ? e : null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
index 9660e4e..b80909f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
@@ -25,22 +25,13 @@ import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
  */
 public interface IgniteTxRemoteEx extends IgniteInternalTx {
     /**
-     * @return Remote thread ID.
-     */
-    public long remoteThreadId();
-
-    /**
      * @param baseVer Base version.
      * @param committedVers Committed version.
      * @param rolledbackVers Rolled back version.
      * @param pendingVers Pending versions.
      */
-    public void doneRemote(GridCacheVersion baseVer, Collection<GridCacheVersion> committedVers,
-        Collection<GridCacheVersion> rolledbackVers, Collection<GridCacheVersion> pendingVers);
-
-    /**
-     * @param e Sets write value for pessimistic transactions.
-     * @return {@code True} if entry was found.
-     */
-    public boolean setWriteValue(IgniteTxEntry e);
+    public void doneRemote(GridCacheVersion baseVer,
+        Collection<GridCacheVersion> committedVers,
+        Collection<GridCacheVersion> rolledbackVers,
+        Collection<GridCacheVersion> pendingVers);
 }
\ No newline at end of file


[13/37] ignite git commit: IGNITE-1790 Implement Apache Camel streamer.

Posted by ag...@apache.org.
IGNITE-1790 Implement Apache Camel streamer.


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

Branch: refs/heads/ignite-1282
Commit: c490de38c7b841fe51fec1001368bda096e82100
Parents: 175b7f2
Author: Raul Kripalani <ra...@apache.org>
Authored: Wed Nov 18 18:03:23 2015 +0000
Committer: Raul Kripalani <ra...@apache.org>
Committed: Wed Nov 18 18:03:23 2015 +0000

----------------------------------------------------------------------
 modules/camel/pom.xml                           | 102 +++++
 .../ignite/stream/camel/CamelStreamer.java      | 237 +++++++++++
 .../stream/camel/IgniteCamelStreamerTest.java   | 420 +++++++++++++++++++
 .../camel/IgniteCamelStreamerTestSuite.java     |  48 +++
 .../src/test/resources/camel.test.properties    |  18 +
 .../org/apache/ignite/stream/StreamAdapter.java |  19 +-
 pom.xml                                         |   1 +
 7 files changed, 835 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/modules/camel/pom.xml
----------------------------------------------------------------------
diff --git a/modules/camel/pom.xml b/modules/camel/pom.xml
new file mode 100644
index 0000000..60f0597
--- /dev/null
+++ b/modules/camel/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>ignite-camel</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <url>http://ignite.apache.org</url>
+
+    <properties>
+        <camel.version>2.16.0</camel.version>
+        <guava.version>18.0</guava.version>
+        <okhttp.version>2.5.0</okhttp.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core</artifactId>
+            <version>${camel.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-log4j</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-spring</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>${guava.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-jetty</artifactId>
+            <version>${camel.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.squareup.okhttp</groupId>
+            <artifactId>okhttp</artifactId>
+            <version>${okhttp.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
----------------------------------------------------------------------
diff --git a/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java b/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
new file mode 100644
index 0000000..40ed6b3
--- /dev/null
+++ b/modules/camel/src/main/java/org/apache/ignite/stream/camel/CamelStreamer.java
@@ -0,0 +1,237 @@
+/*
+ * 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.stream.camel;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.util.CamelContextHelper;
+import org.apache.camel.util.ServiceHelper;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.stream.StreamAdapter;
+import org.apache.ignite.stream.StreamMultipleTupleExtractor;
+import org.apache.ignite.stream.StreamSingleTupleExtractor;
+
+/**
+ * This streamer consumes messages from an Apache Camel consumer endpoint and feeds them into an Ignite data streamer.
+ *
+ * The only mandatory properties are {@link #endpointUri} and the appropriate stream tuple extractor (either {@link
+ * StreamSingleTupleExtractor} or {@link StreamMultipleTupleExtractor)}.
+ *
+ * The user can also provide a custom {@link CamelContext} in case they want to attach custom components, a {@link
+ * org.apache.camel.component.properties.PropertiesComponent}, set tracers, management strategies, etc.
+ *
+ * @see <a href="http://camel.apache.org">Apache Camel</a>
+ * @see <a href="http://camel.apache.org/components.html">Apache Camel components</a>
+ */
+public class CamelStreamer<K, V> extends StreamAdapter<Exchange, K, V> implements Processor {
+    /** Logger. */
+    private IgniteLogger log;
+
+    /** The Camel Context. */
+    private CamelContext camelCtx;
+
+    /** The endpoint URI to consume from. */
+    private String endpointUri;
+
+    /** Camel endpoint. */
+    private Endpoint endpoint;
+
+    /** Camel consumer. */
+    private Consumer consumer;
+
+    /** A {@link Processor} to generate the response. */
+    private Processor resProc;
+
+    /**
+     * Starts the streamer.
+     *
+     * @throws IgniteException In cases when failed to start the streamer.
+     */
+    public void start() throws IgniteException {
+        // Ensure that the endpoint URI is provided.
+        A.notNullOrEmpty(endpointUri, "endpoint URI must be provided");
+
+        // Check that one and only one tuple extractor is provided.
+        A.ensure(!(getSingleTupleExtractor() == null && getMultipleTupleExtractor() == null),
+            "tuple extractor missing");
+
+        // If a custom CamelContext is not provided, initialize one.
+        if (camelCtx == null)
+            camelCtx = new DefaultCamelContext();
+
+        // If the Camel Context is starting or started, reject this call to start.
+        if (camelCtx.getStatus() == ServiceStatus.Started || camelCtx.getStatus() == ServiceStatus.Starting)
+            throw new IgniteException("Failed to start Camel streamer (CamelContext already started or starting).");
+
+        log = getIgnite().log();
+
+        // Instantiate the Camel endpoint.
+        try {
+            endpoint = CamelContextHelper.getMandatoryEndpoint(camelCtx, endpointUri);
+        }
+        catch (Exception e) {
+            U.error(log, e);
+
+            throw new IgniteException("Failed to start Camel streamer [errMsg=" + e.getMessage() + ']');
+        }
+
+        // Create the Camel consumer.
+        try {
+            consumer = endpoint.createConsumer(this);
+        }
+        catch (Exception e) {
+            U.error(log, e);
+
+            throw new IgniteException("Failed to start Camel streamer [errMsg=" + e.getMessage() + ']');
+        }
+
+        // Start the Camel services.
+        try {
+            ServiceHelper.startServices(camelCtx, endpoint, consumer);
+        }
+        catch (Exception e) {
+            U.error(log, e);
+
+            try {
+                ServiceHelper.stopAndShutdownServices(camelCtx, endpoint, consumer);
+
+                consumer = null;
+                endpoint = null;
+            }
+            catch (Exception e1) {
+                throw new IgniteException("Failed to start Camel streamer; failed to stop the context, endpoint or " +
+                    "consumer during rollback of failed initialization [errMsg=" + e.getMessage() + ", stopErrMsg=" +
+                    e1.getMessage() + ']');
+            }
+
+            throw new IgniteException("Failed to start Camel streamer [errMsg=" + e.getMessage() + ']');
+        }
+
+        U.log(log, "Started Camel streamer consuming from endpoint URI: " + endpointUri);
+    }
+
+    /**
+     * Stops the streamer.
+     *
+     * @throws IgniteException In cases if failed to stop the streamer.
+     */
+    public void stop() throws IgniteException {
+        // If the Camel Context is stopping or stopped, reject this call to stop.
+        if (camelCtx.getStatus() == ServiceStatus.Stopped || camelCtx.getStatus() == ServiceStatus.Stopping)
+            throw new IgniteException("Failed to stop Camel streamer (CamelContext already stopped or stopping).");
+
+        // Stop Camel services.
+        try {
+            ServiceHelper.stopAndShutdownServices(camelCtx, endpoint, consumer);
+        }
+        catch (Exception e) {
+            throw new IgniteException("Failed to stop Camel streamer [errMsg=" + e.getMessage() + ']');
+        }
+
+        U.log(log, "Stopped Camel streamer, formerly consuming from endpoint URI: " + endpointUri);
+    }
+
+    /**
+     * Processes the incoming {@link Exchange} and adds the tuple(s) to the underlying streamer.
+     *
+     * @param exchange The Camel Exchange.
+     */
+    @Override public void process(Exchange exchange) throws Exception {
+        // Extract and insert the tuple(s).
+        if (getMultipleTupleExtractor() == null) {
+            Map.Entry<K, V> entry = getSingleTupleExtractor().extract(exchange);
+            getStreamer().addData(entry);
+        }
+        else {
+            Map<K, V> entries = getMultipleTupleExtractor().extract(exchange);
+            getStreamer().addData(entries);
+        }
+
+        // If the user has set a response processor, invoke it before finishing.
+        if (resProc != null)
+            resProc.process(exchange);
+    }
+
+    /**
+     * Gets the underlying {@link CamelContext}, whether created automatically by Ignite or the context specified by the
+     * user.
+     *
+     * @return The Camel Context.
+     */
+    public CamelContext getCamelContext() {
+        return camelCtx;
+    }
+
+    /**
+     * Explicitly sets the {@link CamelContext} to use.
+     *
+     * Doing so gives the user the opportunity to attach custom components, a {@link
+     * org.apache.camel.component.properties.PropertiesComponent}, set tracers, management strategies, etc.
+     *
+     * @param camelCtx The Camel Context to use. In most cases, an instance of {@link DefaultCamelContext}.
+     */
+    public void setCamelContext(CamelContext camelCtx) {
+        this.camelCtx = camelCtx;
+    }
+
+    /**
+     * Gets the endpoint URI from which to consume.
+     *
+     * @return The endpoint URI.
+     */
+    public String getEndpointUri() {
+        return endpointUri;
+    }
+
+    /**
+     * Sets the endpoint URI from which to consume. <b>Mandatory.</b>
+     *
+     * @param endpointUri The endpoint URI.
+     */
+    public void setEndpointUri(String endpointUri) {
+        this.endpointUri = endpointUri;
+    }
+
+    /**
+     * Gets the {@link Processor} used to generate the response.
+     *
+     * @return The {@link Processor}.
+     */
+    public Processor getResponseProcessor() {
+        return resProc;
+    }
+
+    /**
+     * Sets the {@link Processor} used to generate the response.
+     *
+     * @param resProc The {@link Processor}.
+     */
+    public void setResponseProcessor(Processor resProc) {
+        this.resProc = resProc;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTest.java
----------------------------------------------------------------------
diff --git a/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTest.java b/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTest.java
new file mode 100644
index 0000000..4795dff
--- /dev/null
+++ b/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTest.java
@@ -0,0 +1,420 @@
+/*
+ * 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.stream.camel;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.support.LifecycleStrategySupport;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.events.CacheEvent;
+import org.apache.ignite.internal.util.lang.GridMapEntry;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteBiPredicate;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.stream.StreamMultipleTupleExtractor;
+import org.apache.ignite.stream.StreamSingleTupleExtractor;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import com.squareup.okhttp.MediaType;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.RequestBody;
+import com.squareup.okhttp.Response;
+
+import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT;
+
+/**
+ * Test class for {@link CamelStreamer}.
+ */
+public class IgniteCamelStreamerTest extends GridCommonAbstractTest {
+    /** text/plain media type. */
+    private static final MediaType TEXT_PLAIN = MediaType.parse("text/plain;charset=utf-8");
+
+    /** The test data. */
+    private static final Map<Integer, String> TEST_DATA = new HashMap<>();
+
+    /** The Camel streamer currently under test. */
+    private CamelStreamer<Integer, String> streamer;
+
+    /** The Ignite data streamer. */
+    private IgniteDataStreamer<Integer, String> dataStreamer;
+
+    /** URL where the REST service will be exposed. */
+    private String url;
+
+    /** The UUID of the currently active remote listener. */
+    private UUID remoteLsnr;
+
+    /** The OkHttpClient. */
+    private OkHttpClient httpClient = new OkHttpClient();
+
+    // Initialize the test data.
+    static {
+        for (int i = 0; i < 100; i++)
+            TEST_DATA.put(i, "v" + i);
+    }
+
+    /** Constructor. */
+    public IgniteCamelStreamerTest() {
+        super(true);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override public void beforeTest() throws Exception {
+        grid().<Integer, String>getOrCreateCache(defaultCacheConfiguration());
+
+        // find an available local port
+        try (ServerSocket ss = new ServerSocket(0)) {
+            int port = ss.getLocalPort();
+
+            url = "http://localhost:" + port + "/ignite";
+        }
+
+        // create Camel streamer
+        dataStreamer = grid().dataStreamer(null);
+        streamer = createCamelStreamer(dataStreamer);
+    }
+
+    @Override public void afterTest() throws Exception {
+        try {
+            streamer.stop();
+        }
+        catch (Exception e) {
+            // ignore if already stopped
+        }
+
+        dataStreamer.close();
+
+        grid().cache(null).clear();
+    }
+
+    /**
+     * @throws Exception
+     */
+    public void testSendOneEntryPerMessage() throws Exception {
+        streamer.setSingleTupleExtractor(singleTupleExtractor());
+
+        // Subscribe to cache PUT events.
+        CountDownLatch latch = subscribeToPutEvents(50);
+
+        // Action time.
+        streamer.start();
+
+        // Send messages.
+        sendMessages(0, 50, false);
+
+        // Assertions.
+        assertTrue(latch.await(10, TimeUnit.SECONDS));
+        assertCacheEntriesLoaded(50);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public void testMultipleEntriesInOneMessage() throws Exception {
+        streamer.setMultipleTupleExtractor(multipleTupleExtractor());
+
+        // Subscribe to cache PUT events.
+        CountDownLatch latch = subscribeToPutEvents(50);
+
+        // Action time.
+        streamer.start();
+
+        // Send messages.
+        sendMessages(0, 50, true);
+
+        // Assertions.
+        assertTrue(latch.await(10, TimeUnit.SECONDS));
+        assertCacheEntriesLoaded(50);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public void testResponseProcessorIsCalled() throws Exception {
+        streamer.setSingleTupleExtractor(singleTupleExtractor());
+        streamer.setResponseProcessor(new Processor() {
+            @Override public void process(Exchange exchange) throws Exception {
+                exchange.getOut().setBody("Foo bar");
+            }
+        });
+
+        // Subscribe to cache PUT events.
+        CountDownLatch latch = subscribeToPutEvents(50);
+
+        // Action time.
+        streamer.start();
+
+        // Send messages.
+        List<String> responses = sendMessages(0, 50, false);
+
+        for (String r : responses)
+            assertEquals("Foo bar", r);
+
+        // Assertions.
+        assertTrue(latch.await(10, TimeUnit.SECONDS));
+        assertCacheEntriesLoaded(50);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public void testUserSpecifiedCamelContext() throws Exception {
+        final AtomicInteger cnt = new AtomicInteger();
+
+        // Create a CamelContext with a probe that'll help us know if it has been used.
+        CamelContext context = new DefaultCamelContext();
+        context.setTracing(true);
+        context.addLifecycleStrategy(new LifecycleStrategySupport() {
+            @Override public void onEndpointAdd(Endpoint endpoint) {
+                cnt.incrementAndGet();
+            }
+        });
+
+        streamer.setSingleTupleExtractor(singleTupleExtractor());
+        streamer.setCamelContext(context);
+
+        // Subscribe to cache PUT events.
+        CountDownLatch latch = subscribeToPutEvents(50);
+
+        // Action time.
+        streamer.start();
+
+        // Send messages.
+        sendMessages(0, 50, false);
+
+        // Assertions.
+        assertTrue(latch.await(10, TimeUnit.SECONDS));
+        assertCacheEntriesLoaded(50);
+        assertTrue(cnt.get() > 0);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public void testUserSpecifiedCamelContextWithPropertyPlaceholders() throws Exception {
+        // Create a CamelContext with a custom property placeholder.
+        CamelContext context = new DefaultCamelContext();
+
+        PropertiesComponent pc = new PropertiesComponent("camel.test.properties");
+
+        context.addComponent("properties", pc);
+
+        // Replace the context path in the test URL with the property placeholder.
+        url = url.replaceAll("/ignite", "{{test.contextPath}}");
+
+        // Recreate the Camel streamer with the new URL.
+        streamer = createCamelStreamer(dataStreamer);
+
+        streamer.setSingleTupleExtractor(singleTupleExtractor());
+        streamer.setCamelContext(context);
+
+        // Subscribe to cache PUT events.
+        CountDownLatch latch = subscribeToPutEvents(50);
+
+        // Action time.
+        streamer.start();
+
+        // Before sending the messages, get the actual URL after the property placeholder was resolved,
+        // stripping the jetty: prefix from it.
+        url = streamer.getCamelContext().getEndpoints().iterator().next().getEndpointUri().replaceAll("jetty:", "");
+
+        // Send messages.
+        sendMessages(0, 50, false);
+
+        // Assertions.
+        assertTrue(latch.await(10, TimeUnit.SECONDS));
+        assertCacheEntriesLoaded(50);
+    }
+
+    /**
+     * @throws Exception
+     */
+    public void testInvalidEndpointUri() throws Exception {
+        streamer.setSingleTupleExtractor(singleTupleExtractor());
+        streamer.setEndpointUri("abc");
+
+        // Action time.
+        try {
+            streamer.start();
+            fail("Streamer started; should have failed.");
+        }
+        catch (IgniteException e) {
+            assertTrue(streamer.getCamelContext().getStatus() == ServiceStatus.Stopped);
+            assertTrue(streamer.getCamelContext().getEndpointRegistry().size() == 0);
+        }
+    }
+
+    /**
+     * Creates a Camel streamer.
+     */
+    private CamelStreamer<Integer, String> createCamelStreamer(IgniteDataStreamer<Integer, String> dataStreamer) {
+        CamelStreamer<Integer, String> streamer = new CamelStreamer<>();
+
+        streamer.setIgnite(grid());
+        streamer.setStreamer(dataStreamer);
+        streamer.setEndpointUri("jetty:" + url);
+
+        dataStreamer.allowOverwrite(true);
+        dataStreamer.autoFlushFrequency(1);
+
+        return streamer;
+    }
+
+    /**
+     * @throws IOException
+     * @return HTTP response payloads.
+     */
+    private List<String> sendMessages(int fromIdx, int cnt, boolean singleMessage) throws IOException {
+        List<String> responses = Lists.newArrayList();
+
+        if (singleMessage) {
+            StringBuilder sb = new StringBuilder();
+
+            for (int i = fromIdx; i < fromIdx + cnt; i++)
+                sb.append(i).append(",").append(TEST_DATA.get(i)).append("\n");
+
+            Request request = new Request.Builder()
+                .url(url)
+                .post(RequestBody.create(TEXT_PLAIN, sb.toString()))
+                .build();
+
+            Response response = httpClient.newCall(request).execute();
+
+            responses.add(response.body().string());
+        }
+        else {
+            for (int i = fromIdx; i < fromIdx + cnt; i++) {
+                String payload = i + "," + TEST_DATA.get(i);
+
+                Request request = new Request.Builder()
+                    .url(url)
+                    .post(RequestBody.create(TEXT_PLAIN, payload))
+                    .build();
+
+                Response response = httpClient.newCall(request).execute();
+
+                responses.add(response.body().string());
+            }
+        }
+
+        return responses;
+    }
+
+    /**
+     * Returns a {@link StreamSingleTupleExtractor} for testing.
+     */
+    private static StreamSingleTupleExtractor<Exchange, Integer, String> singleTupleExtractor() {
+        return new StreamSingleTupleExtractor<Exchange, Integer, String>() {
+            @Override public Map.Entry<Integer, String> extract(Exchange exchange) {
+                List<String> s = Splitter.on(",").splitToList(exchange.getIn().getBody(String.class));
+
+                return new GridMapEntry<>(Integer.parseInt(s.get(0)), s.get(1));
+            }
+        };
+    }
+
+    /**
+     * Returns a {@link StreamMultipleTupleExtractor} for testing.
+     */
+    private static StreamMultipleTupleExtractor<Exchange, Integer, String> multipleTupleExtractor() {
+        return new StreamMultipleTupleExtractor<Exchange, Integer, String>() {
+            @Override public Map<Integer, String> extract(Exchange exchange) {
+                final Map<String, String> map = Splitter.on("\n")
+                    .omitEmptyStrings()
+                    .withKeyValueSeparator(",")
+                    .split(exchange.getIn().getBody(String.class));
+
+                final Map<Integer, String> answer = new HashMap<>();
+
+                F.forEach(map.keySet(), new IgniteInClosure<String>() {
+                    @Override public void apply(String s) {
+                        answer.put(Integer.parseInt(s), map.get(s));
+                    }
+                });
+
+                return answer;
+            }
+        };
+    }
+
+    /**
+     * Subscribe to cache put events.
+     */
+    private CountDownLatch subscribeToPutEvents(int expect) {
+        Ignite ignite = grid();
+
+        // Listen to cache PUT events and expect as many as messages as test data items
+        final CountDownLatch latch = new CountDownLatch(expect);
+        @SuppressWarnings("serial") IgniteBiPredicate<UUID, CacheEvent> callback =
+            new IgniteBiPredicate<UUID, CacheEvent>() {
+            @Override public boolean apply(UUID uuid, CacheEvent evt) {
+                latch.countDown();
+
+                return true;
+            }
+        };
+
+        remoteLsnr = ignite.events(ignite.cluster().forCacheNodes(null))
+            .remoteListen(callback, null, EVT_CACHE_OBJECT_PUT);
+
+        return latch;
+    }
+
+    /**
+     * Assert a given number of cache entries have been loaded.
+     */
+    private void assertCacheEntriesLoaded(int cnt) {
+        // get the cache and check that the entries are present
+        IgniteCache<Integer, String> cache = grid().cache(null);
+
+        // for each key from 0 to count from the TEST_DATA (ordered by key), check that the entry is present in cache
+        for (Integer key : new ArrayList<>(new TreeSet<>(TEST_DATA.keySet())).subList(0, cnt))
+            assertEquals(TEST_DATA.get(key), cache.get(key));
+
+        // assert that the cache exactly the specified amount of elements
+        assertEquals(cnt, cache.size(CachePeekMode.ALL));
+
+        // remove the event listener
+        grid().events(grid().cluster().forCacheNodes(null)).stopRemoteListen(remoteLsnr);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTestSuite.java b/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTestSuite.java
new file mode 100644
index 0000000..266c9cf
--- /dev/null
+++ b/modules/camel/src/test/java/org/apache/ignite/stream/camel/IgniteCamelStreamerTestSuite.java
@@ -0,0 +1,48 @@
+/*
+ * 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.stream.camel;
+
+import java.util.Set;
+
+import junit.framework.TestSuite;
+
+/**
+ * Camel streamer tests.
+ */
+public class IgniteCamelStreamerTestSuite extends TestSuite {
+    /**
+     * @return {@link IgniteCamelStreamerTest} test suite.
+     * @throws Exception Thrown in case of the failure.
+     */
+    public static TestSuite suite() throws Exception {
+        return suite(null);
+    }
+
+    /**
+     * @param ignoredTests
+     * @return Test suite.
+     * @throws Exception Thrown in case of the failure.
+     */
+    public static TestSuite suite(Set<Class> ignoredTests) throws Exception {
+        TestSuite suite = new TestSuite("IgniteCamelStreamer Test Suite");
+
+        suite.addTestSuite(IgniteCamelStreamerTest.class);
+
+        return suite;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/modules/camel/src/test/resources/camel.test.properties
----------------------------------------------------------------------
diff --git a/modules/camel/src/test/resources/camel.test.properties b/modules/camel/src/test/resources/camel.test.properties
new file mode 100644
index 0000000..30459be
--- /dev/null
+++ b/modules/camel/src/test/resources/camel.test.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+test.contextPath = /ignite-properties

http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/modules/core/src/main/java/org/apache/ignite/stream/StreamAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/stream/StreamAdapter.java b/modules/core/src/main/java/org/apache/ignite/stream/StreamAdapter.java
index 2cb7db7..afc1530 100644
--- a/modules/core/src/main/java/org/apache/ignite/stream/StreamAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/stream/StreamAdapter.java
@@ -37,7 +37,6 @@ import org.apache.ignite.IgniteDataStreamer;
  * </ol>
  */
 public abstract class StreamAdapter<T, K, V> {
-
     /** Tuple extractor extracting a single tuple from an event */
     private StreamSingleTupleExtractor<T, K, V> singleTupleExtractor;
 
@@ -99,9 +98,9 @@ public abstract class StreamAdapter<T, K, V> {
      */
     @Deprecated
     public StreamTupleExtractor<T, K, V> getTupleExtractor() {
-        if (singleTupleExtractor instanceof StreamTupleExtractor) {
+        if (singleTupleExtractor instanceof StreamTupleExtractor)
             return (StreamTupleExtractor) singleTupleExtractor;
-        }
+
         throw new IllegalArgumentException("This method is deprecated and only relevant if using an old " +
             "StreamTupleExtractor; use getSingleTupleExtractor instead");
     }
@@ -112,9 +111,9 @@ public abstract class StreamAdapter<T, K, V> {
      */
     @Deprecated
     public void setTupleExtractor(StreamTupleExtractor<T, K, V> extractor) {
-        if (multipleTupleExtractor != null) {
+        if (multipleTupleExtractor != null)
             throw new IllegalArgumentException("Multiple tuple extractor already set; cannot set both types at once.");
-        }
+
         this.singleTupleExtractor = extractor;
     }
 
@@ -129,9 +128,9 @@ public abstract class StreamAdapter<T, K, V> {
      * @param singleTupleExtractor Extractor for key-value tuples from messages.
      */
     public void setSingleTupleExtractor(StreamSingleTupleExtractor<T, K, V> singleTupleExtractor) {
-        if (multipleTupleExtractor != null) {
+        if (multipleTupleExtractor != null)
             throw new IllegalArgumentException("Multiple tuple extractor already set; cannot set both types at once.");
-        }
+
         this.singleTupleExtractor = singleTupleExtractor;
     }
 
@@ -146,9 +145,9 @@ public abstract class StreamAdapter<T, K, V> {
      * @param multipleTupleExtractor Extractor for 1:n tuple extraction.
      */
     public void setMultipleTupleExtractor(StreamMultipleTupleExtractor<T, K, V> multipleTupleExtractor) {
-        if (singleTupleExtractor != null) {
+        if (singleTupleExtractor != null)
             throw new IllegalArgumentException("Single tuple extractor already set; cannot set both types at once.");
-        }
+
         this.multipleTupleExtractor = multipleTupleExtractor;
     }
 
@@ -188,4 +187,4 @@ public abstract class StreamAdapter<T, K, V> {
         }
     }
 
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/c490de38/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c40b551..b9c51b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -78,6 +78,7 @@
         <module>modules/jms11</module>
         <module>modules/mqtt</module>
         <module>modules/zookeeper</module>
+        <module>modules/camel</module>
         <module>modules/platform</module>
     </modules>
 


[28/37] ignite git commit: Updated benchmark properties file: benchmark-query-put-separated.properties

Posted by ag...@apache.org.
Updated benchmark properties file: benchmark-query-put-separated.properties


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

Branch: refs/heads/ignite-1282
Commit: 8728a5b8a1b70cd0aa2c623e38c7e93e1bd2d5f3
Parents: c85d1f5
Author: ashutak <as...@gridgain.com>
Authored: Thu Nov 19 19:36:56 2015 +0300
Committer: ashutak <as...@gridgain.com>
Committed: Thu Nov 19 19:36:56 2015 +0300

----------------------------------------------------------------------
 .../config/benchmark-query-put-separated.properties         | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8728a5b8/modules/yardstick/config/benchmark-query-put-separated.properties
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/benchmark-query-put-separated.properties b/modules/yardstick/config/benchmark-query-put-separated.properties
index b1b2942..6d2ce33 100644
--- a/modules/yardstick/config/benchmark-query-put-separated.properties
+++ b/modules/yardstick/config/benchmark-query-put-separated.properties
@@ -70,10 +70,10 @@ nodesNum=$((`echo ${SERVER_HOSTS} | tr ',' '\n' | wc -l` + `echo ${DRIVER_HOSTS}
 b=1
 
 # Warmup.
-w=10
+w=60
 
 # Duration.
-d=30
+d=300
 
 # Threads count.
 t=64
@@ -81,8 +81,7 @@ t=64
 # Sync mode.
 sm=PRIMARY_SYNC
 
-# Run configuration which contains all benchmarks.
-# Note that each benchmark is set to run for 300 seconds (5 mins) with warm-up set to 60 seconds (1 minute).
+# Run configuration which contains separated query put benchmark.
 CONFIGS="\
--cfg ${SCRIPT_DIR}/../config/ignite-localhost-config.xml -nn ${nodesNum} -b 1 -w ${w} -d ${d} -t ${t} -sm PRIMARY_SYNC -dn IgniteSqlQueryPutSeparatedBenchmark -sn IgniteNode -ds query-put-1b,\
+-cfg ${SCRIPT_DIR}/../config/ignite-localhost-config.xml -nn ${nodesNum} -b 1 -w ${w} -d ${d} -t ${t} -sm PRIMARY_SYNC -dn IgniteSqlQueryPutSeparatedBenchmark -sn IgniteNode -ds ${ver}query-put-separated-1b,\
 "


[09/37] ignite git commit: 'Single' operations optimizations for tx cache.

Posted by ag...@apache.org.
'Single' operations optimizations for tx cache.


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

Branch: refs/heads/ignite-1282
Commit: 3ff71fd742efda91fef6ed6d92dac11cc6d00976
Parents: 38e66d9
Author: sboikov <sb...@gridgain.com>
Authored: Tue Nov 17 19:38:05 2015 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Nov 17 19:38:05 2015 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheAdapter.java      |   48 +-
 .../processors/cache/GridCacheMapEntry.java     |   11 +-
 .../cache/GridCacheSharedContext.java           |   31 +-
 .../distributed/GridDistributedTxMapping.java   |   78 -
 .../GridDistributedTxRemoteAdapter.java         |  136 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |    1 -
 .../cache/distributed/dht/GridDhtTxLocal.java   |   24 +-
 .../distributed/dht/GridDhtTxLocalAdapter.java  |   80 +-
 .../cache/distributed/dht/GridDhtTxMapping.java |  134 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |   59 +-
 .../cache/distributed/dht/GridDhtTxRemote.java  |   29 +-
 ...arOptimisticSerializableTxPrepareFuture.java |   16 -
 .../near/GridNearOptimisticTxPrepareFuture.java |  103 +-
 ...ridNearOptimisticTxPrepareFutureAdapter.java |   72 +-
 .../GridNearPessimisticTxPrepareFuture.java     |    1 -
 .../near/GridNearTransactionalCache.java        |    1 -
 .../near/GridNearTxFinishFuture.java            |   61 +-
 .../cache/distributed/near/GridNearTxLocal.java |  109 +-
 .../near/GridNearTxPrepareRequest.java          |    9 -
 .../distributed/near/GridNearTxRemote.java      |   26 +-
 .../distributed/near/IgniteTxMappings.java      |   75 +
 .../distributed/near/IgniteTxMappingsImpl.java  |   92 ++
 .../near/IgniteTxMappingsSingleImpl.java        |  101 ++
 .../cache/transactions/IgniteInternalTx.java    |   12 +-
 .../cache/transactions/IgniteTxAdapter.java     |   67 +-
 .../cache/transactions/IgniteTxHandler.java     |   16 +-
 .../IgniteTxImplicitSingleStateImpl.java        |  259 ++++
 .../transactions/IgniteTxLocalAdapter.java      | 1388 ++++++++++--------
 .../cache/transactions/IgniteTxLocalEx.java     |   30 +-
 .../cache/transactions/IgniteTxLocalState.java  |   44 +
 .../transactions/IgniteTxLocalStateAdapter.java |   41 +
 .../cache/transactions/IgniteTxManager.java     |   18 +-
 .../cache/transactions/IgniteTxMap.java         |    3 +-
 .../cache/transactions/IgniteTxRemoteEx.java    |   17 +-
 .../IgniteTxRemoteSingleStateImpl.java          |  108 ++
 .../cache/transactions/IgniteTxRemoteState.java |   34 +
 .../IgniteTxRemoteStateAdapter.java             |  110 ++
 .../transactions/IgniteTxRemoteStateImpl.java   |  124 ++
 .../cache/transactions/IgniteTxState.java       |  171 +++
 .../cache/transactions/IgniteTxStateImpl.java   |  375 +++++
 40 files changed, 2709 insertions(+), 1405 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/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 419ccec..cbb7486 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
@@ -1854,7 +1854,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, filter).get().value();
+                return (V)tx.putAsync(ctx, key, val, true, filter).get().value();
             }
 
             @Override public String toString() {
@@ -1909,7 +1909,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, filter)
+                return tx.putAsync(ctx, key, val, true, filter)
                     .chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>)RET2VAL);
             }
 
@@ -1948,7 +1948,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, filter).get().success();
+                return tx.putAsync(ctx, key, val, false, filter).get().success();
             }
 
             @Override public String toString() {
@@ -2013,10 +2013,8 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
         return syncOp(new SyncOp<EntryProcessorResult<T>>(true) {
             @Nullable @Override public EntryProcessorResult<T> op(IgniteTxLocalAdapter tx)
                 throws IgniteCheckedException {
-                Map<? extends K, EntryProcessor<K, V, Object>> invokeMap =
-                    Collections.singletonMap(key, (EntryProcessor<K, V, Object>) entryProcessor);
-
-                IgniteInternalFuture<GridCacheReturn> fut = tx.invokeAsync(ctx, invokeMap, args);
+                IgniteInternalFuture<GridCacheReturn> fut =
+                    tx.invokeAsync(ctx, key, (EntryProcessor<K, V, Object>)entryProcessor, args);
 
                 Map<K, EntryProcessorResult<T>> resMap = fut.get().value();
 
@@ -2240,8 +2238,8 @@ 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, filter).chain(
-                    (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, Boolean>) RET2FLAG);
+                return tx.putAsync(ctx, key, val, false, filter).chain(
+                    (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, Boolean>)RET2FLAG);
             }
 
             @Override public String toString() {
@@ -2275,7 +2273,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, ctx.noValArray()).get().value();
+                return (V)tx.putAsync(ctx, key, val, true, ctx.noValArray()).get().value();
             }
 
             @Override public String toString() {
@@ -2299,8 +2297,8 @@ 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, ctx.noValArray())
-                    .chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>) RET2VAL);
+                return tx.putAsync(ctx, key, val, true, ctx.noValArray())
+                    .chain((IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>)RET2VAL);
             }
 
             @Override public String toString() {
@@ -2329,7 +2327,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, ctx.noValArray()).get().success();
+                return tx.putAsync(ctx, key, val, false, ctx.noValArray()).get().success();
             }
 
             @Override public String toString() {
@@ -2358,7 +2356,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, ctx.noValArray()).chain(
+                return tx.putAsync(ctx, key, val, false, ctx.noValArray()).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, Boolean>)RET2FLAG);
             }
 
@@ -2384,7 +2382,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, ctx.hasValArray()).get().value();
+                return (V)tx.putAsync(ctx, key, val, true, ctx.hasValArray()).get().value();
             }
 
             @Override public String toString() {
@@ -2408,7 +2406,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, ctx.hasValArray()).chain(
+                return tx.putAsync(ctx, key, val, true, ctx.hasValArray()).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, V>)RET2VAL);
             }
 
@@ -2434,7 +2432,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, ctx.hasValArray()).get().success();
+                return tx.putAsync(ctx, key, val, false, ctx.hasValArray()).get().success();
             }
 
             @Override public String toString() {
@@ -2454,7 +2452,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, ctx.hasValArray()).chain(
+                return tx.putAsync(ctx, key, val, false, ctx.hasValArray()).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, Boolean>) RET2FLAG);
             }
 
@@ -2481,7 +2479,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, ctx.equalsValArray(oldVal)).get()
+                return tx.putAsync(ctx, key, newVal, false, ctx.equalsValArray(oldVal)).get()
                     .success();
             }
 
@@ -2518,7 +2516,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
                     }
                 }
 
-                return tx.putAllAsync(ctx, F.t(key, newVal), false, ctx.equalsValArray(oldVal)).chain(
+                return tx.putAsync(ctx, key, newVal, false, ctx.equalsValArray(oldVal)).chain(
                     (IgniteClosure<IgniteInternalFuture<GridCacheReturn>, Boolean>)RET2FLAG);
             }
 
@@ -2883,8 +2881,9 @@ 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),
+                return tx.putAsync(ctx,
+                        key,
+                        newVal,
                         true,
                         ctx.equalsValArray(oldVal)).get();
             }
@@ -2945,8 +2944,9 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
                     return new GridFinishedFuture<>(e);
                 }
 
-                return (IgniteInternalFuture)tx.putAllAsync(ctx,
-                    F.t(key, newVal),
+                return (IgniteInternalFuture)tx.putAsync(ctx,
+                    key,
+                    newVal,
                     true,
                     ctx.equalsValArray(oldVal));
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/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 df9f5c4..0786a50 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
@@ -74,6 +74,7 @@ import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_EXPIRED;
 import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT;
 import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_READ;
 import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_REMOVED;
+import static org.apache.ignite.internal.processors.cache.GridCacheOperation.DELETE;
 import static org.apache.ignite.internal.processors.dr.GridDrType.DR_NONE;
 
 /**
@@ -4014,7 +4015,15 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
         IgniteInternalTx tx = cctx.tm().localTxx();
 
-        return tx == null || !tx.removed(txKey());
+        if (tx != null) {
+            IgniteTxEntry e = tx.entry(txKey());
+
+            boolean rmvd = e != null && e.op() == DELETE;
+
+            return !rmvd;
+        }
+
+        return true;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
index b37742c..4293b90 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
@@ -582,12 +582,7 @@ public class GridCacheSharedContext<K, V> {
      * @throws IgniteCheckedException If failed.
      */
     public void endTx(IgniteInternalTx tx) throws IgniteCheckedException {
-        Collection<Integer> cacheIds = tx.activeCacheIds();
-
-        if (!cacheIds.isEmpty()) {
-            for (Integer cacheId : cacheIds)
-                cacheContext(cacheId).cache().awaitLastFut();
-        }
+        tx.txState().awaitLastFut(this);
 
         tx.close();
     }
@@ -596,22 +591,17 @@ public class GridCacheSharedContext<K, V> {
      * @param tx Transaction to commit.
      * @return Commit future.
      */
+    @SuppressWarnings("unchecked")
     public IgniteInternalFuture<IgniteInternalTx> commitTxAsync(IgniteInternalTx tx) {
-        Collection<Integer> cacheIds = tx.activeCacheIds();
-
-        if (cacheIds.isEmpty())
-            return tx.commitAsync();
-        else if (cacheIds.size() == 1) {
-            int cacheId = F.first(cacheIds);
+        GridCacheContext ctx = tx.txState().singleCacheContext(this);
 
-            return cacheContext(cacheId).cache().commitTxAsync(tx);
-        }
-        else {
-            for (Integer cacheId : cacheIds)
-                cacheContext(cacheId).cache().awaitLastFut();
+        if (ctx == null) {
+            tx.txState().awaitLastFut(this);
 
             return tx.commitAsync();
         }
+        else
+            return ctx.cache().commitTxAsync(tx);
     }
 
     /**
@@ -620,12 +610,7 @@ public class GridCacheSharedContext<K, V> {
      * @return Rollback future.
      */
     public IgniteInternalFuture rollbackTxAsync(IgniteInternalTx tx) throws IgniteCheckedException {
-        Collection<Integer> cacheIds = tx.activeCacheIds();
-
-        if (!cacheIds.isEmpty()) {
-            for (Integer cacheId : cacheIds)
-                cacheContext(cacheId).cache().awaitLastFut();
-        }
+        tx.txState().awaitLastFut(this);
 
         return tx.rollbackAsync();
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxMapping.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxMapping.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxMapping.java
index 2d2d935..8c9f181 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxMapping.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxMapping.java
@@ -24,9 +24,7 @@ import java.io.ObjectOutput;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.LinkedHashSet;
-import java.util.UUID;
 import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -59,15 +57,9 @@ public class GridDistributedTxMapping implements Externalizable {
     /** DHT version. */
     private GridCacheVersion dhtVer;
 
-    /** Copy on remove flag. */
-    private boolean readOnly;
-
     /** {@code True} if this is last mapping for node. */
     private boolean last;
 
-    /** IDs of backup nodes receiving last prepare request during this mapping. */
-    private Collection<UUID> lastBackups;
-
     /** {@code True} if mapping is for near caches, {@code false} otherwise. */
     private boolean near;
 
@@ -91,20 +83,6 @@ public class GridDistributedTxMapping implements Externalizable {
     }
 
     /**
-     * @return IDs of backup nodes receiving last prepare request during this mapping.
-     */
-    @Nullable public Collection<UUID> lastBackups() {
-        return lastBackups;
-    }
-
-    /**
-     * @param lastBackups IDs of backup nodes receiving last prepare request during this mapping.
-     */
-    public void lastBackups(@Nullable Collection<UUID> lastBackups) {
-        this.lastBackups = lastBackups;
-    }
-
-    /**
      * @return {@code True} if this is last mapping for node.
      */
     public boolean last() {
@@ -161,17 +139,6 @@ public class GridDistributedTxMapping implements Externalizable {
     }
 
     /**
-     * @param entries Mapped entries.
-     * @param readOnly Flag indicating that passed in collection is read-only.
-     */
-    public void entries(Collection<IgniteTxEntry> entries, boolean readOnly) {
-        this.entries = entries;
-
-        // Set copy on remove flag as passed in collection is unmodifiable.
-        this.readOnly = true;
-    }
-
-    /**
      * @return {@code True} if lock is explicit.
      */
     public boolean explicitLock() {
@@ -221,8 +188,6 @@ public class GridDistributedTxMapping implements Externalizable {
      * @param entry Adds entry.
      */
     public void add(IgniteTxEntry entry) {
-        ensureModifiable();
-
         entries.add(entry);
     }
 
@@ -231,48 +196,16 @@ public class GridDistributedTxMapping implements Externalizable {
      * @return {@code True} if entry was removed.
      */
     public boolean removeEntry(IgniteTxEntry entry) {
-        ensureModifiable();
-
         return entries.remove(entry);
     }
 
     /**
-     * @param parts Evicts partitions from mapping.
-     */
-    public void evictPartitions(@Nullable int[] parts) {
-        if (!F.isEmpty(parts)) {
-            ensureModifiable();
-
-            evictPartitions(parts, entries);
-        }
-    }
-
-    /**
-     * @param parts Partitions.
-     * @param c Collection.
-     */
-    private void evictPartitions(int[] parts, Collection<IgniteTxEntry> c) {
-        assert parts != null;
-
-        for (Iterator<IgniteTxEntry> it = c.iterator(); it.hasNext();) {
-            IgniteTxEntry e = it.next();
-
-            GridCacheEntryEx cached = e.cached();
-
-            if (U.containsIntArray(parts, cached.partition()))
-                it.remove();
-        }
-    }
-
-    /**
      * @param keys Keys to evict readers for.
      */
     public void evictReaders(@Nullable Collection<IgniteTxKey> keys) {
         if (keys == null || keys.isEmpty())
             return;
 
-        ensureModifiable();
-
         evictReaders(keys, entries);
     }
 
@@ -293,17 +226,6 @@ public class GridDistributedTxMapping implements Externalizable {
     }
 
     /**
-     * Copies collection of entries if it is read-only.
-     */
-    private void ensureModifiable() {
-        if (readOnly) {
-            entries = new LinkedHashSet<>(entries);
-
-            readOnly = false;
-        }
-    }
-
-    /**
      * Whether empty or not.
      *
      * @return Empty or not.

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
index 93303c8..0d49584 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
@@ -45,6 +45,8 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxAdapter;
 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.IgniteTxRemoteEx;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxRemoteState;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxState;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext;
 import org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException;
@@ -85,18 +87,6 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     /** */
     private static final long serialVersionUID = 0L;
 
-    /** Read set. */
-    @GridToStringInclude
-    protected Map<IgniteTxKey, IgniteTxEntry> readMap;
-
-    /** Write map. */
-    @GridToStringInclude
-    protected Map<IgniteTxKey, IgniteTxEntry> writeMap;
-
-    /** Remote thread ID. */
-    @GridToStringInclude
-    private long rmtThreadId;
-
     /** Explicit versions. */
     @GridToStringInclude
     private List<GridCacheVersion> explicitVers;
@@ -109,6 +99,10 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     @GridToStringInclude
     private AtomicBoolean commitAllowed = new AtomicBoolean(false);
 
+    /** */
+    @GridToStringInclude
+    protected IgniteTxRemoteState txState;
+
     /**
      * Empty constructor required for {@link Externalizable}.
      */
@@ -119,7 +113,6 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     /**
      * @param ctx Cache registry.
      * @param nodeId Node ID.
-     * @param rmtThreadId Remote thread ID.
      * @param xidVer XID version.
      * @param commitVer Commit version.
      * @param sys System flag.
@@ -135,7 +128,6 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     public GridDistributedTxRemoteAdapter(
         GridCacheSharedContext<?, ?> ctx,
         UUID nodeId,
-        long rmtThreadId,
         GridCacheVersion xidVer,
         GridCacheVersion commitVer,
         boolean sys,
@@ -163,7 +155,6 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
             subjId,
             taskNameHash);
 
-        this.rmtThreadId = rmtThreadId;
         this.invalidate = invalidate;
 
         commitVersion(commitVer);
@@ -173,6 +164,11 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     }
 
     /** {@inheritDoc} */
+    @Override public IgniteTxState txState() {
+        return txState;
+    }
+
+    /** {@inheritDoc} */
     @Override public UUID eventNodeId() {
         return nodeId;
     }
@@ -188,11 +184,6 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<Integer> activeCacheIds() {
-        return Collections.emptyList();
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean activeCachesDeploymentEnabled() {
         return false;
     }
@@ -201,14 +192,7 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
      * @return Checks if transaction has no entries.
      */
     @Override public boolean empty() {
-        return readMap.isEmpty() && writeMap.isEmpty();
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean removed(IgniteTxKey key) {
-        IgniteTxEntry e = writeMap.get(key);
-
-        return e != null && e.op() == DELETE;
+        return txState.empty();
     }
 
     /** {@inheritDoc} */
@@ -218,12 +202,12 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
 
     /** {@inheritDoc} */
     @Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
-        return writeMap;
+        return txState.writeMap();
     }
 
     /** {@inheritDoc} */
     @Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
-        return readMap;
+        return txState.readMap();
     }
 
     /** {@inheritDoc} */
@@ -245,12 +229,7 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
 
     /** {@inheritDoc} */
     @Override public IgniteTxEntry entry(IgniteTxKey key) {
-        IgniteTxEntry e = writeMap == null ? null : writeMap.get(key);
-
-        if (e == null)
-            e = readMap == null ? null : readMap.get(key);
-
-        return e;
+        return txState.entry(key);
     }
 
     /**
@@ -259,8 +238,7 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
      * @param key key to be removed.
      */
     public void clearEntry(IgniteTxKey key) {
-        readMap.remove(key);
-        writeMap.remove(key);
+        txState.clearEntry(key);
     }
 
     /**
@@ -268,13 +246,19 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
      * @param committedVers Committed versions.
      * @param rolledbackVers Rolled back versions.
      */
-    @Override public void doneRemote(GridCacheVersion baseVer, Collection<GridCacheVersion> committedVers,
-        Collection<GridCacheVersion> rolledbackVers, Collection<GridCacheVersion> pendingVers) {
+    @Override public void doneRemote(GridCacheVersion baseVer,
+        Collection<GridCacheVersion> committedVers,
+        Collection<GridCacheVersion> rolledbackVers,
+        Collection<GridCacheVersion> pendingVers) {
+        Map<IgniteTxKey, IgniteTxEntry> readMap = txState.readMap();
+
         if (readMap != null && !readMap.isEmpty()) {
             for (IgniteTxEntry txEntry : readMap.values())
                 doneRemote(txEntry, baseVer, committedVers, rolledbackVers, pendingVers);
         }
 
+        Map<IgniteTxKey, IgniteTxEntry> writeMap = txState.writeMap();
+
         if (writeMap != null && !writeMap.isEmpty()) {
             for (IgniteTxEntry txEntry : writeMap.values())
                 doneRemote(txEntry, baseVer, committedVers, rolledbackVers, pendingVers);
@@ -290,8 +274,10 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
      * @param rolledbackVers Rolled back versions relative to base version.
      * @param pendingVers Pending versions.
      */
-    private void doneRemote(IgniteTxEntry txEntry, GridCacheVersion baseVer,
-        Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledbackVers,
+    private void doneRemote(IgniteTxEntry txEntry,
+        GridCacheVersion baseVer,
+        Collection<GridCacheVersion> committedVers,
+        Collection<GridCacheVersion> rolledbackVers,
         Collection<GridCacheVersion> pendingVers) {
         while (true) {
             GridDistributedCacheEntry entry = (GridDistributedCacheEntry)txEntry.cached();
@@ -337,59 +323,9 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
         return started;
     }
 
-    /**
-     * @return Remote node thread ID.
-     */
-    @Override public long remoteThreadId() {
-        return rmtThreadId;
-    }
-
-    /**
-     * @param e Transaction entry to set.
-     * @return {@code True} if value was set.
-     */
-    @Override public boolean setWriteValue(IgniteTxEntry e) {
-        checkInternal(e.txKey());
-
-        IgniteTxEntry entry = writeMap.get(e.txKey());
-
-        if (entry == null) {
-            IgniteTxEntry rmv = readMap.remove(e.txKey());
-
-            if (rmv != null) {
-                e.cached(rmv.cached());
-
-                writeMap.put(e.txKey(), e);
-            }
-            // If lock is explicit.
-            else {
-                e.cached(e.context().cache().entryEx(e.key()));
-
-                // explicit lock.
-                writeMap.put(e.txKey(), e);
-            }
-        }
-        else {
-            // Copy values.
-            entry.value(e.value(), e.hasWriteValue(), e.hasReadValue());
-            entry.entryProcessors(e.entryProcessors());
-            entry.op(e.op());
-            entry.ttl(e.ttl());
-            entry.explicitVersion(e.explicitVersion());
-
-            // Conflict resolution stuff.
-            entry.conflictVersion(e.conflictVersion());
-            entry.conflictExpireTime(e.conflictExpireTime());
-        }
-
-        addExplicit(e);
-
-        return true;
-    }
-
     /** {@inheritDoc} */
     @Override public boolean hasWriteKey(IgniteTxKey key) {
-        return writeMap.containsKey(key);
+        return txState.hasWriteKey(key);
     }
 
     /** {@inheritDoc} */
@@ -400,27 +336,27 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
 
     /** {@inheritDoc} */
     @Override public Set<IgniteTxKey> readSet() {
-        return readMap.keySet();
+        return txState.readSet();
     }
 
     /** {@inheritDoc} */
     @Override public Set<IgniteTxKey> writeSet() {
-        return writeMap.keySet();
+        return txState.writeSet();
     }
 
     /** {@inheritDoc} */
     @Override public Collection<IgniteTxEntry> allEntries() {
-        return F.concat(false, writeEntries(), readEntries());
+        return txState.allEntries();
     }
 
     /** {@inheritDoc} */
     @Override public Collection<IgniteTxEntry> writeEntries() {
-        return writeMap.values();
+        return txState.writeEntries();
     }
 
     /** {@inheritDoc} */
     @Override public Collection<IgniteTxEntry> readEntries() {
-        return readMap.values();
+        return txState.readEntries();
     }
 
     /**
@@ -459,7 +395,7 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
     @SuppressWarnings({"CatchGenericClass"})
     private void commitIfLocked() throws IgniteCheckedException {
         if (state() == COMMITTING) {
-            for (IgniteTxEntry txEntry : writeMap.values()) {
+            for (IgniteTxEntry txEntry : writeEntries()) {
                 assert txEntry != null : "Missing transaction entry for tx: " + this;
 
                 while (true) {
@@ -494,6 +430,8 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
             if (commitAllowed.compareAndSet(false, true)) {
                 IgniteCheckedException err = null;
 
+                Map<IgniteTxKey, IgniteTxEntry> writeMap = txState.writeMap();
+
                 if (!F.isEmpty(writeMap)) {
                     // Register this transaction as completed prior to write-phase to
                     // ensure proper lock ordering for removed entries.

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
index 3069afd..fe91e5b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
@@ -228,7 +228,6 @@ public abstract class GridDhtTransactionalCacheAdapter<K, V> extends GridDhtCach
                                     req.futureId(),
                                     nodeId,
                                     req.nearXidVersion(),
-                                    req.threadId(),
                                     req.topologyVersion(),
                                     req.version(),
                                     /*commitVer*/null,

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
index 44f34aa..2bed931 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
@@ -223,11 +223,6 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
     }
 
     /** {@inheritDoc} */
-    @Override protected IgniteUuid nearMiniId() {
-        return nearMiniId;
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean dht() {
         return true;
     }
@@ -307,8 +302,7 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
                 0,
                 nearMiniId,
                 null,
-                true,
-                null);
+                true);
         }
 
         // For pessimistic mode we don't distribute prepare request.
@@ -322,8 +316,7 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
                 nearMiniId,
                 Collections.<IgniteTxKey, GridCacheVersion>emptyMap(),
                 true,
-                needReturnValue(),
-                null)))
+                needReturnValue())))
                 return prepFut.get();
         }
         else
@@ -378,7 +371,6 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
      * @param nearMiniId Near mini future ID.
      * @param txNodes Transaction nodes mapping.
      * @param last {@code True} if this is last prepare request.
-     * @param lastBackups IDs of backup nodes receiving last prepare request.
      * @return Future that will be completed when locks are acquired.
      */
     public IgniteInternalFuture<GridNearTxPrepareResponse> prepareAsync(
@@ -388,8 +380,7 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
         long msgId,
         IgniteUuid nearMiniId,
         Map<UUID, Collection<UUID>> txNodes,
-        boolean last,
-        Collection<UUID> lastBackups
+        boolean last
     ) {
         // In optimistic mode prepare still can be called explicitly from salvageTx.
         GridDhtTxPrepareFuture fut = prepFut.get();
@@ -404,8 +395,7 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
                 nearMiniId,
                 verMap,
                 last,
-                needReturnValue(),
-                lastBackups))) {
+                needReturnValue()))) {
                 GridDhtTxPrepareFuture f = prepFut.get();
 
                 assert f.nearMiniId().equals(nearMiniId) : "Wrong near mini id on existing future " +
@@ -443,13 +433,15 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
         }
 
         try {
-            if (reads != null)
+            if (reads != null) {
                 for (IgniteTxEntry e : reads)
                     addEntry(msgId, e);
+            }
 
-            if (writes != null)
+            if (writes != null) {
                 for (IgniteTxEntry e : writes)
                     addEntry(msgId, e);
+            }
 
             userPrepare();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
index 6de8795..70ebf3f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
@@ -86,9 +86,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
     protected volatile boolean mapped;
 
     /** */
-    private long dhtThreadId;
-
-    /** */
     protected boolean explicitLock;
 
     /** Versions of pending locks for entries of this tx. */
@@ -159,7 +156,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
         this.explicitLock = explicitLock;
 
         threadId = Thread.currentThread().getId();
-        dhtThreadId = threadId;
     }
 
     /**
@@ -216,11 +212,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
     protected abstract IgniteUuid nearFutureId();
 
     /**
-     * @return Near future mini ID.
-     */
-    protected abstract IgniteUuid nearMiniId();
-
-    /**
      * Adds reader to cached entry.
      *
      * @param msgId Message ID.
@@ -260,13 +251,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
     }
 
     /**
-     * @return DHT thread ID.
-     */
-    long dhtThreadId() {
-        return dhtThreadId;
-    }
-
-    /**
      * Map explicit locks.
      */
     protected void mapExplicitLocks() {
@@ -355,22 +339,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
     }
 
     /**
-     * @param nodeId Node ID.
-     * @return Mapping.
-     */
-    GridDistributedTxMapping dhtMapping(UUID nodeId) {
-        return dhtMap.get(nodeId);
-    }
-
-    /**
-     * @param nodeId Node ID.
-     * @return Mapping.
-     */
-    GridDistributedTxMapping nearMapping(UUID nodeId) {
-        return nearMap.get(nodeId);
-    }
-
-    /**
      * @param mappings Mappings to add.
      */
     void addDhtNodeEntryMapping(Map<ClusterNode, List<GridDhtCacheEntry>> mappings) {
@@ -385,19 +353,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
     }
 
     /**
-     * @param mappings Mappings to add.
-     */
-    public void addDhtMapping(Map<UUID, GridDistributedTxMapping> mappings) {
-        addMapping0(mappings, dhtMap);
-    }
-
-    /**
-     * @param mappings Mappings to add.
-     */
-    public void addNearMapping(Map<UUID, GridDistributedTxMapping> mappings) {
-        addMapping0(mappings, nearMap);
-    }
-    /**
      * @param nodeId Node ID.
      * @return {@code True} if mapping was removed.
      */
@@ -435,7 +390,7 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
             if (log.isDebugEnabled())
                 log.debug("Removing mapping for entry [nodeId=" + nodeId + ", entry=" + entry + ']');
 
-            IgniteTxEntry txEntry = txMap.get(entry.txKey());
+            IgniteTxEntry txEntry = entry(entry.txKey());
 
             if (txEntry == null)
                 return false;
@@ -469,7 +424,7 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
             List<GridDhtCacheEntry> entries = mapping.getValue();
 
             for (GridDhtCacheEntry entry : entries) {
-                IgniteTxEntry txEntry = txMap.get(entry.txKey());
+                IgniteTxEntry txEntry = entry(entry.txKey());
 
                 if (txEntry != null) {
                     if (m == null)
@@ -481,26 +436,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
         }
     }
 
-    /**
-     * @param mappings Mappings to add.
-     * @param dst Map to add to.
-     */
-    private void addMapping0(
-        Map<UUID, GridDistributedTxMapping> mappings,
-        Map<UUID, GridDistributedTxMapping> dst
-    ) {
-        for (Map.Entry<UUID, GridDistributedTxMapping> entry : mappings.entrySet()) {
-            GridDistributedTxMapping targetMapping = dst.get(entry.getKey());
-
-            if (targetMapping == null)
-                dst.put(entry.getKey(), entry.getValue());
-            else {
-                for (IgniteTxEntry txEntry : entry.getValue().entries())
-                    targetMapping.add(txEntry);
-            }
-        }
-    }
-
     /** {@inheritDoc} */
     @Override public void addInvalidPartition(GridCacheContext ctx, int part) {
         assert false : "DHT transaction encountered invalid partition [part=" + part + ", tx=" + this + ']';
@@ -529,7 +464,7 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
         GridDhtCacheAdapter dhtCache = cacheCtx.isNear() ? cacheCtx.near().dht() : cacheCtx.dht();
 
         try {
-            IgniteTxEntry existing = txMap.get(e.txKey());
+            IgniteTxEntry existing = entry(e.txKey());
 
             if (existing != null) {
                 // Must keep NOOP operation if received READ because it means that the lock was sent to a backup node.
@@ -569,7 +504,7 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
                     existing.explicitVersion(dhtVer);
                 }
 
-                txMap.put(existing.txKey(), existing);
+                txState.addEntry(existing);
 
                 if (log.isDebugEnabled())
                     log.debug("Added entry to transaction: " + existing);
@@ -705,7 +640,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
                 passedKeys,
                 read,
                 needRetVal,
-                skipped,
                 accessTtl,
                 null,
                 skipStore);
@@ -723,7 +657,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
      * @param passedKeys Passed keys.
      * @param read {@code True} if read.
      * @param needRetVal Return value flag.
-     * @param skipped Skipped keys.
      * @param accessTtl TTL for read operation.
      * @param filter Entry write filter.
      * @param skipStore Skip store flag.
@@ -735,13 +668,11 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
         final Collection<KeyCacheObject> passedKeys,
         final boolean read,
         final boolean needRetVal,
-        final Set<KeyCacheObject> skipped,
         final long accessTtl,
         @Nullable final CacheEntryPredicate[] filter,
         boolean skipStore) {
         if (log.isDebugEnabled())
-            log.debug("Before acquiring transaction lock on keys [passedKeys=" + passedKeys + ", skipped=" +
-                skipped + ']');
+            log.debug("Before acquiring transaction lock on keys [keys=" + passedKeys + ']');
 
         if (passedKeys.isEmpty())
             return new GridFinishedFuture<>(ret);
@@ -768,7 +699,6 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
 
                     postLockWrite(cacheCtx,
                         passedKeys,
-                        skipped,
                         ret,
                         /*remove*/false,
                         /*retval*/false,

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxMapping.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxMapping.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxMapping.java
index 55cbe96..9ec35b6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxMapping.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxMapping.java
@@ -17,18 +17,15 @@
 
 package org.apache.ignite.internal.processors.cache.distributed.dht;
 
-import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
 import org.apache.ignite.internal.util.GridLeanMap;
+import org.apache.ignite.internal.util.GridLeanSet;
 import org.apache.ignite.internal.util.typedef.F;
-import org.jetbrains.annotations.Nullable;
+import org.apache.ignite.internal.util.typedef.internal.U;
 
 /**
  * DHT transaction mapping.
@@ -37,12 +34,6 @@ public class GridDhtTxMapping {
     /** Transaction nodes mapping (primary node -> related backup nodes). */
     private final Map<UUID, Collection<UUID>> txNodes = new GridLeanMap<>();
 
-    /** */
-    private final List<TxMapping> mappings = new ArrayList<>();
-
-    /** */
-    private TxMapping last;
-
     /**
      * Adds information about next mapping.
      *
@@ -50,24 +41,26 @@ public class GridDhtTxMapping {
      */
     @SuppressWarnings("ConstantConditions")
     public void addMapping(List<ClusterNode> nodes) {
-        ClusterNode primary = F.first(nodes);
+        assert !F.isEmpty(nodes) : nodes;
 
-        Collection<ClusterNode> backups = F.view(nodes, F.notEqualTo(primary));
+        ClusterNode primary = nodes.get(0);
 
-        if (last == null || !last.primary.equals(primary.id())) {
-            last = new TxMapping(primary, backups);
+        int size = nodes.size();
 
-            mappings.add(last);
-        }
-        else
-            last.add(backups);
+        if (size > 1) {
+            Collection<UUID> backups = txNodes.get(primary.id());
 
-        Collection<UUID> storedBackups = txNodes.get(last.primary);
+            if (backups == null) {
+                backups = U.newHashSet(size - 1);
 
-        if (storedBackups == null)
-            txNodes.put(last.primary, storedBackups = new HashSet<>());
+                txNodes.put(primary.id(), backups);
+            }
 
-        storedBackups.addAll(last.backups);
+            for (int i = 1; i < size; i++)
+                backups.add(nodes.get(i).id());
+        }
+        else
+            txNodes.put(primary.id(), new GridLeanSet<UUID>());
     }
 
     /**
@@ -76,99 +69,4 @@ public class GridDhtTxMapping {
     public Map<UUID, Collection<UUID>> transactionNodes() {
         return txNodes;
     }
-
-    /**
-     * For each mapping sets flags indicating if mapping is last for node.
-     *
-     * @param mappings Mappings.
-     */
-    public void initLast(Collection<GridDistributedTxMapping> mappings) {
-        assert this.mappings.size() == mappings.size();
-
-        int idx = 0;
-
-        for (GridDistributedTxMapping map : mappings) {
-            TxMapping mapping = this.mappings.get(idx);
-
-            map.lastBackups(lastBackups(mapping, idx));
-
-            boolean last = true;
-
-            for (int i = idx + 1; i < this.mappings.size(); i++) {
-                TxMapping nextMap = this.mappings.get(i);
-
-                if (nextMap.primary.equals(mapping.primary)) {
-                    last = false;
-
-                    break;
-                }
-            }
-
-            map.last(last);
-
-            idx++;
-        }
-    }
-
-    /**
-     * @param mapping Mapping.
-     * @param idx Mapping index.
-     * @return IDs of backup nodes receiving last prepare request during this mapping.
-     */
-    @Nullable private Collection<UUID> lastBackups(TxMapping mapping, int idx) {
-        Collection<UUID> res = null;
-
-        for (UUID backup : mapping.backups) {
-            boolean foundNext = false;
-
-            for (int i = idx + 1; i < mappings.size(); i++) {
-                TxMapping nextMap = mappings.get(i);
-
-                if (nextMap.primary.equals(mapping.primary) && nextMap.backups.contains(backup)) {
-                    foundNext = true;
-
-                    break;
-                }
-            }
-
-            if (!foundNext) {
-                if (res == null)
-                    res = new ArrayList<>(mapping.backups.size());
-
-                res.add(backup);
-            }
-        }
-
-        return res;
-    }
-
-    /**
-     */
-    private static class TxMapping {
-        /** */
-        private final UUID primary;
-
-        /** */
-        private final Set<UUID> backups;
-
-        /**
-         * @param primary Primary node.
-         * @param backups Backup nodes.
-         */
-        private TxMapping(ClusterNode primary, Iterable<ClusterNode> backups) {
-            this.primary = primary.id();
-
-            this.backups = new HashSet<>();
-
-            add(backups);
-        }
-
-        /**
-         * @param backups Backup nodes.
-         */
-        private void add(Iterable<ClusterNode> backups) {
-            for (ClusterNode n : backups)
-                this.backups.add(n.id());
-        }
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index 1d6f633..a67950d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -165,9 +165,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
     /** {@code True} if this is last prepare operation for node. */
     private boolean last;
 
-    /** IDs of backup nodes receiving last prepare request during this prepare. */
-    private Collection<UUID> lastBackups;
-
     /** Needs return value flag. */
     private boolean retVal;
 
@@ -197,7 +194,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
      * @param dhtVerMap DHT versions map.
      * @param last {@code True} if this is last prepare operation for node.
      * @param retVal Return value flag.
-     * @param lastBackups IDs of backup nodes receiving last prepare request during this prepare.
      */
     public GridDhtTxPrepareFuture(
         GridCacheSharedContext cctx,
@@ -205,8 +201,7 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
         IgniteUuid nearMiniId,
         Map<IgniteTxKey, GridCacheVersion> dhtVerMap,
         boolean last,
-        boolean retVal,
-        Collection<UUID> lastBackups
+        boolean retVal
     ) {
         super(REDUCER);
 
@@ -214,7 +209,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
         this.tx = tx;
         this.dhtVerMap = dhtVerMap;
         this.last = last;
-        this.lastBackups = lastBackups;
 
         futId = IgniteUuid.randomUuid();
 
@@ -864,14 +858,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
     }
 
     /**
-     * @param backupId Backup node ID.
-     * @return {@code True} if backup node receives last prepare request for this transaction.
-     */
-    private boolean lastBackup(UUID backupId) {
-        return lastBackups != null && lastBackups.contains(backupId);
-    }
-
-    /**
      * Checks if this transaction needs previous value for the given tx entry. Will use passed in map to store
      * required key or will create new map if passed in map is {@code null}.
      *
@@ -1022,18 +1008,15 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
             tx.writeVersion(cctx.versions().next(tx.topologyVersion()));
 
             {
-                Map<UUID, GridDistributedTxMapping> futDhtMap = new HashMap<>();
-                Map<UUID, GridDistributedTxMapping> futNearMap = new HashMap<>();
-
                 // Assign keys to primary nodes.
                 if (!F.isEmpty(writes)) {
                     for (IgniteTxEntry write : writes)
-                        map(tx.entry(write.txKey()), futDhtMap, futNearMap);
+                        map(tx.entry(write.txKey()));
                 }
 
                 if (!F.isEmpty(reads)) {
                     for (IgniteTxEntry read : reads)
-                        map(tx.entry(read.txKey()), futDhtMap, futNearMap);
+                        map(tx.entry(read.txKey()));
                 }
             }
 
@@ -1225,14 +1208,8 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
 
     /**
      * @param entry Transaction entry.
-     * @param futDhtMap DHT mapping.
-     * @param futNearMap Near mapping.
      */
-    private void map(
-        IgniteTxEntry entry,
-        Map<UUID, GridDistributedTxMapping> futDhtMap,
-        Map<UUID, GridDistributedTxMapping> futNearMap
-    ) {
+    private void map(IgniteTxEntry entry) {
         if (entry.cached().isLocal())
             return;
 
@@ -1258,26 +1235,25 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
                     log.debug("Mapping entry to DHT nodes [nodes=" + U.toShortString(dhtNodes) +
                         ", entry=" + entry + ']');
 
-                Collection<UUID> readers = cached.readers();
+                // Exclude local node.
+                map(entry, F.view(dhtNodes, F.remoteNodes(cctx.localNodeId())), dhtMap);
 
-                Collection<ClusterNode> nearNodes = null;
+                Collection<UUID> readers = cached.readers();
 
                 if (!F.isEmpty(readers)) {
-                    nearNodes = cctx.discovery().nodes(readers, F0.not(F.idForNodeId(tx.nearNodeId())));
+                    Collection<ClusterNode> nearNodes =
+                        cctx.discovery().nodes(readers, F0.not(F.idForNodeId(tx.nearNodeId())));
 
                     if (log.isDebugEnabled())
                         log.debug("Mapping entry to near nodes [nodes=" + U.toShortString(nearNodes) +
                             ", entry=" + entry + ']');
+
+                    // Exclude DHT nodes.
+                    map(entry, F.view(nearNodes, F0.notIn(dhtNodes)), nearMap);
                 }
                 else if (log.isDebugEnabled())
                     log.debug("Entry has no near readers: " + entry);
 
-                // Exclude local node.
-                map(entry, F.view(dhtNodes, F.remoteNodes(cctx.localNodeId())), dhtMap, futDhtMap);
-
-                // Exclude DHT nodes.
-                map(entry, F.view(nearNodes, F0.notIn(dhtNodes)), nearMap, futNearMap);
-
                 break;
             }
             catch (GridCacheEntryRemovedException ignore) {
@@ -1292,13 +1268,11 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
      * @param entry Entry.
      * @param nodes Nodes.
      * @param globalMap Map.
-     * @param locMap Exclude map.
      */
     private void map(
         IgniteTxEntry entry,
         Iterable<ClusterNode> nodes,
-        Map<UUID, GridDistributedTxMapping> globalMap,
-        Map<UUID, GridDistributedTxMapping> locMap
+        Map<UUID, GridDistributedTxMapping> globalMap
     ) {
         if (nodes != null) {
             for (ClusterNode n : nodes) {
@@ -1321,13 +1295,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
                     globalMap.put(n.id(), global = new GridDistributedTxMapping(n));
 
                 global.add(entry);
-
-                GridDistributedTxMapping loc = locMap.get(n.id());
-
-                if (loc == null)
-                    locMap.put(n.id(), loc = new GridDistributedTxMapping(n));
-
-                loc.add(entry);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
index e268a88..0cbe10f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
@@ -36,6 +36,8 @@ import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxRemoteAdapter;
 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.IgniteTxRemoteSingleStateImpl;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxRemoteStateImpl;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.tostring.GridToStringBuilder;
 import org.apache.ignite.internal.util.typedef.T2;
@@ -77,7 +79,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
      * @param nearNodeId Near node ID.
      * @param rmtFutId Remote future ID.
      * @param nodeId Node ID.
-     * @param rmtThreadId Remote thread ID.
      * @param topVer Topology version.
      * @param xidVer XID version.
      * @param commitVer Commit version.
@@ -96,7 +97,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
         UUID nearNodeId,
         IgniteUuid rmtFutId,
         UUID nodeId,
-        long rmtThreadId,
         AffinityTopologyVersion topVer,
         GridCacheVersion xidVer,
         GridCacheVersion commitVer,
@@ -110,12 +110,12 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
         GridCacheVersion nearXidVer,
         Map<UUID, Collection<UUID>> txNodes,
         @Nullable UUID subjId,
-        int taskNameHash
+        int taskNameHash,
+        boolean single
     ) {
         super(
             ctx,
             nodeId,
-            rmtThreadId,
             xidVer,
             commitVer,
             sys,
@@ -137,9 +137,10 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
         this.nearXidVer = nearXidVer;
         this.txNodes = txNodes;
 
-        readMap = Collections.emptyMap();
-
-        writeMap = new ConcurrentLinkedHashMap<>(U.capacity(txSize), 0.75f, 1);
+        txState = single ? new IgniteTxRemoteSingleStateImpl() :
+            new IgniteTxRemoteStateImpl(
+            Collections.<IgniteTxKey, IgniteTxEntry>emptyMap(),
+            new ConcurrentLinkedHashMap<IgniteTxKey, IgniteTxEntry>(U.capacity(txSize), 0.75f, 1));
 
         topologyVersion(topVer);
     }
@@ -151,7 +152,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
      * @param rmtFutId Remote future ID.
      * @param nodeId Node ID.
      * @param nearXidVer Near transaction ID.
-     * @param rmtThreadId Remote thread ID.
      * @param topVer Topology version.
      * @param xidVer XID version.
      * @param commitVer Commit version.
@@ -169,7 +169,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
         IgniteUuid rmtFutId,
         UUID nodeId,
         GridCacheVersion nearXidVer,
-        long rmtThreadId,
         AffinityTopologyVersion topVer,
         GridCacheVersion xidVer,
         GridCacheVersion commitVer,
@@ -186,7 +185,6 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
         super(
             ctx,
             nodeId,
-            rmtThreadId,
             xidVer,
             commitVer,
             sys,
@@ -207,8 +205,9 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
         this.nearNodeId = nearNodeId;
         this.rmtFutId = rmtFutId;
 
-        readMap = Collections.emptyMap();
-        writeMap = new ConcurrentLinkedHashMap<>(U.capacity(txSize), 0.75f, 1);
+        txState = new IgniteTxRemoteStateImpl(
+            Collections.<IgniteTxKey, IgniteTxEntry>emptyMap(),
+            new ConcurrentLinkedHashMap<IgniteTxKey, IgniteTxEntry>(U.capacity(txSize), 0.75f, 1));
 
         topologyVersion(topVer);
     }
@@ -280,6 +279,8 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
     @Override public void addInvalidPartition(GridCacheContext cacheCtx, int part) {
         super.addInvalidPartition(cacheCtx, part);
 
+        Map<IgniteTxKey, IgniteTxEntry> writeMap = txState.writeMap();
+
         for (Iterator<IgniteTxEntry> it = writeMap.values().iterator(); it.hasNext();) {
             IgniteTxEntry e = it.next();
 
@@ -312,7 +313,7 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
             // Initialize cache entry.
             entry.cached(cached);
 
-            writeMap.put(entry.txKey(), entry);
+            txState.addWriteEntry(entry.txKey(), entry);
 
             addExplicit(entry);
         }
@@ -356,7 +357,7 @@ public class GridDhtTxRemote extends GridDistributedTxRemoteAdapter {
 
         txEntry.entryProcessors(entryProcessors);
 
-        writeMap.put(key, txEntry);
+        txState.addWriteEntry(key, txEntry);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
index 5488bb1..29774a5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
@@ -29,7 +29,6 @@ import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
-import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
@@ -57,7 +56,6 @@ import org.apache.ignite.internal.util.typedef.CI1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.P1;
 import org.apache.ignite.internal.util.typedef.X;
-import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiTuple;
@@ -326,19 +324,6 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
 
         txMapping = new GridDhtTxMapping();
 
-        if (!F.isEmpty(reads) || !F.isEmpty(writes)) {
-            for (int cacheId : tx.activeCacheIds()) {
-                GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
-
-                if (CU.affinityNodes(cacheCtx, topVer).isEmpty()) {
-                    onDone(new ClusterTopologyServerNotFoundException("Failed to map keys for cache (all " +
-                        "partition nodes left the grid): " + cacheCtx.name()));
-
-                    return;
-                }
-            }
-        }
-
         Map<IgniteBiTuple<ClusterNode, Boolean>, GridDistributedTxMapping> mappings = new HashMap<>();
 
         for (IgniteTxEntry write : writes)
@@ -437,7 +422,6 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
             m.near(),
             txMapping.transactionNodes(),
             m.last(),
-            m.lastBackups(),
             tx.onePhaseCommit(),
             tx.needReturnValue() && tx.implicit(),
             tx.implicitSingle(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
index 0002180..791d2f3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
@@ -19,7 +19,9 @@ package org.apache.ignite.internal.processors.cache.distributed.near;
 
 import java.util.ArrayDeque;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Queue;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -28,7 +30,6 @@ import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
-import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
@@ -50,7 +51,6 @@ import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.CI1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
-import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteClosure;
@@ -267,7 +267,12 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
                 return;
             }
 
-            prepare(tx.writeEntries(), topLocked);
+            IgniteTxEntry singleWrite = tx.singleWrite();
+
+            if (singleWrite != null)
+                prepareSingle(singleWrite, topLocked);
+            else
+                prepare(tx.writeEntries(), topLocked);
 
             markInitialized();
         }
@@ -280,6 +285,46 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
     }
 
     /**
+     * @param write Write.
+     * @param topLocked {@code True} if thread already acquired lock preventing topology change.
+     */
+    private void prepareSingle(IgniteTxEntry write, boolean topLocked) {
+        AffinityTopologyVersion topVer = tx.topologyVersion();
+
+        assert topVer.topologyVersion() > 0;
+
+        txMapping = new GridDhtTxMapping();
+
+        GridDistributedTxMapping mapping = map(write, topVer, null, topLocked);
+
+        if (mapping.node().isLocal()) {
+            if (write.context().isNear())
+                tx.nearLocallyMapped(true);
+            else if (write.context().isColocated())
+                tx.colocatedLocallyMapped(true);
+        }
+
+        if (isDone()) {
+            if (log.isDebugEnabled())
+                log.debug("Abandoning (re)map because future is done: " + this);
+
+            return;
+        }
+
+        tx.addSingleEntryMapping(mapping, write);
+
+        cctx.mvcc().recheckPendingLocks();
+
+        mapping.last(true);
+
+        tx.transactionNodes(txMapping.transactionNodes());
+
+        checkOnePhase();
+
+        proceedPrepare(mapping, null);
+    }
+
+    /**
      * @param writes Write entries.
      * @param topLocked {@code True} if thread already acquired lock preventing topology change.
      * @throws IgniteCheckedException If failed.
@@ -294,30 +339,26 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
 
         txMapping = new GridDhtTxMapping();
 
-        Queue<GridDistributedTxMapping> mappings = new ArrayDeque<>();
-
-        if (!F.isEmpty(writes)) {
-            for (int cacheId : tx.activeCacheIds()) {
-                GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
-
-                if (CU.affinityNodes(cacheCtx, topVer).isEmpty()) {
-                    onDone(new ClusterTopologyServerNotFoundException("Failed to map keys for cache (all " +
-                        "partition nodes left the grid): " + cacheCtx.name()));
-
-                    return;
-                }
-            }
-        }
+        Map<UUID, GridDistributedTxMapping> map = new HashMap<>();
 
         // Assign keys to primary nodes.
         GridDistributedTxMapping cur = null;
 
+        Queue<GridDistributedTxMapping> mappings = new ArrayDeque<>();
+
         for (IgniteTxEntry write : writes) {
             GridDistributedTxMapping updated = map(write, topVer, cur, topLocked);
 
             if (cur != updated) {
                 mappings.offer(updated);
 
+                updated.last(true);
+
+                GridDistributedTxMapping prev = map.put(updated.node().id(), updated);
+
+                if (prev != null)
+                    prev.last(false);
+
                 if (updated.node().isLocal()) {
                     if (write.context().isNear())
                         tx.nearLocallyMapped(true);
@@ -340,8 +381,6 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
 
         cctx.mvcc().recheckPendingLocks();
 
-        txMapping.initLast(mappings);
-
         tx.transactionNodes(txMapping.transactionNodes());
 
         checkOnePhase();
@@ -355,14 +394,24 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
      * @param mappings Queue of mappings.
      */
     private void proceedPrepare(final Queue<GridDistributedTxMapping> mappings) {
-        if (isDone())
-            return;
-
         final GridDistributedTxMapping m = mappings.poll();
 
         if (m == null)
             return;
 
+        proceedPrepare(m, mappings);
+    }
+
+    /**
+     * Continues prepare after previous mapping successfully finished.
+     *
+     * @param m Mapping.
+     * @param mappings Queue of mappings.
+     */
+    private void proceedPrepare(GridDistributedTxMapping m, @Nullable final Queue<GridDistributedTxMapping> mappings) {
+        if (isDone())
+            return;
+
         assert !m.empty();
 
         final ClusterNode n = m.node();
@@ -376,7 +425,6 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
             m.near(),
             txMapping.transactionNodes(),
             m.last(),
-            m.lastBackups(),
             tx.onePhaseCommit(),
             tx.needReturnValue() && tx.implicit(),
             tx.implicitSingle(),
@@ -457,7 +505,14 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
     ) {
         GridCacheContext cacheCtx = entry.context();
 
-        List<ClusterNode> nodes = cacheCtx.affinity().nodes(entry.key(), topVer);
+        List<ClusterNode> nodes;
+
+        GridCacheEntryEx cached0 = entry.cached();
+
+        if (cached0.isDht())
+            nodes = cacheCtx.affinity().nodes(cached0.partition(), topVer);
+        else
+            nodes = cacheCtx.affinity().nodes(entry.key(), topVer);
 
         txMapping.addMapping(nodes);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java
index fd9183e..6b7244a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFutureAdapter.java
@@ -20,13 +20,11 @@ package org.apache.ignite.internal.processors.cache.distributed.near;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
-import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import org.apache.ignite.internal.util.lang.GridPlainRunnable;
 import org.apache.ignite.internal.util.typedef.CI1;
-import org.apache.ignite.internal.util.typedef.internal.U;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -75,56 +73,14 @@ public abstract class GridNearOptimisticTxPrepareFutureAdapter extends GridNearT
      * @return Topology ready future.
      */
     protected final GridDhtTopologyFuture topologyReadLock() {
-        if (tx.activeCacheIds().isEmpty())
-            return cctx.exchange().lastTopologyFuture();
-
-        GridCacheContext<?, ?> nonLocCtx = null;
-
-        for (int cacheId : tx.activeCacheIds()) {
-            GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
-
-            if (!cacheCtx.isLocal()) {
-                nonLocCtx = cacheCtx;
-
-                break;
-            }
-        }
-
-        if (nonLocCtx == null)
-            return cctx.exchange().lastTopologyFuture();
-
-        nonLocCtx.topology().readLock();
-
-        if (nonLocCtx.topology().stopping()) {
-            onDone(new IgniteCheckedException("Failed to perform cache operation (cache is stopped): " +
-                nonLocCtx.name()));
-
-            return null;
-        }
-
-        return nonLocCtx.topology().topologyVersionFuture();
+        return tx.txState().topologyReadLock(cctx, this);
     }
 
     /**
      * Releases topology read lock.
      */
     protected final void topologyReadUnlock() {
-        if (!tx.activeCacheIds().isEmpty()) {
-            GridCacheContext<?, ?> nonLocCtx = null;
-
-            for (int cacheId : tx.activeCacheIds()) {
-                GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
-
-                if (!cacheCtx.isLocal()) {
-                    nonLocCtx = cacheCtx;
-
-                    break;
-                }
-            }
-
-            if (nonLocCtx != null)
-                nonLocCtx.topology().readUnlock();
-        }
+        tx.txState().topologyReadUnlock(cctx);
     }
 
     /**
@@ -160,28 +116,10 @@ public abstract class GridNearOptimisticTxPrepareFutureAdapter extends GridNearT
         }
 
         if (topVer != null) {
-            StringBuilder invalidCaches = null;
-
-            for (Integer cacheId : tx.activeCacheIds()) {
-                GridCacheContext ctx = cctx.cacheContext(cacheId);
-
-                assert ctx != null : cacheId;
-
-                Throwable err = topFut.validateCache(ctx);
-
-                if (err != null) {
-                    if (invalidCaches != null)
-                        invalidCaches.append(", ");
-                    else
-                        invalidCaches = new StringBuilder();
-
-                    invalidCaches.append(U.maskName(ctx.name()));
-                }
-            }
+            IgniteCheckedException err = tx.txState().validateTopology(cctx, topFut);
 
-            if (invalidCaches != null) {
-                onDone(new IgniteCheckedException("Failed to perform cache operation (cache topology is not valid): " +
-                    invalidCaches.toString()));
+            if (err != null) {
+                onDone(err);
 
                 return;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
index 11d31b2..1554a62 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
@@ -200,7 +200,6 @@ public class GridNearPessimisticTxPrepareFuture extends GridNearTxPrepareFutureA
                 m.near(),
                 txMapping.transactionNodes(),
                 true,
-                txMapping.transactionNodes().get(node.id()),
                 tx.onePhaseCommit(),
                 tx.needReturnValue() && tx.implicit(),
                 tx.implicitSingle(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
index 5ab85b2..e8546ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
@@ -315,7 +315,6 @@ public class GridNearTransactionalCache<K, V> extends GridNearCacheAdapter<K, V>
                                         nodeId,
                                         req.nearNodeId(),
                                         req.nearXidVersion(),
-                                        req.threadId(),
                                         req.version(),
                                         null,
                                         ctx.systemTx(),

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
index a9dbda2..31aa8c3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
@@ -88,7 +88,7 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
     private boolean commit;
 
     /** Node mappings. */
-    private Map<UUID, GridDistributedTxMapping> mappings;
+    private IgniteTxMappings mappings;
 
     /** Trackable flag. */
     private boolean trackable = true;
@@ -347,8 +347,16 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
 
         try {
             if (tx.finish(commit) || (!commit && tx.state() == UNKNOWN)) {
-                if ((tx.onePhaseCommit() && needFinishOnePhase()) || (!tx.onePhaseCommit() && mappings != null))
-                    finish(mappings.values());
+                if ((tx.onePhaseCommit() && needFinishOnePhase()) || (!tx.onePhaseCommit() && mappings != null)) {
+                    if (mappings.single()) {
+                        GridDistributedTxMapping mapping = mappings.singleMapping();
+
+                        if (mapping != null)
+                            finish(mapping);
+                    }
+                    else
+                        finish(mappings.mappings());
+                }
 
                 markInitialized();
 
@@ -381,11 +389,10 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
      *
      */
     private void checkBackup() {
-        assert mappings.size() <= 1;
+        GridDistributedTxMapping mapping = mappings.singleMapping();
 
-        for (Map.Entry<UUID, GridDistributedTxMapping> entry : mappings.entrySet()) {
-            UUID nodeId = entry.getKey();
-            GridDistributedTxMapping mapping = entry.getValue();
+        if (mapping != null) {
+            UUID nodeId = mapping.node().id();
 
             Collection<UUID> backups = tx.transactionNodes().get(nodeId);
 
@@ -482,25 +489,13 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
      *
      */
     private boolean needFinishOnePhase() {
-        if (F.isEmpty(tx.mappings()))
+        if (tx.mappings().empty())
             return false;
 
-        assert tx.mappings().size() == 1;
-
-        boolean finish = false;
-
-        for (Integer cacheId : tx.activeCacheIds()) {
-            GridCacheContext<K, V> cacheCtx = cctx.cacheContext(cacheId);
-
-            if (cacheCtx.isNear()) {
-                finish = true;
-
-                break;
-            }
-        }
+        boolean finish = tx.txState().hasNearCache(cctx);
 
         if (finish) {
-            GridDistributedTxMapping mapping = F.first(tx.mappings().values());
+            GridDistributedTxMapping mapping = tx.mappings().singleMapping();
 
             if (FINISH_NEAR_ONE_PHASE_SINCE.compareTo(mapping.node().version()) > 0)
                 finish = false;
@@ -520,18 +515,16 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
 
         finishOnePhaseCalled = true;
 
-        // No need to send messages as transaction was already committed on remote node.
-        // Finish local mapping only as we need send commit message to backups.
-        for (GridDistributedTxMapping m : mappings.values()) {
-            if (m.node().isLocal()) {
-                IgniteInternalFuture<IgniteInternalTx> fut = cctx.tm().txHandler().finishColocatedLocal(commit, tx);
+        GridDistributedTxMapping locMapping = mappings.localMapping();
 
-                // Add new future.
-                if (fut != null)
-                    add(fut);
+        if (locMapping != null) {
+            // No need to send messages as transaction was already committed on remote node.
+            // Finish local mapping only as we need send commit message to backups.
+            IgniteInternalFuture<IgniteInternalTx> fut = cctx.tm().txHandler().finishColocatedLocal(commit, tx);
 
-                break;
-            }
+            // Add new future.
+            if (fut != null)
+                add(fut);
         }
     }
 
@@ -544,7 +537,9 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
 
             mapping.dhtVersion(xidVer, xidVer);
 
-            tx.readyNearLocks(mapping, Collections.<GridCacheVersion>emptyList(), Collections.<GridCacheVersion>emptyList(),
+            tx.readyNearLocks(mapping,
+                Collections.<GridCacheVersion>emptyList(),
+                Collections.<GridCacheVersion>emptyList(),
                 Collections.<GridCacheVersion>emptyList());
         }
     }


[35/37] ignite git commit: Merge branch ignite-1.5 into ignite-1282

Posted by ag...@apache.org.
Merge branch ignite-1.5 into ignite-1282


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

Branch: refs/heads/ignite-1282
Commit: 3d4ce809fc96d93936a69a6076e7141da41d739c
Parents: c505f48 900788b
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Fri Nov 20 14:03:43 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Fri Nov 20 14:03:43 2015 +0300

----------------------------------------------------------------------
 modules/camel/README.txt                        |   34 +
 modules/camel/licenses/apache-2.0.txt           |  202 ++
 modules/camel/pom.xml                           |  102 +
 .../ignite/stream/camel/CamelStreamer.java      |  237 ++
 .../stream/camel/IgniteCamelStreamerTest.java   |  420 ++++
 .../camel/IgniteCamelStreamerTestSuite.java     |   48 +
 .../src/test/resources/camel.test.properties    |   18 +
 .../ignite/codegen/MessageCodeGenerator.java    |    1 +
 .../java/org/apache/ignite/IgniteCache.java     |    3 +-
 .../java/org/apache/ignite/IgniteCompute.java   |    3 +-
 .../org/apache/ignite/compute/ComputeJob.java   |    2 +-
 .../internal/GridEventConsumeHandler.java       |   22 +-
 .../internal/GridMessageListenHandler.java      |   18 +
 .../ignite/internal/GridUpdateNotifier.java     |    2 +-
 .../apache/ignite/internal/IgniteKernal.java    |    9 +-
 .../communication/GridIoMessageFactory.java     |   26 +-
 .../discovery/GridDiscoveryManager.java         |    2 +-
 .../processors/cache/GridCacheAdapter.java      |  151 +-
 .../processors/cache/GridCacheAtomicFuture.java |    6 +
 .../cache/GridCacheDeploymentManager.java       |    2 +-
 .../processors/cache/GridCacheEntryEx.java      |   12 +-
 .../processors/cache/GridCacheFuture.java       |   13 -
 .../processors/cache/GridCacheGateway.java      |    1 -
 .../processors/cache/GridCacheIoManager.java    |   50 +-
 .../processors/cache/GridCacheMapEntry.java     |  158 +-
 .../processors/cache/GridCacheMessage.java      |   20 +-
 .../processors/cache/GridCacheMvcc.java         |    7 -
 .../processors/cache/GridCacheMvccFuture.java   |    7 +
 .../processors/cache/GridCacheMvccManager.java  |  150 +-
 .../GridCachePartitionExchangeManager.java      |   59 +-
 .../cache/GridCacheSharedContext.java           |   38 +-
 .../cache/GridCacheUpdateAtomicResult.java      |   15 +-
 .../cache/GridCacheUpdateTxResult.java          |   24 +-
 .../processors/cache/IgniteCacheProxy.java      |    3 +
 .../distributed/GridCacheTxRecoveryFuture.java  |   54 +-
 .../distributed/GridDistributedBaseMessage.java |   56 -
 .../distributed/GridDistributedLockRequest.java |    6 -
 .../GridDistributedLockResponse.java            |   32 +-
 .../distributed/GridDistributedTxMapping.java   |   78 -
 .../GridDistributedTxPrepareRequest.java        |   67 +-
 .../GridDistributedTxRemoteAdapter.java         |  158 +-
 .../dht/CacheDistributedGetFutureAdapter.java   |   27 +-
 .../cache/distributed/dht/CacheGetFuture.java   |   32 +
 .../dht/GridClientPartitionTopology.java        |   38 +-
 .../distributed/dht/GridDhtCacheAdapter.java    |  141 ++
 .../distributed/dht/GridDhtLocalPartition.java  |   35 +
 .../distributed/dht/GridDhtLockFuture.java      |   79 +-
 .../distributed/dht/GridDhtLockRequest.java     |    2 +-
 .../dht/GridDhtPartitionTopology.java           |   26 +-
 .../dht/GridDhtPartitionTopologyImpl.java       |  112 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |   14 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |   38 +-
 .../distributed/dht/GridDhtTxFinishRequest.java |  112 +-
 .../cache/distributed/dht/GridDhtTxLocal.java   |   28 +-
 .../distributed/dht/GridDhtTxLocalAdapter.java  |   89 +-
 .../cache/distributed/dht/GridDhtTxMapping.java |  134 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |  136 +-
 .../dht/GridDhtTxPrepareRequest.java            |   54 +-
 .../cache/distributed/dht/GridDhtTxRemote.java  |   29 +-
 .../dht/GridPartitionedGetFuture.java           |   69 +-
 .../dht/GridPartitionedSingleGetFuture.java     |  697 ++++++
 .../dht/atomic/GridDhtAtomicCache.java          |  206 +-
 .../dht/atomic/GridDhtAtomicUpdateFuture.java   |  159 +-
 .../dht/atomic/GridDhtAtomicUpdateRequest.java  |  121 +-
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |    5 -
 .../dht/colocated/GridDhtColocatedCache.java    |  162 +-
 .../colocated/GridDhtColocatedLockFuture.java   |   81 +-
 .../GridDhtPartitionsExchangeFuture.java        |   35 +-
 .../preloader/GridDhtPartitionsFullMessage.java |   64 +-
 .../GridDhtPartitionsSingleMessage.java         |   56 +-
 .../distributed/near/CacheVersionedValue.java   |    2 +-
 .../distributed/near/GridNearAtomicCache.java   |   10 +-
 .../distributed/near/GridNearCacheAdapter.java  |    4 +-
 .../distributed/near/GridNearGetFuture.java     |   49 +-
 .../distributed/near/GridNearGetRequest.java    |    1 -
 .../distributed/near/GridNearGetResponse.java   |    2 -
 .../distributed/near/GridNearLockFuture.java    |   72 +-
 .../distributed/near/GridNearLockRequest.java   |    4 +-
 ...arOptimisticSerializableTxPrepareFuture.java |  124 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |  170 +-
 ...ridNearOptimisticTxPrepareFutureAdapter.java |   72 +-
 .../GridNearPessimisticTxPrepareFuture.java     |   59 +-
 .../near/GridNearSingleGetRequest.java          |  396 ++++
 .../near/GridNearSingleGetResponse.java         |  321 +++
 .../near/GridNearTransactionalCache.java        |   10 +-
 .../near/GridNearTxFinishFuture.java            |  103 +-
 .../cache/distributed/near/GridNearTxLocal.java |  273 ++-
 .../near/GridNearTxPrepareFutureAdapter.java    |   20 +-
 .../near/GridNearTxPrepareRequest.java          |   61 +-
 .../distributed/near/GridNearTxRemote.java      |   33 +-
 .../distributed/near/IgniteTxMappings.java      |   75 +
 .../distributed/near/IgniteTxMappingsImpl.java  |   92 +
 .../near/IgniteTxMappingsSingleImpl.java        |  101 +
 .../processors/cache/local/GridLocalCache.java  |    4 +-
 .../cache/local/GridLocalLockFuture.java        |    5 -
 .../CacheContinuousQueryBatchAck.java           |  163 ++
 .../continuous/CacheContinuousQueryEntry.java   |  196 +-
 .../continuous/CacheContinuousQueryHandler.java |  811 ++++++-
 .../CacheContinuousQueryListener.java           |   35 +
 .../continuous/CacheContinuousQueryManager.java |  151 +-
 .../cache/transactions/IgniteInternalTx.java    |   13 +-
 .../cache/transactions/IgniteTxAdapter.java     |   68 +-
 .../cache/transactions/IgniteTxEntry.java       |   29 +-
 .../cache/transactions/IgniteTxHandler.java     |   38 +-
 .../IgniteTxImplicitSingleStateImpl.java        |  266 +++
 .../transactions/IgniteTxLocalAdapter.java      | 1424 ++++++-----
 .../cache/transactions/IgniteTxLocalEx.java     |   30 +-
 .../cache/transactions/IgniteTxLocalState.java  |   44 +
 .../transactions/IgniteTxLocalStateAdapter.java |   41 +
 .../cache/transactions/IgniteTxManager.java     |   21 +-
 .../cache/transactions/IgniteTxMap.java         |    3 +-
 .../cache/transactions/IgniteTxRemoteEx.java    |   18 +-
 .../IgniteTxRemoteSingleStateImpl.java          |  108 +
 .../cache/transactions/IgniteTxRemoteState.java |   34 +
 .../IgniteTxRemoteStateAdapter.java             |  115 +
 .../transactions/IgniteTxRemoteStateImpl.java   |  124 +
 .../cache/transactions/IgniteTxState.java       |  177 ++
 .../cache/transactions/IgniteTxStateImpl.java   |  414 ++++
 .../clock/GridClockSyncProcessor.java           |   28 +-
 .../continuous/GridContinuousBatch.java         |   44 +
 .../continuous/GridContinuousBatchAdapter.java  |   46 +
 .../continuous/GridContinuousHandler.java       |   22 +
 .../continuous/GridContinuousProcessor.java     |  221 +-
 .../StartRoutineAckDiscoveryMessage.java        |   14 +-
 .../StartRoutineDiscoveryMessage.java           |   21 +-
 .../internal/util/UUIDCollectionMessage.java    |  114 +
 .../util/future/GridCompoundFuture.java         |   15 +-
 .../ignite/internal/util/lang/GridFunc.java     |    8 +-
 .../ignite/internal/util/nio/GridNioServer.java |   13 +-
 .../ignite/marshaller/MarshallerExclusions.java |    4 +-
 .../org/apache/ignite/mxbean/IgniteMXBean.java  |    8 +-
 .../org/apache/ignite/stream/StreamAdapter.java |   18 +-
 .../IgniteClientReconnectCacheTest.java         |   11 +-
 .../cache/GridCacheAbstractFullApiSelfTest.java |   75 +
 .../GridCacheConcurrentTxMultiNodeTest.java     |   15 -
 .../cache/GridCachePartitionedGetSelfTest.java  |    3 +-
 .../processors/cache/GridCacheTestEntryEx.java  |   10 +-
 .../IgniteCacheAbstractStopBusySelfTest.java    |   27 +-
 .../IgniteCacheP2pUnmarshallingErrorTest.java   |  184 +-
 .../CacheGetFutureHangsSelfTest.java            |    6 +
 .../GridCacheAbstractNodeRestartSelfTest.java   |    2 +
 .../IgniteCacheSingleGetMessageTest.java        |  357 +++
 .../GridCacheReplicatedMetricsSelfTest.java     |    9 -
 .../IgniteCacheTxStoreSessionTest.java          |    2 +-
 ...ContinuousQueryFailoverAbstractSelfTest.java | 2235 ++++++++++++++++++
 ...ryFailoverAtomicNearEnabledSelfSelfTest.java |   46 +
 ...FailoverAtomicPrimaryWriteOrderSelfTest.java |   44 +
 ...usQueryFailoverAtomicReplicatedSelfTest.java |   40 +
 ...inuousQueryFailoverTxReplicatedSelfTest.java |   32 +
 .../CacheContinuousQueryFailoverTxSelfTest.java |   39 +
 ...ridCacheContinuousQueryAbstractSelfTest.java |  153 +-
 .../GridCacheContinuousQueryTxSelfTest.java     |   49 +
 ...CacheContinuousQueryClientReconnectTest.java |  187 ++
 .../IgniteCacheContinuousQueryClientTest.java   |  157 +-
 ...cheContinuousQueryClientTxReconnectTest.java |   32 +
 .../p2p/GridP2PSameClassLoaderSelfTest.java     |   16 +-
 .../testframework/junits/GridAbstractTest.java  |    2 +-
 .../junits/common/GridCommonAbstractTest.java   |    3 +
 .../testsuites/IgniteCacheTestSuite3.java       |    2 +
 .../testsuites/IgniteCacheTestSuite4.java       |    3 +
 .../ignite/util/mbeans/GridMBeanSelfTest.java   |   33 +-
 modules/flume/README.txt                        |   72 +
 modules/flume/licenses/apache-2.0.txt           |  202 ++
 modules/flume/pom.xml                           |   77 +
 .../ignite/stream/flume/EventTransformer.java   |   36 +
 .../apache/ignite/stream/flume/IgniteSink.java  |  186 ++
 .../stream/flume/IgniteSinkConstants.java       |   35 +
 .../ignite/stream/flume/IgniteSinkTest.java     |  142 ++
 .../stream/flume/IgniteSinkTestSuite.java       |   37 +
 .../stream/flume/TestEventTransformer.java      |   66 +
 .../flume/src/test/resources/example-ignite.xml |   71 +
 .../IgniteCacheQuerySelfTestSuite.java          |   16 +-
 .../GridSpringResourceInjectionSelfTest.java    |  143 ++
 .../processors/resource/spring-resource.xml     |   27 +
 .../testsuites/IgniteResourceSelfTestSuite.java |    2 +
 modules/twitter/README.txt                      |   32 +
 modules/twitter/licenses/apache-2.0.txt         |  202 ++
 modules/twitter/pom.xml                         |  122 +
 .../ignite/stream/twitter/OAuthSettings.java    |   86 +
 .../ignite/stream/twitter/TwitterStreamer.java  |  295 +++
 .../twitter/IgniteTwitterStreamerTest.java      |  234 ++
 .../twitter/IgniteTwitterStreamerTestSuite.java |   32 +
 .../stream/twitter/TwitterStreamerImpl.java     |   79 +
 .../config/benchmark-multicast.properties       |    6 +-
 .../benchmark-query-put-separated.properties    |   87 +
 .../yardstick/cache/CacheEntryEventProbe.java   |  156 ++
 .../cache/IgniteSqlQueryPutBenchmark.java       |   31 +-
 .../IgniteSqlQueryPutSeparatedBenchmark.java    |   84 +
 parent/pom.xml                                  |    1 +
 pom.xml                                         |    3 +
 190 files changed, 15606 insertions(+), 2789 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
----------------------------------------------------------------------
diff --cc modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
index b8ccc03,74c71c4..5a31415
--- a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
+++ b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
@@@ -43,7 -43,10 +43,8 @@@ import org.apache.ignite.internal.GridD
  import org.apache.ignite.internal.GridDirectMap;
  import org.apache.ignite.internal.GridDirectTransient;
  import org.apache.ignite.internal.IgniteCodeGeneratingFail;
 -import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxPrepareRequest;
 -import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxPrepareRequest;
 -import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareRequest;
 +import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicUpdateRequest;
+ import org.apache.ignite.internal.util.UUIDCollectionMessage;
  import org.apache.ignite.internal.util.typedef.internal.SB;
  import org.apache.ignite.internal.util.typedef.internal.U;
  import org.apache.ignite.lang.IgniteUuid;

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/IgniteKernal.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryEx.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index 5ced545,8d363ad..512a801
--- 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
@@@ -1205,14 -1186,15 +1215,16 @@@ public abstract class GridCacheMapEntr
                      val != null,
                      evtOld,
                      evtOld != null || hasValueUnlocked(),
 -                    subjId, null, taskName);
 +                    subjId, null, taskName,
 +                    keepPortable);
              }
  
-             if (cctx.isLocal() || cctx.isReplicated() || (tx != null && tx.local() && !isNear()))
-                 cctx.continuousQueries().onEntryUpdated(this, key, val, old, false);
+             if (cctx.isLocal() || cctx.isReplicated() ||
+                 (!isNear() && !(tx != null && tx.onePhaseCommit() && !tx.local())))
+                 cctx.continuousQueries().onEntryUpdated(key, val, old, isInternal() || !context().userCache(),
+                     partition(), tx.local(), false, updateCntr0, topVer);
  
 -            cctx.dataStructures().onEntryUpdated(key, false);
 +            cctx.dataStructures().onEntryUpdated(key, false, keepPortable);
          }
  
          if (log.isDebugEnabled())
@@@ -1224,9 -1206,9 +1236,9 @@@
              cctx.store().put(tx, keyValue(false), CU.value(val, cctx, false), newVer);
  
          if (intercept)
 -            cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, val, val0));
 +            cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, val, val0, keepPortable));
  
-         return valid ? new GridCacheUpdateTxResult(true, retval ? old : null) :
+         return valid ? new GridCacheUpdateTxResult(true, retval ? old : null, updateCntr0) :
              new GridCacheUpdateTxResult(false, null);
      }
  
@@@ -1377,14 -1366,15 +1397,16 @@@
                      evtOld != null || hasValueUnlocked(),
                      subjId,
                      null,
 -                    taskName);
 +                    taskName,
 +                    keepPortable);
              }
  
-             if (cctx.isLocal() || cctx.isReplicated() || (tx != null && tx.local() && !isNear()))
-                 cctx.continuousQueries().onEntryUpdated(this, key, null, old, false);
+             if (cctx.isLocal() || cctx.isReplicated() ||
+                 (!isNear() && !(tx != null && tx.onePhaseCommit() && !tx.local())))
+                 cctx.continuousQueries().onEntryUpdated(key, null, old, isInternal()
+                     || !context().userCache(),partition(), tx.local(), false, updateCntr0, topVer);
  
 -            cctx.dataStructures().onEntryUpdated(key, true);
 +            cctx.dataStructures().onEntryUpdated(key, true, keepPortable);
  
              deferred = cctx.deferredDelete() && !detached() && !isInternal();
  
@@@ -1718,9 -1707,14 +1740,14 @@@
              if (res)
                  updateMetrics(op, metrics);
  
-             cctx.continuousQueries().onEntryUpdated(this, key, val, old, false);
+             if (!isNear()) {
+                 long updateCntr = nextPartCounter(AffinityTopologyVersion.NONE);
+ 
+                 cctx.continuousQueries().onEntryUpdated(key, val, old, isInternal() || !context().userCache(),
+                     partition(), true, false, updateCntr, AffinityTopologyVersion.NONE);
+             }
  
 -            cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE);
 +            cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE, keepBinary);
  
              if (intercept) {
                  if (op == GridCacheOperation.UPDATE)
@@@ -2336,10 -2377,7 +2415,7 @@@
              if (res)
                  updateMetrics(op, metrics);
  
-             if (cctx.isReplicated() || primary)
-                 cctx.continuousQueries().onEntryUpdated(this, key, val, oldVal, false);
- 
 -            cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE);
 +            cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE, keepPortable);
  
              if (intercept) {
                  if (op == GridCacheOperation.UPDATE)
@@@ -3186,10 -3230,10 +3268,10 @@@
                  drReplicate(drType, val, ver);
  
                  if (!skipQryNtf) {
-                     if (cctx.isLocal() || cctx.isReplicated() || cctx.affinity().primary(cctx.localNode(), key, topVer))
-                         cctx.continuousQueries().onEntryUpdated(this, key, val, null, preload);
+                     cctx.continuousQueries().onEntryUpdated(key, val, null, this.isInternal()
+                         || !this.context().userCache(), this.partition(), true, preload, updateCntr, topVer);
  
 -                    cctx.dataStructures().onEntryUpdated(key, false);
 +                    cctx.dataStructures().onEntryUpdated(key, false, true);
                  }
  
                  if (cctx.store().isLocal()) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
index db19c67,55ca12d..2330a95
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
@@@ -707,11 -649,9 +651,10 @@@ public abstract class GridDhtTxLocalAda
                  passedKeys,
                  read,
                  needRetVal,
-                 skipped,
                  accessTtl,
                  null,
 -                skipStore);
 +                skipStore,
 +                keepBinary);
          }
          catch (IgniteCheckedException e) {
              setRollbackOnly();
@@@ -738,14 -677,11 +680,12 @@@
          final Collection<KeyCacheObject> passedKeys,
          final boolean read,
          final boolean needRetVal,
-         final Set<KeyCacheObject> skipped,
          final long accessTtl,
          @Nullable final CacheEntryPredicate[] filter,
 -        boolean skipStore) {
 +        boolean skipStore,
 +        boolean keepBinary) {
          if (log.isDebugEnabled())
-             log.debug("Before acquiring transaction lock on keys [passedKeys=" + passedKeys + ", skipped=" +
-                 skipped + ']');
+             log.debug("Before acquiring transaction lock on keys [keys=" + passedKeys + ']');
  
          if (passedKeys.isEmpty())
              return new GridFinishedFuture<>(ret);

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxRemote.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index 255640f,3ee1048..cd76a56
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@@ -1765,8 -1875,7 +1881,8 @@@ public class GridDhtAtomicCache<K, V> e
                      req.invokeArguments(),
                      primary && writeThrough() && !req.skipStore(),
                      !req.skipStore(),
-                     req.returnValue(),
+                     sndPrevVal || req.returnValue(),
 +                    req.keepBinary(),
                      expiry,
                      true,
                      true,
@@@ -2036,8 -2156,7 +2164,8 @@@
                          null,
                          /*write-through*/false,
                          /*read-through*/false,
-                         /*retval*/false,
+                         /*retval*/sndPrevVal,
 +                        req.keepBinary(),
                          expiry,
                          /*event*/true,
                          /*metrics*/true,

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
index 7b95042,72a60d2..a8807e1
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
@@@ -139,9 -144,19 +144,22 @@@ public class GridDhtAtomicUpdateReques
      /** Task name hash. */
      private int taskNameHash;
  
+     /** Partition. */
+     private GridLongList updateCntrs;
+ 
+     /** On response flag. Access should be synced on future. */
+     @GridDirectTransient
+     private boolean onRes;
+ 
+     @GridDirectTransient
+     private List<Integer> partIds;
+ 
+     @GridDirectTransient
+     private List<CacheObject> localPrevVals;
+ 
 +    /** Keep portable flag. */
 +    private boolean keepBinary;
 +
      /**
       * Empty constructor required by {@link Externalizable}.
       */
@@@ -191,9 -205,10 +209,11 @@@
          this.taskNameHash = taskNameHash;
          this.invokeArgs = invokeArgs;
          this.addDepInfo = addDepInfo;
 +        this.keepBinary = keepBinary;
  
          keys = new ArrayList<>();
+         partIds = new ArrayList<>();
+         localPrevVals = new ArrayList<>();
  
          if (forceTransformBackups) {
              entryProcessors = new ArrayList<>();

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
index 648a248,706655b..49a267a
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearAtomicCache.java
@@@ -251,8 -249,7 +251,8 @@@ public class GridNearAtomicCache<K, V> 
                          /*write-through*/false,
                          /*read-through*/false,
                          /*retval*/false,
 +                        keepPortable,
-                         /**expiry policy*/null,
+                         /*expiry policy*/null,
                          /*event*/true,
                          /*metrics*/true,
                          /*primary*/false,

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
index 685b998,dfaa44e..00f0a75
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
@@@ -562,8 -520,17 +545,10 @@@ public final class GridNearGetFuture<K
                              add(new GridFinishedFuture<>(Collections.singletonMap(key0, val0)));
                          }
                          else {
 -                            K key0 = key.value(cctx.cacheObjectContext(), true);
 -                            key0 = (K)cctx.unwrapPortableIfNeeded(key0, !deserializePortable);
 -
 -                            V val0;
 -
 -                            if (!skipVals) {
 -                                val0 = v.value(cctx.cacheObjectContext(), true);
 -                                val0 = (V)cctx.unwrapPortableIfNeeded(val0, !deserializePortable);
 -                            }
 -                            else
 -                                val0 = (V)Boolean.TRUE;
 +                            K key0 = (K)cctx.unwrapPortableIfNeeded(key, !deserializePortable);
-                             V val0 = (V)cctx.unwrapPortableIfNeeded(v, !deserializePortable);
++                            V val0 = !skipVals ? 
++                                (V)cctx.unwrapPortableIfNeeded(v, !deserializePortable) : 
++                                (V)Boolean.TRUE;
  
                              add(new GridFinishedFuture<>(Collections.singletonMap(key0, val0)));
                          }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockRequest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index 4b5b204,1c01e4e..2eb4c68
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@@ -347,9 -332,8 +332,9 @@@ public class GridNearTxLocal extends Gr
          boolean readThrough,
          boolean async,
          final Collection<KeyCacheObject> keys,
-         boolean skipVals,
+         final boolean skipVals,
          final boolean needVer,
 +        boolean keepBinary,
          final GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c
      ) {
          if (cacheCtx.isNear()) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
index 58ee0c6,ba58f57..cef8371
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxRemote.java
@@@ -390,10 -392,9 +393,10 @@@ public class GridNearTxRemote extends G
                          -1L,
                          cached,
                          drVer,
 -                        skipStore);
 +                        skipStore,
 +                        keepBinary);
  
-                     writeMap.put(key, txEntry);
+                     txState.addWriteEntry(key, txEntry);
  
                      return true;
                  }

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalLockFuture.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index 9f52699,cff62d9..fae7d8c
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@@ -2133,265 -2183,363 +2201,363 @@@ public abstract class IgniteTxLocalAdap
  
                  KeyCacheObject cacheKey = cacheCtx.toCacheKeyObject(key);
  
-                 IgniteTxKey txKey = cacheCtx.txKey(cacheKey);
- 
-                 IgniteTxEntry txEntry = entry(txKey);
- 
-                 // First time access.
-                 if (txEntry == null) {
-                     while (true) {
-                         GridCacheEntryEx entry = entryEx(cacheCtx, txKey, topologyVersion());
- 
-                         try {
-                             entry.unswap(false);
- 
-                             // Check if lock is being explicitly acquired by the same thread.
-                             if (!implicit && cctx.kernalContext().config().isCacheSanityCheckEnabled() &&
-                                 entry.lockedByThread(threadId, xidVer))
-                                 throw new IgniteCheckedException("Cannot access key within transaction if lock is " +
-                                     "externally held [key=" + key + ", entry=" + entry + ", xidVer=" + xidVer +
-                                     ", threadId=" + threadId +
-                                     ", locNodeId=" + cctx.localNodeId() + ']');
- 
-                             CacheObject old = null;
-                             GridCacheVersion readVer = null;
+                 boolean loadMissed = enlistWriteEntry(cacheCtx,
+                     cacheKey,
+                     val,
+                     entryProcessor,
+                     invokeArgs,
+                     expiryPlc,
+                     retval,
+                     lockOnly,
+                     filter,
+                     drVer,
+                     drTtl,
+                     drExpireTime,
+                     ret,
+                     enlisted,
+                     skipStore,
+                     singleRmv,
+                     hasFilters,
+                     needVal,
+                     needReadVer);
+ 
+                 if (loadMissed) {
+                     if (missedForLoad == null)
+                         missedForLoad = new HashSet<>();
+ 
+                     missedForLoad.add(cacheKey);
+                 }
+             }
  
-                             if (optimistic() && !implicit()) {
-                                 try {
-                                     if (needReadVer) {
-                                         T2<CacheObject, GridCacheVersion> res = primaryLocal(entry) ?
-                                             entry.innerGetVersioned(this,
-                                                 /*swap*/false,
-                                                 /*unmarshal*/retval,
-                                                 /*metrics*/retval,
-                                                 /*events*/retval,
-                                                 CU.subjectId(this, cctx),
-                                                 entryProcessor,
-                                                 resolveTaskName(),
-                                                 null,
-                                                 keepBinary) : null;
+             if (missedForLoad != null) {
+                 return loadMissing(cacheCtx,
+                     missedForLoad,
+                     filter,
+                     ret,
+                     needReadVer,
+                     singleRmv,
+                     hasFilters,
+                     skipStore,
+                     retval);
+             }
  
-                                         if (res != null) {
-                                             old = res.get1();
-                                             readVer = res.get2();
-                                         }
-                                     }
-                                     else {
-                                         old = entry.innerGet(this,
-                                             /*swap*/false,
-                                             /*read-through*/false,
-                                             /*fail-fast*/false,
-                                             /*unmarshal*/retval,
-                                             /*metrics*/retval,
-                                             /*events*/retval,
-                                             /*temporary*/false,
-                                             CU.subjectId(this, cctx),
-                                             entryProcessor,
-                                             resolveTaskName(),
-                                             null,
-                                             keepBinary);
-                                     }
-                                 }
-                                 catch (ClusterTopologyCheckedException e) {
-                                     entry.context().evicts().touch(entry, topologyVersion());
+             return new GridFinishedFuture<>();
+         }
+         catch (IgniteCheckedException e) {
+             return new GridFinishedFuture<>(e);
+         }
+     }
  
-                                     throw e;
-                                 }
-                             }
-                             else
-                                 old = retval ? entry.rawGetOrUnmarshal(false) : entry.rawGet();
+     /**
+      * @param cacheCtx Cache context.
+      * @param keys Keys to load.
+      * @param filter Filter.
+      * @param ret Return value.
+      * @param needReadVer Read version flag.
+      * @param singleRmv {@code True} for single remove operation.
+      * @param hasFilters {@code True} if filters not empty.
+      * @param skipStore Skip store flag.
+      * @param retval Return value flag.
+      * @return Load future.
+      */
+     private IgniteInternalFuture<Void> loadMissing(
+         final GridCacheContext cacheCtx,
+         final Set<KeyCacheObject> keys,
+         final CacheEntryPredicate[] filter,
+         final GridCacheReturn ret,
+         final boolean needReadVer,
+         final boolean singleRmv,
+         final boolean hasFilters,
+         final boolean skipStore,
+         final boolean retval) {
+         GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c =
+             new GridInClosure3<KeyCacheObject, Object, GridCacheVersion>() {
+                 @Override public void apply(KeyCacheObject key,
+                     @Nullable Object val,
+                     @Nullable GridCacheVersion loadVer) {
+                     if (log.isDebugEnabled())
+                         log.debug("Loaded value from remote node [key=" + key + ", val=" + val + ']');
  
-                             if (old != null && hasFilters && !filter(entry.context(), cacheKey, old, filter)) {
-                                 skipped = skip(skipped, cacheKey);
+                     IgniteTxEntry e = entry(new IgniteTxKey(key, cacheCtx.cacheId()));
  
-                                 ret.set(cacheCtx, old, false, keepBinary);
+                     assert e != null;
  
-                                 if (!readCommitted()) {
-                                     // Enlist failed filters as reads for non-read-committed mode,
-                                     // so future ops will get the same values.
-                                     txEntry = addEntry(READ,
-                                         old,
-                                         null,
-                                         null,
-                                         entry,
-                                         null,
-                                         CU.empty0(),
-                                         false,
-                                         -1L,
-                                         -1L,
-                                         null,
-                                         skipStore,
-                                         keepBinary);
+                     if (needReadVer) {
+                         assert loadVer != null;
  
-                                     txEntry.markValid();
+                         e.serializableReadVersion(singleRmv && val != null ? SER_READ_NOT_EMPTY_VER : loadVer);
+                     }
  
-                                     if (needReadVer) {
-                                         assert readVer != null;
+                     if (singleRmv) {
+                         assert !hasFilters && !retval;
+                         assert val == null || Boolean.TRUE.equals(val) : val;
  
-                                         txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
-                                     }
-                                 }
 -                        ret.set(cacheCtx, null, val != null);
++                        ret.set(cacheCtx, null, val != null, keepBinary);
+                     }
+                     else {
+                         CacheObject cacheVal = cacheCtx.toCacheObject(val);
  
-                                 if (readCommitted())
-                                     cacheCtx.evicts().touch(entry, topologyVersion());
+                         if (e.op() == TRANSFORM) {
+                             GridCacheVersion ver;
  
-                                 break; // While.
+                             try {
+                                 ver = e.cached().version();
                              }
+                             catch (GridCacheEntryRemovedException ex) {
+                                 assert optimistic() : e;
  
-                             final GridCacheOperation op = lockOnly ? NOOP : rmv ? DELETE :
-                                 entryProcessor != null ? TRANSFORM : old != null ? UPDATE : CREATE;
+                                 if (log.isDebugEnabled())
+                                     log.debug("Failed to get entry version: [msg=" + ex.getMessage() + ']');
  
-                             txEntry = addEntry(op,
-                                 cacheCtx.toCacheObject(val),
-                                 entryProcessor,
-                                 invokeArgs,
-                                 entry,
-                                 expiryPlc,
-                                 filter,
-                                 true,
-                                 drTtl,
-                                 drExpireTime,
-                                 drVer,
-                                 skipStore,
-                                 keepBinary);
+                                 ver = null;
+                             }
  
-                             if (!implicit() && readCommitted() && !cacheCtx.offheapTiered())
-                                 cacheCtx.evicts().touch(entry, topologyVersion());
+                             addInvokeResult(e, cacheVal, ret, ver);
+                         }
+                         else {
+                             boolean success = !hasFilters || isAll(e.context(), key, cacheVal, filter);
  
-                             enlisted.add(cacheKey);
+                             ret.set(cacheCtx, cacheVal, success);
+                         }
+                     }
+                 }
+             };
  
-                             if (!pessimistic() && !implicit()) {
-                                 txEntry.markValid();
+         return loadMissing(
+             cacheCtx,
+             /*read through*/cacheCtx.config().isLoadPreviousValue() && !skipStore,
+             /*async*/true,
+             keys,
+             /*skipVals*/singleRmv,
+             needReadVer,
+             c);
+     }
  
-                                 if (old == null) {
-                                     if (needVal) {
-                                         if (missedForLoad == null)
-                                             missedForLoad = new HashSet<>();
+     /**
+      * @param cacheCtx Cache context.
+      * @param cacheKey Key.
+      * @param val Value.
+      * @param entryProcessor Entry processor.
+      * @param invokeArgs Optional arguments for EntryProcessor.
+      * @param expiryPlc Explicitly specified expiry policy for entry.
+      * @param retval Return value flag.
+      * @param lockOnly
+      * @param filter Filter.
+      * @param drVer DR version.
+      * @param drTtl DR ttl.
+      * @param drExpireTime DR expire time.
+      * @param ret Return value.
+      * @param enlisted Enlisted keys collection.
+      * @param skipStore Skip store flag.
+      * @param singleRmv {@code True} for single remove operation.
+      * @param hasFilters {@code True} if filters not empty.
+      * @param needVal {@code True} if value is needed.
+      * @param needReadVer {@code True} if need read entry version.
+      * @return {@code True} if entry value should be loaded.
+      * @throws IgniteCheckedException If failed.
+      */
+     private boolean enlistWriteEntry(GridCacheContext cacheCtx,
+         final KeyCacheObject cacheKey,
+         final @Nullable Object val,
+         final @Nullable EntryProcessor<?, ?, ?> entryProcessor,
+         final @Nullable Object[] invokeArgs,
+         final @Nullable ExpiryPolicy expiryPlc,
+         final boolean retval,
+         final boolean lockOnly,
+         final CacheEntryPredicate[] filter,
+         final GridCacheVersion drVer,
+         final long drTtl,
+         long drExpireTime,
+         final GridCacheReturn ret,
+         @Nullable final Collection<KeyCacheObject> enlisted,
+         boolean skipStore,
+         boolean singleRmv,
+         boolean hasFilters,
+         final boolean needVal,
+         boolean needReadVer
+     ) throws IgniteCheckedException {
+         boolean loadMissed = false;
  
-                                         missedForLoad.add(cacheKey);
-                                     }
-                                     else {
-                                         assert !implicit() || !transform : this;
-                                         assert txEntry.op() != TRANSFORM : txEntry;
+         final boolean rmv = val == null && entryProcessor == null;
  
-                                         if (retval)
-                                             ret.set(cacheCtx, null, true, keepBinary);
-                                         else
-                                             ret.success(true);
-                                     }
-                                 }
-                                 else {
-                                     if (needReadVer) {
-                                         assert readVer != null;
+         IgniteTxKey txKey = cacheCtx.txKey(cacheKey);
  
-                                         txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
-                                     }
+         IgniteTxEntry txEntry = entry(txKey);
  
-                                     if (retval && !transform)
-                                         ret.set(cacheCtx, old, true, keepBinary);
-                                     else {
-                                         if (txEntry.op() == TRANSFORM) {
-                                             GridCacheVersion ver;
+         // First time access.
+         if (txEntry == null) {
+             while (true) {
+                 GridCacheEntryEx entry = entryEx(cacheCtx, txKey, topologyVersion());
  
-                                             try {
-                                                 ver = entry.version();
-                                             }
-                                             catch (GridCacheEntryRemovedException ex) {
-                                                 assert optimistic() : txEntry;
+                 try {
+                     entry.unswap(false);
+ 
+                     // Check if lock is being explicitly acquired by the same thread.
+                     if (!implicit && cctx.kernalContext().config().isCacheSanityCheckEnabled() &&
+                         entry.lockedByThread(threadId, xidVer)) {
+                         throw new IgniteCheckedException("Cannot access key within transaction if lock is " +
+                             "externally held [key=" + CU.value(cacheKey, cacheCtx, false) +
+                             ", entry=" + entry +
+                             ", xidVer=" + xidVer +
+                             ", threadId=" + threadId +
+                             ", locNodeId=" + cctx.localNodeId() + ']');
+                     }
  
-                                                 if (log.isDebugEnabled())
-                                                     log.debug("Failed to get entry version " +
-                                                         "[err=" + ex.getMessage() + ']');
+                     CacheObject old = null;
+                     GridCacheVersion readVer = null;
  
-                                                 ver = null;
-                                             }
+                     if (optimistic() && !implicit()) {
+                         try {
+                             if (needReadVer) {
+                                 T2<CacheObject, GridCacheVersion> res = primaryLocal(entry) ?
+                                     entry.innerGetVersioned(this,
+                                         /*swap*/false,
+                                         /*unmarshal*/retval,
+                                         /*metrics*/retval,
+                                         /*events*/retval,
+                                         CU.subjectId(this, cctx),
+                                         entryProcessor,
+                                         resolveTaskName(),
+                                         null) : null;
  
-                                             addInvokeResult(txEntry, old, ret, ver);
-                                         }
-                                         else
-                                             ret.success(true);
-                                     }
+                                 if (res != null) {
+                                     old = res.get1();
+                                     readVer = res.get2();
                                  }
                              }
-                             // Pessimistic.
                              else {
-                                 if (retval && !transform)
-                                     ret.set(cacheCtx, old, true, keepBinary);
-                                 else
-                                     ret.success(true);
+                                 old = entry.innerGet(this,
+                                     /*swap*/false,
+                                     /*read-through*/false,
+                                     /*fail-fast*/false,
+                                     /*unmarshal*/retval,
+                                     /*metrics*/retval,
+                                     /*events*/retval,
+                                     /*temporary*/false,
+                                     CU.subjectId(this, cctx),
+                                     entryProcessor,
+                                     resolveTaskName(),
+                                     null);
                              }
- 
-                             break; // While.
                          }
-                         catch (GridCacheEntryRemovedException ignore) {
-                             if (log.isDebugEnabled())
-                                 log.debug("Got removed entry in transaction putAll0 method: " + entry);
+                         catch (ClusterTopologyCheckedException e) {
+                             entry.context().evicts().touch(entry, topologyVersion());
+ 
+                             throw e;
                          }
                      }
-                 }
-                 else {
-                     if (entryProcessor == null && txEntry.op() == TRANSFORM)
-                         throw new IgniteCheckedException("Failed to enlist write value for key (cannot have update value in " +
-                             "transaction after EntryProcessor is applied): " + key);
- 
-                     GridCacheEntryEx entry = txEntry.cached();
+                     else
+                         old = retval ? entry.rawGetOrUnmarshal(false) : entry.rawGet();
  
-                     CacheObject v = txEntry.value();
+                     if (old != null && hasFilters && !filter(entry.context(), cacheKey, old, filter)) {
+                         ret.set(cacheCtx, old, false);
  
-                     boolean del = txEntry.op() == DELETE && rmv;
+                         if (!readCommitted()) {
+                             // Enlist failed filters as reads for non-read-committed mode,
+                             // so future ops will get the same values.
+                             txEntry = addEntry(READ,
+                                 old,
+                                 null,
+                                 null,
+                                 entry,
+                                 null,
+                                 CU.empty0(),
+                                 false,
+                                 -1L,
+                                 -1L,
+                                 null,
+                                 skipStore);
  
-                     if (!del) {
-                         if (hasFilters && !filter(entry.context(), cacheKey, v, filter)) {
-                             skipped = skip(skipped, cacheKey);
+                             txEntry.markValid();
  
-                             ret.set(cacheCtx, v, false, keepBinary);
+                             if (needReadVer) {
+                                 assert readVer != null;
  
-                             continue;
+                                 txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
+                             }
                          }
  
-                         GridCacheOperation op = rmv ? DELETE : entryProcessor != null ? TRANSFORM :
-                             v != null ? UPDATE : CREATE;
+                         if (readCommitted())
+                             cacheCtx.evicts().touch(entry, topologyVersion());
  
-                         txEntry = addEntry(op,
-                             cacheCtx.toCacheObject(val),
-                             entryProcessor,
-                             invokeArgs,
-                             entry,
-                             expiryPlc,
-                             filter,
-                             true,
-                             drTtl,
-                             drExpireTime,
-                             drVer,
-                             skipStore,
-                             keepBinary);
+                         break; // While.
+                     }
+ 
+                     final GridCacheOperation op = lockOnly ? NOOP : rmv ? DELETE :
+                         entryProcessor != null ? TRANSFORM : old != null ? UPDATE : CREATE;
+ 
+                     txEntry = addEntry(op,
+                         cacheCtx.toCacheObject(val),
+                         entryProcessor,
+                         invokeArgs,
+                         entry,
+                         expiryPlc,
+                         filter,
+                         true,
+                         drTtl,
+                         drExpireTime,
+                         drVer,
+                         skipStore);
  
+                     if (!implicit() && readCommitted() && !cacheCtx.offheapTiered())
+                         cacheCtx.evicts().touch(entry, topologyVersion());
+ 
+                     if (enlisted != null)
                          enlisted.add(cacheKey);
  
-                         if (txEntry.op() == TRANSFORM) {
-                             GridCacheVersion ver;
+                     if (!pessimistic() && !implicit()) {
+                         txEntry.markValid();
  
-                             try {
-                                 ver = entry.version();
-                             }
-                             catch (GridCacheEntryRemovedException e) {
-                                 assert optimistic() : txEntry;
+                         if (old == null) {
+                             if (needVal)
+                                 loadMissed = true;
+                             else {
+                                 assert !implicit() || !transform : this;
+                                 assert txEntry.op() != TRANSFORM : txEntry;
  
-                                 if (log.isDebugEnabled())
-                                     log.debug("Failed to get entry version: [msg=" + e.getMessage() + ']');
+                                 if (retval)
+                                     ret.set(cacheCtx, null, true);
+                                 else
+                                     ret.success(true);
+                             }
+                         }
+                         else {
+                             if (needReadVer) {
+                                 assert readVer != null;
  
-                                 ver = null;
+                                 txEntry.serializableReadVersion(singleRmv ? SER_READ_NOT_EMPTY_VER : readVer);
                              }
  
-                             addInvokeResult(txEntry, txEntry.value(), ret, ver);
-                         }
-                     }
+                             if (retval && !transform)
+                                 ret.set(cacheCtx, old, true);
+                             else {
+                                 if (txEntry.op() == TRANSFORM) {
+                                     GridCacheVersion ver;
  
-                     if (!pessimistic()) {
-                         txEntry.markValid();
+                                     try {
+                                         ver = entry.version();
+                                     }
+                                     catch (GridCacheEntryRemovedException ex) {
+                                         assert optimistic() : txEntry;
  
+                                         if (log.isDebugEnabled())
+                                             log.debug("Failed to get entry version " +
+                                                 "[err=" + ex.getMessage() + ']');
+ 
+                                         ver = null;
+                                     }
+ 
+                                     addInvokeResult(txEntry, old, ret, ver);
+                                 }
+                                 else
+                                     ret.success(true);
+                             }
+                         }
+                     }
+                     // Pessimistic.
+                     else {
                          if (retval && !transform)
-                             ret.set(cacheCtx, v, true, keepBinary);
+                             ret.set(cacheCtx, old, true);
                          else
                              ret.success(true);
                      }
@@@ -2829,19 -3081,15 +3101,16 @@@
                  drMap,
                  null,
                  opCtx != null && opCtx.skipStore(),
 -                false);
 +                false,
 +                opCtx != null && opCtx.isKeepBinary());
  
              if (pessimistic()) {
-                 // Loose all skipped.
-                 final Set<KeyCacheObject> loaded = loadFut.get();
- 
-                 final Collection<KeyCacheObject> keys = F.view(enlisted, F0.notIn(loaded));
+                 assert loadFut == null || loadFut.isDone() : loadFut;
  
                  if (log.isDebugEnabled())
-                     log.debug("Before acquiring transaction lock for put on keys: " + keys);
+                     log.debug("Before acquiring transaction lock for put on keys: " + enlisted);
  
-                 IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(keys,
+                 IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(enlisted,
                      lockTimeout(),
                      this,
                      false,
@@@ -3029,141 -3292,131 +3313,132 @@@
  
          init();
  
-         try {
-             Collection<KeyCacheObject> enlisted = new ArrayList<>();
- 
-             CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
+         final Collection<KeyCacheObject> enlisted = new ArrayList<>();
  
-             ExpiryPolicy plc;
+         CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
  
-             if (!F.isEmpty(filter))
-                 plc = opCtx != null ? opCtx.expiry() : null;
-             else
-                 plc = null;
+         ExpiryPolicy plc;
  
-             final IgniteInternalFuture<Set<KeyCacheObject>> loadFut = enlistWrite(
-                 cacheCtx,
-                 keys0,
-                 plc,
-                 implicit,
-                 /** lookup map */null,
-                 /** invoke map */null,
-                 /** invoke arguments */null,
-                 retval,
-                 /** lock only */false,
-                 filter,
-                 ret,
-                 enlisted,
-                 null,
-                 drMap,
-                 opCtx != null && opCtx.skipStore(),
-                 singleRmv,
-                 opCtx != null && opCtx.isKeepBinary()
-             );
+         if (!F.isEmpty(filter))
+             plc = opCtx != null ? opCtx.expiry() : null;
+         else
+             plc = null;
  
-             if (log.isDebugEnabled())
-                 log.debug("Remove keys: " + enlisted);
+         final IgniteInternalFuture<Void> loadFut = enlistWrite(
+             cacheCtx,
+             keys0,
+             plc,
+             /** lookup map */null,
+             /** invoke map */null,
+             /** invoke arguments */null,
+             retval,
+             /** lock only */false,
+             filter,
+             ret,
+             enlisted,
+             null,
+             drMap,
+             opCtx != null && opCtx.skipStore(),
 -            singleRmv
++            singleRmv,
++            opCtx != null && opCtx.isKeepBinary()
+         );
  
-             // Acquire locks only after having added operation to the write set.
-             // Otherwise, during rollback we will not know whether locks need
-             // to be rolled back.
-             if (pessimistic()) {
-                 // Loose all skipped.
-                 final Collection<KeyCacheObject> passedKeys = F.view(enlisted, F0.notIn(loadFut.get()));
+         if (log.isDebugEnabled())
+             log.debug("Remove keys: " + enlisted);
  
-                 if (log.isDebugEnabled())
-                     log.debug("Before acquiring transaction lock for remove on keys: " + passedKeys);
+         // Acquire locks only after having added operation to the write set.
+         // Otherwise, during rollback we will not know whether locks need
+         // to be rolled back.
+         if (pessimistic()) {
+             assert loadFut.isDone() : loadFut;
  
-                 IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(passedKeys,
-                     lockTimeout(),
-                     this,
-                     false,
-                     retval,
-                     isolation,
-                     isInvalidate(),
-                     -1L);
+             if (log.isDebugEnabled())
+                 log.debug("Before acquiring transaction lock for remove on keys: " + enlisted);
  
-                 PLC1<GridCacheReturn> plc1 = new PLC1<GridCacheReturn>(ret) {
-                     @Override protected GridCacheReturn postLock(GridCacheReturn ret)
-                         throws IgniteCheckedException
-                     {
-                         if (log.isDebugEnabled())
-                             log.debug("Acquired transaction lock for remove on keys: " + passedKeys);
+             IgniteInternalFuture<Boolean> fut = cacheCtx.cache().txLockAsync(enlisted,
+                 lockTimeout(),
+                 this,
+                 false,
+                 retval,
+                 isolation,
+                 isInvalidate(),
+                 -1L);
+ 
+             PLC1<GridCacheReturn> plc1 = new PLC1<GridCacheReturn>(ret) {
+                 @Override protected GridCacheReturn postLock(GridCacheReturn ret)
+                     throws IgniteCheckedException
+                 {
+                     if (log.isDebugEnabled())
+                         log.debug("Acquired transaction lock for remove on keys: " + enlisted);
  
-                         postLockWrite(cacheCtx,
-                             passedKeys,
-                             loadFut.get(),
-                             ret,
+                     postLockWrite(cacheCtx,
+                         enlisted,
+                         ret,
                              /*remove*/true,
-                             retval,
+                         retval,
                              /*read*/false,
-                             -1L,
-                             filter,
+                         -1L,
+                         filter,
                              /*computeInvoke*/false);
  
-                         return ret;
-                     }
-                 };
+                     return ret;
+                 }
+             };
  
-                 if (fut.isDone()) {
+             if (fut.isDone()) {
+                 try {
+                     return nonInterruptable(plc1.apply(fut.get(), null));
+                 }
+                 catch (GridClosureException e) {
+                     return new GridFinishedFuture<>(e.unwrap());
+                 }
+                 catch (IgniteCheckedException e) {
                      try {
-                         return nonInterruptable(plc1.apply(fut.get(), null));
+                         return nonInterruptable(plc1.apply(false, e));
                      }
-                     catch (GridClosureException e) {
-                         return new GridFinishedFuture<>(e.unwrap());
-                     }
-                     catch (IgniteCheckedException e) {
-                         try {
-                             return nonInterruptable(plc1.apply(false, e));
-                         }
-                         catch (Exception e1) {
-                             return new GridFinishedFuture<>(e1);
-                         }
+                     catch (Exception e1) {
+                         return new GridFinishedFuture<>(e1);
                      }
                  }
-                 else
-                     return nonInterruptable(new GridEmbeddedFuture<>(
-                         fut,
-                         plc1
-                     ));
              }
-             else {
-                 if (implicit()) {
-                     // Should never load missing values for implicit transaction as values will be returned
-                     // with prepare response, if required.
-                     assert loadFut.isDone();
- 
-                     return nonInterruptable(commitAsync().chain(new CX1<IgniteInternalFuture<IgniteInternalTx>, GridCacheReturn>() {
-                         @Override public GridCacheReturn applyx(IgniteInternalFuture<IgniteInternalTx> txFut)
-                             throws IgniteCheckedException {
-                             try {
-                                 txFut.get();
+             else
+                 return nonInterruptable(new GridEmbeddedFuture<>(
+                     fut,
+                     plc1
+                 ));
+         }
+         else {
+             if (implicit()) {
+                 // Should never load missing values for implicit transaction as values will be returned
+                 // with prepare response, if required.
+                 assert loadFut.isDone();
  
-                                 return implicitRes;
-                             }
-                             catch (IgniteCheckedException | RuntimeException e) {
-                                 rollbackAsync();
+                 return nonInterruptable(commitAsync().chain(new CX1<IgniteInternalFuture<IgniteInternalTx>, GridCacheReturn>() {
+                     @Override public GridCacheReturn applyx(IgniteInternalFuture<IgniteInternalTx> txFut)
+                         throws IgniteCheckedException {
+                         try {
+                             txFut.get();
  
-                                 throw e;
-                             }
+                             return implicitRes;
                          }
-                     }));
-                 }
-                 else
-                     return nonInterruptable(loadFut.chain(new CX1<IgniteInternalFuture<Set<KeyCacheObject>>, GridCacheReturn>() {
-                         @Override public GridCacheReturn applyx(IgniteInternalFuture<Set<KeyCacheObject>> f)
-                             throws IgniteCheckedException {
-                             f.get();
+                         catch (IgniteCheckedException | RuntimeException e) {
+                             rollbackAsync();
  
-                             return ret;
+                             throw e;
                          }
-                     }));
+                     }
+                 }));
              }
-         }
-         catch (IgniteCheckedException e) {
-             setRollbackOnly();
+             else {
+                 return nonInterruptable(loadFut.chain(new CX1<IgniteInternalFuture<Void>, GridCacheReturn>() {
+                     @Override public GridCacheReturn applyx(IgniteInternalFuture<Void> f)
+                         throws IgniteCheckedException {
+                         f.get();
  
-             return new GridFinishedFuture<>(e);
+                         return ret;
+                     }
+                 }));
+             }
          }
      }
  

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalEx.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
----------------------------------------------------------------------
diff --cc modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
index db44fac,99b2423..dfa4cbc
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
@@@ -74,21 -76,6 +76,11 @@@ public class IgniteSqlQueryPutBenchmar
          return true;
      }
  
 +    /** {@inheritDoc} */
 +    @Override public void onWarmupFinished() {
 +        super.onWarmupFinished();
- 
-         resCnt.reset();
-         cnt.reset();
-     }
- 
-     /** {@inheritDoc} */
-     @Override public void tearDown() throws Exception {
-         ignite().log().info("Average number of entries per query: " + ((double)resCnt.longValue() / cnt.longValue()));
- 
-         super.tearDown();
 +    }
 +
      /**
       * @param minSalary Min salary.
       * @param maxSalary Max salary.

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/parent/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/3d4ce809/pom.xml
----------------------------------------------------------------------
diff --cc pom.xml
index 68e57c6,1008981..115df88
--- a/pom.xml
+++ b/pom.xml
@@@ -73,10 -73,14 +73,13 @@@
          <module>modules/cloud</module>
          <module>modules/mesos</module>
          <module>modules/kafka</module>
+         <module>modules/flume</module>
          <module>modules/yarn</module>
          <module>modules/jms11</module>
+         <module>modules/twitter</module>
          <module>modules/mqtt</module>
          <module>modules/zookeeper</module>
+         <module>modules/camel</module>
 -        <module>modules/platform</module>
      </modules>
  
      <profiles>


[02/37] ignite git commit: ignite-1865: Need to add tests on SpringResource annotation

Posted by ag...@apache.org.
ignite-1865: Need to add tests on SpringResource annotation


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

Branch: refs/heads/ignite-1282
Commit: db221f52ef895d475e399f8cec49b75aeba4817d
Parents: dc32789
Author: Roman Shtykh <ap...@gmail.com>
Authored: Mon Nov 16 14:34:24 2015 +0300
Committer: dmagda <ma...@gmail.com>
Committed: Mon Nov 16 14:34:24 2015 +0300

----------------------------------------------------------------------
 .../GridSpringResourceInjectionSelfTest.java    | 143 +++++++++++++++++++
 .../processors/resource/spring-resource.xml     |  27 ++++
 .../testsuites/IgniteResourceSelfTestSuite.java |   2 +
 3 files changed, 172 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/db221f52/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
new file mode 100644
index 0000000..968c8c4
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.resource;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteSpring;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.resources.SpringResource;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Tests for injected resource.
+ */
+public class GridSpringResourceInjectionSelfTest extends GridCommonAbstractTest {
+    /** Bean name. */
+    private static final String DUMMY_BEAN = "dummyResourceBean";
+
+    /** Test grid with Spring context. */
+    private static Ignite grid;
+
+    /** {@inheritDoc} */
+    @Override public void beforeTestsStarted() throws Exception {
+        grid = IgniteSpring.start(new ClassPathXmlApplicationContext(
+            "/org/apache/ignite/internal/processors/resource/spring-resource.xml"));
+    }
+
+    /** {@inheritDoc} */
+    @Override public void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testClosureField() throws Exception {
+        grid.compute().call(new IgniteCallable<Object>() {
+            @SpringResource(resourceName = DUMMY_BEAN)
+            private transient DummyResourceBean dummyResourceBean;
+
+            @Override public Object call() throws Exception {
+                assertNotNull(dummyResourceBean);
+
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Resource injection with non-existing resource name.
+     */
+    public void testClosureFieldWithWrongResourceName() throws Exception {
+        try {
+            grid.compute().call(new IgniteCallable<Object>() {
+                @SpringResource(resourceName = "")
+                private transient DummyResourceBean dummyResourceBean;
+
+                @Override public Object call() throws Exception {
+                    assertNull(dummyResourceBean);
+
+                    return null;
+                }
+            });
+        }
+        catch (IgniteException e) {
+            if (e.getMessage().contains("No bean named '' is defined"))
+                return;
+        }
+
+        fail();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testClosureMethod() throws Exception {
+        grid.compute().call(new IgniteCallable<Object>() {
+            private DummyResourceBean dummyResourceBean;
+
+            @SpringResource(resourceName = DUMMY_BEAN)
+            private void setDummyResourceBean(DummyResourceBean dummyResourceBean) {
+                assertNotNull(dummyResourceBean);
+
+                this.dummyResourceBean = dummyResourceBean;
+            }
+
+            @Override public Object call() throws Exception {
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Resource injection with non-existing resource name.
+     */
+    public void testClosureMethodWithWrongResourceName() throws Exception {
+        try {
+            grid.compute().call(new IgniteCallable<Object>() {
+                private DummyResourceBean dummyResourceBean;
+
+                @SpringResource(resourceName = "")
+                private void setDummyResourceBean(DummyResourceBean dummyResourceBean) {
+                }
+
+                @Override public Object call() throws Exception {
+                    assertNull(dummyResourceBean);
+
+                    return null;
+                }
+            });
+        }
+        catch (IgniteException e) {
+            if (e.getMessage().contains("No bean named '' is defined"))
+                return;
+        }
+
+        fail();
+    }
+
+    /**
+     * Dummy resource bean.
+     */
+    public static class DummyResourceBean {
+        public DummyResourceBean() {
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/db221f52/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
new file mode 100644
index 0000000..3abb521
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+    	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+    <bean id="dummyResourceBean"
+          class="org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean">
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/db221f52/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteResourceSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteResourceSelfTestSuite.java b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteResourceSelfTestSuite.java
index 5ad93e8..742190b 100644
--- a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteResourceSelfTestSuite.java
+++ b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteResourceSelfTestSuite.java
@@ -21,6 +21,7 @@ import junit.framework.TestSuite;
 import org.apache.ignite.internal.processors.resource.GridLoggerInjectionSelfTest;
 import org.apache.ignite.internal.processors.resource.GridResourceProcessorSelfTest;
 import org.apache.ignite.internal.processors.resource.GridServiceInjectionSelfTest;
+import org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest;
 
 /**
  * Ignite resource injection test Suite.
@@ -37,6 +38,7 @@ public class IgniteResourceSelfTestSuite extends TestSuite {
         suite.addTest(new TestSuite(GridResourceProcessorSelfTest.class));
         suite.addTest(new TestSuite(GridLoggerInjectionSelfTest.class));
         suite.addTest(new TestSuite(GridServiceInjectionSelfTest.class));
+        suite.addTest(new TestSuite(GridSpringResourceInjectionSelfTest.class));
 
         return suite;
     }


[10/37] ignite git commit: IGNITE-529 Rat fail fix

Posted by ag...@apache.org.
 IGNITE-529 Rat fail fix


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

Branch: refs/heads/ignite-1282
Commit: 4c9ea5864e731a876673d6d3cda3639ef4d421fa
Parents: 3ff71fd
Author: Anton Vinogradov <av...@apache.org>
Authored: Wed Nov 18 11:16:47 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Wed Nov 18 11:16:47 2015 +0300

----------------------------------------------------------------------
 parent/pom.xml | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4c9ea586/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 765ecf1..cb7c533 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -680,6 +680,7 @@
                                         <exclude>**/licenses/*.txt</exclude><!--files of licenses-->
                                         <exclude>**/*readme*.txt</exclude><!--readme files-->
                                         <exclude>**/*README*.txt</exclude><!--readme files-->
+                                        <exclude>**/*README*.md</exclude><!--readme files-->
                                         <exclude>**/*.timestamp</exclude><!--tmp-files-->
                                         <exclude>**/*.iml</exclude><!--IDEA files-->
                                         <exclude>**/pom-installed.xml</exclude><!--tmp-files-->


[29/37] ignite git commit: IGNITE-426 Implemented failover for Continuous query.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
index 46a5f8c..5f5dfd4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
@@ -75,6 +75,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
 import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.LOCAL;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheMode.REPLICATED;
 import static org.apache.ignite.cache.CacheRebalanceMode.ASYNC;
@@ -192,12 +193,6 @@ public abstract class GridCacheContinuousQueryAbstractSelfTest extends GridCommo
             }
         }
 
-        for (int i = 0; i < gridCount(); i++)
-            assertEquals("Cache is not empty [entrySet=" + grid(i).cache(null).localEntries() +
-                ", i=" + i + ']',
-                0, grid(i).cache(null).localSize());
-
-
         for (int i = 0; i < gridCount(); i++) {
             GridContinuousProcessor proc = grid(i).context().continuous();
 
@@ -368,6 +363,114 @@ public abstract class GridCacheContinuousQueryAbstractSelfTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
+    public void testTwoQueryListener() throws Exception {
+        if (cacheMode() == LOCAL)
+            return;
+
+        IgniteCache<Integer, Integer> cache = grid(0).cache(null);
+        IgniteCache<Integer, Integer> cache1 = grid(1).cache(null);
+
+        final AtomicInteger cntr = new AtomicInteger(0);
+        final AtomicInteger cntr1 = new AtomicInteger(0);
+
+        ContinuousQuery<Integer, Integer> qry1 = new ContinuousQuery<>();
+        ContinuousQuery<Integer, Integer> qry2 = new ContinuousQuery<>();
+
+        qry1.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
+            @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> evts) {
+                for (CacheEntryEvent<? extends Integer, ? extends Integer> ignore : evts)
+                    cntr.incrementAndGet();
+            }
+        });
+
+        qry2.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
+            @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> evts) {
+                for (CacheEntryEvent<? extends Integer, ? extends Integer> ignore : evts)
+                    cntr1.incrementAndGet();
+            }
+        });
+
+        try (QueryCursor<Cache.Entry<Integer, Integer>> query2 = cache1.query(qry2);
+            QueryCursor<Cache.Entry<Integer, Integer>> query1 = cache.query(qry1)) {
+            for (int i = 0; i < gridCount(); i++) {
+                IgniteCache<Object, Object> cache0 = grid(i).cache(null);
+
+                cache0.put(1, 1);
+                cache0.put(2, 2);
+                cache0.put(3, 3);
+
+                cache0.remove(1);
+                cache0.remove(2);
+                cache0.remove(3);
+
+                final int iter = i + 1;
+
+                assert GridTestUtils.waitForCondition(new PA() {
+                    @Override public boolean apply() {
+                        return iter * 6 /* count operation */ * 2 /* count continues queries*/
+                            == (cntr.get() + cntr1.get());
+                    }
+                }, 5000L);
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRestartQuery() throws Exception {
+        if (cacheMode() == LOCAL)
+            return;
+
+        IgniteCache<Integer, Integer> cache = grid(0).cache(null);
+
+        final int parts = grid(0).affinity(null).partitions();
+
+        final int keyCnt = parts * 2;
+
+        for (int i = 0; i < parts / 2; i++)
+            cache.put(i, i);
+
+        for (int i = 0; i < 10; i++) {
+            if (i % 2 == 0) {
+                final AtomicInteger cntr = new AtomicInteger(0);
+
+                ContinuousQuery<Integer, Integer> qry = new ContinuousQuery<>();
+
+                qry.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
+                    @Override public void onUpdated(
+                        Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> evts) {
+                        for (CacheEntryEvent<? extends Integer, ? extends Integer> ignore : evts)
+                            cntr.incrementAndGet();
+                    }
+                });
+
+                QueryCursor<Cache.Entry<Integer, Integer>> query = cache.query(qry);
+
+                for (int key = 0; key < keyCnt; key++)
+                    cache.put(key, key);
+
+                try {
+                    assert GridTestUtils.waitForCondition(new PA() {
+                        @Override public boolean apply() {
+                            return cntr.get() == keyCnt;
+                        }
+                    }, 2000L);
+                }
+                finally {
+                    query.close();
+                }
+            }
+            else {
+                for (int key = 0; key < keyCnt; key++)
+                    cache.put(key, key);
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testEntriesByFilter() throws Exception {
         IgniteCache<Integer, Integer> cache = grid(0).cache(null);
 
@@ -852,44 +955,6 @@ public abstract class GridCacheContinuousQueryAbstractSelfTest extends GridCommo
     /**
      * @throws Exception If failed.
      */
-    public void testNodeJoin() throws Exception {
-        IgniteCache<Integer, Integer> cache = grid(0).cache(null);
-
-        ContinuousQuery<Integer, Integer> qry = new ContinuousQuery<>();
-
-        final Collection<CacheEntryEvent<? extends Integer, ? extends Integer>> all = new ConcurrentLinkedDeque8<>();
-        final CountDownLatch latch = new CountDownLatch(30);
-
-        qry.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
-            @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> evts) {
-                for (CacheEntryEvent<? extends Integer, ? extends Integer> evt : evts)
-                    all.add(evt);
-
-                latch.countDown();
-            }
-        });
-
-        try (QueryCursor<Cache.Entry<Integer, Integer>> ignored = cache.query(qry)) {
-            cache.put(0, 0);
-
-            startGrid("anotherGrid");
-
-            for (int i = 1; i < 30; i++) {
-                cache.put(i, i);
-            }
-
-            assert latch.await(LATCH_TIMEOUT, MILLISECONDS) : all;
-
-            assertEquals(30, all.size());
-        }
-        finally {
-            stopGrid("anotherGrid");
-        }
-    }
-
-    /**
-     * @throws Exception If failed.
-     */
     @SuppressWarnings("TryFinallyCanBeTryWithResources")
     public void testNodeJoinWithoutCache() throws Exception {
         IgniteCache<Integer, Integer> cache = grid(0).cache(null);

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryTxSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryTxSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryTxSelfTest.java
new file mode 100644
index 0000000..91b6b9c
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryTxSelfTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ * Continuous queries tests for atomic cache.
+ */
+public class GridCacheContinuousQueryTxSelfTest extends GridCacheContinuousQueryPartitionedSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return TRANSACTIONAL;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.REPLICATED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected NearCacheConfiguration nearConfiguration() {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void testInternalKey() throws Exception {
+        // No-op.
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientReconnectTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientReconnectTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientReconnectTest.java
new file mode 100644
index 0000000..2e1d78d
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientReconnectTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.query.continuous;
+
+import java.util.concurrent.CountDownLatch;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteClientReconnectAbstractTest;
+import org.apache.ignite.resources.LoggerResource;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheContinuousQueryClientReconnectTest extends IgniteClientReconnectAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected int serverCount() {
+        return 4;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected int clientCount() {
+        return 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        CacheConfiguration ccfg = new CacheConfiguration();
+
+        ccfg.setCacheMode(PARTITIONED);
+        ccfg.setAtomicityMode(atomicMode());
+        ccfg.setWriteSynchronizationMode(FULL_SYNC);
+
+        cfg.setCacheConfiguration(ccfg);
+
+        return cfg;
+    }
+
+    /**
+     * @return Atomic mode.
+     */
+    protected CacheAtomicityMode atomicMode() {
+        return ATOMIC;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testReconnectClient() throws Exception {
+        Ignite client = grid(serverCount());
+
+        Ignite srv = clientRouter(client);
+
+        assertTrue(client.cluster().localNode().isClient());
+
+        final CacheEventListener lsnr = new CacheEventListener();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        IgniteCache<Object, Object> clnCache = client.cache(null);
+
+        QueryCursor<?> cur = clnCache.query(qry);
+
+        int keyCnt = 100;
+
+        for (int i = 0; i < 10; i++) {
+            lsnr.latch = new CountDownLatch(keyCnt);
+
+            for (int key = 0; key < keyCnt; key++)
+                clnCache.put(key, key);
+
+            assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+
+            reconnectClientNode(client, srv, null);
+
+            lsnr.latch = new CountDownLatch(keyCnt);
+
+            for (int key = 0; key < keyCnt; key++)
+                clnCache.put(key, key);
+
+            assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+        }
+
+        cur.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testReconnectClientAndLeftRouter() throws Exception {
+        Ignite client = grid(serverCount());
+
+        final Ignite srv = clientRouter(client);
+
+        final String clnRouterName = srv.name();
+
+        assertTrue(client.cluster().localNode().isClient());
+
+        final CacheEventListener lsnr = new CacheEventListener();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        IgniteCache<Object, Object> clnCache = client.cache(null);
+
+        QueryCursor<?> cur = clnCache.query(qry);
+
+        int keyCnt = 100;
+
+        lsnr.latch = new CountDownLatch(keyCnt);
+
+        for (int key = 0; key < keyCnt; key++)
+            clnCache.put(key, key);
+
+        assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+
+        reconnectClientNode(client, srv, new Runnable() {
+            @Override public void run() {
+                stopGrid(clnRouterName);
+            }
+        });
+
+        assertFalse("Client connected to the same server node.", clnRouterName.equals(clientRouter(client).name()));
+
+        lsnr.latch = new CountDownLatch(keyCnt);
+
+        for (int key = 0; key < keyCnt; key++)
+            clnCache.put(key, key);
+
+        assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+
+        cur.close();
+    }
+
+    /**
+     *
+     */
+    private static class CacheEventListener implements CacheEntryUpdatedListener<Object, Object> {
+        /** */
+        private volatile CountDownLatch latch = new CountDownLatch(1);
+
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /** {@inheritDoc} */
+        @Override public void onUpdated(Iterable<CacheEntryEvent<?, ?>> evts) {
+            for (CacheEntryEvent<?, ?> evt : evts) {
+                log.info("Received cache event: " + evt);
+
+                latch.countDown();
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTest.java
index 1afeb05..534f298 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTest.java
@@ -27,11 +27,13 @@ import org.apache.ignite.cache.query.ContinuousQuery;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.lang.IgniteOutClosure;
 import org.apache.ignite.resources.LoggerResource;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -83,11 +85,13 @@ public class IgniteCacheContinuousQueryClientTest extends GridCommonAbstractTest
 
         client = true;
 
-        Ignite clientNode = startGrid(3);
+        final int CLIENT_ID = 3;
+
+        Ignite clientNode = startGrid(CLIENT_ID);
 
         client = false;
 
-        CacheEventListener lsnr = new CacheEventListener();
+        final CacheEventListener lsnr = new CacheEventListener();
 
         ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
 
@@ -95,27 +99,154 @@ public class IgniteCacheContinuousQueryClientTest extends GridCommonAbstractTest
 
         QueryCursor<?> cur = clientNode.cache(null).query(qry);
 
-        Ignite joined1 = startGrid(4);
+        for (int i = 0; i < 10; i++) {
+            log.info("Start iteration: " + i);
+
+            lsnr.latch = new CountDownLatch(1);
+
+            Ignite joined1 = startGrid(4);
+
+            IgniteCache<Object, Object> joinedCache1 = joined1.cache(null);
+
+            joinedCache1.put(primaryKey(joinedCache1), 1);
+
+            assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+
+            lsnr.latch = new CountDownLatch(1);
+
+            Ignite joined2 = startGrid(5);
+
+            IgniteCache<Object, Object> joinedCache2 = joined2.cache(null);
 
-        IgniteCache<Object, Object> joinedCache1 = joined1.cache(null);
+            joinedCache2.put(primaryKey(joinedCache2), 2);
 
-        joinedCache1.put(primaryKey(joinedCache1), 1);
+            assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
 
-        assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+            stopGrid(4);
+
+            stopGrid(5);
+        }
 
         cur.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNodeJoinsRestartQuery() throws Exception {
+        startGrids(2);
+
+        client = true;
+
+        final int CLIENT_ID = 3;
+
+        Ignite clientNode = startGrid(CLIENT_ID);
+
+        client = false;
+
+        for (int i = 0; i < 10; i++) {
+            log.info("Start iteration: " + i);
+
+            final CacheEventListener lsnr = new CacheEventListener();
+
+            ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+            qry.setLocalListener(lsnr);
+
+            QueryCursor<?> cur = clientNode.cache(null).query(qry);
+
+            lsnr.latch = new CountDownLatch(1);
+
+            Ignite joined1 = startGrid(4);
+
+            IgniteCache<Object, Object> joinedCache1 = joined1.cache(null);
+
+            joinedCache1.put(primaryKey(joinedCache1), 1);
+
+            assertTrue("Failed to wait for event.", lsnr.latch.await(5, SECONDS));
+
+            cur.close();
 
-        lsnr.latch = new CountDownLatch(1);
+            lsnr.latch = new CountDownLatch(1);
 
-        Ignite joined2 = startGrid(5);
+            Ignite joined2 = startGrid(5);
 
-        IgniteCache<Object, Object> joinedCache2 = joined2.cache(null);
+            IgniteCache<Object, Object> joinedCache2 = joined2.cache(null);
 
-        joinedCache2.put(primaryKey(joinedCache2), 2);
+            joinedCache2.put(primaryKey(joinedCache2), 2);
 
-        U.sleep(1000);
+            assertFalse("Unexpected event received.", GridTestUtils.waitForCondition(new GridAbsPredicate() {
+                @Override public boolean apply() {
+                    return 1 != lsnr.latch.getCount();
+                }
+            }, 1000));
 
-        assertEquals("Unexpected event received.", 1, lsnr.latch.getCount());
+            stopGrid(4);
+
+            stopGrid(5);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testServerNodeLeft() throws Exception {
+        startGrids(3);
+
+        client = true;
+
+        final int CLIENT_ID = 3;
+
+        Ignite clnNode = startGrid(CLIENT_ID);
+
+        client = false;
+
+        IgniteOutClosure<IgniteCache<Integer, Integer>> rndCache =
+            new IgniteOutClosure<IgniteCache<Integer, Integer>>() {
+                int cnt = 0;
+
+                @Override public IgniteCache<Integer, Integer> apply() {
+                    ++cnt;
+
+                    return grid(CLIENT_ID).cache(null);
+                }
+            };
+
+        final CacheEventListener lsnr = new CacheEventListener();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        QueryCursor<?> cur = clnNode.cache(null).query(qry);
+
+        boolean first = true;
+
+        int keyCnt = 1;
+
+        for (int i = 0; i < 10; i++) {
+            log.info("Start iteration: " + i);
+
+            if (first)
+                first = false;
+            else {
+                for (int srv = 0; srv < CLIENT_ID - 1; srv++)
+                    startGrid(srv);
+            }
+
+            lsnr.latch = new CountDownLatch(keyCnt);
+
+            for (int key = 0; key < keyCnt; key++)
+                rndCache.apply().put(key, key);
+
+            assertTrue("Failed to wait for event. Left events: " + lsnr.latch.getCount(),
+                lsnr.latch.await(10, SECONDS));
+
+            for (int srv = 0; srv < CLIENT_ID - 1; srv++)
+                stopGrid(srv);
+        }
+
+        cur.close();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTxReconnectTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTxReconnectTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTxReconnectTest.java
new file mode 100644
index 0000000..a10ebc9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/IgniteCacheContinuousQueryClientTxReconnectTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ *
+ */
+public class IgniteCacheContinuousQueryClientTxReconnectTest extends IgniteCacheContinuousQueryClientReconnectTest {
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicMode() {
+        return TRANSACTIONAL;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PSameClassLoaderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PSameClassLoaderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PSameClassLoaderSelfTest.java
index 108b11d..ba5e15b 100644
--- a/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PSameClassLoaderSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/p2p/GridP2PSameClassLoaderSelfTest.java
@@ -23,7 +23,11 @@ import java.net.URLClassLoader;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.configuration.DeploymentMode;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.PA;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.config.GridTestProperties;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.testframework.junits.common.GridCommonTest;
@@ -41,6 +45,9 @@ public class GridP2PSameClassLoaderSelfTest extends GridCommonAbstractTest {
     private static final String TEST_TASK2_NAME = "org.apache.ignite.tests.p2p.P2PTestTaskExternalPath2";
 
     /** */
+    private static final TcpDiscoveryIpFinder FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
     private static final ClassLoader CLASS_LOADER;
 
     /** Current deployment mode. Used in {@link #getConfiguration(String)}. */
@@ -66,6 +73,7 @@ public class GridP2PSameClassLoaderSelfTest extends GridCommonAbstractTest {
         cfg.setDeploymentMode(depMode);
 
         ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setHeartbeatFrequency(500);
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(FINDER);
 
         cfg.setCacheConfiguration();
 
@@ -81,10 +89,16 @@ public class GridP2PSameClassLoaderSelfTest extends GridCommonAbstractTest {
     @SuppressWarnings({"unchecked"})
     private void processTest(boolean isIsolatedDifferentTask, boolean isIsolatedDifferentNode) throws Exception {
         try {
-            Ignite ignite1 = startGrid(1);
+            final Ignite ignite1 = startGrid(1);
             Ignite ignite2 = startGrid(2);
             Ignite ignite3 = startGrid(3);
 
+            assert GridTestUtils.waitForCondition(new PA() {
+                @Override public boolean apply() {
+                    return ignite1.cluster().nodes().size() == 3;
+                }
+            }, 20000L);
+
             Class task1 = CLASS_LOADER.loadClass(TEST_TASK1_NAME);
             Class task2 = CLASS_LOADER.loadClass(TEST_TASK2_NAME);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
index 3e41979..6f9c559 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/GridAbstractTest.java
@@ -1248,7 +1248,7 @@ public abstract class GridAbstractTest extends TestCase {
 
         if (isDebug()) {
             discoSpi.setMaxMissedHeartbeats(Integer.MAX_VALUE);
-            cfg.setNetworkTimeout(Long.MAX_VALUE);
+            cfg.setNetworkTimeout(Long.MAX_VALUE / 3);
         }
         else {
             // Set network timeout to 10 sec to avoid unexpected p2p class loading errors.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
index c19e718..e0ffc60 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
@@ -431,6 +431,9 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
             for (IgniteCacheProxy<?, ?> c : g0.context().cache().jcaches()) {
                 CacheConfiguration cfg = c.context().config();
 
+                if (cfg == null)
+                    continue;
+
                 if (cfg.getCacheMode() == PARTITIONED &&
                     cfg.getRebalanceMode() != NONE &&
                     g.cluster().nodes().size() > 1) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 6cb1a52..6cc2599 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -65,6 +65,10 @@ import org.apache.ignite.internal.processors.cache.local.IgniteCacheLocalAtomicQ
 import org.apache.ignite.internal.processors.cache.local.IgniteCacheLocalFieldsQuerySelfTest;
 import org.apache.ignite.internal.processors.cache.local.IgniteCacheLocalQuerySelfTest;
 import org.apache.ignite.internal.processors.cache.query.GridCacheSwapScanQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverAtomicReplicatedSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverTxReplicatedSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryFailoverTxSelfTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryAtomicNearEnabledSelfTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryAtomicP2PDisabledSelfTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryAtomicSelfTest;
@@ -77,7 +81,10 @@ import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheCon
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryReplicatedOneNodeSelfTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryReplicatedP2PDisabledSelfTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryReplicatedSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryTxSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.IgniteCacheContinuousQueryClientReconnectTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.IgniteCacheContinuousQueryClientTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.IgniteCacheContinuousQueryClientTxReconnectTest;
 import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryAtomicSelfTest;
 import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryLocalSelfTest;
 import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryPartitionedSelfTest;
@@ -157,11 +164,18 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         suite.addTestSuite(GridCacheContinuousQueryPartitionedSelfTest.class);
         suite.addTestSuite(GridCacheContinuousQueryPartitionedOnlySelfTest.class);
         suite.addTestSuite(GridCacheContinuousQueryPartitionedP2PDisabledSelfTest.class);
+        suite.addTestSuite(GridCacheContinuousQueryTxSelfTest.class);
         suite.addTestSuite(GridCacheContinuousQueryAtomicSelfTest.class);
         suite.addTestSuite(GridCacheContinuousQueryAtomicNearEnabledSelfTest.class);
         suite.addTestSuite(GridCacheContinuousQueryAtomicP2PDisabledSelfTest.class);
-        suite.addTestSuite(IgniteCacheContinuousQueryClientTest.class);
         suite.addTestSuite(GridCacheContinuousQueryReplicatedOneNodeSelfTest.class);
+        suite.addTestSuite(IgniteCacheContinuousQueryClientTest.class);
+        suite.addTestSuite(IgniteCacheContinuousQueryClientReconnectTest.class);
+        suite.addTestSuite(IgniteCacheContinuousQueryClientTxReconnectTest.class);
+        suite.addTestSuite(CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest.class);
+        suite.addTestSuite(CacheContinuousQueryFailoverAtomicReplicatedSelfTest.class);
+        suite.addTestSuite(CacheContinuousQueryFailoverTxSelfTest.class);
+        suite.addTestSuite(CacheContinuousQueryFailoverTxReplicatedSelfTest.class);
 
         // Reduce fields queries.
         suite.addTestSuite(GridCacheReduceFieldsQueryLocalSelfTest.class);

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
new file mode 100644
index 0000000..e42479a
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/CacheEntryEventProbe.java
@@ -0,0 +1,156 @@
+/*
+ * 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.yardstick.cache;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.yardstickframework.BenchmarkConfiguration;
+import org.yardstickframework.BenchmarkDriver;
+import org.yardstickframework.BenchmarkProbe;
+import org.yardstickframework.BenchmarkProbePoint;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static org.yardstickframework.BenchmarkUtils.errorHelp;
+import static org.yardstickframework.BenchmarkUtils.println;
+
+/**
+ * Probe which calculate continuous query events.
+ */
+public class CacheEntryEventProbe implements BenchmarkProbe {
+    /** */
+    private BenchmarkConfiguration cfg;
+
+    /** Counter. */
+    private AtomicLong cnt = new AtomicLong(0);
+
+    /** Collected points. */
+    private Collection<BenchmarkProbePoint> collected = new ArrayList<>();
+
+    /** Query cursor. */
+    private QueryCursor qryCur;
+
+    /** Service building probe points. */
+    private ExecutorService buildingService;
+
+    /** {@inheritDoc} */
+    @Override public void start(BenchmarkDriver drv, BenchmarkConfiguration cfg) throws Exception {
+        this.cfg = cfg;
+
+        if (drv instanceof IgniteCacheAbstractBenchmark) {
+            IgniteCacheAbstractBenchmark drv0 = (IgniteCacheAbstractBenchmark)drv;
+
+            if (drv0.cache() != null) {
+                ContinuousQuery<Integer, Integer> qry = new ContinuousQuery<>();
+
+                qry.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
+                    @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>>
+                        events) throws CacheEntryListenerException {
+                        int size = 0;
+
+                        for (CacheEntryEvent<? extends Integer, ? extends Integer> e : events)
+                            ++size;
+
+                        cnt.addAndGet(size);
+                    }
+                });
+
+                qryCur = drv0.cache().query(qry);
+
+                buildingService = Executors.newSingleThreadExecutor();
+
+                buildingService.submit(new Runnable() {
+                    @Override public void run() {
+                        try {
+                            while (!Thread.currentThread().isInterrupted()) {
+                                Thread.sleep(1000);
+
+                                long evts = cnt.getAndSet(0);
+
+                                BenchmarkProbePoint pnt = new BenchmarkProbePoint(
+                                    TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()),
+                                    new double[] {evts});
+
+                                collectPoint(pnt);
+                            }
+                        }
+                        catch (InterruptedException e) {
+                            // No-op.
+                        }
+                    }
+                });
+
+                println(cfg, getClass().getSimpleName() + " probe is started.");
+            }
+        }
+
+        if (qryCur == null)
+            errorHelp(cfg, "Can not start " + getClass().getSimpleName()
+                + " probe. Probably, the driver doesn't provide \"cache()\" method.");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() throws Exception {
+        if (qryCur != null) {
+            qryCur.close();
+
+            qryCur = null;
+
+            buildingService.shutdownNow();
+
+            buildingService.awaitTermination(1, MINUTES);
+
+            println(cfg, getClass().getSimpleName() + " is stopped.");
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<String> metaInfo() {
+        return Arrays.asList("Time, sec", "Received events/sec (more is better)");
+    }
+
+    /** {@inheritDoc} */
+    @Override public synchronized Collection<BenchmarkProbePoint> points() {
+        Collection<BenchmarkProbePoint> ret = collected;
+
+        collected = new ArrayList<>(ret.size() + 5);
+
+        return ret;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void buildPoint(long time) {
+        // No-op.
+    }
+
+    /**
+     * @param pnt Probe point.
+     */
+    private synchronized void collectPoint(BenchmarkProbePoint pnt) {
+        collected.add(pnt);
+    }
+}


[05/37] ignite git commit: IGNITE-529 Javadoc warning fix

Posted by ag...@apache.org.
 IGNITE-529 Javadoc warning fix


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

Branch: refs/heads/ignite-1282
Commit: 38e66d93fffce130437355062c5c9d314e48b23b
Parents: 9a5fc05
Author: Anton Vinogradov <av...@apache.org>
Authored: Tue Nov 17 18:39:23 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Tue Nov 17 18:39:23 2015 +0300

----------------------------------------------------------------------
 .../java/org/apache/ignite/stream/flume/EventTransformer.java    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/38e66d93/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java b/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
index e85a98b..913ebb4 100644
--- a/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
+++ b/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
@@ -22,12 +22,12 @@ import java.util.Map;
 import org.jetbrains.annotations.Nullable;
 
 /**
- * Flume event transformer to convert a list of Flume {@link Event} to cache entries.
+ * Flume event transformer to convert a list of Flume Events to cache entries.
  */
 public interface EventTransformer<Event, K, V> {
 
     /**
-     * Transforms a list of Flume {@link Event} to cache entries.
+     * Transforms a list of Flume Events to cache entries.
      *
      * @param events List of Flume events to transform.
      * @return Cache entries to be written into the grid.


[04/37] ignite git commit: IGNITE-529 Initial implementation

Posted by ag...@apache.org.
 IGNITE-529 Initial implementation


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

Branch: refs/heads/ignite-1282
Commit: 9a5fc056786494e748c982e0c766fa9842ba523e
Parents: b382062
Author: shtykh_roman <rs...@yahoo.com>
Authored: Tue Nov 17 17:38:12 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Tue Nov 17 17:38:12 2015 +0300

----------------------------------------------------------------------
 modules/flume/README.md                         |  40 ++++
 modules/flume/pom.xml                           |  77 ++++++++
 .../ignite/stream/flume/EventTransformer.java   |  36 ++++
 .../apache/ignite/stream/flume/IgniteSink.java  | 186 +++++++++++++++++++
 .../stream/flume/IgniteSinkConstants.java       |  35 ++++
 .../ignite/stream/flume/IgniteSinkTest.java     | 142 ++++++++++++++
 .../stream/flume/IgniteSinkTestSuite.java       |  37 ++++
 .../stream/flume/TestEventTransformer.java      |  66 +++++++
 .../flume/src/test/resources/example-ignite.xml |  71 +++++++
 pom.xml                                         |   1 +
 10 files changed, 691 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/README.md
----------------------------------------------------------------------
diff --git a/modules/flume/README.md b/modules/flume/README.md
new file mode 100644
index 0000000..2247cf3
--- /dev/null
+++ b/modules/flume/README.md
@@ -0,0 +1,40 @@
+#Flume NG sink
+
+## Setting up and running
+
+1. Create a transformer by implementing EventTransformer interface.
+2. Build it and copy to ${FLUME_HOME}/plugins.d/ignite-sink/lib.
+3. Copy other Ignite-related jar files to ${FLUME_HOME}/plugins.d/ignite-sink/libext to have them as shown below.
+
+```
+plugins.d/
+`-- ignite
+    |-- lib
+    |   `-- ignite-flume-transformer-x.x.x.jar <-- your jar
+    `-- libext
+        |-- cache-api-1.0.0.jar
+        |-- ignite-core-x.x.x.jar
+        |-- ignite-flume-x.x.x.jar
+        |-- ignite-spring-x.x.x.jar
+        |-- spring-aop-4.1.0.RELEASE.jar
+        |-- spring-beans-4.1.0.RELEASE.jar
+        |-- spring-context-4.1.0.RELEASE.jar
+        |-- spring-core-4.1.0.RELEASE.jar
+        `-- spring-expression-4.1.0.RELEASE.jar
+```
+
+4. In Flume configuration file, specify Ignite configuration XML file's location with cache properties
+(see [Apache Ignite](https://apacheignite.readme.io/) with cache name specified for cache creation,
+cache name (same as in Ignite configuration file), your EventTransformer's implementation class,
+and, optionally, batch size (default -- 100).
+
+```
+# Describe the sink
+a1.sinks.k1.type = org.apache.ignite.stream.flume.IgniteSink
+a1.sinks.k1.igniteCfg = /some-path/ignite.xml
+a1.sinks.k1.cacheName = testCache
+a1.sinks.k1.eventTransformer = my.company.MyEventTransformer
+a1.sinks.k1.batchSize = 100
+```
+
+After specifying your source and channel (see Flume's docs), you are ready to run a Flume agent.

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/pom.xml
----------------------------------------------------------------------
diff --git a/modules/flume/pom.xml b/modules/flume/pom.xml
new file mode 100644
index 0000000..cd4ee98
--- /dev/null
+++ b/modules/flume/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>ignite-flume</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <url>http://ignite.apache.org</url>
+
+    <properties>
+        <flume-ng.version>1.6.0</flume-ng.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.flume</groupId>
+            <artifactId>flume-ng-core</artifactId>
+            <version>${flume-ng.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-spring</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-log4j</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java b/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
new file mode 100644
index 0000000..e85a98b
--- /dev/null
+++ b/modules/flume/src/main/java/org/apache/ignite/stream/flume/EventTransformer.java
@@ -0,0 +1,36 @@
+/*
+ * 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.stream.flume;
+
+import java.util.List;
+import java.util.Map;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Flume event transformer to convert a list of Flume {@link Event} to cache entries.
+ */
+public interface EventTransformer<Event, K, V> {
+
+    /**
+     * Transforms a list of Flume {@link Event} to cache entries.
+     *
+     * @param events List of Flume events to transform.
+     * @return Cache entries to be written into the grid.
+     */
+    @Nullable Map<K, V> transform(List<Event> events);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSink.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSink.java b/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSink.java
new file mode 100644
index 0000000..e6e7e90
--- /dev/null
+++ b/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSink.java
@@ -0,0 +1,186 @@
+/*
+ * 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.stream.flume;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.flume.Channel;
+import org.apache.flume.Context;
+import org.apache.flume.Event;
+import org.apache.flume.EventDeliveryException;
+import org.apache.flume.FlumeException;
+import org.apache.flume.Transaction;
+import org.apache.flume.conf.Configurable;
+import org.apache.flume.instrumentation.SinkCounter;
+import org.apache.flume.sink.AbstractSink;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Flume sink for Apache Ignite.
+ */
+public class IgniteSink extends AbstractSink implements Configurable {
+    /** Logger. */
+    private static final Logger log = LoggerFactory.getLogger(IgniteSink.class);
+
+    /** Default batch size. */
+    private static final int DFLT_BATCH_SIZE = 100;
+
+    /** Ignite configuration file. */
+    private String springCfgPath;
+
+    /** Cache name. */
+    private String cacheName;
+
+    /** Event transformer implementation class. */
+    private String eventTransformerCls;
+
+    /** Number of events to be written per Flume transaction. */
+    private int batchSize;
+
+    /** Monitoring counter. */
+    private SinkCounter sinkCounter;
+
+    /** Event transformer. */
+    private EventTransformer<Event, Object, Object> eventTransformer;
+
+    /** Ignite instance. */
+    private Ignite ignite;
+
+    /** Empty constructor. */
+    public IgniteSink() {
+    }
+
+    /**
+     * Sink configurations with Ignite-specific settings.
+     *
+     * @param context Context for sink.
+     */
+    @Override public void configure(Context context) {
+        springCfgPath = context.getString(IgniteSinkConstants.CFG_PATH);
+        cacheName = context.getString(IgniteSinkConstants.CFG_CACHE_NAME);
+        eventTransformerCls = context.getString(IgniteSinkConstants.CFG_EVENT_TRANSFORMER);
+        batchSize = context.getInteger(IgniteSinkConstants.CFG_BATCH_SIZE, DFLT_BATCH_SIZE);
+
+        if (sinkCounter == null)
+            sinkCounter = new SinkCounter(getName());
+    }
+
+    /**
+     * Starts a grid and initializes na event transformer.
+     */
+    @SuppressWarnings("unchecked")
+    @Override synchronized public void start() {
+        A.notNull(springCfgPath, "Ignite config file");
+        A.notNull(cacheName, "Cache name");
+        A.notNull(eventTransformerCls, "Event transformer class");
+
+        sinkCounter.start();
+
+        try {
+            if (ignite == null)
+                ignite = Ignition.start(springCfgPath);
+
+            if (eventTransformerCls != null && !eventTransformerCls.isEmpty()) {
+                Class<? extends EventTransformer> clazz =
+                    (Class<? extends EventTransformer<Event, Object, Object>>)Class.forName(eventTransformerCls);
+
+                eventTransformer = clazz.newInstance();
+            }
+        }
+        catch (Exception e) {
+            log.error("Failed to start grid", e);
+
+            throw new FlumeException("Failed to start grid", e);
+        }
+
+        super.start();
+    }
+
+    /**
+     * Stops the grid.
+     */
+    @Override synchronized public void stop() {
+        if (ignite != null)
+            ignite.close();
+
+        sinkCounter.stop();
+
+        super.stop();
+    }
+
+    /**
+     * Processes Flume events.
+     */
+    @Override public Status process() throws EventDeliveryException {
+        Channel channel = getChannel();
+
+        Transaction transaction = channel.getTransaction();
+
+        int eventCount = 0;
+
+        try {
+            transaction.begin();
+
+            List<Event> batch = new ArrayList<>(batchSize);
+
+            for (; eventCount < batchSize; ++eventCount) {
+                Event event = channel.take();
+
+                if (event == null) {
+                    break;
+                }
+
+                batch.add(event);
+            }
+
+            if (!batch.isEmpty()) {
+                ignite.cache(cacheName).putAll(eventTransformer.transform(batch));
+
+                if (batch.size() < batchSize)
+                    sinkCounter.incrementBatchUnderflowCount();
+                else
+                    sinkCounter.incrementBatchCompleteCount();
+            }
+            else {
+                sinkCounter.incrementBatchEmptyCount();
+            }
+
+            sinkCounter.addToEventDrainAttemptCount(batch.size());
+
+            transaction.commit();
+
+            sinkCounter.addToEventDrainSuccessCount(batch.size());
+        }
+        catch (Exception e) {
+            log.error("Failed to process events", e);
+
+            transaction.rollback();
+
+            throw new EventDeliveryException(e);
+        }
+        finally {
+            transaction.close();
+        }
+
+        return eventCount == 0 ? Status.BACKOFF : Status.READY;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSinkConstants.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSinkConstants.java b/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSinkConstants.java
new file mode 100644
index 0000000..ddefb24
--- /dev/null
+++ b/modules/flume/src/main/java/org/apache/ignite/stream/flume/IgniteSinkConstants.java
@@ -0,0 +1,35 @@
+/*
+ * 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.stream.flume;
+
+/**
+ * Configuration strings for sending data to cache. Used in Flume agent configuration file.
+ */
+public class IgniteSinkConstants {
+    /** Ignite configuration file path. */
+    public static final String CFG_PATH = "igniteCfg";
+
+    /** Cache name. */
+    public static final String CFG_CACHE_NAME = "cacheName";
+
+    /** Event transformer implementation. */
+    public static final String CFG_EVENT_TRANSFORMER = "eventTransformer";
+
+    /** Batch size. */
+    public static final String CFG_BATCH_SIZE = "batchSize";
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTest.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTest.java b/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTest.java
new file mode 100644
index 0000000..2f33ed4
--- /dev/null
+++ b/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTest.java
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.stream.flume;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.apache.flume.Channel;
+import org.apache.flume.Context;
+import org.apache.flume.Sink;
+import org.apache.flume.Transaction;
+import org.apache.flume.channel.MemoryChannel;
+import org.apache.flume.conf.Configurables;
+import org.apache.flume.event.EventBuilder;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.events.Event;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT;
+
+/**
+ * {@link IgniteSink} test.
+ */
+public class IgniteSinkTest extends GridCommonAbstractTest {
+    /** Number of events to be sent to memory channel. */
+    private static final int EVENT_CNT = 10000;
+
+    /** Cache name. */
+    private static final String CACHE_NAME = "testCache";
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception {@link Exception}.
+     */
+    public void testSink() throws Exception {
+        IgniteConfiguration cfg = loadConfiguration("modules/flume/src/test/resources/example-ignite.xml");
+
+        cfg.setClientMode(false);
+
+        final Ignite grid = startGrid("igniteServerNode", cfg);
+
+        Context channelContext = new Context();
+
+        channelContext.put("capacity", String.valueOf(EVENT_CNT));
+        channelContext.put("transactionCapacity", String.valueOf(EVENT_CNT));
+
+        Channel memoryChannel = new MemoryChannel();
+
+        Configurables.configure(memoryChannel, channelContext);
+
+        final CountDownLatch latch = new CountDownLatch(EVENT_CNT);
+
+        final IgnitePredicate<Event> putLsnr = new IgnitePredicate<Event>() {
+            @Override public boolean apply(Event evt) {
+                assert evt != null;
+
+                latch.countDown();
+
+                return true;
+            }
+        };
+
+        IgniteSink sink = new IgniteSink() {
+            // Setting the listener on cache before sink processing starts.
+            @Override synchronized public void start() {
+                super.start();
+
+                grid.events(grid.cluster().forCacheNodes(CACHE_NAME)).localListen(putLsnr, EVT_CACHE_OBJECT_PUT);
+            }
+        };
+
+        sink.setName("IgniteSink");
+        sink.setChannel(memoryChannel);
+
+        Context ctx = new Context();
+
+        ctx.put(IgniteSinkConstants.CFG_CACHE_NAME, CACHE_NAME);
+        ctx.put(IgniteSinkConstants.CFG_PATH, "example-ignite.xml");
+        ctx.put(IgniteSinkConstants.CFG_EVENT_TRANSFORMER, "org.apache.ignite.stream.flume.TestEventTransformer");
+
+        Configurables.configure(sink, ctx);
+
+        sink.start();
+
+        try {
+            Transaction tx = memoryChannel.getTransaction();
+
+            tx.begin();
+
+            for (int i = 0; i < EVENT_CNT; i++)
+                memoryChannel.put(EventBuilder.withBody((String.valueOf(i) + ": " + i).getBytes()));
+
+            tx.commit();
+            tx.close();
+
+            Sink.Status status = Sink.Status.READY;
+
+            while (status != Sink.Status.BACKOFF) {
+                status = sink.process();
+            }
+        }
+        finally {
+            sink.stop();
+        }
+
+        // Checks that 10000 events successfully processed in 10 seconds.
+        assertTrue(latch.await(10, TimeUnit.SECONDS));
+
+        grid.events(grid.cluster().forCacheNodes(CACHE_NAME)).stopLocalListen(putLsnr);
+
+        IgniteCache<String, Integer> cache = grid.cache(CACHE_NAME);
+
+        // Checks that each event was processed properly.
+        for (int i = 0; i < EVENT_CNT; i++) {
+            assertEquals(i, (int)cache.get(String.valueOf(i)));
+        }
+
+        assertEquals(EVENT_CNT, cache.size(CachePeekMode.PRIMARY));
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTestSuite.java b/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTestSuite.java
new file mode 100644
index 0000000..ad6d162
--- /dev/null
+++ b/modules/flume/src/test/java/org/apache/ignite/stream/flume/IgniteSinkTestSuite.java
@@ -0,0 +1,37 @@
+/*
+ * 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.stream.flume;
+
+import junit.framework.TestSuite;
+
+/**
+ * Tests for a Flume sink for Ignite.
+ */
+public class IgniteSinkTestSuite extends TestSuite {
+    /**
+     * @return Test suite.
+     * @throws Exception Thrown in case of the failure.
+     */
+    public static TestSuite suite() throws Exception {
+        TestSuite suite = new TestSuite("Apache Flume NG Sink Test Suite");
+
+        suite.addTest(new TestSuite(IgniteSinkTest.class));
+
+        return suite;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/test/java/org/apache/ignite/stream/flume/TestEventTransformer.java
----------------------------------------------------------------------
diff --git a/modules/flume/src/test/java/org/apache/ignite/stream/flume/TestEventTransformer.java b/modules/flume/src/test/java/org/apache/ignite/stream/flume/TestEventTransformer.java
new file mode 100644
index 0000000..c15efbf
--- /dev/null
+++ b/modules/flume/src/test/java/org/apache/ignite/stream/flume/TestEventTransformer.java
@@ -0,0 +1,66 @@
+/*
+ * 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.stream.flume;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.flume.Event;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A test transformer to convert {@link org.apache.flume.Event} to cacheable entries.
+ */
+public class TestEventTransformer implements EventTransformer<Event, String, Integer> {
+
+    /**
+     * Transforms a Flume event to cacheable entries.
+     *
+     * @param event Flume event to transform.
+     * @return Map of cacheable entries.
+     */
+    private Map<String, Integer> transform(Event event) {
+        final Map<String, Integer> map = new HashMap<>();
+
+        String eventStr = new String(event.getBody());
+
+        if (!eventStr.isEmpty()) {
+            String[] tokens = eventStr.split(":"); // Expects column-delimited one line.
+
+            map.put(tokens[0].trim(), Integer.valueOf(tokens[1].trim()));
+        }
+
+        return map;
+    }
+
+    /**
+     * Transforms a list of Flume event to cacheable entries.
+     *
+     * @param events Flume events to transform.
+     * @return Map of cacheable entries.
+     */
+    @Nullable @Override public Map<String, Integer> transform(List<Event> events) {
+        final Map<String, Integer> map = new HashMap<>();
+
+        for (Event event : events) {
+            map.putAll(transform(event));
+        }
+
+        return map;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/modules/flume/src/test/resources/example-ignite.xml
----------------------------------------------------------------------
diff --git a/modules/flume/src/test/resources/example-ignite.xml b/modules/flume/src/test/resources/example-ignite.xml
new file mode 100644
index 0000000..fbb05d3
--- /dev/null
+++ b/modules/flume/src/test/resources/example-ignite.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<!--
+    Ignite configuration with all defaults and enabled p2p deployment and enabled events.
+    Used for testing IgniteSink running Ignite in a client mode.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+    <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <!-- Enable client mode. -->
+        <property name="clientMode" value="true"/>
+
+        <!-- Cache accessed from IgniteSink. -->
+        <property name="cacheConfiguration">
+            <list>
+                <!-- Partitioned cache example configuration with configurations adjusted to server nodes'. -->
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="atomicityMode" value="ATOMIC"/>
+
+                    <property name="name" value="testCache"/>
+                </bean>
+            </list>
+        </property>
+
+        <!-- Enable cache events. -->
+        <property name="includeEventTypes">
+            <list>
+                <!-- Cache events (only EVT_CACHE_OBJECT_PUT for tests). -->
+                <util:constant static-field="org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT"/>
+            </list>
+        </property>
+
+        <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. -->
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <value>127.0.0.1:47500</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a5fc056/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 5f06555..c40b551 100644
--- a/pom.xml
+++ b/pom.xml
@@ -73,6 +73,7 @@
         <module>modules/cloud</module>
         <module>modules/mesos</module>
         <module>modules/kafka</module>
+        <module>modules/flume</module>
         <module>modules/yarn</module>
         <module>modules/jms11</module>
         <module>modules/mqtt</module>


[25/37] ignite git commit: ACCEPT_ALL predicate should have SUID. This closes #248.

Posted by ag...@apache.org.
ACCEPT_ALL predicate should have SUID. This closes #248.


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

Branch: refs/heads/ignite-1282
Commit: f708c1a4d33b202bf0e74edef2f5113612797f8e
Parents: e369e1f
Author: agura <ag...@gridgain.com>
Authored: Thu Nov 19 19:29:27 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Thu Nov 19 19:29:27 2015 +0300

----------------------------------------------------------------------
 .../apache/ignite/internal/processors/cache/IgniteCacheProxy.java | 3 +++
 1 file changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f708c1a4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
index 4b03bb9..d896249 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
@@ -97,6 +97,9 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
 
     /** */
     private static final IgniteBiPredicate ACCEPT_ALL = new IgniteBiPredicate() {
+        /** */
+        private static final long serialVersionUID = -1640538788290240617L;
+
         @Override public boolean apply(Object k, Object v) {
             return true;
         }


[18/37] ignite git commit: IGNITE-530 pom.xml fix

Posted by ag...@apache.org.
 IGNITE-530 pom.xml fix


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

Branch: refs/heads/ignite-1282
Commit: ba1d563ae04b6e3a30fcfb2b89456f6fcd36d246
Parents: a39681e
Author: Anton Vinogradov <av...@apache.org>
Authored: Thu Nov 19 15:53:03 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Thu Nov 19 15:53:03 2015 +0300

----------------------------------------------------------------------
 modules/twitter/pom.xml | 6 ++++++
 1 file changed, 6 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ba1d563a/modules/twitter/pom.xml
----------------------------------------------------------------------
diff --git a/modules/twitter/pom.xml b/modules/twitter/pom.xml
index 21e6f51..6c02935 100644
--- a/modules/twitter/pom.xml
+++ b/modules/twitter/pom.xml
@@ -41,17 +41,20 @@
             <artifactId>ignite-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+
         <dependency>
             <groupId>org.apache.ignite</groupId>
             <artifactId>ignite-log4j</artifactId>
             <version>${project.version}</version>
         </dependency>
+
         <dependency>
             <groupId>org.apache.ignite</groupId>
             <artifactId>ignite-spring</artifactId>
             <version>${project.version}</version>
             <scope>test</scope>
         </dependency>
+
         <dependency>
             <groupId>org.apache.ignite</groupId>
             <artifactId>ignite-core</artifactId>
@@ -59,11 +62,13 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
+
         <dependency>
             <groupId>com.twitter</groupId>
             <artifactId>hbc-twitter4j</artifactId>
             <version>2.2.0</version>
         </dependency>
+
         <dependency>
             <groupId>com.github.tomakehurst</groupId>
             <artifactId>wiremock</artifactId>
@@ -111,6 +116,7 @@
                     <artifactId>jopt-simple</artifactId>
                 </exclusion>
             </exclusions>
+            <scope>test</scope>
         </dependency>
     </dependencies>
 </project>


[21/37] ignite git commit: Optimization for single key cache 'get' operation.

Posted by ag...@apache.org.
Optimization for single key cache 'get' operation.


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

Branch: refs/heads/ignite-1282
Commit: 1f1030670a6e7f9fbad1d939301c884f29b7885a
Parents: ba1d563
Author: sboikov <sb...@gridgain.com>
Authored: Thu Nov 19 17:29:04 2015 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Thu Nov 19 17:29:04 2015 +0300

----------------------------------------------------------------------
 .../communication/GridIoMessageFactory.java     |  12 +
 .../processors/cache/GridCacheAdapter.java      | 103 ++-
 .../processors/cache/GridCacheAtomicFuture.java |   6 +
 .../processors/cache/GridCacheFuture.java       |  13 -
 .../processors/cache/GridCacheIoManager.java    |  50 +-
 .../processors/cache/GridCacheMessage.java      |  20 +-
 .../processors/cache/GridCacheMvccFuture.java   |   7 +
 .../processors/cache/GridCacheMvccManager.java  | 108 +--
 .../distributed/GridCacheTxRecoveryFuture.java  |  13 +-
 .../dht/CacheDistributedGetFutureAdapter.java   |  27 +-
 .../cache/distributed/dht/CacheGetFuture.java   |  32 +
 .../distributed/dht/GridDhtCacheAdapter.java    | 141 ++++
 .../distributed/dht/GridDhtLockFuture.java      |  16 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |   9 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |  24 +-
 .../cache/distributed/dht/GridDhtTxLocal.java   |   4 +-
 .../distributed/dht/GridDhtTxPrepareFuture.java |  17 +-
 .../dht/GridPartitionedGetFuture.java           |  69 +-
 .../dht/GridPartitionedSingleGetFuture.java     | 697 +++++++++++++++++++
 .../dht/atomic/GridDhtAtomicCache.java          | 127 +++-
 .../dht/atomic/GridDhtAtomicUpdateFuture.java   |  84 +--
 .../dht/atomic/GridDhtAtomicUpdateRequest.java  |  11 +
 .../dht/atomic/GridNearAtomicUpdateFuture.java  |   5 -
 .../dht/colocated/GridDhtColocatedCache.java    | 160 ++++-
 .../colocated/GridDhtColocatedLockFuture.java   |  26 +-
 .../distributed/near/CacheVersionedValue.java   |   2 +-
 .../distributed/near/GridNearCacheAdapter.java  |   4 +-
 .../distributed/near/GridNearGetFuture.java     |  57 +-
 .../distributed/near/GridNearGetRequest.java    |   1 -
 .../distributed/near/GridNearGetResponse.java   |   2 -
 .../distributed/near/GridNearLockFuture.java    |  16 +-
 ...arOptimisticSerializableTxPrepareFuture.java |  17 +-
 .../near/GridNearOptimisticTxPrepareFuture.java |  19 +-
 .../GridNearPessimisticTxPrepareFuture.java     |  19 +-
 .../near/GridNearSingleGetRequest.java          | 396 +++++++++++
 .../near/GridNearSingleGetResponse.java         | 321 +++++++++
 .../near/GridNearTransactionalCache.java        |   2 +-
 .../near/GridNearTxFinishFuture.java            |  24 +-
 .../cache/distributed/near/GridNearTxLocal.java | 149 ++--
 .../near/GridNearTxPrepareFutureAdapter.java    |   6 +-
 .../processors/cache/local/GridLocalCache.java  |   4 +-
 .../cache/local/GridLocalLockFuture.java        |   5 -
 .../cache/transactions/IgniteTxHandler.java     |  19 +-
 .../transactions/IgniteTxLocalAdapter.java      |   2 +-
 .../cache/transactions/IgniteTxManager.java     |   2 +-
 .../IgniteClientReconnectCacheTest.java         |  11 +-
 .../cache/GridCacheAbstractFullApiSelfTest.java |  75 ++
 .../GridCacheConcurrentTxMultiNodeTest.java     |  15 -
 .../cache/GridCachePartitionedGetSelfTest.java  |   3 +-
 .../IgniteCacheAbstractStopBusySelfTest.java    |  27 +-
 .../IgniteCacheP2pUnmarshallingErrorTest.java   | 184 +++--
 .../CacheGetFutureHangsSelfTest.java            |   6 +
 .../GridCacheAbstractNodeRestartSelfTest.java   |   2 +
 .../IgniteCacheSingleGetMessageTest.java        | 357 ++++++++++
 .../GridCacheReplicatedMetricsSelfTest.java     |   9 -
 .../testsuites/IgniteCacheTestSuite4.java       |   3 +
 56 files changed, 2908 insertions(+), 632 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 2503eda..3548aac 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -83,6 +83,8 @@ import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetR
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareRequest;
@@ -696,6 +698,16 @@ public class GridIoMessageFactory implements MessageFactory {
 
                 break;
 
+            case 116:
+                msg = new GridNearSingleGetRequest();
+
+                break;
+
+            case 117:
+                msg = new GridNearSingleGetResponse();
+
+                break;
+
             // [-3..114] - this
             // [120..123] - DR
             // [-4..-22] - SQL

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/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 cbb7486..562a0eb 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
@@ -599,11 +599,11 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /** {@inheritDoc} */
-    @Override public IgniteInternalFuture<Boolean> containsKeyAsync(K key) {
+    @Override public final IgniteInternalFuture<Boolean> containsKeyAsync(K key) {
         A.notNull(key, "key");
 
-        return getAllAsync(
-            Collections.singletonList(key),
+        return (IgniteInternalFuture)getAsync(
+            key,
             /*force primary*/false,
             /*skip tx*/false,
             /*subj id*/null,
@@ -611,15 +611,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             /*deserialize portable*/false,
             /*skip values*/true,
             /*can remap*/true
-        ).chain(new CX1<IgniteInternalFuture<Map<K, V>>, Boolean>() {
-            @Override public Boolean applyx(IgniteInternalFuture<Map<K, V>> fut) throws IgniteCheckedException {
-                Map<K, V> map = fut.get();
-
-                assert map.isEmpty() || map.size() == 1 : map.size();
-
-                return map.isEmpty() ? false : map.values().iterator().next() != null;
-            }
-        });
+        );
     }
 
     /** {@inheritDoc} */
@@ -1473,6 +1465,52 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /**
+     * @param key Key.
+     * @param forcePrimary Force primary.
+     * @param skipTx Skip tx.
+     * @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.
+     */
+    protected IgniteInternalFuture<V> getAsync(
+        final K key,
+        boolean forcePrimary,
+        boolean skipTx,
+        @Nullable UUID subjId,
+        String taskName,
+        boolean deserializePortable,
+        final boolean skipVals,
+        boolean canRemap
+    ) {
+        return getAllAsync(Collections.singletonList(key),
+            forcePrimary,
+            skipTx,
+            subjId,
+            taskName,
+            deserializePortable,
+            skipVals,
+            canRemap).chain(
+            new CX1<IgniteInternalFuture<Map<K, V>>, V>() {
+                @Override public V applyx(IgniteInternalFuture<Map<K, V>> e) throws IgniteCheckedException {
+                    Map<K, V> map = e.get();
+
+                    assert map.isEmpty() || map.size() == 1 : map.size();
+
+                    if (skipVals) {
+                        Boolean val = map.isEmpty() ? false : (Boolean)F.firstValue(map);
+
+                        return (V)(val);
+                    }
+
+                    return map.get(key);
+                }
+            });
+    }
+
+    /**
      * @param keys Keys.
      * @param forcePrimary Force primary.
      * @param skipTx Skip tx.
@@ -1524,7 +1562,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
      * @return Future for the get operation.
      * @see GridCacheAdapter#getAllAsync(Collection)
      */
-    public IgniteInternalFuture<Map<K, V>> getAllAsync(@Nullable final Collection<? extends K> keys,
+    public final IgniteInternalFuture<Map<K, V>> getAllAsync(@Nullable final Collection<? extends K> keys,
         boolean readThrough,
         boolean checkTx,
         @Nullable final UUID subjId,
@@ -1605,11 +1643,20 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
 
                 final boolean storeEnabled = !skipVals && readThrough && ctx.readThrough();
 
+                final boolean needEntry = storeEnabled || ctx.isSwapOrOffheapEnabled();
+
                 Map<KeyCacheObject, GridCacheVersion> misses = null;
 
                 for (KeyCacheObject key : keys) {
                     while (true) {
-                        GridCacheEntryEx entry = entryEx(key);
+                        GridCacheEntryEx entry = needEntry ? entryEx(key) : peekEx(key);
+
+                        if (entry == null) {
+                            if (!skipVals && ctx.config().isStatisticsEnabled())
+                                ctx.cache().metrics0().onRead(false);
+
+                            break;
+                        }
 
                         try {
                             T2<CacheObject, GridCacheVersion> res = entry.innerGetVersioned(null,
@@ -4389,11 +4436,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
      */
     @Nullable public V get(K key, boolean deserializePortable)
         throws IgniteCheckedException {
-        Map<K, V> map = getAllAsync(F.asList(key), deserializePortable).get();
-
-        assert map.isEmpty() || map.size() == 1 : map.size();
-
-        return map.get(key);
+        return getAsync(key, deserializePortable).get();
     }
 
     /**
@@ -4409,16 +4452,16 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
             return new GridFinishedFuture<>(e);
         }
 
-        return getAllAsync(Collections.singletonList(key), deserializePortable).chain(
-            new CX1<IgniteInternalFuture<Map<K, V>>, V>() {
-                    @Override public V applyx(IgniteInternalFuture<Map<K, V>> e) throws IgniteCheckedException {
-                    Map<K, V> map = e.get();
-
-                    assert map.isEmpty() || map.size() == 1 : map.size();
+        String taskName = ctx.kernalContext().job().currentTaskName();
 
-                    return map.get(key);
-                }
-            });
+        return getAsync(key,
+            !ctx.config().isReadFromBackup(),
+            /*skip tx*/false,
+            null,
+            taskName,
+            deserializePortable,
+            false,
+            /*can remap*/true);
     }
 
     /**
@@ -4445,10 +4488,10 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
         return getAllAsync(keys,
             !ctx.config().isReadFromBackup(),
             /*skip tx*/false,
-            null,
+            /*subject id*/null,
             taskName,
             deserializePortable,
-            false,
+            /*skip vals*/false,
             /*can remap*/true);
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAtomicFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAtomicFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAtomicFuture.java
index be35c5c..359909e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAtomicFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAtomicFuture.java
@@ -20,12 +20,18 @@ package org.apache.ignite.internal.processors.cache;
 import java.util.Collection;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 
 /**
  * Update future for atomic cache.
  */
 public interface GridCacheAtomicFuture<R> extends GridCacheFuture<R> {
     /**
+     * @return Future version.
+     */
+    public GridCacheVersion version();
+
+    /**
      * Gets future that will be completed when it is safe when update is finished on the given version of topology.
      *
      * @param topVer Topology version to finish.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheFuture.java
index caa3d3f..8bf8d40 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheFuture.java
@@ -17,11 +17,8 @@
 
 package org.apache.ignite.internal.processors.cache;
 
-import java.util.Collection;
 import java.util.UUID;
-import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.lang.IgniteUuid;
 
 /**
@@ -34,16 +31,6 @@ public interface GridCacheFuture<R> extends IgniteInternalFuture<R> {
     public IgniteUuid futureId();
 
     /**
-     * @return Future version.
-     */
-    public GridCacheVersion version();
-
-    /**
-     * @return Involved nodes.
-     */
-    public Collection<? extends ClusterNode> nodes();
-
-    /**
      * Callback for when node left.
      *
      * @param nodeId Left node ID.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
index 2334780..9afbca8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheIoManager.java
@@ -34,22 +34,24 @@ import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.managers.communication.GridMessageListener;
 import org.apache.ignite.internal.managers.deployment.GridDeploymentInfo;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.distributed.dht.CacheGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLockRequest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLockResponse;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxPrepareRequest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxPrepareResponse;
-import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedGetFuture;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedSingleGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateRequest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridDhtAtomicUpdateResponse;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicUpdateRequest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNearAtomicUpdateResponse;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtForceKeysRequest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtForceKeysResponse;
-import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryRequest;
@@ -437,7 +439,7 @@ public class GridCacheIoManager extends GridCacheSharedManagerAdapter {
             case 50: {
                 GridNearGetResponse res = (GridNearGetResponse)msg;
 
-                GridCacheFuture fut = ctx.mvcc().future(res.version(), res.futureId());
+                CacheGetFuture fut = (CacheGetFuture)ctx.mvcc().future(res.futureId());
 
                 if (fut == null) {
                     if (log.isDebugEnabled())
@@ -448,10 +450,7 @@ public class GridCacheIoManager extends GridCacheSharedManagerAdapter {
 
                 res.error(res.classError());
 
-                if (fut instanceof GridNearGetFuture)
-                    ((GridNearGetFuture)fut).onResult(nodeId, res);
-                else
-                    ((GridPartitionedGetFuture)fut).onResult(nodeId, res);
+                fut.onResult(nodeId, res);
             }
 
             break;
@@ -521,6 +520,43 @@ public class GridCacheIoManager extends GridCacheSharedManagerAdapter {
 
             break;
 
+            case 116: {
+                GridNearSingleGetRequest req = (GridNearSingleGetRequest)msg;
+
+                GridNearSingleGetResponse res = new GridNearSingleGetResponse(
+                    ctx.cacheId(),
+                    req.futureId(),
+                    req.topologyVersion(),
+                    null,
+                    false,
+                    req.deployInfo() != null);
+
+                res.error(req.classError());
+
+                sendResponseOnFailedMessage(nodeId, res, cctx, ctx.ioPolicy());
+            }
+
+            break;
+
+            case 117: {
+                GridNearSingleGetResponse res = (GridNearSingleGetResponse)msg;
+
+                GridPartitionedSingleGetFuture fut = (GridPartitionedSingleGetFuture)ctx.mvcc().future(res.futureId());
+
+                if (fut == null) {
+                    if (log.isDebugEnabled())
+                        log.debug("Failed to find future for get response [sender=" + nodeId + ", res=" + res + ']');
+
+                    return;
+                }
+
+                res.error(res.classError());
+
+                fut.onResult(nodeId, res);
+            }
+
+            break;
+
             default:
                 throw new IgniteCheckedException("Failed to send response to node. Unsupported direct type [message="
                     + msg + "]");

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMessage.java
index bdd2118..61136bf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMessage.java
@@ -499,15 +499,21 @@ public abstract class GridCacheMessage implements Message {
 
         int size = col.size();
 
-        for (int i = 0 ; i < size; i++) {
-            CacheObject obj = col.get(i);
+        for (int i = 0 ; i < size; i++)
+            prepareMarshalCacheObject(col.get(i), ctx);
+    }
 
-            if (obj != null) {
-                obj.prepareMarshal(ctx.cacheObjectContext());
+    /**
+     * @param obj Object.
+     * @param ctx Context.
+     * @throws IgniteCheckedException If failed.
+     */
+    protected final void prepareMarshalCacheObject(CacheObject obj, GridCacheContext ctx) throws IgniteCheckedException {
+        if (obj != null) {
+            obj.prepareMarshal(ctx.cacheObjectContext());
 
-                if (addDepInfo)
-                    prepareObject(obj.value(ctx.cacheObjectContext(), false), ctx);
-            }
+            if (addDepInfo)
+                prepareObject(obj.value(ctx.cacheObjectContext(), false), ctx);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFuture.java
index 67c1330..080a6f1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccFuture.java
@@ -17,11 +17,18 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+
 /**
  * Distributed future aware of MVCC locking.
  */
 public interface GridCacheMvccFuture<T> extends GridCacheFuture<T> {
     /**
+     * @return Future version.
+     */
+    public GridCacheVersion version();
+
+    /**
      * @param entry Entry which received new owner.
      * @param owner Owner.
      * @return {@code True} if future cares about this entry.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
index 8562f37..9104acb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.processors.cache;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -31,7 +30,6 @@ import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ConcurrentMap;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
-import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.events.DiscoveryEvent;
 import org.apache.ignite.events.Event;
 import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
@@ -101,12 +99,15 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
 
     /** Active futures mapped by version ID. */
     @GridToStringExclude
-    private final ConcurrentMap<GridCacheVersion, Collection<GridCacheFuture<?>>> futs = newMap();
+    private final ConcurrentMap<GridCacheVersion, Collection<GridCacheMvccFuture<?>>> mvccFuts = newMap();
 
     /** Pending atomic futures. */
     private final ConcurrentMap<GridCacheVersion, GridCacheAtomicFuture<?>> atomicFuts =
         new ConcurrentHashMap8<>();
 
+    /** */
+    private final ConcurrentMap<IgniteUuid, GridCacheFuture<?>> futs = new ConcurrentHashMap8<>();
+
     /** Near to DHT version mapping. */
     private final ConcurrentMap<GridCacheVersion, GridCacheVersion> near2dht = newMap();
 
@@ -137,12 +138,12 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
                     prev + ']');
 
             if (owner != null && (owner.local() || owner.nearLocal())) {
-                Collection<? extends GridCacheFuture> futCol = futs.get(owner.version());
+                Collection<GridCacheMvccFuture<?>> futCol = mvccFuts.get(owner.version());
 
                 if (futCol != null) {
                     synchronized (futCol) {
-                        for (GridCacheFuture fut : futCol) {
-                            if (fut instanceof GridCacheMvccFuture && !fut.isDone()) {
+                        for (GridCacheMvccFuture<?> fut : futCol) {
+                            if (!fut.isDone()) {
                                 GridCacheMvccFuture<Boolean> mvccFut = (GridCacheMvccFuture<Boolean>)fut;
 
                                 // Since this method is called outside of entry synchronization,
@@ -206,18 +207,14 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
             for (GridCacheFuture<?> fut : activeFutures())
                 fut.onNodeLeft(discoEvt.eventNode().id());
 
-            for (IgniteInternalFuture<?> fut : atomicFuts.values()) {
-                if (fut instanceof GridCacheFuture) {
-                    GridCacheFuture cacheFut = (GridCacheFuture)fut;
+            for (GridCacheAtomicFuture<?> cacheFut : atomicFuts.values()) {
+                cacheFut.onNodeLeft(discoEvt.eventNode().id());
 
-                    cacheFut.onNodeLeft(discoEvt.eventNode().id());
+                if (cacheFut.isCancelled() || cacheFut.isDone()) {
+                    GridCacheVersion futVer = cacheFut.version();
 
-                    if (cacheFut.isCancelled() || cacheFut.isDone()) {
-                        GridCacheVersion futVer = cacheFut.version();
-
-                        if (futVer != null)
-                            atomicFuts.remove(futVer, fut);
-                    }
+                    if (futVer != null)
+                        atomicFuts.remove(futVer, cacheFut);
                 }
             }
         }
@@ -261,12 +258,14 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
     public Collection<GridCacheFuture<?>> activeFutures() {
         ArrayList<GridCacheFuture<?>> col = new ArrayList<>();
 
-        for (Collection<GridCacheFuture<?>> verFuts : futs.values()) {
-            synchronized (verFuts) {
-                col.addAll(verFuts);
+        for (Collection<GridCacheMvccFuture<?>> futs : mvccFuts.values()) {
+            synchronized (futs) {
+                col.addAll(futs);
             }
         }
 
+        col.addAll(futs.values());
+
         return col;
     }
 
@@ -420,13 +419,25 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
     }
 
     /**
+     * @param fut Future.
+     * @param futId Future ID.
+     */
+    public void addFuture(final GridCacheFuture<?> fut, final IgniteUuid futId) {
+        GridCacheFuture<?> old = futs.put(futId, fut);
+
+        assert old == null : old;
+
+        onFutureAdded(fut);
+    }
+
+    /**
      * Adds future.
      *
      * @param fut Future.
      * @return {@code True} if added.
      */
     @SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})
-    public boolean addFuture(final GridCacheFuture<?> fut) {
+    public boolean addFuture(final GridCacheMvccFuture<?> fut) {
         if (fut.isDone()) {
             fut.markNotTrackable();
 
@@ -437,10 +448,10 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
             return true;
 
         while (true) {
-            Collection<GridCacheFuture<?>> old = futs.get(fut.version());
+            Collection<GridCacheMvccFuture<?>> old = mvccFuts.get(fut.version());
 
             if (old == null) {
-                Collection<GridCacheFuture<?>> col = new HashSet<GridCacheFuture<?>>(U.capacity(4), 0.75f) {
+                Collection<GridCacheMvccFuture<?>> col = new HashSet<GridCacheMvccFuture<?>>(U.capacity(4), 0.75f) {
                     {
                         // Make sure that we add future to queue before
                         // adding queue to the map of futures.
@@ -456,7 +467,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
                     }
                 };
 
-                old = futs.putIfAbsent(fut.version(), col);
+                old = mvccFuts.putIfAbsent(fut.version(), col);
             }
 
             if (old != null) {
@@ -471,7 +482,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
 
                 // Future is being removed, so we force-remove here and try again.
                 if (empty) {
-                    if (futs.remove(fut.version(), old)) {
+                    if (mvccFuts.remove(fut.version(), old)) {
                         if (log.isDebugEnabled())
                             log.debug("Removed future list from futures map for lock version: " + fut.version());
                     }
@@ -501,16 +512,9 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
             break;
         }
 
-        // Close window in case of node is gone before the future got added to
-        // the map of futures.
-        for (ClusterNode n : fut.nodes()) {
-            if (cctx.discovery().node(n.id()) == null)
-                fut.onNodeLeft(n.id());
-        }
-
         // Just in case if future was completed before it was added.
         if (fut.isDone())
-            removeFuture(fut);
+            removeMvccFuture(fut);
         else
             onFutureAdded(fut);
 
@@ -537,15 +541,22 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
     }
 
     /**
+     * @param futId Future ID.
+     */
+    public void removeFuture(IgniteUuid futId) {
+        futs.remove(futId);
+    }
+
+    /**
      * @param fut Future to remove.
      * @return {@code True} if removed.
      */
     @SuppressWarnings({"SynchronizationOnLocalVariableOrMethodParameter"})
-    public boolean removeFuture(GridCacheFuture<?> fut) {
+    public boolean removeMvccFuture(GridCacheMvccFuture<?> fut) {
         if (!fut.trackable())
             return true;
 
-        Collection<GridCacheFuture<?>> cur = futs.get(fut.version());
+        Collection<GridCacheMvccFuture<?>> cur = mvccFuts.get(fut.version());
 
         if (cur == null)
             return false;
@@ -565,7 +576,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
         else if (log.isDebugEnabled())
             log.debug("Attempted to remove a non-registered future (has it been already removed?): " + fut);
 
-        if (empty && futs.remove(fut.version(), cur))
+        if (empty && mvccFuts.remove(fut.version(), cur))
             if (log.isDebugEnabled())
                 log.debug("Removed future list from futures map for lock version: " + fut.version());
 
@@ -580,12 +591,12 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
      * @return Future.
      */
     @SuppressWarnings({"unchecked"})
-    @Nullable public GridCacheFuture future(GridCacheVersion ver, IgniteUuid futId) {
-        Collection<? extends GridCacheFuture> futs = this.futs.get(ver);
+    @Nullable public GridCacheMvccFuture<?> mvccFuture(GridCacheVersion ver, IgniteUuid futId) {
+        Collection<GridCacheMvccFuture<?>> futs = this.mvccFuts.get(ver);
 
         if (futs != null) {
             synchronized (futs) {
-                for (GridCacheFuture<?> fut : futs) {
+                for (GridCacheMvccFuture<?> fut : futs) {
                     if (fut.futureId().equals(futId)) {
                         if (log.isDebugEnabled())
                             log.debug("Found future in futures map: " + fut);
@@ -603,22 +614,11 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
     }
 
     /**
-     * Gets all futures for given lock version, possibly empty collection.
-     *
-     * @param ver Version.
-     * @return All futures for given lock version.
+     * @param futId Future ID.
+     * @return Found future.
      */
-    @SuppressWarnings("unchecked")
-    public <T> Collection<? extends IgniteInternalFuture<T>> futures(GridCacheVersion ver) {
-        Collection c = futs.get(ver);
-
-        if (c == null)
-            return Collections.<IgniteInternalFuture<T>>emptyList();
-        else {
-            synchronized (c) {
-                return new ArrayList<>((Collection<IgniteInternalFuture<T>>)c);
-            }
-        }
+    @Nullable public GridCacheFuture future(IgniteUuid futId) {
+        return futs.get(futId);
     }
 
     /**
@@ -913,7 +913,7 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
         X.println(">>> Mvcc manager memory stats [grid=" + cctx.gridName() + ']');
         X.println(">>>   rmvLocksSize: " + rmvLocks.sizex());
         X.println(">>>   lockedSize: " + locked.size());
-        X.println(">>>   futsSize: " + futs.size());
+        X.println(">>>   futsSize: " + (mvccFuts.size() + futs.size()));
         X.println(">>>   near2dhtSize: " + near2dht.size());
         X.println(">>>   finishFutsSize: " + finishFuts.sizex());
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
index 01c4867..1648de0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
@@ -29,7 +29,6 @@ import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.processors.cache.GridCacheFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
-import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.GridLeanMap;
 import org.apache.ignite.internal.util.future.GridCompoundIdentityFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -389,16 +388,6 @@ public class GridCacheTxRecoveryFuture extends GridCompoundIdentityFuture<Boolea
     }
 
     /** {@inheritDoc} */
-    @Override public GridCacheVersion version() {
-        return tx.xidVersion();
-    }
-
-    /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return nodes.values();
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         for (IgniteInternalFuture<?> fut : futures())
             if (isMini(fut)) {
@@ -424,7 +413,7 @@ public class GridCacheTxRecoveryFuture extends GridCompoundIdentityFuture<Boolea
     /** {@inheritDoc} */
     @Override public boolean onDone(@Nullable Boolean res, @Nullable Throwable err) {
         if (super.onDone(res, err)) {
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeFuture(futId);
 
             if (err == null) {
                 assert res != null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheDistributedGetFutureAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheDistributedGetFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheDistributedGetFutureAdapter.java
index 721ba4e..245ffc6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheDistributedGetFutureAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheDistributedGetFutureAdapter.java
@@ -18,9 +18,12 @@
 package org.apache.ignite.internal.processors.cache.distributed.dht;
 
 import java.util.Collection;
+import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheFuture;
 import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy;
@@ -40,7 +43,7 @@ import static org.apache.ignite.IgniteSystemProperties.getInteger;
  *
  */
 public abstract class CacheDistributedGetFutureAdapter<K, V> extends GridCompoundIdentityFuture<Map<K, V>>
-    implements GridCacheFuture<Map<K, V>> {
+    implements GridCacheFuture<Map<K, V>>, CacheGetFuture {
     /** Default max remap count value. */
     public static final int DFLT_MAX_REMAP_CNT = 3;
 
@@ -155,4 +158,26 @@ public abstract class CacheDistributedGetFutureAdapter<K, V> extends GridCompoun
 
         map.put(key, new T2<>(skipVals ? true : val, ver));
     }
+
+    /**
+     * Affinity node to send get request to.
+     *
+     * @param key Key to get.
+     * @param topVer Topology version.
+     * @return Affinity node to get key from.
+     */
+    protected final ClusterNode affinityNode(KeyCacheObject key, AffinityTopologyVersion topVer) {
+        if (!canRemap) {
+            List<ClusterNode> affNodes = cctx.affinity().nodes(key, topVer);
+
+            for (ClusterNode node : affNodes) {
+                if (cctx.discovery().alive(node))
+                    return node;
+            }
+
+            return null;
+        }
+        else
+            return cctx.affinity().primary(key, topVer);
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheGetFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheGetFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheGetFuture.java
new file mode 100644
index 0000000..ebe2cff
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/CacheGetFuture.java
@@ -0,0 +1,32 @@
+/*
+ * 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.distributed.dht;
+
+import java.util.UUID;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
+
+/**
+ *
+ */
+public interface CacheGetFuture {
+    /**
+     * @param nodeId Node ID.
+     * @param res Response.
+     */
+    public void onResult(UUID nodeId, GridNearGetResponse res);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
index bdd1140..8537357 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtCacheAdapter.java
@@ -57,9 +57,12 @@ import org.apache.ignite.internal.processors.cache.distributed.GridDistributedCa
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedCacheEntry;
 import org.apache.ignite.internal.processors.cache.distributed.dht.colocated.GridDhtDetachedCacheEntry;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPreloader;
+import org.apache.ignite.internal.processors.cache.distributed.near.CacheVersionedValue;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.platform.cache.PlatformCacheEntryFilter;
 import org.apache.ignite.internal.util.future.GridCompoundFuture;
@@ -76,6 +79,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiPredicate;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.Message;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jsr166.ConcurrentHashMap8;
@@ -110,6 +114,46 @@ public abstract class GridDhtCacheAdapter<K, V> extends GridDistributedCacheAdap
     }
 
     /**
+     * @param nodeId Sender node ID.
+     * @param res Near get response.
+     */
+    protected final void processNearGetResponse(UUID nodeId, GridNearGetResponse res) {
+        if (log.isDebugEnabled())
+            log.debug("Processing near get response [nodeId=" + nodeId + ", res=" + res + ']');
+
+        CacheGetFuture fut = (CacheGetFuture)ctx.mvcc().future(res.futureId());
+
+        if (fut == null) {
+            if (log.isDebugEnabled())
+                log.debug("Failed to find future for get response [sender=" + nodeId + ", res=" + res + ']');
+
+            return;
+        }
+
+        fut.onResult(nodeId, res);
+    }
+
+    /**
+     * @param nodeId Sender node ID.
+     * @param res Near get response.
+     */
+    protected void processNearSingleGetResponse(UUID nodeId, GridNearSingleGetResponse res) {
+        if (log.isDebugEnabled())
+            log.debug("Processing near get response [nodeId=" + nodeId + ", res=" + res + ']');
+
+        GridPartitionedSingleGetFuture fut = (GridPartitionedSingleGetFuture)ctx.mvcc().future(res.futureId());
+
+        if (fut == null) {
+            if (log.isDebugEnabled())
+                log.debug("Failed to find future for get response [sender=" + nodeId + ", res=" + res + ']');
+
+            return;
+        }
+
+        fut.onResult(nodeId, res);
+    }
+
+    /**
      * @param ctx Context.
      */
     protected GridDhtCacheAdapter(GridCacheContext<K, V> ctx) {
@@ -669,6 +713,103 @@ public abstract class GridDhtCacheAdapter<K, V> extends GridDistributedCacheAdap
      * @param nodeId Node ID.
      * @param req Get request.
      */
+    protected void processNearSingleGetRequest(final UUID nodeId, final GridNearSingleGetRequest req) {
+        assert ctx.affinityNode();
+
+        long ttl = req.accessTtl();
+
+        final CacheExpiryPolicy expiryPlc = CacheExpiryPolicy.forAccess(ttl);
+
+        LinkedHashMap<KeyCacheObject, Boolean> map = U.newLinkedHashMap(1);
+
+        map.put(req.key(), req.addReader());
+
+        IgniteInternalFuture<Collection<GridCacheEntryInfo>> fut =
+            getDhtAsync(nodeId,
+                req.messageId(),
+                map,
+                req.readThrough(),
+                req.topologyVersion(),
+                req.subjectId(),
+                req.taskNameHash(),
+                expiryPlc,
+                req.skipValues());
+
+        fut.listen(new CI1<IgniteInternalFuture<Collection<GridCacheEntryInfo>>>() {
+            @Override public void apply(IgniteInternalFuture<Collection<GridCacheEntryInfo>> f) {
+                GridNearSingleGetResponse res;
+
+                GridDhtFuture<Collection<GridCacheEntryInfo>> fut =
+                    (GridDhtFuture<Collection<GridCacheEntryInfo>>)f;
+
+                try {
+                    Collection<GridCacheEntryInfo> entries = fut.get();
+
+                    if (F.isEmpty(fut.invalidPartitions())) {
+                        GridCacheEntryInfo info = F.first(entries);
+
+                        Message res0 = null;
+
+                        if (info != null) {
+                            if (req.needEntryInfo()) {
+                                info.key(null);
+
+                                res0 = info;
+                            } else if (req.needVersion())
+                                res0 = new CacheVersionedValue(info.value(), info.version());
+                            else
+                                res0 = info.value();
+                        }
+
+                        res = new GridNearSingleGetResponse(ctx.cacheId(),
+                            req.futureId(),
+                            req.topologyVersion(),
+                            res0,
+                            false,
+                            req.addDeploymentInfo());
+
+                        if (info != null && req.skipValues())
+                            res.setContainsValue();
+                    }
+                    else {
+                        res = new GridNearSingleGetResponse(ctx.cacheId(),
+                            req.futureId(),
+                            ctx.shared().exchange().readyAffinityVersion(),
+                            null,
+                            true,
+                            req.addDeploymentInfo());
+                    }
+                }
+                catch (IgniteCheckedException e) {
+                    U.error(log, "Failed processing get request: " + req, e);
+
+                    res = new GridNearSingleGetResponse(ctx.cacheId(),
+                        req.futureId(),
+                        req.topologyVersion(),
+                        null,
+                        false,
+                        req.addDeploymentInfo());
+
+                    res.error(e);
+                }
+
+                try {
+                    ctx.io().send(nodeId, res, ctx.ioPolicy());
+                }
+                catch (IgniteCheckedException e) {
+                    U.error(log, "Failed to send get response to node (is node still alive?) [nodeId=" + nodeId +
+                        ",req=" + req + ", res=" + res + ']', e);
+                }
+
+                sendTtlUpdateRequest(expiryPlc);
+            }
+        });
+    }
+
+    /**
+     * @param nodeId Node ID.
+     * @param req Get request.
+     */
     protected void processNearGetRequest(final UUID nodeId, final GridNearGetRequest req) {
         assert ctx.affinityNode();
         assert !req.reload() : req;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
index 7284fd4..a7978c9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
@@ -262,20 +262,6 @@ public final class GridDhtLockFuture extends GridCompoundIdentityFuture<Boolean>
             log.debug("Added invalid partition to future [invalidPart=" + invalidPart + ", fut=" + this + ']');
     }
 
-    /**
-     * @return Participating nodes.
-     */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-            @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                if (isMini(f))
-                    return ((MiniFuture)f).node();
-
-                return cctx.discovery().localNode();
-            }
-        });
-    }
-
     /** {@inheritDoc} */
     @Override public GridCacheVersion version() {
         return lockVer;
@@ -756,7 +742,7 @@ public final class GridDhtLockFuture extends GridCompoundIdentityFuture<Boolean>
                 log.debug("Completing future: " + this);
 
             // Clean up.
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             if (timeoutObj != null)
                 cctx.time().removeTimeoutObject(timeoutObj);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
index 35f63e3..2468cf0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
@@ -50,6 +50,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.Gri
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTransactionalCache;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxRemote;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearUnlockRequest;
@@ -126,6 +127,12 @@ public abstract class GridDhtTransactionalCacheAdapter<K, V> extends GridDhtCach
             }
         });
 
+        ctx.io().addHandler(ctx.cacheId(), GridNearSingleGetRequest.class, new CI2<UUID, GridNearSingleGetRequest>() {
+            @Override public void apply(UUID nodeId, GridNearSingleGetRequest req) {
+                processNearSingleGetRequest(nodeId, req);
+            }
+        });
+
         ctx.io().addHandler(ctx.cacheId(), GridNearLockRequest.class, new CI2<UUID, GridNearLockRequest>() {
             @Override public void apply(UUID nodeId, GridNearLockRequest req) {
                 processNearLockRequest(nodeId, req);
@@ -566,7 +573,7 @@ public abstract class GridDhtTransactionalCacheAdapter<K, V> extends GridDhtCach
     private void processDhtLockResponse(UUID nodeId, GridDhtLockResponse res) {
         assert nodeId != null;
         assert res != null;
-        GridDhtLockFuture fut = (GridDhtLockFuture)ctx.mvcc().<Boolean>future(res.version(), res.futureId());
+        GridDhtLockFuture fut = (GridDhtLockFuture)ctx.mvcc().<Boolean>mvccFuture(res.version(), res.futureId());
 
         if (fut == null) {
             if (log.isDebugEnabled())

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
index 992bd66..bb370a5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
@@ -66,7 +66,7 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCompoundIdentityFutur
     private GridCacheSharedContext<K, V> cctx;
 
     /** Future ID. */
-    private IgniteUuid futId;
+    private final IgniteUuid futId;
 
     /** Transaction. */
     @GridToStringExclude
@@ -115,26 +115,6 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCompoundIdentityFutur
     }
 
     /** {@inheritDoc} */
-    @Override public GridCacheVersion version() {
-        return tx.xidVersion();
-    }
-
-    /**
-     * @return Involved nodes.
-     */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return
-            F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-                @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                    if (isMini(f))
-                        return ((MiniFuture)f).node();
-
-                    return cctx.discovery().localNode();
-                }
-            });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         for (IgniteInternalFuture<?> fut : futures())
             if (isMini(fut)) {
@@ -228,7 +208,7 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCompoundIdentityFutur
                 this.tx.sendFinishReply(commit, error());
 
                 // Don't forget to clean up.
-                cctx.mvcc().removeFuture(this);
+                cctx.mvcc().removeFuture(futId);
 
                 return true;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
index 2bed931..f344d48 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocal.java
@@ -490,7 +490,7 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
 
         final GridDhtTxFinishFuture fut = new GridDhtTxFinishFuture<>(cctx, this, /*commit*/true);
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         GridDhtTxPrepareFuture prep = prepFut.get();
 
@@ -580,7 +580,7 @@ public class GridDhtTxLocal extends GridDhtTxLocalAdapter implements GridCacheMa
 
         final GridDhtTxFinishFuture fut = new GridDhtTxFinishFuture<>(cctx, this, /*rollback*/false);
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         if (prepFut == null) {
             try {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index d081c0c..4cb5d05 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -243,21 +243,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
         return tx.xidVersion();
     }
 
-    /**
-     * @return Involved nodes.
-     */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return
-            F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-                @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                    if (isMini(f))
-                        return ((MiniFuture)f).node();
-
-                    return cctx.discovery().localNode();
-                }
-            });
-    }
-
     /** {@inheritDoc} */
     @Override public boolean onOwnerChanged(GridCacheEntryEx entry, GridCacheMvccCandidate owner) {
         if (log.isDebugEnabled())
@@ -823,7 +808,7 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
 
         if (super.onDone(res, err.get())) {
             // Don't forget to clean up.
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             return true;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
index febe9ba..c3d9836 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedGetFuture.java
@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
@@ -57,10 +56,11 @@ import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteUuid;
 import org.jetbrains.annotations.Nullable;
 
+import static org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedSingleGetFuture.*;
+
 /**
  * Colocated get future.
  */
@@ -71,15 +71,15 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
     /** Logger reference. */
     private static final AtomicReference<IgniteLogger> logRef = new AtomicReference<>();
 
+    /** Dummy version sent to older nodes for backward compatibility, */
+    private static final GridCacheVersion DUMMY_VER = new GridCacheVersion(0, 0, 0, 0);
+
     /** Logger. */
     private static IgniteLogger log;
 
     /** Topology version. */
     private AffinityTopologyVersion topVer;
 
-    /** Version. */
-    private GridCacheVersion ver;
-
     /**
      * @param cctx Context.
      * @param keys Keys.
@@ -126,8 +126,6 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
 
         this.topVer = topVer;
 
-        ver = cctx.versions().next();
-
         if (log == null)
             log = U.logger(cctx.kernalContext(), logRef, GridPartitionedGetFuture.class);
     }
@@ -160,25 +158,6 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
     }
 
     /** {@inheritDoc} */
-    @Override public GridCacheVersion version() {
-        return ver;
-    }
-
-    /** {@inheritDoc} */
-    @SuppressWarnings("unchecked")
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return
-            F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<Map<K, V>>, ClusterNode>() {
-                @Nullable @Override public ClusterNode apply(IgniteInternalFuture<Map<K, V>> f) {
-                    if (isMini(f))
-                        return ((MiniFuture)f).node();
-
-                    return cctx.discovery().localNode();
-                }
-            });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         boolean found = false;
 
@@ -219,7 +198,7 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
         if (super.onDone(res, err)) {
             // Don't forget to clean up.
             if (trackable)
-                cctx.mvcc().removeFuture(this);
+                cctx.mvcc().removeFuture(futId);
 
             cache().sendTtlUpdateRequest(expiryPlc);
 
@@ -274,9 +253,11 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
             add(new GridFinishedFuture<>(locVals));
 
         if (hasRmtNodes) {
-            trackable = true;
+            if (!trackable) {
+                trackable = true;
 
-            cctx.mvcc().addFuture(this);
+                cctx.mvcc().addFuture(this, futId);
+            }
         }
 
         // Create mini futures.
@@ -343,7 +324,7 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
                     cctx.cacheId(),
                     futId,
                     fut.futureId(),
-                    ver,
+                    n.version().compareTo(SINGLE_GET_MSG_SINCE) >= 0 ? null : DUMMY_VER,
                     mappedKeys,
                     readThrough,
                     topVer,
@@ -390,7 +371,8 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
         boolean remote = false;
 
         // Allow to get cached value from the local node.
-        boolean allowLocRead = !forcePrimary || cctx.affinity().primary(cctx.localNode(), key, topVer);
+        boolean allowLocRead = (cctx.affinityNode() && !forcePrimary) ||
+                cctx.affinity().primary(cctx.localNode(), key, topVer);
 
         while (true) {
             GridCacheEntryEx entry;
@@ -521,28 +503,6 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
     }
 
     /**
-     * Finds affinity node to send get request to.
-     *
-     * @param key Key to get.
-     * @param topVer Topology version.
-     * @return Affinity node from which the key will be requested.
-     */
-    private ClusterNode affinityNode(KeyCacheObject key, AffinityTopologyVersion topVer) {
-        if (!canRemap) {
-            List<ClusterNode> nodes = cctx.affinity().nodes(key, topVer);
-
-            for (ClusterNode node : nodes) {
-                if (cctx.discovery().alive(node))
-                    return node;
-            }
-
-            return null;
-        }
-        else
-            return cctx.affinity().primary(key, topVer);
-    }
-
-    /**
      * @param infos Entry infos.
      * @return Result map.
      */
@@ -557,7 +517,7 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
 
                 if (needVer)
                     versionedResult(map, info.key(), info.value(), info.version());
-                else
+                else {
                     cctx.addResult(map,
                         info.key(),
                         info.value(),
@@ -565,6 +525,7 @@ public class GridPartitionedGetFuture<K, V> extends CacheDistributedGetFutureAda
                         keepCacheObjects,
                         deserializePortable,
                         false);
+                }
             }
 
             return map;


[12/37] ignite git commit: Performance optimizations - reviewed by Yakov.

Posted by ag...@apache.org.
Performance optimizations - reviewed by Yakov.


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

Branch: refs/heads/ignite-1282
Commit: 175b7f24e1d62a90e7a7159ad670036216e6d278
Parents: 4c9ea58
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Wed Nov 18 19:20:45 2015 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Wed Nov 18 19:20:45 2015 +0300

----------------------------------------------------------------------
 .../ignite/codegen/MessageCodeGenerator.java    |  11 +-
 .../communication/GridIoMessageFactory.java     |   6 +
 .../discovery/GridDiscoveryManager.java         |   2 +-
 .../cache/GridCacheDeploymentManager.java       |   2 +-
 .../processors/cache/GridCacheGateway.java      |   1 -
 .../processors/cache/GridCacheMvcc.java         |   7 --
 .../processors/cache/GridCacheMvccManager.java  |  42 -------
 .../GridCachePartitionExchangeManager.java      |  55 ++++++++-
 .../cache/GridCacheSharedContext.java           |   7 +-
 .../distributed/GridCacheTxRecoveryFuture.java  |  41 +++++--
 .../distributed/GridDistributedBaseMessage.java |  56 ---------
 .../distributed/GridDistributedLockRequest.java |   6 -
 .../GridDistributedLockResponse.java            |  32 +-----
 .../GridDistributedTxPrepareRequest.java        |  67 +++++++++--
 .../distributed/dht/GridDhtLockFuture.java      |  63 ++++++----
 .../distributed/dht/GridDhtLockRequest.java     |   2 +-
 .../dht/GridDhtTransactionalCacheAdapter.java   |   5 +-
 .../distributed/dht/GridDhtTxLocalAdapter.java  |   9 ++
 .../distributed/dht/GridDhtTxPrepareFuture.java |  60 ++++++----
 .../dht/GridDhtTxPrepareRequest.java            |  54 ++++-----
 .../dht/colocated/GridDhtColocatedCache.java    |   2 +-
 .../colocated/GridDhtColocatedLockFuture.java   |  55 ++++++---
 .../distributed/near/GridNearLockFuture.java    |  56 ++++++---
 .../distributed/near/GridNearLockRequest.java   |   4 +-
 ...arOptimisticSerializableTxPrepareFuture.java |  91 +++++++++------
 .../near/GridNearOptimisticTxPrepareFuture.java |  50 +++++---
 .../GridNearPessimisticTxPrepareFuture.java     |  39 +++++--
 .../near/GridNearTransactionalCache.java        |   7 +-
 .../near/GridNearTxFinishFuture.java            |  18 ++-
 .../cache/distributed/near/GridNearTxLocal.java |  15 ---
 .../near/GridNearTxPrepareFutureAdapter.java    |  14 ++-
 .../near/GridNearTxPrepareRequest.java          |  52 ++++-----
 .../cache/transactions/IgniteInternalTx.java    |   1 +
 .../cache/transactions/IgniteTxAdapter.java     |   1 +
 .../cache/transactions/IgniteTxEntry.java       |   9 +-
 .../IgniteTxImplicitSingleStateImpl.java        |   7 ++
 .../transactions/IgniteTxLocalAdapter.java      |  12 +-
 .../cache/transactions/IgniteTxManager.java     |   1 +
 .../IgniteTxRemoteStateAdapter.java             |   5 +
 .../cache/transactions/IgniteTxState.java       |   6 +
 .../cache/transactions/IgniteTxStateImpl.java   |  69 ++++++++---
 .../clock/GridClockSyncProcessor.java           |  28 ++++-
 .../internal/util/UUIDCollectionMessage.java    | 114 +++++++++++++++++++
 .../util/future/GridCompoundFuture.java         |  15 ++-
 .../ignite/internal/util/lang/GridFunc.java     |   8 +-
 .../ignite/internal/util/nio/GridNioServer.java |  13 ++-
 .../IgniteCacheTxStoreSessionTest.java          |   2 +-
 .../testsuites/IgniteCacheTestSuite3.java       |   2 +
 48 files changed, 805 insertions(+), 419 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
index 8d9a3f5..74c71c4 100644
--- a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
+++ b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
@@ -43,6 +43,10 @@ import org.apache.ignite.internal.GridDirectCollection;
 import org.apache.ignite.internal.GridDirectMap;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.IgniteCodeGeneratingFail;
+import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxPrepareRequest;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxPrepareRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareRequest;
+import org.apache.ignite.internal.util.UUIDCollectionMessage;
 import org.apache.ignite.internal.util.typedef.internal.SB;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteUuid;
@@ -165,7 +169,12 @@ public class MessageCodeGenerator {
 
         MessageCodeGenerator gen = new MessageCodeGenerator(srcDir);
 
-        gen.generateAll(true);
+        gen.generateAndWrite(GridDistributedTxPrepareRequest.class);
+        gen.generateAndWrite(GridDhtTxPrepareRequest.class);
+        gen.generateAndWrite(GridNearTxPrepareRequest.class);
+        gen.generateAndWrite(UUIDCollectionMessage.class);
+
+//        gen.generateAll(true);
 
 //        gen.generateAndWrite(DataStreamerEntry.class);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index ae8c753..2503eda 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -121,6 +121,7 @@ import org.apache.ignite.internal.processors.rest.handlers.task.GridTaskResultRe
 import org.apache.ignite.internal.processors.rest.handlers.task.GridTaskResultResponse;
 import org.apache.ignite.internal.util.GridByteArrayList;
 import org.apache.ignite.internal.util.GridLongList;
+import org.apache.ignite.internal.util.UUIDCollectionMessage;
 import org.apache.ignite.lang.IgniteOutClosure;
 import org.apache.ignite.plugin.extensions.communication.Message;
 import org.apache.ignite.plugin.extensions.communication.MessageFactory;
@@ -690,6 +691,11 @@ public class GridIoMessageFactory implements MessageFactory {
 
                 break;
 
+            case 115:
+                msg = new UUIDCollectionMessage();
+
+                break;
+
             // [-3..114] - this
             // [120..123] - DR
             // [-4..-22] - SQL

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
index cd2f49c..4880338 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/discovery/GridDiscoveryManager.java
@@ -2136,7 +2136,7 @@ public class GridDiscoveryManager extends GridManagerAdapter<DiscoverySpi> {
                         customEvt.node(ctx.discovery().localNode());
                         customEvt.eventNode(node);
                         customEvt.type(type);
-                        customEvt.topologySnapshot(topVer.topologyVersion(), null);
+                        customEvt.topologySnapshot(topVer.topologyVersion(), evt.get4());
                         customEvt.affinityTopologyVersion(topVer);
                         customEvt.customMessage(evt.get5());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
index 40c5b0f..35e8b75 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDeploymentManager.java
@@ -164,7 +164,7 @@ public class GridCacheDeploymentManager<K, V> extends GridCacheSharedManagerAdap
      * Callback on method enter.
      */
     public void onEnter() {
-        if (!locDepOwner && depEnabled && !ignoreOwnership.get()
+        if (depEnabled && !locDepOwner && !ignoreOwnership.get()
             && !cctx.kernalContext().job().internal()) {
             ClassLoader ldr = Thread.currentThread().getContextClassLoader();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
index 0eac5ba..1562d70 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheGateway.java
@@ -109,7 +109,6 @@ public class GridCacheGateway<K, V> {
         rwLock.readLock();
 
         return checkState(true, false);
-
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/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 12583ad..adcbf92 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
@@ -348,9 +348,6 @@ public final class GridCacheMvcc {
 
                     reassign();
 
-                    if (cand.local())
-                        cctx.mvcc().removeLocal(cand);
-
                     return true;
                 }
             }
@@ -596,8 +593,6 @@ public final class GridCacheMvcc {
         );
 
         if (serOrder == null) {
-            cctx.mvcc().addLocal(cand);
-
             boolean add = add0(cand);
 
             assert add : cand;
@@ -605,8 +600,6 @@ public final class GridCacheMvcc {
         else {
             if (!add0(cand))
                 return null;
-
-            cctx.mvcc().addLocal(cand);
         }
 
         return cand;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
index 2c14209..8562f37 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMvccManager.java
@@ -29,7 +29,6 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ConcurrentSkipListSet;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cluster.ClusterNode;
@@ -92,9 +91,6 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
     private GridBoundedConcurrentLinkedHashSet<GridCacheVersion> rmvLocks =
         new GridBoundedConcurrentLinkedHashSet<>(MAX_REMOVED_LOCKS, MAX_REMOVED_LOCKS, 0.75f, 16, PER_SEGMENT_Q);
 
-    /** Current local candidates. */
-    private Collection<GridCacheMvccCandidate> dhtLocCands = new ConcurrentSkipListSet<>();
-
     /** Locked keys. */
     @GridToStringExclude
     private final ConcurrentMap<IgniteTxKey, GridDistributedCacheEntry> locked = newMap();
@@ -707,43 +703,6 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
     }
 
     /**
-     * @param cand Local lock.
-     * @return {@code True} if added.
-     */
-    public boolean addLocal(GridCacheMvccCandidate cand) {
-        assert cand.key() != null : cand;
-        assert cand.local() : cand;
-
-        if (cand.dhtLocal() && dhtLocCands.add(cand)) {
-            if (log.isDebugEnabled())
-                log.debug("Added local candidate: " + cand);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
-     *
-     * @param cand Local candidate to remove.
-     * @return {@code True} if removed.
-     */
-    public boolean removeLocal(GridCacheMvccCandidate cand) {
-        assert cand.key() != null : cand;
-        assert cand.local() : cand;
-
-        if (cand.dhtLocal() && dhtLocCands.remove(cand)) {
-            if (log.isDebugEnabled())
-                log.debug("Removed local candidate: " + cand);
-
-            return true;
-        }
-
-        return false;
-    }
-
-    /**
      * @param cacheCtx Cache context.
      * @param cand Cache lock candidate to add.
      * @return {@code True} if added as a result of this operation,
@@ -953,7 +912,6 @@ public class GridCacheMvccManager extends GridCacheSharedManagerAdapter {
         X.println(">>> ");
         X.println(">>> Mvcc manager memory stats [grid=" + cctx.gridName() + ']');
         X.println(">>>   rmvLocksSize: " + rmvLocks.sizex());
-        X.println(">>>   dhtLocCandsSize: " + dhtLocCands.size());
         X.println(">>>   lockedSize: " + locked.size());
         X.println(">>>   futsSize: " + futs.size());
         X.println(">>>   near2dhtSize: " + near2dht.size());

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
index 81ff028..e19b310 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
@@ -30,6 +30,7 @@ import java.util.UUID;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentSkipListMap;
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
@@ -66,6 +67,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObject;
 import org.apache.ignite.internal.util.GridListSet;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.apache.ignite.internal.util.lang.IgnitePair;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.CI1;
@@ -77,6 +79,7 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.internal.util.worker.GridWorker;
 import org.apache.ignite.lang.IgniteBiInClosure;
+import org.apache.ignite.lang.IgniteProductVersion;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.thread.IgniteThread;
 import org.jetbrains.annotations.Nullable;
@@ -134,6 +137,10 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
     private final ConcurrentMap<AffinityTopologyVersion, AffinityReadyFuture> readyFuts = new ConcurrentHashMap8<>();
 
     /** */
+    private final ConcurrentSkipListMap<AffinityTopologyVersion, IgnitePair<IgniteProductVersion>> nodeVers =
+        new ConcurrentSkipListMap<>();
+
+    /** */
     private final AtomicReference<AffinityTopologyVersion> readyTopVer =
         new AtomicReference<>(AffinityTopologyVersion.NONE);
 
@@ -572,6 +579,30 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
     }
 
     /**
+     * Gets minimum node version for the given topology version.
+     *
+     * @param topVer Topology version to get minimum node version for.
+     * @return Minimum node version.
+     */
+    public IgniteProductVersion minimumNodeVersion(AffinityTopologyVersion topVer) {
+        IgnitePair<IgniteProductVersion> vers = nodeVers.get(topVer);
+
+        return vers == null ? cctx.localNode().version() : vers.get1();
+    }
+
+    /**
+     * Gets maximum node version for the given topology version.
+     *
+     * @param topVer Topology version to get maximum node version for.
+     * @return Maximum node version.
+     */
+    public IgniteProductVersion maximumNodeVersion(AffinityTopologyVersion topVer) {
+        IgnitePair<IgniteProductVersion> vers = nodeVers.get(topVer);
+
+        return vers == null ? cctx.localNode().version() : vers.get2();
+    }
+
+    /**
      * @return {@code true} if entered to busy state.
      */
     private boolean enterBusy() {
@@ -832,6 +863,28 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
         if (log.isDebugEnabled())
             log.debug("Exchange done [topVer=" + topVer + ", fut=" + exchFut + ", err=" + err + ']');
 
+        IgniteProductVersion minVer = cctx.localNode().version();
+        IgniteProductVersion maxVer = cctx.localNode().version();
+
+        if (err == null) {
+            if (!F.isEmpty(exchFut.discoveryEvent().topologyNodes())) {
+                for (ClusterNode node : exchFut.discoveryEvent().topologyNodes()) {
+                    IgniteProductVersion ver = node.version();
+
+                    if (ver.compareTo(minVer) < 0)
+                        minVer = ver;
+
+                    if (ver.compareTo(maxVer) > 0)
+                        maxVer = ver;
+                }
+            }
+        }
+
+        nodeVers.put(topVer, new IgnitePair<>(minVer, maxVer));
+
+        for (AffinityTopologyVersion oldVer : nodeVers.headMap(new AffinityTopologyVersion(topVer.topologyVersion() - 10, 0)).keySet())
+            nodeVers.remove(oldVer);
+
         if (err == null) {
             while (true) {
                 AffinityTopologyVersion readyVer = readyTopVer.get();
@@ -1050,7 +1103,7 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
 
             int cnt = 0;
 
-            for (GridDhtPartitionsExchangeFuture fut : exchFuts) {
+            for (GridDhtPartitionsExchangeFuture fut : exchFuts.values()) {
                 U.warn(log, ">>> " + fut);
 
                 if (++cnt == 10)

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
index 4293b90..608829a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheSharedContext.java
@@ -44,6 +44,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxManager;
 import org.apache.ignite.internal.processors.cache.transactions.TransactionMetricsAdapter;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersionManager;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridCompoundFuture;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -533,7 +534,7 @@ public class GridCacheSharedContext<K, V> {
      * @param cacheCtx Cache context.
      * @return Error message if transactions are incompatible.
      */
-    @Nullable public String verifyTxCompatibility(IgniteInternalTx tx, Iterable<Integer> activeCacheIds,
+    @Nullable public String verifyTxCompatibility(IgniteInternalTx tx, GridLongList activeCacheIds,
         GridCacheContext<K, V> cacheCtx) {
         if (cacheCtx.systemTx() && !tx.system())
             return "system cache can be enlisted only in system transaction";
@@ -541,7 +542,9 @@ public class GridCacheSharedContext<K, V> {
         if (!cacheCtx.systemTx() && tx.system())
             return "non-system cache can't be enlisted in system transaction";
 
-        for (Integer cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             GridCacheContext<K, V> activeCacheCtx = cacheContext(cacheId);
 
             if (cacheCtx.systemTx()) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
index b266c4d..01c4867 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTxRecoveryFuture.java
@@ -342,20 +342,45 @@ public class GridCacheTxRecoveryFuture extends GridCompoundIdentityFuture<Boolea
      */
     public void onResult(UUID nodeId, GridCacheTxRecoveryResponse res) {
         if (!isDone()) {
-            for (IgniteInternalFuture<Boolean> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture f = (MiniFuture)fut;
+            MiniFuture mini = miniFuture(res.miniId());
 
-                    if (f.futureId().equals(res.miniId())) {
-                        assert f.nodeId().equals(nodeId);
+            if (mini != null) {
+                assert mini.nodeId().equals(nodeId);
 
-                        f.onResult(res);
+                mini.onResult(res);
+            }
+        }
+    }
 
-                        break;
-                    }
+    /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<Boolean> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
                 }
             }
         }
+
+        return null;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedBaseMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedBaseMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedBaseMessage.java
index f4a16dc..ebbc9ae 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedBaseMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedBaseMessage.java
@@ -21,13 +21,10 @@ import java.io.Externalizable;
 import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.Collections;
-import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridDirectCollection;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.processors.cache.GridCacheDeployable;
 import org.apache.ignite.internal.processors.cache.GridCacheMessage;
-import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
-import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersionable;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -49,15 +46,6 @@ public abstract class GridDistributedBaseMessage extends GridCacheMessage implem
     @GridToStringInclude
     protected GridCacheVersion ver;
 
-    /**
-     * Candidates for every key ordered in the order of keys. These
-     * can be either local-only candidates in case of lock acquisition,
-     * or pending candidates in case of transaction commit.
-     */
-    @GridToStringInclude
-    @GridDirectTransient
-    private Collection<GridCacheMvccCandidate>[] candsByIdx;
-
     /** */
     @GridToStringExclude
     private byte[] candsByIdxBytes;
@@ -108,23 +96,6 @@ public abstract class GridDistributedBaseMessage extends GridCacheMessage implem
         this.ver = ver;
     }
 
-    /** {@inheritDoc}
-     * @param ctx*/
-    @Override public void prepareMarshal(GridCacheSharedContext ctx) throws IgniteCheckedException {
-        super.prepareMarshal(ctx);
-
-        if (candsByIdx != null)
-            candsByIdxBytes = ctx.marshaller().marshal(candsByIdx);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void finishUnmarshal(GridCacheSharedContext ctx, ClassLoader ldr) throws IgniteCheckedException {
-        super.finishUnmarshal(ctx, ldr);
-
-        if (candsByIdxBytes != null)
-            candsByIdx = ctx.marshaller().unmarshal(candsByIdxBytes, ldr);
-    }
-
     /** {@inheritDoc} */
     @Override public boolean addDeploymentInfo() {
         return addDepInfo;
@@ -169,33 +140,6 @@ public abstract class GridDistributedBaseMessage extends GridCacheMessage implem
     }
 
     /**
-     * @param idx Key index.
-     * @param candsByIdx List of candidates for that key.
-     */
-    @SuppressWarnings({"unchecked"})
-    public void candidatesByIndex(int idx, Collection<GridCacheMvccCandidate> candsByIdx) {
-        assert idx < cnt;
-
-        // If nothing to add.
-        if (candsByIdx == null || candsByIdx.isEmpty())
-            return;
-
-        if (this.candsByIdx == null)
-            this.candsByIdx = new Collection[cnt];
-
-        this.candsByIdx[idx] = candsByIdx;
-    }
-
-    /**
-     * @param idx Key index.
-     * @return Candidates for given key.
-     */
-    public Collection<GridCacheMvccCandidate> candidatesByIndex(int idx) {
-        return candsByIdx == null ||
-            candsByIdx[idx] == null ? Collections.<GridCacheMvccCandidate>emptyList() : candsByIdx[idx];
-    }
-
-    /**
      * @return Count of keys referenced in candidates array (needed only locally for optimization).
      */
     public int keysCount() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
index 2899e25..b584f8a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockRequest.java
@@ -19,14 +19,12 @@ package org.apache.ignite.internal.processors.cache.distributed;
 
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridDirectCollection;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
-import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
@@ -261,14 +259,12 @@ public class GridDistributedLockRequest extends GridDistributedBaseMessage {
      *
      * @param key Key.
      * @param retVal Flag indicating whether value should be returned.
-     * @param cands Candidates.
      * @param ctx Context.
      * @throws IgniteCheckedException If failed.
      */
     public void addKeyBytes(
         KeyCacheObject key,
         boolean retVal,
-        @Nullable Collection<GridCacheMvccCandidate> cands,
         GridCacheContext ctx
     ) throws IgniteCheckedException {
         if (keys == null)
@@ -276,8 +272,6 @@ public class GridDistributedLockRequest extends GridDistributedBaseMessage {
 
         keys.add(key);
 
-        candidatesByIndex(idx, cands);
-
         retVals[idx] = retVal;
 
         idx++;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java
index cdd58b5..bb3f9ff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedLockResponse.java
@@ -26,7 +26,6 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridDirectCollection;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.processors.cache.CacheObject;
-import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
@@ -156,34 +155,11 @@ public class GridDistributedLockResponse extends GridDistributedBaseMessage {
     }
 
     /**
-     * @param idx Index of locked flag.
-     * @return Value of locked flag at given index.
-     */
-    public boolean isCurrentlyLocked(int idx) {
-        assert idx >= 0;
-
-        Collection<GridCacheMvccCandidate> cands = candidatesByIndex(idx);
-
-        for (GridCacheMvccCandidate cand : cands)
-            if (cand.owner())
-                return true;
-
-        return false;
-    }
-
-    /**
-     * @param idx Candidates index.
-     * @param cands Collection of candidates.
      * @param committedVers Committed versions relative to lock version.
      * @param rolledbackVers Rolled back versions relative to lock version.
      */
-    public void setCandidates(int idx, Collection<GridCacheMvccCandidate> cands,
-        Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledbackVers) {
-        assert idx >= 0;
-
+    public void setCandidates(Collection<GridCacheVersion> committedVers, Collection<GridCacheVersion> rolledbackVers) {
         completedVersions(committedVers, rolledbackVers);
-
-        candidatesByIndex(idx, cands);
     }
 
     /**
@@ -218,9 +194,6 @@ public class GridDistributedLockResponse extends GridDistributedBaseMessage {
 
         prepareMarshalCacheObjects(vals, ctx.cacheContext(cacheId));
 
-//        if (F.isEmpty(valBytes) && !F.isEmpty(vals))
-//            valBytes = marshalValuesCollection(vals, ctx);
-
         if (err != null)
             errBytes = ctx.marshaller().marshal(err);
     }
@@ -231,9 +204,6 @@ public class GridDistributedLockResponse extends GridDistributedBaseMessage {
 
         finishUnmarshalCacheObjects(vals, ctx.cacheContext(cacheId), ldr);
 
-//        if (F.isEmpty(vals) && !F.isEmpty(valBytes))
-//            vals = unmarshalValueBytesCollection(valBytes, ctx, ldr);
-
         if (errBytes != null)
             err = ctx.marshaller().unmarshal(errBytes, ldr);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
index 533c8ca..95176ff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxPrepareRequest.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.GridDirectMap;
 import org.apache.ignite.internal.GridDirectTransient;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
@@ -34,9 +35,13 @@ 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.version.GridCacheVersion;
+import org.apache.ignite.internal.util.UUIDCollectionMessage;
 import org.apache.ignite.internal.util.tostring.GridToStringBuilder;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.C1;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteProductVersion;
 import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
 import org.apache.ignite.plugin.extensions.communication.MessageReader;
 import org.apache.ignite.plugin.extensions.communication.MessageWriter;
@@ -52,6 +57,23 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** Version in which direct marshalling of tx nodes was introduced. */
+    public static final IgniteProductVersion TX_NODES_DIRECT_MARSHALLABLE_SINCE = IgniteProductVersion.fromString("1.5.0");
+
+    /** Collection to message converter. */
+    public static final C1<Collection<UUID>, UUIDCollectionMessage> COL_TO_MSG = new C1<Collection<UUID>, UUIDCollectionMessage>() {
+        @Override public UUIDCollectionMessage apply(Collection<UUID> uuids) {
+            return new UUIDCollectionMessage(uuids);
+        }
+    };
+
+    /** Message to collection converter. */
+    public static final C1<UUIDCollectionMessage, Collection<UUID>> MSG_TO_COL = new C1<UUIDCollectionMessage, Collection<UUID>>() {
+        @Override public Collection<UUID> apply(UUIDCollectionMessage msg) {
+            return msg.uuids();
+        }
+    };
+
     /** Thread ID. */
     @GridToStringInclude
     private long threadId;
@@ -106,6 +128,10 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
     @GridDirectTransient
     private Map<UUID, Collection<UUID>> txNodes;
 
+    /** Tx nodes direct marshallable message. */
+    @GridDirectMap(keyType = UUID.class, valueType = UUIDCollectionMessage.class)
+    private Map<UUID, UUIDCollectionMessage> txNodesMsg;
+
     /** */
     private byte[] txNodesBytes;
 
@@ -302,8 +328,16 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
             dhtVerVals = dhtVers.values();
         }
 
-        if (txNodes != null)
-            txNodesBytes = ctx.marshaller().marshal(txNodes);
+        // Marshal txNodes only if there is a node in topology with an older version.
+        if (ctx.exchange().minimumNodeVersion(topologyVersion())
+            .compareTo(TX_NODES_DIRECT_MARSHALLABLE_SINCE) < 0) {
+            if (txNodes != null && txNodesBytes == null)
+                txNodesBytes = ctx.marshaller().marshal(txNodes);
+        }
+        else {
+            if (txNodesMsg == null)
+                txNodesMsg = F.viewReadOnly(txNodes, COL_TO_MSG);
+        }
     }
 
     /** {@inheritDoc} */
@@ -334,7 +368,10 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
             }
         }
 
-        if (txNodesBytes != null)
+        if (txNodesMsg != null)
+            txNodes = F.viewReadOnly(txNodesMsg, MSG_TO_COL);
+
+        if (txNodesBytes != null && txNodes == null)
             txNodes = ctx.marshaller().unmarshal(txNodesBytes, ldr);
     }
 
@@ -431,18 +468,24 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
                 writer.incrementState();
 
             case 19:
-                if (!writer.writeInt("txSize", txSize))
+                if (!writer.writeMap("txNodesMsg", txNodesMsg, MessageCollectionItemType.UUID, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
             case 20:
-                if (!writer.writeMessage("writeVer", writeVer))
+                if (!writer.writeInt("txSize", txSize))
                     return false;
 
                 writer.incrementState();
 
             case 21:
+                if (!writer.writeMessage("writeVer", writeVer))
+                    return false;
+
+                writer.incrementState();
+
+            case 22:
                 if (!writer.writeCollection("writes", writes, MessageCollectionItemType.MSG))
                     return false;
 
@@ -569,7 +612,7 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
                 reader.incrementState();
 
             case 19:
-                txSize = reader.readInt("txSize");
+                txNodesMsg = reader.readMap("txNodesMsg", MessageCollectionItemType.UUID, MessageCollectionItemType.MSG, false);
 
                 if (!reader.isLastRead())
                     return false;
@@ -577,7 +620,7 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
                 reader.incrementState();
 
             case 20:
-                writeVer = reader.readMessage("writeVer");
+                txSize = reader.readInt("txSize");
 
                 if (!reader.isLastRead())
                     return false;
@@ -585,6 +628,14 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
                 reader.incrementState();
 
             case 21:
+                writeVer = reader.readMessage("writeVer");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 22:
                 writes = reader.readCollection("writes", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
@@ -604,7 +655,7 @@ public class GridDistributedTxPrepareRequest extends GridDistributedBaseMessage
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 22;
+        return 23;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
index 579d701..7284fd4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockFuture.java
@@ -380,10 +380,9 @@ public final class GridDhtLockFuture extends GridCompoundIdentityFuture<Boolean>
      * @return Lock candidate.
      * @throws GridCacheEntryRemovedException If entry was removed.
      * @throws GridDistributedLockCancelledException If lock is canceled.
-     * @throws IgniteCheckedException If failed.
      */
     @Nullable public GridCacheMvccCandidate addEntry(GridDhtCacheEntry entry)
-        throws GridCacheEntryRemovedException, GridDistributedLockCancelledException, IgniteCheckedException {
+        throws GridCacheEntryRemovedException, GridDistributedLockCancelledException {
         if (log.isDebugEnabled())
             log.debug("Adding entry: " + entry);
 
@@ -529,35 +528,57 @@ public final class GridDhtLockFuture extends GridCompoundIdentityFuture<Boolean>
             if (log.isDebugEnabled())
                 log.debug("Received lock response from node [nodeId=" + nodeId + ", res=" + res + ", fut=" + this + ']');
 
-            boolean found = false;
+            MiniFuture mini = miniFuture(res.miniId());
 
-            for (IgniteInternalFuture<Boolean> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture mini = (MiniFuture)fut;
+            if (mini != null) {
+                assert mini.node().id().equals(nodeId);
 
-                    if (mini.futureId().equals(res.miniId())) {
-                        assert mini.node().id().equals(nodeId);
+                if (log.isDebugEnabled())
+                    log.debug("Found mini future for response [mini=" + mini + ", res=" + res + ']');
 
-                        if (log.isDebugEnabled())
-                            log.debug("Found mini future for response [mini=" + mini + ", res=" + res + ']');
+                mini.onResult(res);
 
-                        found = true;
+                if (log.isDebugEnabled())
+                    log.debug("Futures after processed lock response [fut=" + this + ", mini=" + mini +
+                        ", res=" + res + ']');
 
-                        mini.onResult(res);
+                return;
+            }
 
-                        if (log.isDebugEnabled())
-                            log.debug("Futures after processed lock response [fut=" + this + ", mini=" + mini +
-                                ", res=" + res + ']');
+            U.warn(log, "Failed to find mini future for response (perhaps due to stale message) [res=" + res +
+                ", fut=" + this + ']');
+        }
+    }
 
-                        break;
-                    }
+    /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<Boolean> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
                 }
             }
-
-            if (!found)
-                U.warn(log, "Failed to find mini future for response (perhaps due to stale message) [res=" + res +
-                    ", fut=" + this + ']');
         }
+
+        return null;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
index 91ab1ca..18281d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLockRequest.java
@@ -236,7 +236,7 @@ public class GridDhtLockRequest extends GridDistributedLockRequest {
     ) throws IgniteCheckedException {
         invalidateEntries.set(idx, invalidateEntry);
 
-        addKeyBytes(key, false, null, ctx);
+        addKeyBytes(key, false, ctx);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
index fe91e5b..35f63e3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTransactionalCacheAdapter.java
@@ -39,7 +39,6 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryInfo;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
-import org.apache.ignite.internal.processors.cache.GridCacheFilterFailedException;
 import org.apache.ignite.internal.processors.cache.GridCacheLockTimeoutException;
 import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
 import org.apache.ignite.internal.processors.cache.GridCacheReturn;
@@ -187,8 +186,6 @@ public abstract class GridDhtTransactionalCacheAdapter<K, V> extends GridDhtCach
 
             IgniteTxKey txKey = ctx.txKey(key);
 
-            assert F.isEmpty(req.candidatesByIndex(i));
-
             if (log.isDebugEnabled())
                 log.debug("Unmarshalled key: " + key);
 
@@ -671,7 +668,7 @@ public abstract class GridDhtTransactionalCacheAdapter<K, V> extends GridDhtCach
                         if (log.isDebugEnabled())
                             log.debug("Got removed entry when adding lock (will retry): " + entry);
                     }
-                    catch (IgniteCheckedException | GridDistributedLockCancelledException e) {
+                    catch (GridDistributedLockCancelledException e) {
                         if (log.isDebugEnabled())
                             log.debug("Failed to add entry [err=" + e + ", entry=" + entry + ']');
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
index 70ebf3f..55ca12d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxLocalAdapter.java
@@ -181,6 +181,15 @@ public abstract class GridDhtTxLocalAdapter extends IgniteTxLocalAdapter {
     }
 
     /**
+     * Gets flag that indicates that originating node has a near cache that participates in this transaction.
+     *
+     * @return Has near cache flag.
+     */
+    public boolean nearOnOriginatingNode() {
+        return nearOnOriginatingNode;
+    }
+
+    /**
      * @return {@code True} if explicit lock transaction.
      */
     public boolean explicitLock() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
index a67950d..d081c0c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareFuture.java
@@ -450,20 +450,45 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
      */
     public void onResult(UUID nodeId, GridDhtTxPrepareResponse res) {
         if (!isDone()) {
-            for (IgniteInternalFuture<IgniteInternalTx> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture f = (MiniFuture)fut;
+            MiniFuture mini = miniFuture(res.miniId());
 
-                    if (f.futureId().equals(res.miniId())) {
-                        assert f.node().id().equals(nodeId);
+            if (mini != null) {
+                assert mini.node().id().equals(nodeId);
 
-                        f.onResult(res);
+                mini.onResult(res);
+            }
+        }
+    }
 
-                        break;
-                    }
+    /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<IgniteInternalTx> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
                 }
             }
         }
+
+        return null;
     }
 
     /**
@@ -693,7 +718,8 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
             tx.activeCachesDeploymentEnabled());
 
         if (prepErr == null) {
-            addDhtValues(res);
+            if (tx.needReturnValue() || tx.nearOnOriginatingNode() || tx.hasInterceptor())
+                addDhtValues(res);
 
             GridCacheVersion min = tx.minVersion();
 
@@ -949,7 +975,7 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
                 }
             }
         }
-        catch (GridCacheEntryRemovedException e) {
+        catch (GridCacheEntryRemovedException ignore) {
             assert false : "Got removed exception on entry with dht local candidate: " + entries;
         }
 
@@ -1072,18 +1098,6 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
 
                             GridCacheContext<?, ?> cacheCtx = cached.context();
 
-                            if (entry.explicitVersion() == null) {
-                                GridCacheMvccCandidate added = cached.candidate(version());
-
-                                assert added != null : "Null candidate for non-group-lock entry " +
-                                    "[added=" + added + ", entry=" + entry + ']';
-                                assert added.dhtLocal() : "Got non-dht-local candidate for prepare future" +
-                                    "[added=" + added + ", entry=" + entry + ']';
-
-                                if (added != null && added.ownerVersion() != null)
-                                    req.owned(entry.txKey(), added.ownerVersion());
-                            }
-
                             // Do not invalidate near entry on originating transaction node.
                             req.invalidateNearEntry(idx, !tx.nearNodeId().equals(n.id()) &&
                                 cached.readerId(n.id()) != null);
@@ -1092,7 +1106,7 @@ public final class GridDhtTxPrepareFuture extends GridCompoundFuture<IgniteInter
                                 List<ClusterNode> owners = cacheCtx.topology().owners(cached.partition(),
                                     tx != null ? tx.topologyVersion() : cacheCtx.affinity().affinityTopologyVersion());
 
-                                // Do not preload if local node is partition owner.
+                                // Do not preload if local node is a partition owner.
                                 if (!owners.contains(cctx.localNode()))
                                     req.markKeyForPreload(idx);
                             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
index fcd66c2..394ff89 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxPrepareRequest.java
@@ -345,79 +345,79 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
         }
 
         switch (writer.state()) {
-            case 22:
+            case 23:
                 if (!writer.writeIgniteUuid("futId", futId))
                     return false;
 
                 writer.incrementState();
 
-            case 23:
+            case 24:
                 if (!writer.writeBitSet("invalidateNearEntries", invalidateNearEntries))
                     return false;
 
                 writer.incrementState();
 
-            case 24:
+            case 25:
                 if (!writer.writeBoolean("last", last))
                     return false;
 
                 writer.incrementState();
 
-            case 25:
+            case 26:
                 if (!writer.writeIgniteUuid("miniId", miniId))
                     return false;
 
                 writer.incrementState();
 
-            case 26:
+            case 27:
                 if (!writer.writeUuid("nearNodeId", nearNodeId))
                     return false;
 
                 writer.incrementState();
 
-            case 27:
+            case 28:
                 if (!writer.writeCollection("nearWrites", nearWrites, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
-            case 28:
+            case 29:
                 if (!writer.writeMessage("nearXidVer", nearXidVer))
                     return false;
 
                 writer.incrementState();
 
-            case 29:
+            case 30:
                 if (!writer.writeCollection("ownedKeys", ownedKeys, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
-            case 30:
+            case 31:
                 if (!writer.writeCollection("ownedVals", ownedVals, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
-            case 31:
+            case 32:
                 if (!writer.writeBitSet("preloadKeys", preloadKeys))
                     return false;
 
                 writer.incrementState();
 
-            case 32:
+            case 33:
                 if (!writer.writeUuid("subjId", subjId))
                     return false;
 
                 writer.incrementState();
 
-            case 33:
+            case 34:
                 if (!writer.writeInt("taskNameHash", taskNameHash))
                     return false;
 
                 writer.incrementState();
 
-            case 34:
+            case 35:
                 if (!writer.writeMessage("topVer", topVer))
                     return false;
 
@@ -439,7 +439,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
             return false;
 
         switch (reader.state()) {
-            case 22:
+            case 23:
                 futId = reader.readIgniteUuid("futId");
 
                 if (!reader.isLastRead())
@@ -447,7 +447,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 23:
+            case 24:
                 invalidateNearEntries = reader.readBitSet("invalidateNearEntries");
 
                 if (!reader.isLastRead())
@@ -455,7 +455,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 24:
+            case 25:
                 last = reader.readBoolean("last");
 
                 if (!reader.isLastRead())
@@ -463,7 +463,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 25:
+            case 26:
                 miniId = reader.readIgniteUuid("miniId");
 
                 if (!reader.isLastRead())
@@ -471,7 +471,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 26:
+            case 27:
                 nearNodeId = reader.readUuid("nearNodeId");
 
                 if (!reader.isLastRead())
@@ -479,7 +479,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 27:
+            case 28:
                 nearWrites = reader.readCollection("nearWrites", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
@@ -487,7 +487,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 28:
+            case 29:
                 nearXidVer = reader.readMessage("nearXidVer");
 
                 if (!reader.isLastRead())
@@ -495,7 +495,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 29:
+            case 30:
                 ownedKeys = reader.readCollection("ownedKeys", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
@@ -503,7 +503,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 30:
+            case 31:
                 ownedVals = reader.readCollection("ownedVals", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
@@ -511,7 +511,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 31:
+            case 32:
                 preloadKeys = reader.readBitSet("preloadKeys");
 
                 if (!reader.isLastRead())
@@ -519,7 +519,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 32:
+            case 33:
                 subjId = reader.readUuid("subjId");
 
                 if (!reader.isLastRead())
@@ -527,7 +527,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 33:
+            case 34:
                 taskNameHash = reader.readInt("taskNameHash");
 
                 if (!reader.isLastRead())
@@ -535,7 +535,7 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 34:
+            case 35:
                 topVer = reader.readMessage("topVer");
 
                 if (!reader.isLastRead())
@@ -555,6 +555,6 @@ public class GridDhtTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 35;
+        return 36;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
index 83c220d..7131aa5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
@@ -873,7 +873,7 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
                         if (log.isDebugEnabled())
                             log.debug("Got removed entry when adding lock (will retry): " + entry);
                     }
-                    catch (IgniteCheckedException | GridDistributedLockCancelledException e) {
+                    catch (GridDistributedLockCancelledException e) {
                         if (log.isDebugEnabled())
                             log.debug("Failed to add entry [err=" + e + ", entry=" + entry + ']');
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
index 365b46b..abeb509 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
@@ -428,25 +428,21 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                 log.debug("Received lock response from node [nodeId=" + nodeId + ", res=" + res + ", fut=" +
                     this + ']');
 
-            for (IgniteInternalFuture<Boolean> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture mini = (MiniFuture)fut;
+            MiniFuture mini = miniFuture(res.miniId());
 
-                    if (mini.futureId().equals(res.miniId())) {
-                        assert mini.node().id().equals(nodeId);
+            if (mini != null) {
+                assert mini.node().id().equals(nodeId);
 
-                        if (log.isDebugEnabled())
-                            log.debug("Found mini future for response [mini=" + mini + ", res=" + res + ']');
+                if (log.isDebugEnabled())
+                    log.debug("Found mini future for response [mini=" + mini + ", res=" + res + ']');
 
-                        mini.onResult(res);
+                mini.onResult(res);
 
-                        if (log.isDebugEnabled())
-                            log.debug("Future after processed lock response [fut=" + this + ", mini=" + mini +
-                                ", res=" + res + ']');
+                if (log.isDebugEnabled())
+                    log.debug("Future after processed lock response [fut=" + this + ", mini=" + mini +
+                        ", res=" + res + ']');
 
-                        return;
-                    }
-                }
+                return;
             }
 
             U.warn(log, "Failed to find mini future for response (perhaps due to stale message) [res=" + res +
@@ -458,6 +454,37 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
     }
 
     /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<Boolean> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * @param t Error.
      */
     private void onError(Throwable t) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
index c5b55bd..9c3701f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
@@ -478,25 +478,21 @@ public final class GridNearLockFuture extends GridCompoundIdentityFuture<Boolean
             if (log.isDebugEnabled())
                 log.debug("Received lock response from node [nodeId=" + nodeId + ", res=" + res + ", fut=" + this + ']');
 
-            for (IgniteInternalFuture<Boolean> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture mini = (MiniFuture)fut;
+            MiniFuture mini = miniFuture(res.miniId());
 
-                    if (mini.futureId().equals(res.miniId())) {
-                        assert mini.node().id().equals(nodeId);
+            if (mini != null) {
+                assert mini.node().id().equals(nodeId);
 
-                        if (log.isDebugEnabled())
-                            log.debug("Found mini future for response [mini=" + mini + ", res=" + res + ']');
+                if (log.isDebugEnabled())
+                    log.debug("Found mini future for response [mini=" + mini + ", res=" + res + ']');
 
-                        mini.onResult(res);
+                mini.onResult(res);
 
-                        if (log.isDebugEnabled())
-                            log.debug("Future after processed lock response [fut=" + this + ", mini=" + mini +
-                                ", res=" + res + ']');
+                if (log.isDebugEnabled())
+                    log.debug("Future after processed lock response [fut=" + this + ", mini=" + mini +
+                        ", res=" + res + ']');
 
-                        return;
-                    }
-                }
+                return;
             }
 
             U.warn(log, "Failed to find mini future for response (perhaps due to stale message) [res=" + res +
@@ -508,6 +504,38 @@ public final class GridNearLockFuture extends GridCompoundIdentityFuture<Boolean
     }
 
     /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<Boolean> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
+                }
+            }
+        }
+
+        return null;
+    }
+
+
+    /**
      * @param t Error.
      */
     private void onError(Throwable t) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockRequest.java
index 165da84..805a6a2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockRequest.java
@@ -20,13 +20,11 @@ package org.apache.ignite.internal.processors.cache.distributed.near;
 import java.io.Externalizable;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
-import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedLockRequest;
@@ -300,7 +298,7 @@ public class GridNearLockRequest extends GridDistributedLockRequest {
         dhtVers[idx] = dhtVer;
 
         // Delegate to super.
-        addKeyBytes(key, retVal, (Collection<GridCacheMvccCandidate>)null, ctx);
+        addKeyBytes(key, retVal, ctx);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
index 29774a5..1569b14 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
@@ -46,6 +46,7 @@ import org.apache.ignite.internal.transactions.IgniteTxOptimisticCheckedExceptio
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
 import org.apache.ignite.internal.util.GridConcurrentHashSet;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridCompoundFuture;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -210,17 +211,10 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
     /** {@inheritDoc} */
     @Override public void onResult(UUID nodeId, GridNearTxPrepareResponse res) {
         if (!isDone()) {
-            for (IgniteInternalFuture<GridNearTxPrepareResponse> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture f = (MiniFuture)fut;
+            MiniFuture mini = miniFuture(res.miniId());
 
-                    if (f.futureId().equals(res.miniId())) {
-                        assert f.node().id().equals(nodeId);
-
-                        f.onResult(res);
-                    }
-                }
-            }
+            if (mini != null)
+                mini.onResult(res);
         }
     }
 
@@ -239,6 +233,37 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
     }
 
     /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<GridNearTxPrepareResponse> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * @param f Future.
      * @return {@code True} if mini-future.
      */
@@ -276,32 +301,27 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
      * @param remap Remap flag.
      */
     @Override protected void prepare0(boolean remap, boolean topLocked) {
-        try {
-            boolean txStateCheck = remap ? tx.state() == PREPARING : tx.state(PREPARING);
-
-            if (!txStateCheck) {
-                if (tx.setRollbackOnly()) {
-                    if (tx.timedOut())
-                        onError(null, new IgniteTxTimeoutCheckedException("Transaction timed out and " +
-                            "was rolled back: " + this));
-                    else
-                        onError(null, new IgniteCheckedException("Invalid transaction state for prepare " +
-                            "[state=" + tx.state() + ", tx=" + this + ']'));
-                }
-                else
-                    onError(null, new IgniteTxRollbackCheckedException("Invalid transaction state for " +
-                        "prepare [state=" + tx.state() + ", tx=" + this + ']'));
+        boolean txStateCheck = remap ? tx.state() == PREPARING : tx.state(PREPARING);
 
-                return;
+        if (!txStateCheck) {
+            if (tx.setRollbackOnly()) {
+                if (tx.timedOut())
+                    onError(null, new IgniteTxTimeoutCheckedException("Transaction timed out and " +
+                        "was rolled back: " + this));
+                else
+                    onError(null, new IgniteCheckedException("Invalid transaction state for prepare " +
+                        "[state=" + tx.state() + ", tx=" + this + ']'));
             }
+            else
+                onError(null, new IgniteTxRollbackCheckedException("Invalid transaction state for " +
+                    "prepare [state=" + tx.state() + ", tx=" + this + ']'));
 
-            prepare(tx.readEntries(), tx.writeEntries(), remap, topLocked);
-
-            markInitialized();
-        }
-        catch (IgniteCheckedException e) {
-            onDone(e);
+            return;
         }
+
+        prepare(tx.readEntries(), tx.writeEntries(), remap, topLocked);
+
+        markInitialized();
     }
 
     /**
@@ -309,7 +329,6 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
      * @param writes Write entries.
      * @param remap Remap flag.
      * @param topLocked Topology locked flag.
-     * @throws IgniteCheckedException If failed.
      */
     @SuppressWarnings("unchecked")
     private void prepare(
@@ -317,7 +336,7 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
         Iterable<IgniteTxEntry> writes,
         boolean remap,
         boolean topLocked
-    ) throws IgniteCheckedException {
+    ) {
         AffinityTopologyVersion topVer = tx.topologyVersion();
 
         assert topVer.topologyVersion() > 0;
@@ -355,9 +374,7 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
         for (GridDistributedTxMapping m : mappings.values()) {
             assert !m.empty();
 
-            MiniFuture fut = new MiniFuture(m);
-
-            add(fut);
+            add(new MiniFuture(m));
         }
 
         Collection<IgniteInternalFuture<?>> futs = (Collection)futures();

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
index 791d2f3..82e3868 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
@@ -45,6 +45,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
 import org.apache.ignite.internal.util.GridConcurrentHashSet;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.C1;
@@ -187,18 +188,45 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
     /** {@inheritDoc} */
     @Override public void onResult(UUID nodeId, GridNearTxPrepareResponse res) {
         if (!isDone()) {
-            for (IgniteInternalFuture<GridNearTxPrepareResponse> fut : pending()) {
-                if (isMini(fut)) {
-                    MiniFuture f = (MiniFuture)fut;
+            MiniFuture mini = miniFuture(res.miniId());
 
-                    if (f.futureId().equals(res.miniId())) {
-                        assert f.node().id().equals(nodeId);
+            if (mini != null) {
+                assert mini.node().id().equals(nodeId);
 
-                        f.onResult(nodeId, res);
-                    }
+                mini.onResult(nodeId, res);
+            }
+        }
+    }
+
+    /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<GridNearTxPrepareResponse> fut = futs.get(i);
+
+                if (!isMini(fut))
+                    continue;
+
+                MiniFuture mini = (MiniFuture)fut;
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
                 }
             }
         }
+
+        return null;
     }
 
     /** {@inheritDoc} */
@@ -277,10 +305,7 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
             markInitialized();
         }
         catch (TransactionTimeoutException e) {
-            onError( e);
-        }
-        catch (IgniteCheckedException e) {
-            onDone(e);
+            onError(e);
         }
     }
 
@@ -327,12 +352,11 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
     /**
      * @param writes Write entries.
      * @param topLocked {@code True} if thread already acquired lock preventing topology change.
-     * @throws IgniteCheckedException If failed.
      */
     private void prepare(
         Iterable<IgniteTxEntry> writes,
         boolean topLocked
-    ) throws IgniteCheckedException {
+    ) {
         AffinityTopologyVersion topVer = tx.topologyVersion();
 
         assert topVer.topologyVersion() > 0;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
index 1554a62..103105e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
@@ -103,20 +103,45 @@ public class GridNearPessimisticTxPrepareFuture extends GridNearTxPrepareFutureA
         if (!isDone()) {
             assert res.clientRemapVersion() == null : res;
 
-            for (IgniteInternalFuture<GridNearTxPrepareResponse> fut : pending()) {
-                MiniFuture f = (MiniFuture)fut;
+            MiniFuture f = miniFuture(res.miniId());
 
-                if (f.futureId().equals(res.miniId())) {
-                    assert f.node().id().equals(nodeId);
+            if (f != null) {
+                assert f.node().id().equals(nodeId);
 
-                    if (log.isDebugEnabled())
-                        log.debug("Remote node left grid while sending or waiting for reply (will not retry): " + f);
+                if (log.isDebugEnabled())
+                    log.debug("Remote node left grid while sending or waiting for reply (will not retry): " + f);
 
-                    f.onResult(res);
+                f.onResult(res);
+            }
+        }
+    }
+
+    /**
+     * Finds pending mini future by the given mini ID.
+     *
+     * @param miniId Mini ID to find.
+     * @return Mini future.
+     */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
+    private MiniFuture miniFuture(IgniteUuid miniId) {
+        // We iterate directly over the futs collection here to avoid copy.
+        synchronized (futs) {
+            // Avoid iterator creation.
+            for (int i = 0; i < futs.size(); i++) {
+                MiniFuture mini = (MiniFuture)futs.get(i);
+
+                if (mini.futureId().equals(miniId)) {
+                    if (!mini.isDone())
+                        return mini;
+                    else
+                        return null;
                 }
             }
         }
+
+        return null;
     }
+
     /** {@inheritDoc} */
     @Override public void prepare() {
         if (!tx.state(PREPARING)) {


[33/37] ignite git commit: IGNITE-426 Implemented failover for Continuous query.

Posted by ag...@apache.org.
IGNITE-426 Implemented failover for Continuous query.


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

Branch: refs/heads/ignite-1282
Commit: ce6363729f3553c6854ed2e8cfc3b5c244678fcd
Parents: 8728a5b
Author: nikolay_tikhonov <nt...@gridgain.com>
Authored: Thu Nov 19 19:50:58 2015 +0300
Committer: nikolay_tikhonov <nt...@gridgain.com>
Committed: Thu Nov 19 19:50:58 2015 +0300

----------------------------------------------------------------------
 .../internal/GridEventConsumeHandler.java       |   22 +-
 .../internal/GridMessageListenHandler.java      |   18 +
 .../communication/GridIoMessageFactory.java     |    8 +-
 .../processors/cache/GridCacheEntryEx.java      |   12 +-
 .../processors/cache/GridCacheMapEntry.java     |  147 +-
 .../GridCachePartitionExchangeManager.java      |    4 +-
 .../cache/GridCacheUpdateAtomicResult.java      |   15 +-
 .../cache/GridCacheUpdateTxResult.java          |   24 +-
 .../GridDistributedTxRemoteAdapter.java         |   22 +-
 .../dht/GridClientPartitionTopology.java        |   38 +-
 .../distributed/dht/GridDhtLocalPartition.java  |   35 +
 .../dht/GridDhtPartitionTopology.java           |   26 +-
 .../dht/GridDhtPartitionTopologyImpl.java       |  112 +-
 .../distributed/dht/GridDhtTxFinishFuture.java  |   14 +-
 .../distributed/dht/GridDhtTxFinishRequest.java |  112 +-
 .../dht/atomic/GridDhtAtomicCache.java          |   79 +-
 .../dht/atomic/GridDhtAtomicUpdateFuture.java   |   75 +-
 .../dht/atomic/GridDhtAtomicUpdateRequest.java  |  140 +-
 .../GridDhtPartitionsExchangeFuture.java        |   35 +-
 .../preloader/GridDhtPartitionsFullMessage.java |   64 +-
 .../GridDhtPartitionsSingleMessage.java         |   56 +-
 .../distributed/near/GridNearAtomicCache.java   |   10 +-
 .../distributed/near/GridNearTxRemote.java      |    7 +
 .../CacheContinuousQueryBatchAck.java           |  163 ++
 .../continuous/CacheContinuousQueryEntry.java   |  196 +-
 .../continuous/CacheContinuousQueryEvent.java   |    3 +-
 .../continuous/CacheContinuousQueryHandler.java |  811 ++++++-
 .../CacheContinuousQueryListener.java           |   35 +
 .../continuous/CacheContinuousQueryManager.java |  151 +-
 .../cache/transactions/IgniteTxEntry.java       |   20 +
 .../cache/transactions/IgniteTxHandler.java     |    3 +
 .../transactions/IgniteTxLocalAdapter.java      |   18 +-
 .../cache/transactions/IgniteTxRemoteEx.java    |    7 +-
 .../continuous/GridContinuousBatch.java         |   44 +
 .../continuous/GridContinuousBatchAdapter.java  |   46 +
 .../continuous/GridContinuousHandler.java       |   22 +
 .../continuous/GridContinuousProcessor.java     |  221 +-
 .../StartRoutineAckDiscoveryMessage.java        |   14 +-
 .../StartRoutineDiscoveryMessage.java           |   21 +-
 .../processors/cache/GridCacheTestEntryEx.java  |   10 +-
 ...ContinuousQueryFailoverAbstractSelfTest.java | 2235 ++++++++++++++++++
 ...ryFailoverAtomicNearEnabledSelfSelfTest.java |   46 +
 ...FailoverAtomicPrimaryWriteOrderSelfTest.java |   44 +
 ...usQueryFailoverAtomicReplicatedSelfTest.java |   40 +
 ...inuousQueryFailoverTxReplicatedSelfTest.java |   32 +
 .../CacheContinuousQueryFailoverTxSelfTest.java |   39 +
 ...ridCacheContinuousQueryAbstractSelfTest.java |  153 +-
 .../GridCacheContinuousQueryTxSelfTest.java     |   49 +
 ...CacheContinuousQueryClientReconnectTest.java |  187 ++
 .../IgniteCacheContinuousQueryClientTest.java   |  157 +-
 ...cheContinuousQueryClientTxReconnectTest.java |   32 +
 .../p2p/GridP2PSameClassLoaderSelfTest.java     |   16 +-
 .../testframework/junits/GridAbstractTest.java  |    2 +-
 .../junits/common/GridCommonAbstractTest.java   |    3 +
 .../IgniteCacheQuerySelfTestSuite.java          |   16 +-
 .../yardstick/cache/CacheEntryEventProbe.java   |  156 ++
 56 files changed, 5753 insertions(+), 314 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/GridEventConsumeHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridEventConsumeHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/GridEventConsumeHandler.java
index b4ce4ab..3918976 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridEventConsumeHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridEventConsumeHandler.java
@@ -23,6 +23,7 @@ import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.Collection;
 import java.util.LinkedList;
+import java.util.Map;
 import java.util.Queue;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
@@ -38,6 +39,8 @@ import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheDeployable;
 import org.apache.ignite.internal.processors.cache.GridCacheDeploymentManager;
+import org.apache.ignite.internal.processors.continuous.GridContinuousBatch;
+import org.apache.ignite.internal.processors.continuous.GridContinuousBatchAdapter;
 import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
 import org.apache.ignite.internal.processors.platform.PlatformEventFilterListener;
 import org.apache.ignite.internal.util.typedef.F;
@@ -127,6 +130,11 @@ class GridEventConsumeHandler implements GridContinuousHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public void updateCounters(Map<Integer, Long> cntrs) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
     @Override public RegisterStatus register(final UUID nodeId, final UUID routineId, final GridKernalContext ctx)
         throws IgniteCheckedException {
         assert nodeId != null;
@@ -213,8 +221,8 @@ class GridEventConsumeHandler implements GridContinuousHandler {
                                                     }
                                                 }
 
-                                                ctx.continuous().addNotification(t3.get1(), t3.get2(), wrapper, null, false,
-                                                    false);
+                                                ctx.continuous().addNotification(t3.get1(), t3.get2(), wrapper, null,
+                                                    false, false);
                                             }
                                             catch (ClusterTopologyCheckedException ignored) {
                                                 // No-op.
@@ -377,6 +385,16 @@ class GridEventConsumeHandler implements GridContinuousHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public GridContinuousBatch createBatch() {
+        return new GridContinuousBatchAdapter();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBatchAcknowledged(UUID routineId, GridContinuousBatch batch, GridKernalContext ctx) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
     @Nullable @Override public Object orderedTopic() {
         return null;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java
index ff38949..aa837b8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/GridMessageListenHandler.java
@@ -22,10 +22,13 @@ import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.Collection;
+import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.managers.deployment.GridDeployment;
 import org.apache.ignite.internal.managers.deployment.GridDeploymentInfoBean;
+import org.apache.ignite.internal.processors.continuous.GridContinuousBatch;
+import org.apache.ignite.internal.processors.continuous.GridContinuousBatchAdapter;
 import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
 import org.apache.ignite.internal.util.lang.GridPeerDeployAware;
 import org.apache.ignite.internal.util.typedef.internal.S;
@@ -100,6 +103,11 @@ public class GridMessageListenHandler implements GridContinuousHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public void updateCounters(Map<Integer, Long> cntrs) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
     @Override public RegisterStatus register(UUID nodeId, UUID routineId, final GridKernalContext ctx) throws IgniteCheckedException {
         ctx.io().addUserMessageListener(topic, pred);
 
@@ -167,6 +175,16 @@ public class GridMessageListenHandler implements GridContinuousHandler {
     }
 
     /** {@inheritDoc} */
+    @Override public GridContinuousBatch createBatch() {
+        return new GridContinuousBatchAdapter();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onBatchAcknowledged(UUID routineId, GridContinuousBatch batch, GridKernalContext ctx) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
     @Nullable @Override public Object orderedTopic() {
         return null;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 3548aac..c671582 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -93,6 +93,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.GridNearUnlo
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryRequest;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryResponse;
 import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
+import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryBatchAck;
 import org.apache.ignite.internal.processors.cache.query.continuous.CacheContinuousQueryEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxKey;
@@ -708,7 +709,12 @@ public class GridIoMessageFactory implements MessageFactory {
 
                 break;
 
-            // [-3..114] - this
+            case 118:
+                msg = new CacheContinuousQueryBatchAck();
+
+                break;
+
+            // [-3..118] - this
             // [120..123] - DR
             // [-4..-22] - SQL
             default:

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/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 af62e39..8d50616 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
@@ -360,6 +360,7 @@ public interface GridCacheEntryEx {
      * @param subjId Subject ID initiated this update.
      * @param taskName Task name.
      * @param dhtVer Dht version for near cache entry.
+     * @param updateCntr Update counter.
      * @return Tuple containing success flag and old value. If success is {@code false},
      *      then value is {@code null}.
      * @throws IgniteCheckedException If storing value failed.
@@ -382,7 +383,8 @@ public interface GridCacheEntryEx {
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
         String taskName,
-        @Nullable GridCacheVersion dhtVer
+        @Nullable GridCacheVersion dhtVer,
+        @Nullable Long updateCntr
     ) throws IgniteCheckedException, GridCacheEntryRemovedException;
 
     /**
@@ -417,7 +419,8 @@ public interface GridCacheEntryEx {
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
         String taskName,
-        @Nullable GridCacheVersion dhtVer
+        @Nullable GridCacheVersion dhtVer,
+        @Nullable Long updateCntr
     ) throws IgniteCheckedException, GridCacheEntryRemovedException;
 
     /**
@@ -446,6 +449,7 @@ public interface GridCacheEntryEx {
      * @param intercept If {@code true} then calls cache interceptor.
      * @param subjId Subject ID initiated this update.
      * @param taskName Task name.
+     * @param updateCntr Update counter.
      * @return Tuple where first value is flag showing whether operation succeeded,
      *      second value is old entry value if return value is requested, third is updated entry value,
      *      fourth is the version to enqueue for deferred delete the fifth is DR conflict context
@@ -478,7 +482,9 @@ public interface GridCacheEntryEx {
         boolean conflictResolve,
         boolean intercept,
         @Nullable UUID subjId,
-        String taskName
+        String taskName,
+        @Nullable CacheObject prevVal,
+        @Nullable Long updateCntr
     ) throws IgniteCheckedException, GridCacheEntryRemovedException;
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/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 0786a50..8d363ad 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,6 +37,7 @@ 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.dht.GridDhtLocalPartition;
 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;
@@ -1060,7 +1061,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
         String taskName,
-        @Nullable GridCacheVersion dhtVer
+        @Nullable GridCacheVersion dhtVer,
+        @Nullable Long updateCntr
     ) throws IgniteCheckedException, GridCacheEntryRemovedException {
         CacheObject old;
 
@@ -1077,6 +1079,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         Object key0 = null;
         Object val0 = null;
 
+        long updateCntr0;
+
         synchronized (this) {
             checkObsolete();
 
@@ -1155,6 +1159,11 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                     deletedUnlocked(false);
             }
 
+            updateCntr0 = nextPartCounter(topVer);
+
+            if (updateCntr != null && updateCntr != 0)
+                updateCntr0 = updateCntr;
+
             update(val, expireTime, ttl, newVer);
 
             drReplicate(drType, val, newVer);
@@ -1180,8 +1189,10 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                     subjId, null, taskName);
             }
 
-            if (cctx.isLocal() || cctx.isReplicated() || (tx != null && tx.local() && !isNear()))
-                cctx.continuousQueries().onEntryUpdated(this, key, val, old, false);
+            if (cctx.isLocal() || cctx.isReplicated() ||
+                (!isNear() && !(tx != null && tx.onePhaseCommit() && !tx.local())))
+                cctx.continuousQueries().onEntryUpdated(key, val, old, isInternal() || !context().userCache(),
+                    partition(), tx.local(), false, updateCntr0, topVer);
 
             cctx.dataStructures().onEntryUpdated(key, false);
         }
@@ -1197,7 +1208,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         if (intercept)
             cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, val, val0));
 
-        return valid ? new GridCacheUpdateTxResult(true, retval ? old : null) :
+        return valid ? new GridCacheUpdateTxResult(true, retval ? old : null, updateCntr0) :
             new GridCacheUpdateTxResult(false, null);
     }
 
@@ -1223,7 +1234,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         @Nullable GridCacheVersion explicitVer,
         @Nullable UUID subjId,
         String taskName,
-        @Nullable GridCacheVersion dhtVer
+        @Nullable GridCacheVersion dhtVer,
+        @Nullable Long updateCntr
         ) throws IgniteCheckedException, GridCacheEntryRemovedException {
         assert cctx.transactional();
 
@@ -1245,6 +1257,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
         Cache.Entry entry0 = null;
 
+        Long updateCntr0;
+
         boolean deferred;
 
         boolean marked = false;
@@ -1261,7 +1275,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             }
 
             assert tx == null || (!tx.local() && tx.onePhaseCommit()) || tx.ownsLock(this) :
-                    "Transaction does not own lock for remove[entry=" + this + ", tx=" + tx + ']';
+                "Transaction does not own lock for remove[entry=" + this + ", tx=" + tx + ']';
 
             boolean startVer = isStartVersion();
 
@@ -1318,6 +1332,11 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                 }
             }
 
+            updateCntr0 = nextPartCounter(topVer);
+
+            if (updateCntr != null && updateCntr != 0)
+                updateCntr0 = updateCntr;
+
             drReplicate(drType, null, newVer);
 
             if (metrics && cctx.cache().configuration().isStatisticsEnabled())
@@ -1350,8 +1369,10 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                     taskName);
             }
 
-            if (cctx.isLocal() || cctx.isReplicated() || (tx != null && tx.local() && !isNear()))
-                cctx.continuousQueries().onEntryUpdated(this, key, null, old, false);
+            if (cctx.isLocal() || cctx.isReplicated() ||
+                (!isNear() && !(tx != null && tx.onePhaseCommit() && !tx.local())))
+                cctx.continuousQueries().onEntryUpdated(key, null, old, isInternal()
+                    || !context().userCache(),partition(), tx.local(), false, updateCntr0, topVer);
 
             cctx.dataStructures().onEntryUpdated(key, true);
 
@@ -1394,7 +1415,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             else
                 ret = old;
 
-            return new GridCacheUpdateTxResult(true, ret);
+            return new GridCacheUpdateTxResult(true, ret, updateCntr0);
         }
         else
             return new GridCacheUpdateTxResult(false, null);
@@ -1686,7 +1707,12 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             if (res)
                 updateMetrics(op, metrics);
 
-            cctx.continuousQueries().onEntryUpdated(this, key, val, old, false);
+            if (!isNear()) {
+                long updateCntr = nextPartCounter(AffinityTopologyVersion.NONE);
+
+                cctx.continuousQueries().onEntryUpdated(key, val, old, isInternal() || !context().userCache(),
+                    partition(), true, false, updateCntr, AffinityTopologyVersion.NONE);
+            }
 
             cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE);
 
@@ -1729,7 +1755,9 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         boolean conflictResolve,
         boolean intercept,
         @Nullable UUID subjId,
-        String taskName
+        String taskName,
+        @Nullable CacheObject prevVal,
+        @Nullable Long updateCntr
     ) throws IgniteCheckedException, GridCacheEntryRemovedException, GridClosureException {
         assert cctx.atomic();
 
@@ -1755,6 +1783,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         Object key0 = null;
         Object updated0 = null;
 
+        Long updateCntr0 = null;
+
         synchronized (this) {
             boolean needVal = intercept || retval || op == GridCacheOperation.TRANSFORM || !F.isEmptyOrNulls(filter);
 
@@ -1862,7 +1892,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                             CU.EXPIRE_TIME_ETERNAL,
                             null,
                             null,
-                            false);
+                            false,
+                            updateCntr0 == null ? 0 : updateCntr0);
                     }
                     // Will update something.
                     else {
@@ -1911,6 +1942,38 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                                     "[entry=" + this + ", newVer=" + newVer + ']');
                         }
 
+                        if (!cctx.isNear()) {
+                            CacheObject evtVal;
+
+                            if (op == GridCacheOperation.TRANSFORM) {
+                                EntryProcessor<Object, Object, ?> entryProcessor =
+                                    (EntryProcessor<Object, Object, ?>)writeObj;
+
+                                CacheInvokeEntry<Object, Object> entry =
+                                    new CacheInvokeEntry<>(cctx, key, prevVal, version());
+
+                                try {
+                                    entryProcessor.process(entry, invokeArgs);
+
+                                    evtVal = entry.modified() ?
+                                        cctx.toCacheObject(cctx.unwrapTemporary(entry.getValue())) : prevVal;
+                                }
+                                catch (Exception e) {
+                                    evtVal = prevVal;
+                                }
+                            }
+                            else
+                                evtVal = (CacheObject)writeObj;
+
+                            updateCntr0 = nextPartCounter(topVer);
+
+                            if (updateCntr != null)
+                                updateCntr0 = updateCntr;
+
+                            cctx.continuousQueries().onEntryUpdated(key, evtVal, prevVal, isInternal()
+                                || !context().userCache(), partition(), primary, false, updateCntr0, topVer);
+                        }
+
                         return new GridCacheUpdateAtomicResult(false,
                             retval ? rawGetOrUnmarshalUnlocked(false) : null,
                             null,
@@ -1919,7 +1982,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                             CU.EXPIRE_TIME_ETERNAL,
                             null,
                             null,
-                            false);
+                            false,
+                            updateCntr0 == null ? 0 : updateCntr0);
                     }
                 }
                 else
@@ -1995,7 +2059,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                         CU.EXPIRE_TIME_ETERNAL,
                         null,
                         null,
-                        false);
+                        false,
+                        updateCntr0 == null ? 0 : updateCntr0);
                 }
             }
 
@@ -2042,7 +2107,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                         CU.EXPIRE_TIME_ETERNAL,
                         null,
                         null,
-                        false);
+                        false,
+                        updateCntr0 == null ? 0 : updateCntr);
                 }
             }
             else
@@ -2142,7 +2208,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                             CU.EXPIRE_TIME_ETERNAL,
                             null,
                             null,
-                            false);
+                            false,
+                            updateCntr0 == null ? 0 : updateCntr0);
                     else if (interceptorVal != updated0) {
                         updated0 = cctx.unwrapTemporary(interceptorVal);
 
@@ -2179,6 +2246,11 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
                 update(updated, newExpireTime, newTtl, newVer);
 
+                updateCntr0 = nextPartCounter(topVer);
+
+                if (updateCntr != null)
+                    updateCntr0 = updateCntr;
+
                 drReplicate(drType, updated, newVer);
 
                 recordNodeId(affNodeId, topVer);
@@ -2218,7 +2290,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                             CU.EXPIRE_TIME_ETERNAL,
                             null,
                             null,
-                            false);
+                            false,
+                            updateCntr0 == null ? 0 : updateCntr0);
                 }
 
                 if (writeThrough)
@@ -2270,6 +2343,11 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
 
                 recordNodeId(affNodeId, topVer);
 
+                updateCntr0 = nextPartCounter(topVer);
+
+                if (updateCntr != null)
+                    updateCntr0 = updateCntr;
+
                 drReplicate(drType, null, newVer);
 
                 if (evt) {
@@ -2299,9 +2377,6 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             if (res)
                 updateMetrics(op, metrics);
 
-            if (cctx.isReplicated() || primary)
-                cctx.continuousQueries().onEntryUpdated(this, key, val, oldVal, false);
-
             cctx.dataStructures().onEntryUpdated(key, op == GridCacheOperation.DELETE);
 
             if (intercept) {
@@ -2326,7 +2401,8 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
             newSysExpireTime,
             enqueueVer,
             conflictCtx,
-            true);
+            true,
+            updateCntr0);
     }
 
     /**
@@ -3146,11 +3222,16 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
                 else if (deletedUnlocked())
                     deletedUnlocked(false);
 
+                long updateCntr = 0;
+
+                if (!preload)
+                    updateCntr = nextPartCounter(topVer);
+
                 drReplicate(drType, val, ver);
 
                 if (!skipQryNtf) {
-                    if (cctx.isLocal() || cctx.isReplicated() || cctx.affinity().primary(cctx.localNode(), key, topVer))
-                        cctx.continuousQueries().onEntryUpdated(this, key, val, null, preload);
+                    cctx.continuousQueries().onEntryUpdated(key, val, null, this.isInternal()
+                        || !this.context().userCache(), this.partition(), true, preload, updateCntr, topVer);
 
                     cctx.dataStructures().onEntryUpdated(key, false);
                 }
@@ -3167,6 +3248,26 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
         }
     }
 
+    /**
+     * @param topVer Topology version.
+     * @return Update counter.
+     */
+    private long nextPartCounter(AffinityTopologyVersion topVer) {
+        long updateCntr;
+
+        if (!cctx.isLocal() && !isNear()) {
+            GridDhtLocalPartition locPart = cctx.topology().localPartition(partition(), topVer, false);
+
+            assert locPart != null;
+
+            updateCntr = locPart.nextUpdateCounter();
+        }
+        else
+            updateCntr = 0;
+
+        return updateCntr;
+    }
+
     /** {@inheritDoc} */
     @Override public synchronized boolean initialValue(KeyCacheObject key, GridCacheSwapEntry unswapped) throws
         IgniteCheckedException,

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
index e19b310..cd89416 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCachePartitionExchangeManager.java
@@ -989,7 +989,7 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                         top = cacheCtx.topology();
 
                     if (top != null)
-                        updated |= top.update(null, entry.getValue()) != null;
+                        updated |= top.update(null, entry.getValue(), null) != null;
                 }
 
                 if (!cctx.kernalContext().clientNode() && updated)
@@ -1032,7 +1032,7 @@ public class GridCachePartitionExchangeManager<K, V> extends GridCacheSharedMana
                         top = cacheCtx.topology();
 
                     if (top != null)
-                        updated |= top.update(null, entry.getValue()) != null;
+                        updated |= top.update(null, entry.getValue(), null) != null;
                 }
 
                 if (updated)

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateAtomicResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateAtomicResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateAtomicResult.java
index 3674284..9df476e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateAtomicResult.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateAtomicResult.java
@@ -57,6 +57,9 @@ public class GridCacheUpdateAtomicResult {
     /** Whether update should be propagated to DHT node. */
     private final boolean sndToDht;
 
+    /** */
+    private final Long updateCntr;
+
     /** Value computed by entry processor. */
     private IgniteBiTuple<Object, Exception> res;
 
@@ -72,6 +75,7 @@ public class GridCacheUpdateAtomicResult {
      * @param rmvVer Version for deferred delete.
      * @param conflictRes DR resolution result.
      * @param sndToDht Whether update should be propagated to DHT node.
+     * @param updateCntr Partition update counter.
      */
     public GridCacheUpdateAtomicResult(boolean success,
         @Nullable CacheObject oldVal,
@@ -81,7 +85,8 @@ public class GridCacheUpdateAtomicResult {
         long conflictExpireTime,
         @Nullable GridCacheVersion rmvVer,
         @Nullable GridCacheVersionConflictContext<?, ?> conflictRes,
-        boolean sndToDht) {
+        boolean sndToDht,
+        long updateCntr) {
         this.success = success;
         this.oldVal = oldVal;
         this.newVal = newVal;
@@ -91,6 +96,7 @@ public class GridCacheUpdateAtomicResult {
         this.rmvVer = rmvVer;
         this.conflictRes = conflictRes;
         this.sndToDht = sndToDht;
+        this.updateCntr = updateCntr;
     }
 
     /**
@@ -129,6 +135,13 @@ public class GridCacheUpdateAtomicResult {
     }
 
     /**
+     * @return Partition update index.
+     */
+    public Long updateCounter() {
+        return updateCntr;
+    }
+
+    /**
      * @return Explicit conflict expire time (if any). Set only if it is necessary to propagate concrete expire time
      * value to DHT node. Otherwise set to {@link GridCacheUtils#EXPIRE_TIME_CALCULATE}.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateTxResult.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateTxResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateTxResult.java
index ffda7a2..461baa7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateTxResult.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheUpdateTxResult.java
@@ -32,6 +32,9 @@ public class GridCacheUpdateTxResult {
     @GridToStringInclude
     private final CacheObject oldVal;
 
+    /** Partition idx. */
+    private long updateCntr;
+
     /**
      * Constructor.
      *
@@ -44,6 +47,25 @@ public class GridCacheUpdateTxResult {
     }
 
     /**
+     * Constructor.
+     *
+     * @param success Success flag.
+     * @param oldVal Old value (if any),
+     */
+    GridCacheUpdateTxResult(boolean success, @Nullable CacheObject oldVal, long updateCntr) {
+        this.success = success;
+        this.oldVal = oldVal;
+        this.updateCntr = updateCntr;
+    }
+
+    /**
+     * @return Partition idx.
+     */
+    public long updatePartitionCounter() {
+        return updateCntr;
+    }
+
+    /**
      * @return Success flag.
      */
     public boolean success() {
@@ -61,4 +83,4 @@ public class GridCacheUpdateTxResult {
     @Override public String toString() {
         return S.toString(GridCacheUpdateTxResult.class, this);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
index 0d49584..f9ac2df 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java
@@ -265,6 +265,19 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
         }
     }
 
+    /** {@inheritDoc} */
+    @Override public void setPartitionUpdateCounters(long[] cntrs) {
+        if (writeMap() != null && !writeMap().isEmpty() && cntrs != null && cntrs.length > 0) {
+            int i = 0;
+
+            for (IgniteTxEntry txEntry : writeMap().values()) {
+                txEntry.updateCounter(cntrs[i]);
+
+                ++i;
+            }
+        }
+    }
+
     /**
      * Adds completed versions to an entry.
      *
@@ -529,7 +542,8 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
                                                 near() ? null : explicitVer,
                                                 CU.subjectId(this, cctx),
                                                 resolveTaskName(),
-                                                dhtVer);
+                                                dhtVer,
+                                                txEntry.updateCounter());
                                         else {
                                             cached.innerSet(this,
                                                 eventNodeId(),
@@ -547,7 +561,8 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
                                                 near() ? null : explicitVer,
                                                 CU.subjectId(this, cctx),
                                                 resolveTaskName(),
-                                                dhtVer);
+                                                dhtVer,
+                                                txEntry.updateCounter());
 
                                             // Keep near entry up to date.
                                             if (nearCached != null) {
@@ -575,7 +590,8 @@ public class GridDistributedTxRemoteAdapter extends IgniteTxAdapter
                                             near() ? null : explicitVer,
                                             CU.subjectId(this, cctx),
                                             resolveTaskName(),
-                                            dhtVer);
+                                            dhtVer,
+                                            txEntry.updateCounter());
 
                                         // Keep near entry up to date.
                                         if (nearCached != null)

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
index 162c116..b7169bf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridClientPartitionTopology.java
@@ -94,6 +94,9 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
     /** Lock. */
     private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
 
+    /** Partition update counters. */
+    private Map<Integer, Long> cntrMap = new HashMap<>();
+
     /**
      * @param cctx Context.
      * @param cacheId Cache ID.
@@ -527,7 +530,8 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
     /** {@inheritDoc} */
     @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
     @Nullable @Override public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId,
-        GridDhtPartitionFullMap partMap) {
+        GridDhtPartitionFullMap partMap,
+        Map<Integer, Long> cntrMap) {
         if (log.isDebugEnabled())
             log.debug("Updating full partition map [exchId=" + exchId + ", parts=" + fullMapString() + ']');
 
@@ -602,6 +606,9 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
 
             part2node = p2n;
 
+            if (cntrMap != null)
+                this.cntrMap = new HashMap<>(cntrMap);
+
             consistencyCheck();
 
             if (log.isDebugEnabled())
@@ -617,7 +624,8 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
     /** {@inheritDoc} */
     @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
     @Nullable @Override public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId,
-        GridDhtPartitionMap parts) {
+        GridDhtPartitionMap parts,
+        Map<Integer, Long> cntrMap) {
         if (log.isDebugEnabled())
             log.debug("Updating single partition map [exchId=" + exchId + ", parts=" + mapString(parts) + ']');
 
@@ -698,6 +706,15 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
                 }
             }
 
+            if (cntrMap != null) {
+                for (Map.Entry<Integer, Long> e : cntrMap.entrySet()) {
+                    Long cntr = this.cntrMap.get(e.getKey());
+
+                    if (cntr == null || cntr < e.getValue())
+                        this.cntrMap.put(e.getKey(), e.getValue());
+                }
+            }
+
             consistencyCheck();
 
             if (log.isDebugEnabled())
@@ -852,6 +869,23 @@ public class GridClientPartitionTopology implements GridDhtPartitionTopology {
     }
 
     /** {@inheritDoc} */
+    @Override public Map<Integer, Long> updateCounters() {
+        lock.readLock().lock();
+
+        try {
+            return new HashMap<>(cntrMap);
+        }
+        finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean rebalanceFinished(AffinityTopologyVersion topVer) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
     @Override public void printMemoryStats(int threshold) {
         X.println(">>>  Cache partition topology stats [grid=" + cctx.gridName() + ", cacheId=" + cacheId + ']');
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
index 1516ee4..63e2899 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtLocalPartition.java
@@ -24,6 +24,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.atomic.AtomicStampedReference;
 import java.util.concurrent.locks.ReentrantLock;
@@ -114,6 +115,9 @@ public class GridDhtLocalPartition implements Comparable<GridDhtLocalPartition>,
     /** Group reservations. */
     private final CopyOnWriteArrayList<GridDhtPartitionsReservation> reservations = new CopyOnWriteArrayList<>();
 
+    /** Update counter. */
+    private final AtomicLong cntr = new AtomicLong();
+
     /**
      * @param cctx Context.
      * @param id Partition ID.
@@ -532,6 +536,8 @@ public class GridDhtLocalPartition implements Comparable<GridDhtLocalPartition>,
             if (cctx.isDrEnabled())
                 cctx.dr().partitionEvicted(id);
 
+            cctx.continuousQueries().onPartitionEvicted(id);
+
             cctx.dataStructures().onPartitionEvicted(id);
 
             rent.onDone();
@@ -599,6 +605,35 @@ public class GridDhtLocalPartition implements Comparable<GridDhtLocalPartition>,
     }
 
     /**
+     * @return Next update index.
+     */
+    public long nextUpdateCounter() {
+        return cntr.incrementAndGet();
+    }
+
+    /**
+     * @return Current update index.
+     */
+    public long updateCounter() {
+        return cntr.get();
+    }
+
+    /**
+     * @param val Update index value.
+     */
+    public void updateCounter(long val) {
+        while (true) {
+            long val0 = cntr.get();
+
+            if (val0 >= val)
+                break;
+
+            if (cntr.compareAndSet(val0, val))
+                break;
+        }
+    }
+
+    /**
      * Clears values for this partition.
      */
     private void clearAll() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java
index d642314..3ac2b85 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopology.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.distributed.dht;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cluster.ClusterNode;
@@ -51,6 +52,8 @@ public interface GridDhtPartitionTopology {
      *
      * @param exchId Exchange ID.
      * @param exchFut Exchange future.
+     * @param updateSeq Update sequence.
+     * @param stopping Stopping flag.
      * @throws IgniteInterruptedCheckedException If interrupted.
      */
     public void updateTopologyVersion(
@@ -193,17 +196,27 @@ public interface GridDhtPartitionTopology {
     /**
      * @param exchId Exchange ID.
      * @param partMap Update partition map.
+     * @param cntrMap Partition update counters.
      * @return Local partition map if there were evictions or {@code null} otherwise.
      */
-    public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId, GridDhtPartitionFullMap partMap);
+    public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId,
+        GridDhtPartitionFullMap partMap,
+        @Nullable Map<Integer, Long> cntrMap);
 
     /**
      * @param exchId Exchange ID.
      * @param parts Partitions.
+     * @param cntrMap Partition update counters.
      * @return Local partition map if there were evictions or {@code null} otherwise.
      */
     @Nullable public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId,
-        GridDhtPartitionMap parts);
+        GridDhtPartitionMap parts,
+        @Nullable Map<Integer, Long> cntrMap);
+
+    /**
+     * @return Partition update counters.
+     */
+    public Map<Integer, Long> updateCounters();
 
     /**
      * @param part Partition to own.
@@ -213,6 +226,7 @@ public interface GridDhtPartitionTopology {
 
     /**
      * @param part Evicted partition.
+     * @param updateSeq Update sequence increment flag.
      */
     public void onEvicted(GridDhtLocalPartition part, boolean updateSeq);
 
@@ -228,4 +242,10 @@ public interface GridDhtPartitionTopology {
      * @param threshold Threshold for number of entries.
      */
     public void printMemoryStats(int threshold);
-}
\ No newline at end of file
+
+    /**
+     * @param topVer Topology version.
+     * @return {@code True} if rebalance process finished.
+     */
+    public boolean rebalanceFinished(AffinityTopologyVersion topVer);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
index 6bd283a..39c55db 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
@@ -102,6 +102,12 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
     /** Lock. */
     private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
 
+    /** Partition update counter. */
+    private Map<Integer, Long> cntrMap = new HashMap<>();
+
+    /** */
+    private volatile AffinityTopologyVersion rebalancedTopVer = AffinityTopologyVersion.NONE;
+
     /**
      * @param cctx Context.
      */
@@ -131,6 +137,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
             topReadyFut = null;
 
             topVer = AffinityTopologyVersion.NONE;
+
+            rebalancedTopVer = AffinityTopologyVersion.NONE;
         }
         finally {
             lock.writeLock().unlock();
@@ -220,6 +228,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
             updateSeq.setIfGreater(updSeq);
 
             topReadyFut = exchFut;
+
+            rebalancedTopVer = AffinityTopologyVersion.NONE;
         }
         finally {
             lock.writeLock().unlock();
@@ -292,6 +302,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
 
             long updateSeq = this.updateSeq.incrementAndGet();
 
+            cntrMap.clear();
+
             // If this is the oldest node.
             if (oldest.id().equals(loc.id()) || exchFut.isCacheAdded(cctx.cacheId(), exchId.topologyVersion())) {
                 if (node2part == null) {
@@ -525,6 +537,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
                 }
             }
 
+            updateRebalanceVersion();
+
             consistencyCheck();
         }
         finally {
@@ -732,7 +746,10 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
      * @param states Additional partition states.
      * @return List of nodes for the partition.
      */
-    private List<ClusterNode> nodes(int p, AffinityTopologyVersion topVer, GridDhtPartitionState state, GridDhtPartitionState... states) {
+    private List<ClusterNode> nodes(int p,
+        AffinityTopologyVersion topVer,
+        GridDhtPartitionState state,
+        GridDhtPartitionState... states) {
         Collection<UUID> allIds = topVer.topologyVersion() > 0 ? F.nodeIds(CU.affinityNodes(cctx, topVer)) : null;
 
         lock.readLock().lock();
@@ -831,7 +848,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
     /** {@inheritDoc} */
     @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
     @Nullable @Override public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId,
-        GridDhtPartitionFullMap partMap) {
+        GridDhtPartitionFullMap partMap,
+        @Nullable Map<Integer, Long> cntrMap) {
         if (log.isDebugEnabled())
             log.debug("Updating full partition map [exchId=" + exchId + ", parts=" + fullMapString() + ']');
 
@@ -843,6 +861,22 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
             if (stopping)
                 return null;
 
+            if (cntrMap != null) {
+                for (Map.Entry<Integer, Long> e : cntrMap.entrySet()) {
+                    Long cntr = this.cntrMap.get(e.getKey());
+
+                    if (cntr == null || cntr < e.getValue())
+                        this.cntrMap.put(e.getKey(), e.getValue());
+                }
+
+                for (GridDhtLocalPartition part : locParts.values()) {
+                    Long cntr = cntrMap.get(part.id());
+
+                    if (cntr != null)
+                        part.updateCounter(cntr);
+                }
+            }
+
             if (exchId != null && lastExchangeId != null && lastExchangeId.compareTo(exchId) >= 0) {
                 if (log.isDebugEnabled())
                     log.debug("Stale exchange id for full partition map update (will ignore) [lastExchId=" +
@@ -913,6 +947,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
 
             boolean changed = checkEvictions(updateSeq);
 
+            updateRebalanceVersion();
+
             consistencyCheck();
 
             if (log.isDebugEnabled())
@@ -928,7 +964,7 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
     /** {@inheritDoc} */
     @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
     @Nullable @Override public GridDhtPartitionMap update(@Nullable GridDhtPartitionExchangeId exchId,
-        GridDhtPartitionMap parts) {
+        GridDhtPartitionMap parts, @Nullable Map<Integer, Long> cntrMap) {
         if (log.isDebugEnabled())
             log.debug("Updating single partition map [exchId=" + exchId + ", parts=" + mapString(parts) + ']');
 
@@ -946,6 +982,22 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
             if (stopping)
                 return null;
 
+            if (cntrMap != null) {
+                for (Map.Entry<Integer, Long> e : cntrMap.entrySet()) {
+                    Long cntr = this.cntrMap.get(e.getKey());
+
+                    if (cntr == null || cntr < e.getValue())
+                        this.cntrMap.put(e.getKey(), e.getValue());
+                }
+
+                for (GridDhtLocalPartition part : locParts.values()) {
+                    Long cntr = cntrMap.get(part.id());
+
+                    if (cntr != null)
+                        part.updateCounter(cntr);
+                }
+            }
+
             if (lastExchangeId != null && exchId != null && lastExchangeId.compareTo(exchId) > 0) {
                 if (log.isDebugEnabled())
                     log.debug("Stale exchange id for single partition map update (will ignore) [lastExchId=" +
@@ -1008,6 +1060,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
 
             changed |= checkEvictions(updateSeq);
 
+            updateRebalanceVersion();
+
             consistencyCheck();
 
             if (log.isDebugEnabled())
@@ -1254,6 +1308,33 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
     }
 
     /** {@inheritDoc} */
+    @Override public Map<Integer, Long> updateCounters() {
+        lock.readLock().lock();
+
+        try {
+            Map<Integer, Long> res = new HashMap<>(cntrMap);
+
+            for (GridDhtLocalPartition part : locParts.values()) {
+                Long cntr0 = res.get(part.id());
+                Long cntr1 = part.updateCounter();
+
+                if (cntr0 == null || cntr1 > cntr0)
+                    res.put(part.id(), cntr1);
+            }
+
+            return res;
+        }
+        finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean rebalanceFinished(AffinityTopologyVersion topVer) {
+        return topVer.equals(rebalancedTopVer);
+    }
+
+    /** {@inheritDoc} */
     @Override public void printMemoryStats(int threshold) {
         X.println(">>>  Cache partition topology stats [grid=" + cctx.gridName() + ", cache=" + cctx.name() + ']');
 
@@ -1266,6 +1347,31 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
     }
 
     /**
+     *
+     */
+    private void updateRebalanceVersion() {
+        if (!rebalancedTopVer.equals(topVer)) {
+            for (int i = 0; i < cctx.affinity().partitions(); i++) {
+                List<ClusterNode> affNodes = cctx.affinity().nodes(i, topVer);
+
+                // Topology doesn't contain server nodes (just clients).
+                if (affNodes.isEmpty() || (node2part != null && !node2part.valid()))
+                    continue;
+
+                List<ClusterNode> owners = owners(i);
+
+                if (affNodes.size() != owners.size() || !owners.containsAll(affNodes))
+                    return;
+            }
+
+            rebalancedTopVer = topVer;
+
+            if (log.isDebugEnabled())
+                log.debug("Updated rebalanced version [cache=" + cctx.name() + ", ver=" + rebalancedTopVer + ']');
+        }
+    }
+
+    /**
      * @param p Partition.
      * @param nodeId Node ID.
      * @param match State to match.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
index bb370a5..e8ef5d4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java
@@ -17,9 +17,9 @@
 
 package org.apache.ignite.internal.processors.cache.distributed.dht;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.ignite.IgniteCheckedException;
@@ -31,7 +31,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
-import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.util.future.GridCompoundIdentityFuture;
@@ -42,9 +42,7 @@ import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteUuid;
-import org.jetbrains.annotations.Nullable;
 
 import static org.apache.ignite.transactions.TransactionState.COMMITTING;
 
@@ -356,6 +354,11 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCompoundIdentityFutur
 
             add(fut); // Append new future.
 
+            Collection<Long> updCntrs = new ArrayList<>(dhtMapping.entries().size());
+
+            for (IgniteTxEntry e : dhtMapping.entries())
+                updCntrs.add(e.updateCounter());
+
             GridDhtTxFinishRequest req = new GridDhtTxFinishRequest(
                 tx.nearNodeId(),
                 futId,
@@ -379,7 +382,8 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCompoundIdentityFutur
                 tx.size(),
                 tx.subjectId(),
                 tx.taskNameHash(),
-                tx.activeCachesDeploymentEnabled());
+                tx.activeCachesDeploymentEnabled(),
+                updCntrs);
 
             req.writeVersion(tx.writeVersion() != null ? tx.writeVersion() : tx.xidVersion());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
index caa0aa5..65f1cb4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishRequest.java
@@ -26,6 +26,7 @@ import org.apache.ignite.internal.GridDirectCollection;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxFinishRequest;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.lang.IgniteUuid;
@@ -66,6 +67,11 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
     /** Check comitted flag. */
     private boolean checkCommitted;
 
+    /** Partition update counter. */
+    @GridToStringInclude
+    @GridDirectCollection(Long.class)
+    private GridLongList partUpdateCnt;
+
     /** One phase commit write version. */
     private GridCacheVersion writeVer;
 
@@ -163,6 +169,76 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
     }
 
     /**
+     * @param nearNodeId Near node ID.
+     * @param futId Future ID.
+     * @param miniId Mini future ID.
+     * @param topVer Topology version.
+     * @param xidVer Transaction ID.
+     * @param threadId Thread ID.
+     * @param commitVer Commit version.
+     * @param isolation Transaction isolation.
+     * @param commit Commit flag.
+     * @param invalidate Invalidate flag.
+     * @param sys System flag.
+     * @param sysInvalidate System invalidation flag.
+     * @param syncCommit Synchronous commit flag.
+     * @param syncRollback Synchronous rollback flag.
+     * @param baseVer Base version.
+     * @param committedVers Committed versions.
+     * @param rolledbackVers Rolled back versions.
+     * @param pendingVers Pending versions.
+     * @param txSize Expected transaction size.
+     * @param subjId Subject ID.
+     * @param taskNameHash Task name hash.
+     * @param updateIdxs Partition update idxs.
+     * @param addDepInfo Deployment info flag.
+     */
+    public GridDhtTxFinishRequest(
+        UUID nearNodeId,
+        IgniteUuid futId,
+        IgniteUuid miniId,
+        @NotNull AffinityTopologyVersion topVer,
+        GridCacheVersion xidVer,
+        GridCacheVersion commitVer,
+        long threadId,
+        TransactionIsolation isolation,
+        boolean commit,
+        boolean invalidate,
+        boolean sys,
+        byte plc,
+        boolean sysInvalidate,
+        boolean syncCommit,
+        boolean syncRollback,
+        GridCacheVersion baseVer,
+        Collection<GridCacheVersion> committedVers,
+        Collection<GridCacheVersion> rolledbackVers,
+        Collection<GridCacheVersion> pendingVers,
+        int txSize,
+        @Nullable UUID subjId,
+        int taskNameHash,
+        boolean addDepInfo,
+        Collection<Long> updateIdxs
+    ) {
+        this(nearNodeId, futId, miniId, topVer, xidVer, commitVer, threadId, isolation, commit, invalidate, sys, plc,
+            sysInvalidate, syncCommit, syncRollback, baseVer, committedVers, rolledbackVers, pendingVers, txSize,
+            subjId, taskNameHash, addDepInfo);
+
+        if (updateIdxs != null && !updateIdxs.isEmpty()) {
+            partUpdateCnt = new GridLongList(updateIdxs.size());
+
+            for (Long idx : updateIdxs)
+                partUpdateCnt.add(idx);
+        }
+    }
+
+    /**
+     * @return Partition update counters.
+     */
+    public GridLongList partUpdateCounters(){
+        return partUpdateCnt;
+    }
+
+    /**
      * @return Mini ID.
      */
     public IgniteUuid miniId() {
@@ -294,36 +370,42 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 writer.incrementState();
 
             case 22:
-                if (!writer.writeCollection("pendingVers", pendingVers, MessageCollectionItemType.MSG))
+                if (!writer.writeMessage("partUpdateCnt", partUpdateCnt))
                     return false;
 
                 writer.incrementState();
 
             case 23:
-                if (!writer.writeUuid("subjId", subjId))
+                if (!writer.writeCollection("pendingVers", pendingVers, MessageCollectionItemType.MSG))
                     return false;
 
                 writer.incrementState();
 
             case 24:
-                if (!writer.writeBoolean("sysInvalidate", sysInvalidate))
+                if (!writer.writeUuid("subjId", subjId))
                     return false;
 
                 writer.incrementState();
 
             case 25:
-                if (!writer.writeInt("taskNameHash", taskNameHash))
+                if (!writer.writeBoolean("sysInvalidate", sysInvalidate))
                     return false;
 
                 writer.incrementState();
 
             case 26:
-                if (!writer.writeMessage("topVer", topVer))
+                if (!writer.writeInt("taskNameHash", taskNameHash))
                     return false;
 
                 writer.incrementState();
 
             case 27:
+                if (!writer.writeMessage("topVer", topVer))
+                    return false;
+
+                writer.incrementState();
+
+            case 28:
                 if (!writer.writeMessage("writeVer", writeVer))
                     return false;
 
@@ -382,7 +464,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 22:
-                pendingVers = reader.readCollection("pendingVers", MessageCollectionItemType.MSG);
+                partUpdateCnt = reader.readMessage("partUpdateCnt");
 
                 if (!reader.isLastRead())
                     return false;
@@ -390,7 +472,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 23:
-                subjId = reader.readUuid("subjId");
+                pendingVers = reader.readCollection("pendingVers", MessageCollectionItemType.MSG);
 
                 if (!reader.isLastRead())
                     return false;
@@ -398,7 +480,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 24:
-                sysInvalidate = reader.readBoolean("sysInvalidate");
+                subjId = reader.readUuid("subjId");
 
                 if (!reader.isLastRead())
                     return false;
@@ -406,7 +488,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 25:
-                taskNameHash = reader.readInt("taskNameHash");
+                sysInvalidate = reader.readBoolean("sysInvalidate");
 
                 if (!reader.isLastRead())
                     return false;
@@ -414,7 +496,7 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 26:
-                topVer = reader.readMessage("topVer");
+                taskNameHash = reader.readInt("taskNameHash");
 
                 if (!reader.isLastRead())
                     return false;
@@ -422,6 +504,14 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
                 reader.incrementState();
 
             case 27:
+                topVer = reader.readMessage("topVer");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 28:
                 writeVer = reader.readMessage("writeVer");
 
                 if (!reader.isLastRead())
@@ -441,6 +531,6 @@ public class GridDhtTxFinishRequest extends GridDistributedTxFinishRequest {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 28;
+        return 29;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index 75f8c2f..3ee1048 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -64,6 +64,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheA
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtInvalidPartitionException;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedSingleGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPreloader;
@@ -1204,7 +1205,9 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
             Collection<IgniteBiTuple<GridDhtCacheEntry, GridCacheVersion>> deleted = null;
 
             try {
-                topology().readLock();
+                GridDhtPartitionTopology top = topology();
+
+                top.readLock();
 
                 try {
                     if (topology().stopping()) {
@@ -1221,7 +1224,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                     // Also do not check topology version if topology was locked on near node by
                     // external transaction or explicit lock.
                     if ((req.fastMap() && !req.clientRequest()) || req.topologyLocked() ||
-                        !needRemap(req.topologyVersion(), topology().topologyVersion())) {
+                        !needRemap(req.topologyVersion(), top.topologyVersion())) {
                         ClusterNode node = ctx.discovery().node(nodeId);
 
                         if (node == null) {
@@ -1236,7 +1239,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
 
                         if (ver == null) {
                             // Assign next version for update inside entries lock.
-                            ver = ctx.versions().next(topology().topologyVersion());
+                            ver = ctx.versions().next(top.topologyVersion());
 
                             if (hasNear)
                                 res.nearVersion(ver);
@@ -1248,6 +1251,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                             log.debug("Using cache version for update request on primary node [ver=" + ver +
                                 ", req=" + req + ']');
 
+                        boolean sndPrevVal = !top.rebalanceFinished(req.topologyVersion());
+
                         dhtFut = createDhtFuture(ver, req, res, completionCb, false);
 
                         expiry = expiryPolicy(req.expiry());
@@ -1270,7 +1275,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 completionCb,
                                 ctx.isDrEnabled(),
                                 taskName,
-                                expiry);
+                                expiry,
+                                sndPrevVal);
 
                             deleted = updRes.deleted();
                             dhtFut = updRes.dhtFuture();
@@ -1289,7 +1295,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 completionCb,
                                 ctx.isDrEnabled(),
                                 taskName,
-                                expiry);
+                                expiry,
+                                sndPrevVal);
 
                             retVal = updRes.returnValue();
                             deleted = updRes.deleted();
@@ -1309,7 +1316,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                         remap = true;
                 }
                 finally {
-                    topology().readUnlock();
+                    top.readUnlock();
                 }
             }
             catch (GridCacheEntryRemovedException e) {
@@ -1384,6 +1391,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
      * @param replicate Whether replication is enabled.
      * @param taskName Task name.
      * @param expiry Expiry policy.
+     * @param sndPrevVal If {@code true} sends previous value to backups.
      * @return Deleted entries.
      * @throws GridCacheEntryRemovedException Should not be thrown.
      */
@@ -1399,7 +1407,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
         CI2<GridNearAtomicUpdateRequest, GridNearAtomicUpdateResponse> completionCb,
         boolean replicate,
         String taskName,
-        @Nullable IgniteCacheExpiryPolicy expiry
+        @Nullable IgniteCacheExpiryPolicy expiry,
+        boolean sndPrevVal
     ) throws GridCacheEntryRemovedException {
         assert !ctx.dr().receiveEnabled(); // Cannot update in batches during DR due to possible conflicts.
         assert !req.returnValue() || req.operation() == TRANSFORM; // Should not request return values for putAll.
@@ -1546,7 +1555,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 replicate,
                                 updRes,
                                 taskName,
-                                expiry);
+                                expiry,
+                                sndPrevVal);
 
                             firstEntryIdx = i;
 
@@ -1594,7 +1604,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 replicate,
                                 updRes,
                                 taskName,
-                                expiry);
+                                expiry,
+                                sndPrevVal);
 
                             firstEntryIdx = i;
 
@@ -1713,7 +1724,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                 replicate,
                 updRes,
                 taskName,
-                expiry);
+                expiry,
+                sndPrevVal);
         }
         else
             assert filtered.isEmpty();
@@ -1790,6 +1802,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
      * @param replicate Whether DR is enabled for that cache.
      * @param taskName Task name.
      * @param expiry Expiry policy.
+     * @param sndPrevVal If {@code true} sends previous value to backups.
      * @return Return value.
      * @throws GridCacheEntryRemovedException Should be never thrown.
      */
@@ -1804,7 +1817,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
         CI2<GridNearAtomicUpdateRequest, GridNearAtomicUpdateResponse> completionCb,
         boolean replicate,
         String taskName,
-        @Nullable IgniteCacheExpiryPolicy expiry
+        @Nullable IgniteCacheExpiryPolicy expiry,
+        boolean sndPrevVal
     ) throws GridCacheEntryRemovedException {
         GridCacheReturn retVal = null;
         Collection<IgniteBiTuple<GridDhtCacheEntry, GridCacheVersion>> deleted = null;
@@ -1861,7 +1875,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                     req.invokeArguments(),
                     primary && writeThrough() && !req.skipStore(),
                     !req.skipStore(),
-                    req.returnValue(),
+                    sndPrevVal || req.returnValue(),
                     expiry,
                     true,
                     true,
@@ -1876,7 +1890,9 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                     true,
                     intercept,
                     req.subjectId(),
-                    taskName);
+                    taskName,
+                    null,
+                    null);
 
                 if (dhtFut == null && !F.isEmpty(filteredReaders)) {
                     dhtFut = createDhtFuture(ver, req, res, completionCb, true);
@@ -1901,7 +1917,10 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 entryProcessor,
                                 updRes.newTtl(),
                                 updRes.conflictExpireTime(),
-                                newConflictVer);
+                                newConflictVer,
+                                sndPrevVal,
+                                updRes.oldValue(),
+                                updRes.updateCounter());
                         }
 
                         if (!F.isEmpty(filteredReaders))
@@ -1918,6 +1937,11 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 "[entry=" + entry + ", filter=" + Arrays.toString(req.filter()) + ']');
                     }
                 }
+                else if (!entry.isNear() && updRes.success()) {
+                    ctx.continuousQueries().onEntryUpdated(entry.key(), updRes.newValue(), updRes.oldValue(),
+                        entry.isInternal() || !context().userCache(), entry.partition(), primary, false,
+                        updRes.updateCounter(), topVer);
+                }
 
                 if (hasNear) {
                     if (primary && updRes.sendToDht()) {
@@ -2008,6 +2032,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
      * @param batchRes Batch update result.
      * @param taskName Task name.
      * @param expiry Expiry policy.
+     * @param sndPrevVal If {@code true} sends previous value to backups.
      * @return Deleted entries.
      */
     @SuppressWarnings("ForLoopReplaceableByForEach")
@@ -2028,7 +2053,8 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
         boolean replicate,
         UpdateBatchResult batchRes,
         String taskName,
-        @Nullable IgniteCacheExpiryPolicy expiry
+        @Nullable IgniteCacheExpiryPolicy expiry,
+        boolean sndPrevVal
     ) {
         assert putMap == null ^ rmvKeys == null;
 
@@ -2130,7 +2156,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                         null,
                         /*write-through*/false,
                         /*read-through*/false,
-                        /*retval*/false,
+                        /*retval*/sndPrevVal,
                         expiry,
                         /*event*/true,
                         /*metrics*/true,
@@ -2145,7 +2171,9 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                         /*conflict resolve*/false,
                         /*intercept*/false,
                         req.subjectId(),
-                        taskName);
+                        taskName,
+                        null,
+                        null);
 
                     assert !updRes.success() || updRes.newTtl() == CU.TTL_NOT_CHANGED || expiry != null :
                         "success=" + updRes.success() + ", newTtl=" + updRes.newTtl() + ", expiry=" + expiry;
@@ -2184,7 +2212,10 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                                 entryProcessor,
                                 updRes.newTtl(),
                                 CU.EXPIRE_TIME_CALCULATE,
-                                null);
+                                null,
+                                sndPrevVal,
+                                updRes.oldValue(),
+                                updRes.updateCounter());
 
                         if (!F.isEmpty(filteredReaders))
                             dhtFut.addNearWriteEntries(filteredReaders,
@@ -2573,7 +2604,10 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                         entry = entryExx(key);
 
                         CacheObject val = req.value(i);
+                        CacheObject prevVal = req.previousValue(i);
+
                         EntryProcessor<Object, Object, Object> entryProcessor = req.entryProcessor(i);
+                        Long updateIdx = req.updateCounter(i);
 
                         GridCacheOperation op = entryProcessor != null ? TRANSFORM :
                             (val != null) ? UPDATE : DELETE;
@@ -2605,11 +2639,18 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                             false,
                             intercept,
                             req.subjectId(),
-                            taskName);
+                            taskName,
+                            prevVal,
+                            updateIdx);
 
                         if (updRes.removeVersion() != null)
                             ctx.onDeferredDelete(entry, updRes.removeVersion());
 
+                        if (updRes.success() && !entry.isNear())
+                            ctx.continuousQueries().onEntryUpdated(entry.key(), updRes.newValue(),
+                                updRes.oldValue(), entry.isInternal() || !context().userCache(), entry.partition(),
+                                false, false, updRes.updateCounter(), req.topologyVersion());
+
                         entry.onUnlock();
 
                         break; // While.

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
index c34dcfd..c73b3b7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
@@ -215,13 +215,17 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
      * @param ttl TTL (optional).
      * @param conflictExpireTime Conflict expire time (optional).
      * @param conflictVer Conflict version (optional).
+     * @param updateCntr Partition update counter.
      */
     public void addWriteEntry(GridDhtCacheEntry entry,
         @Nullable CacheObject val,
         EntryProcessor<Object, Object, Object> entryProcessor,
         long ttl,
         long conflictExpireTime,
-        @Nullable GridCacheVersion conflictVer) {
+        @Nullable GridCacheVersion conflictVer,
+        boolean addPrevVal,
+        @Nullable CacheObject prevVal,
+        @Nullable Long updateCntr) {
         AffinityTopologyVersion topVer = updateReq.topologyVersion();
 
         Collection<ClusterNode> dhtNodes = cctx.dht().topology().nodes(entry.partition(), topVer);
@@ -261,7 +265,22 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
                     entryProcessor,
                     ttl,
                     conflictExpireTime,
-                    conflictVer);
+                    conflictVer,
+                    addPrevVal,
+                    entry.partition(),
+                    prevVal,
+                    updateCntr);
+            }
+            else if (dhtNodes.size() == 1) {
+                try {
+                    cctx.continuousQueries().onEntryUpdated(entry.key(), val, prevVal,
+                        entry.key().internal() || !cctx.userCache(), entry.partition(), true, false,
+                        updateCntr, updateReq.topologyVersion());
+                }
+                catch (IgniteCheckedException e) {
+                    U.warn(log, "Failed to send continuous query message. [key=" + entry.key() + ", newVal="
+                        + val + ", err=" + e + "]");
+                }
             }
         }
     }
@@ -331,8 +350,56 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
             cctx.mvcc().removeAtomicFuture(version());
 
             if (err != null) {
-                for (KeyCacheObject key : keys)
-                    updateRes.addFailedKey(key, err);
+                if (!mappings.isEmpty()) {
+                    Collection<KeyCacheObject> hndKeys = new ArrayList<>(keys.size());
+
+                    exit: for (GridDhtAtomicUpdateRequest req : mappings.values()) {
+                        for (int i = 0; i < req.size(); i++) {
+                            KeyCacheObject key = req.key(i);
+
+                            if (!hndKeys.contains(key)) {
+                                updateRes.addFailedKey(key, err);
+
+                                cctx.continuousQueries().skipUpdateEvent(key, req.partitionId(i), req.updateCounter(i),
+                                    updateReq.topologyVersion());
+
+                                hndKeys.add(key);
+
+                                if (hndKeys.size() == keys.size())
+                                    break exit;
+                            }
+                        }
+                    }
+                }
+                else
+                    for (KeyCacheObject key : keys)
+                        updateRes.addFailedKey(key, err);
+            }
+            else {
+                Collection<KeyCacheObject> hndKeys = new ArrayList<>(keys.size());
+
+                exit: for (GridDhtAtomicUpdateRequest req : mappings.values()) {
+                    for (int i = 0; i < req.size(); i++) {
+                        KeyCacheObject key = req.key(i);
+
+                        if (!hndKeys.contains(key)) {
+                            try {
+                                cctx.continuousQueries().onEntryUpdated(key, req.value(i), req.localPreviousValue(i),
+                                    key.internal() || !cctx.userCache(), req.partitionId(i), true, false,
+                                    req.updateCounter(i), updateReq.topologyVersion());
+                            }
+                            catch (IgniteCheckedException e) {
+                                U.warn(log, "Failed to send continuous query message. [key=" + key + ", newVal="
+                                    + req.value(i) + ", err=" + e + "]");
+                            }
+
+                            hndKeys.add(key);
+
+                            if (hndKeys.size() == keys.size())
+                                break exit;
+                        }
+                    }
+                }
             }
 
             if (updateReq.writeSynchronizationMode() == FULL_SYNC)


[17/37] ignite git commit: IGNITE-530 Initial implementation

Posted by ag...@apache.org.
 IGNITE-530 Initial implementation


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

Branch: refs/heads/ignite-1282
Commit: a39681ef54206ac23f3dff9dab930dc2596d9870
Parents: 480d457
Author: sylentprayer <un4given>
Authored: Thu Nov 19 15:32:24 2015 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Thu Nov 19 15:32:24 2015 +0300

----------------------------------------------------------------------
 modules/twitter/README.txt                      |  32 ++
 modules/twitter/licenses/apache-2.0.txt         | 202 +++++++++++++
 modules/twitter/pom.xml                         | 116 ++++++++
 .../ignite/stream/twitter/OAuthSettings.java    |  86 ++++++
 .../ignite/stream/twitter/TwitterStreamer.java  | 295 +++++++++++++++++++
 .../twitter/IgniteTwitterStreamerTest.java      | 234 +++++++++++++++
 .../twitter/IgniteTwitterStreamerTestSuite.java |  32 ++
 .../stream/twitter/TwitterStreamerImpl.java     |  79 +++++
 pom.xml                                         |   1 +
 9 files changed, 1077 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/README.txt
----------------------------------------------------------------------
diff --git a/modules/twitter/README.txt b/modules/twitter/README.txt
new file mode 100644
index 0000000..1c412f9
--- /dev/null
+++ b/modules/twitter/README.txt
@@ -0,0 +1,32 @@
+Apache Ignite Twitter Streamer Module
+------------------------
+
+Apache Ignite Twitter Streamer module provides streaming from Twitter to Ignite cache.
+
+To enable Twitter Streamer module when starting a standalone node, move 'optional/ignite-twitter' folder to
+'libs' folder before running 'ignite.{sh|bat}' script. The content of the module folder will
+be added to classpath in this case.
+
+Importing Ignite Twitter Streamer Module In Maven Project
+-------------------------------------
+
+If you are using Maven to manage dependencies of your project, you can add JCL module
+dependency like this (replace '${ignite.version}' with actual Ignite version you are
+interested in):
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
+                        http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    ...
+    <dependencies>
+        ...
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-twitter</artifactId>
+            <version>${ignite.version}</version>
+        </dependency>
+        ...
+    </dependencies>
+    ...
+</project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/licenses/apache-2.0.txt
----------------------------------------------------------------------
diff --git a/modules/twitter/licenses/apache-2.0.txt b/modules/twitter/licenses/apache-2.0.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/modules/twitter/licenses/apache-2.0.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/pom.xml
----------------------------------------------------------------------
diff --git a/modules/twitter/pom.xml b/modules/twitter/pom.xml
new file mode 100644
index 0000000..21e6f51
--- /dev/null
+++ b/modules/twitter/pom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<!--
+    POM file.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.ignite</groupId>
+        <artifactId>ignite-parent</artifactId>
+        <version>1</version>
+        <relativePath>../../parent</relativePath>
+    </parent>
+
+    <artifactId>ignite-twitter</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <url>http://ignite.apache.org</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-log4j</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-spring</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-core</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.twitter</groupId>
+            <artifactId>hbc-twitter4j</artifactId>
+            <version>2.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.tomakehurst</groupId>
+            <artifactId>wiremock</artifactId>
+            <version>1.57</version>
+            <classifier>standalone</classifier>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.mortbay.jetty</groupId>
+                    <artifactId>jetty</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.guava</groupId>
+                    <artifactId>guava</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-annotations</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.fasterxml.jackson.core</groupId>
+                    <artifactId>jackson-databind</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.httpcomponents</groupId>
+                    <artifactId>httpclient</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.skyscreamer</groupId>
+                    <artifactId>jsonassert</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>xmlunit</groupId>
+                    <artifactId>xmlunit</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.jayway.jsonpath</groupId>
+                    <artifactId>json-path</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>net.sf.jopt-simple</groupId>
+                    <artifactId>jopt-simple</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/OAuthSettings.java
----------------------------------------------------------------------
diff --git a/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/OAuthSettings.java b/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/OAuthSettings.java
new file mode 100644
index 0000000..c2e46a5
--- /dev/null
+++ b/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/OAuthSettings.java
@@ -0,0 +1,86 @@
+/*
+ * 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.stream.twitter;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * OAuth keys holder.
+ */
+public class OAuthSettings {
+    /** */
+    private final String consumerKey;
+
+    /** */
+    private final String consumerSecret;
+
+    /** */
+    private final String accessToken;
+
+    /** */
+    private final String accessTokenSecret;
+
+    /**
+     * @param consumerKey Consumer key.
+     * @param consumerSecret Consumer secret.
+     * @param accessToken Access token.
+     * @param accessTokenSecret Access secret token.
+     */
+    public OAuthSettings(
+        @NotNull String consumerKey,
+        @NotNull String consumerSecret,
+        @NotNull String accessToken,
+        @NotNull String accessTokenSecret) {
+        this.consumerKey = consumerKey;
+        this.consumerSecret = consumerSecret;
+        this.accessToken = accessToken;
+        this.accessTokenSecret = accessTokenSecret;
+    }
+
+    /**
+     * @return Consumer key.
+     */
+    @NotNull
+    public String getConsumerKey() {
+        return consumerKey;
+    }
+
+    /**
+     * @return Consumer secret.
+     */
+    @NotNull
+    public String getConsumerSecret() {
+        return consumerSecret;
+    }
+
+    /**
+     * @return Access token.
+     */
+    @NotNull
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    /**
+     * @return Access token secret.
+     */
+    @NotNull
+    public String getAccessTokenSecret() {
+        return accessTokenSecret;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/TwitterStreamer.java
----------------------------------------------------------------------
diff --git a/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/TwitterStreamer.java b/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/TwitterStreamer.java
new file mode 100644
index 0000000..309cc52
--- /dev/null
+++ b/modules/twitter/src/main/java/org/apache/ignite/stream/twitter/TwitterStreamer.java
@@ -0,0 +1,295 @@
+/*
+ * 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.stream.twitter;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import com.twitter.hbc.ClientBuilder;
+import com.twitter.hbc.core.Client;
+import com.twitter.hbc.core.HttpConstants;
+import com.twitter.hbc.core.HttpHosts;
+import com.twitter.hbc.core.endpoint.DefaultStreamingEndpoint;
+import com.twitter.hbc.core.endpoint.SitestreamEndpoint;
+import com.twitter.hbc.core.endpoint.StatusesFilterEndpoint;
+import com.twitter.hbc.core.endpoint.StatusesFirehoseEndpoint;
+import com.twitter.hbc.core.endpoint.StatusesSampleEndpoint;
+import com.twitter.hbc.core.endpoint.StreamingEndpoint;
+import com.twitter.hbc.core.endpoint.UserstreamEndpoint;
+import com.twitter.hbc.core.processor.StringDelimitedProcessor;
+import com.twitter.hbc.httpclient.auth.Authentication;
+import com.twitter.hbc.httpclient.auth.OAuth1;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.stream.StreamAdapter;
+
+/**
+ * Streamer that consumes from a Twitter Streaming API and feeds transformed key-value pairs,
+ * by default <tweetId, text>, into an {@link IgniteDataStreamer} instance.
+ * <p>
+ * This streamer uses https://dev.twitter.com/streaming API and supports Public API, User Streams,
+ * Site Streams and Firehose.
+ * <p>
+ * This Streamer features:
+ * <ul>
+ *     <li>Supports OAuth1 authentication scheme.
+ *     <br/> BasicAuth not supported by Streaming API https://dev.twitter.com/streaming/overview/connecting</li>
+ *     <li>Provide all params in apiParams map. https://dev.twitter.com/streaming/overview/request-parameters</li>
+ * </ul>
+ */
+public class TwitterStreamer<K, V> extends StreamAdapter<String, K, V> {
+    /** Logger. */
+    protected IgniteLogger log;
+
+    /** Threads count used to transform tweets. */
+    private int threadsCount = 1;
+
+    /** Twitter Streaming API params. See https://dev.twitter.com/streaming/overview/request-parameters */
+    private Map<String, String> apiParams;
+
+    /** Twitter streaming API endpoint example, '/statuses/filter.json' or '/statuses/firehose.json' */
+    private String endpointUrl;
+
+    /** OAuth params holder */
+    private OAuthSettings oAuthSettings;
+
+    /** shared variable to communicate/signal that streamer is already running or can be started */
+    private final AtomicInteger running = new AtomicInteger();
+
+    /**
+     * Size of buffer for streaming, as for some tracking terms traffic can be low and for others high, this is
+     * configurable
+     */
+    private Integer bufferCapacity = 100000;
+
+    /** Twitter streaming client (Twitter HBC) to interact with stream */
+    private Client client;
+
+    /** Process stream asynchronously */
+    private ExecutorService tweetStreamProcessor;
+
+    /** Param key name constant for Site streaming */
+    private final String SITE_USER_ID_KEY = "follow";
+
+    /**
+     * @param oAuthSettings OAuth Settings
+     */
+    public TwitterStreamer(OAuthSettings oAuthSettings) {
+        this.oAuthSettings = oAuthSettings;
+    }
+
+    /**
+     * Starts streamer.
+     */
+    public void start() {
+        if (!running.compareAndSet(0, 1))
+            throw new IgniteException("Attempted to start an already started Twitter Streamer");
+
+        validateConfig();
+
+        log = getIgnite().log();
+
+        final BlockingQueue<String> tweetQueue = new LinkedBlockingQueue<>(bufferCapacity);
+
+        client = getClient(tweetQueue);
+
+        client.connect();
+
+        tweetStreamProcessor = Executors.newFixedThreadPool(threadsCount);
+
+        for (int i = 0; i < threadsCount; i++) {
+            Callable<Boolean> task = new Callable<Boolean>() {
+
+                @Override
+                public Boolean call() {
+                    while (true) {
+                        try {
+                            String tweet = tweetQueue.take();
+
+                            addMessage(tweet);
+                        }
+                        catch (InterruptedException e) {
+                            U.warn(log, "Tweets transformation was interrupted", e);
+
+                            return true;
+                        }
+                    }
+                }
+            };
+
+            tweetStreamProcessor.submit(task);
+        }
+    }
+
+    /**
+     * Stops streamer.
+     */
+    public void stop() {
+        if (running.get() == 0)
+            throw new IgniteException("Attempted to stop an already stopped Twitter Streamer");
+
+        tweetStreamProcessor.shutdownNow();
+
+        client.stop();
+
+        running.compareAndSet(1, 0);
+    }
+
+    /**
+     * Validates config at start.
+     */
+    protected void validateConfig() {
+        A.notNull(getStreamer(), "Streamer");
+        A.notNull(getIgnite(), "Ignite");
+        A.notNull(endpointUrl, "Twitter Streaming API endpoint");
+
+        A.ensure(getSingleTupleExtractor() != null || getMultipleTupleExtractor() != null, "Twitter extractor");
+
+        String followParam = apiParams.get(SITE_USER_ID_KEY);
+
+        A.ensure(followParam != null && followParam.matches("^(\\d+,? ?)+$"),
+            "Site streaming endpoint must provide 'follow' param with value as comma separated numbers");
+    }
+
+    /**
+     * @param tweetQueue Tweet queue.
+     * @return Client.
+     */
+    protected Client getClient(BlockingQueue<String> tweetQueue) {
+        StreamingEndpoint endpoint;
+
+        HttpHosts hosts;
+
+        switch (endpointUrl.toLowerCase()) {
+            case StatusesFilterEndpoint.PATH:
+                endpoint = new StatusesFilterEndpoint();
+
+                hosts = HttpHosts.STREAM_HOST;
+
+                break;
+            case StatusesFirehoseEndpoint.PATH:
+                endpoint = new StatusesFirehoseEndpoint();
+
+                hosts = HttpHosts.STREAM_HOST;
+
+                break;
+            case StatusesSampleEndpoint.PATH:
+                endpoint = new StatusesSampleEndpoint();
+
+                hosts = HttpHosts.STREAM_HOST;
+
+                break;
+            case UserstreamEndpoint.PATH:
+                endpoint = new UserstreamEndpoint();
+
+                hosts = HttpHosts.USERSTREAM_HOST;
+
+                break;
+            case SitestreamEndpoint.PATH:
+                String follow = apiParams.remove(SITE_USER_ID_KEY);
+
+                List<Long> followers = Lists.newArrayList();
+
+                for (String follower : Splitter.on(',').trimResults().omitEmptyStrings().split(follow))
+                    followers.add(Long.valueOf(follower));
+
+                endpoint = new SitestreamEndpoint(followers);
+
+                hosts = HttpHosts.SITESTREAM_HOST;
+
+                break;
+            default:
+                endpoint = new DefaultStreamingEndpoint(endpointUrl, HttpConstants.HTTP_GET, false);
+
+                hosts = HttpHosts.STREAM_HOST;
+
+        }
+
+        for (Map.Entry<String, String> entry : apiParams.entrySet()) {
+            endpoint.addPostParameter(entry.getKey(), entry.getValue());
+        }
+
+        return buildClient(tweetQueue, hosts, endpoint);
+    }
+
+    /**
+     * @param tweetQueue tweet Queue.
+     * @param hosts Hostes.
+     * @param endpoint Endpoint.
+     * @return Client.
+     */
+    protected Client buildClient(BlockingQueue<String> tweetQueue, HttpHosts hosts, StreamingEndpoint endpoint) {
+        Authentication authentication = new OAuth1(oAuthSettings.getConsumerKey(), oAuthSettings.getConsumerSecret(),
+            oAuthSettings.getAccessToken(), oAuthSettings.getAccessTokenSecret());
+
+        ClientBuilder builder = new ClientBuilder()
+            .name("Ignite-Twitter-Client")
+            .hosts(hosts)
+            .authentication(authentication)
+            .endpoint(endpoint)
+            .processor(new StringDelimitedProcessor(tweetQueue));
+
+        return builder.build();
+    }
+
+    /**
+     * Sets API Params.
+     *
+     * @param apiParams API Params.
+     */
+    public void setApiParams(Map<String, String> apiParams) {
+        this.apiParams = apiParams;
+    }
+
+    /**
+     * Sets Endpoint URL.
+     *
+     * @param endpointUrl Endpoint URL.
+     */
+    public void setEndpointUrl(String endpointUrl) {
+        this.endpointUrl = endpointUrl;
+    }
+
+    /**
+     * Sets Buffer capacity.
+     *
+     * @param bufferCapacity Buffer capacity.
+     */
+    public void setBufferCapacity(Integer bufferCapacity) {
+        this.bufferCapacity = bufferCapacity;
+    }
+
+    /**
+     * Sets Threads count.
+     *
+     * @param threadsCount Threads count.
+     */
+    public void setThreadsCount(int threadsCount) {
+        this.threadsCount = threadsCount;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTest.java
----------------------------------------------------------------------
diff --git a/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTest.java b/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTest.java
new file mode 100644
index 0000000..4ba07ff
--- /dev/null
+++ b/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTest.java
@@ -0,0 +1,234 @@
+/*
+ * 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.stream.twitter;
+
+import com.github.tomakehurst.wiremock.WireMockServer;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.twitter.hbc.core.HttpHosts;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.events.CacheEvent;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.junit.Rule;
+import twitter4j.Status;
+import twitter4j.TwitterException;
+import twitter4j.TwitterObjectFactory;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
+import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_PUT;
+
+/**
+ * Test for {@link TwitterStreamer}. Tests Public Status streaming API https://dev.twitter.com/streaming/public.
+ */
+public class IgniteTwitterStreamerTest extends GridCommonAbstractTest {
+
+    /** Cache entries count. */
+    private static final int CACHE_ENTRY_COUNT = 100;
+
+    /** Mocked api in embedded server. */
+    private static final String MOCK_TWEET_PATH = "/tweet/mock";
+
+    /** Sample tweet. */
+    private static final String tweet = "{\"id\":647375831971590144,\"text\":\"sample tweet to test streamer\"}\n";
+
+    /** Constructor. */
+    public IgniteTwitterStreamerTest() {
+        super(true);
+    }
+
+    /** Embedded mock HTTP server's for Twitter API rule. */
+    @Rule
+    public final WireMockRule wireMockRule = new WireMockRule();
+
+    /** Embedded mock HTTP server for Twitter API. */
+    public final WireMockServer mockServer = new WireMockServer(); //Starts server on 8080 port.
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return 10_000;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void beforeTest() throws Exception {
+        grid().getOrCreateCache(defaultCacheConfiguration());
+
+        mockServer.start();
+
+        stubFor(get(urlMatching("/1.1" + MOCK_TWEET_PATH + ".*")).willReturn(aResponse().
+            withHeader("Content-Type", "text/plain").withBody(tweet.length() + "\n" + tweet)));
+    }
+
+    /** {@inheritDoc} */
+    public void afterTest() throws Exception {
+        stopAllGrids();
+
+        mockServer.stop();
+    }
+
+    /**
+     * @throws Exception Test exception.
+     */
+    public void testStatusesFilterEndpointOAuth1() throws Exception {
+        try (IgniteDataStreamer<Long, String> dataStreamer = grid().dataStreamer(null)) {
+            TwitterStreamerImpl streamer = newStreamerInstance(dataStreamer);
+
+            Map<String, String> params = new HashMap<>();
+
+            params.put("track", "apache, twitter");
+            params.put("follow", "3004445758");// @ApacheIgnite id.
+
+            streamer.setApiParams(params);
+            streamer.setEndpointUrl(MOCK_TWEET_PATH);
+            streamer.setHosts(new HttpHosts("http://localhost:8080"));
+            streamer.setThreadsCount(8);
+
+            executeStreamer(streamer);
+        }
+    }
+
+    /**
+     * @param streamer Twitter streamer.
+     * @throws InterruptedException Test exception.
+     * @throws TwitterException Test exception.
+     */
+    private void executeStreamer(TwitterStreamer streamer) throws InterruptedException, TwitterException {
+        // Checking streaming.
+
+        CacheListener listener = subscribeToPutEvents();
+
+        streamer.start();
+
+        try {
+            streamer.start();
+
+            fail("Successful start of already started Twitter Streamer");
+        }
+        catch (IgniteException ex) {
+            // No-op.
+        }
+
+        CountDownLatch latch = listener.getLatch();
+
+        // Enough tweets was handled in 10 seconds. Limited by test's timeout.
+        latch.await();
+
+        unsubscribeToPutEvents(listener);
+
+        streamer.stop();
+
+        try {
+            streamer.stop();
+
+            fail("Successful stop of already stopped Twitter Streamer");
+        }
+        catch (IgniteException ex) {
+            // No-op.
+        }
+
+        // Checking cache content after streaming finished.
+
+        Status status = TwitterObjectFactory.createStatus(tweet);
+
+        IgniteCache<Long, String> cache = grid().cache(null);
+
+        String cachedValue = cache.get(status.getId());
+
+        // Tweet successfully put to cache.
+        assertTrue(cachedValue != null && cachedValue.equals(status.getText()));
+
+        // Same tweets does not produce duplicate entries.
+        assertTrue(cache.size() == 1);
+    }
+
+    /**
+     * @return Cache listener.
+     */
+    private CacheListener subscribeToPutEvents() {
+        Ignite ignite = grid();
+
+        // Listen to cache PUT events and expect as many as messages as test data items.
+        CacheListener listener = new CacheListener();
+
+        ignite.events(ignite.cluster().forCacheNodes(null)).localListen(listener, EVT_CACHE_OBJECT_PUT);
+
+        return listener;
+    }
+
+    /**
+     * @param listener Cache listener.
+     */
+    private void unsubscribeToPutEvents(CacheListener listener) {
+        Ignite ignite = grid();
+
+        ignite.events(ignite.cluster().forCacheNodes(null)).stopLocalListen(listener, EVT_CACHE_OBJECT_PUT);
+    }
+
+    /**
+     * @param dataStreamer Ignite Data Streamer.
+     * @return Twitter Streamer.
+     */
+    private TwitterStreamerImpl newStreamerInstance(IgniteDataStreamer<Long, String> dataStreamer) {
+        OAuthSettings oAuthSettings = new OAuthSettings("<dummy>", "<dummy>", "<dummy>", "<dummy>");
+
+        TwitterStreamerImpl streamer = new TwitterStreamerImpl(oAuthSettings);
+
+        streamer.setIgnite(grid());
+        streamer.setStreamer(dataStreamer);
+
+        dataStreamer.allowOverwrite(true);
+        dataStreamer.autoFlushFrequency(10);
+
+        return streamer;
+    }
+
+    /**
+     * Listener.
+     */
+    private class CacheListener implements IgnitePredicate<CacheEvent> {
+
+        /** */
+        private final CountDownLatch latch = new CountDownLatch(CACHE_ENTRY_COUNT);
+
+        /**
+         * @return Latch.
+         */
+        public CountDownLatch getLatch() {
+            return latch;
+        }
+
+        /**
+         * @param evt Cache Event.
+         * @return {@code true}.
+         */
+        @Override
+        public boolean apply(CacheEvent evt) {
+            latch.countDown();
+
+            return true;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTestSuite.java b/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTestSuite.java
new file mode 100644
index 0000000..b458bed
--- /dev/null
+++ b/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/IgniteTwitterStreamerTestSuite.java
@@ -0,0 +1,32 @@
+/*
+ * 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.stream.twitter;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+/**
+ * Twitter streamer tests.
+ */
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+    IgniteTwitterStreamerTest.class
+})
+public class IgniteTwitterStreamerTestSuite {
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/TwitterStreamerImpl.java
----------------------------------------------------------------------
diff --git a/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/TwitterStreamerImpl.java b/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/TwitterStreamerImpl.java
new file mode 100644
index 0000000..3c047e0
--- /dev/null
+++ b/modules/twitter/src/test/java/org/apache/ignite/stream/twitter/TwitterStreamerImpl.java
@@ -0,0 +1,79 @@
+/*
+ *  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.stream.twitter;
+
+import com.twitter.hbc.core.Client;
+import com.twitter.hbc.core.HttpHosts;
+import com.twitter.hbc.core.endpoint.StreamingEndpoint;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.stream.StreamSingleTupleExtractor;
+import twitter4j.Status;
+import twitter4j.TwitterException;
+import twitter4j.TwitterObjectFactory;
+
+/**
+ * Long, String (With Mocked server support) implementation of TwitterStreamer.
+ */
+public class TwitterStreamerImpl extends TwitterStreamer<Long, String> {
+    /** Mocked server support. */
+    HttpHosts hosts;
+
+    /**
+     * @param oAuthSettings OAuth Settings
+     */
+    public TwitterStreamerImpl(OAuthSettings oAuthSettings) {
+        super(oAuthSettings);
+
+        setSingleTupleExtractor(new TwitterStreamSingleTupleExtractorImpl());
+    }
+
+    /**
+     * @param hosts hosts.
+     */
+    public void setHosts(HttpHosts hosts) {
+        this.hosts = hosts;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected Client buildClient(BlockingQueue<String> tweetQueue, HttpHosts hosts,
+        StreamingEndpoint endpoint) {
+        return super.buildClient(tweetQueue, this.hosts, endpoint);
+    }
+
+    /**
+     * Long, String Tweet Single Tuple Extractor.
+     */
+    class TwitterStreamSingleTupleExtractorImpl implements StreamSingleTupleExtractor<String, Long, String> {
+        @Override public Map.Entry<Long, String> extract(String tweet) {
+            try {
+                Status status = TwitterObjectFactory.createStatus(tweet);
+
+                return new IgniteBiTuple<>(status.getId(), status.getText());
+            }
+            catch (TwitterException e) {
+                U.error(log, e);
+
+                return null;
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/a39681ef/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index b9c51b2..1008981 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,7 @@
         <module>modules/flume</module>
         <module>modules/yarn</module>
         <module>modules/jms11</module>
+        <module>modules/twitter</module>
         <module>modules/mqtt</module>
         <module>modules/zookeeper</module>
         <module>modules/camel</module>


[06/37] ignite git commit: 'Single' operations optimizations for tx cache.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteSingleStateImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteSingleStateImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteSingleStateImpl.java
new file mode 100644
index 0000000..22f04a8
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteSingleStateImpl.java
@@ -0,0 +1,108 @@
+/*
+ * 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.transactions;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class IgniteTxRemoteSingleStateImpl extends IgniteTxRemoteStateAdapter {
+    /** */
+    private IgniteTxEntry entry;
+
+    /** {@inheritDoc} */
+    @Override public void addWriteEntry(IgniteTxKey key, IgniteTxEntry e) {
+        this.entry = e;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clearEntry(IgniteTxKey key) {
+        if (entry != null && entry.txKey().equals(key))
+            entry = null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry entry(IgniteTxKey key) {
+        if (entry != null && entry.txKey().equals(key))
+            return entry;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasWriteKey(IgniteTxKey key) {
+        return entry != null && entry.txKey().equals(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> readSet() {
+        return Collections.emptySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> writeSet() {
+        return entry != null ? Collections.singleton(entry.txKey()) : Collections.<IgniteTxKey>emptySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> writeEntries() {
+        return entry != null ? Collections.singletonList(entry) : Collections.<IgniteTxEntry>emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> readEntries() {
+        return Collections.emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
+        return entry != null ? Collections.singletonMap(entry.txKey(), entry) :
+            Collections.<IgniteTxKey, IgniteTxEntry>emptyMap();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
+        return Collections.emptyMap();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean empty() {
+        return entry == null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> allEntries() {
+        return entry != null ? Collections.singletonList(entry) : Collections.<IgniteTxEntry>emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public IgniteTxEntry singleWrite() {
+        return entry;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return S.toString(IgniteTxRemoteSingleStateImpl.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteState.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteState.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteState.java
new file mode 100644
index 0000000..b8290a1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteState.java
@@ -0,0 +1,34 @@
+/*
+ * 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.transactions;
+
+/**
+ *
+ */
+public interface IgniteTxRemoteState extends IgniteTxState {
+    /**
+     * @param key Key.
+     * @param e Entry.
+     */
+    public void addWriteEntry(IgniteTxKey key, IgniteTxEntry e);
+
+    /**
+     * @param key Entry key.
+     */
+    public void clearEntry(IgniteTxKey key);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
new file mode 100644
index 0000000..e7c4c96
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
@@ -0,0 +1,110 @@
+/*
+ * 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.transactions;
+
+import java.util.Collection;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
+import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public abstract class IgniteTxRemoteStateAdapter implements IgniteTxRemoteState {
+    /** {@inheritDoc} */
+    @Override public boolean implicitSingle() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Integer firstCacheId() {
+        assert false;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void awaitLastFut(GridCacheSharedContext cctx) {
+        assert false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCheckedException validateTopology(GridCacheSharedContext cctx, GridDhtTopologyFuture topFut) {
+        assert false;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean sync(GridCacheSharedContext cctx) {
+        assert false;
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasNearCache(GridCacheSharedContext cctx) {
+        assert false;
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addActiveCache(GridCacheContext cacheCtx, IgniteTxLocalAdapter tx)
+        throws IgniteCheckedException {
+        assert false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDhtTopologyFuture topologyReadLock(GridCacheSharedContext cctx, GridFutureAdapter<?> fut) {
+        assert false;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void topologyReadUnlock(GridCacheSharedContext cctx) {
+        assert false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean storeUsed(GridCacheSharedContext cctx) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
+        assert false;
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridCacheContext singleCacheContext(GridCacheSharedContext cctx) {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onTxEnd(GridCacheSharedContext cctx, IgniteInternalTx tx, boolean commit) {
+        assert false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateImpl.java
new file mode 100644
index 0000000..32bc646
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateImpl.java
@@ -0,0 +1,124 @@
+/*
+ * 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.transactions;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+/**
+ *
+ */
+public class IgniteTxRemoteStateImpl extends IgniteTxRemoteStateAdapter {
+    /** Read set. */
+    @GridToStringInclude
+    protected Map<IgniteTxKey, IgniteTxEntry> readMap;
+
+    /** Write map. */
+    @GridToStringInclude
+    protected Map<IgniteTxKey, IgniteTxEntry> writeMap;
+
+    /**
+     * @param readMap Read map.
+     * @param writeMap Write map.
+     */
+    public IgniteTxRemoteStateImpl(Map<IgniteTxKey, IgniteTxEntry> readMap,
+        Map<IgniteTxKey, IgniteTxEntry> writeMap) {
+        this.readMap = readMap;
+        this.writeMap = writeMap;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry entry(IgniteTxKey key) {
+        IgniteTxEntry e = writeMap == null ? null : writeMap.get(key);
+
+        if (e == null)
+            e = readMap == null ? null : readMap.get(key);
+
+        return e;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasWriteKey(IgniteTxKey key) {
+        return writeMap.containsKey(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> readSet() {
+        return readMap.keySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> writeSet() {
+        return writeMap.keySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> writeEntries() {
+        return writeMap.values();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> readEntries() {
+        return readMap.values();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
+        return writeMap;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
+        return readMap;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean empty() {
+        return readMap.isEmpty() && writeMap.isEmpty();
+    }
+
+    /** {@inheritDoc} */
+    public void addWriteEntry(IgniteTxKey key, IgniteTxEntry e) {
+        writeMap.put(key, e);
+    }
+
+    /** {@inheritDoc} */
+    public void clearEntry(IgniteTxKey key) {
+        readMap.remove(key);
+        writeMap.remove(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> allEntries() {
+        return F.concat(false, writeEntries(), readEntries());
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry singleWrite() {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return S.toString(IgniteTxRemoteStateImpl.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
new file mode 100644
index 0000000..81707ba
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
@@ -0,0 +1,171 @@
+/*
+ * 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.transactions;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
+import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public interface IgniteTxState {
+    /**
+     *
+     * @return Flag indicating whether transaction is implicit with only one key.
+     */
+    public boolean implicitSingle();
+
+    /**
+     * @return First tx cache id.
+     */
+    @Nullable public Integer firstCacheId();
+
+    /**
+     * @param cctx Context.
+     * @return cctx Non-null cache context if tx has only one active cache.
+     */
+    @Nullable public GridCacheContext singleCacheContext(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Awaits for previous async operations on active caches to be completed.
+     */
+    public void awaitLastFut(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Context.
+     * @param topFut Topology future.
+     * @return Error if validation failed.
+     */
+    public IgniteCheckedException validateTopology(GridCacheSharedContext cctx, GridDhtTopologyFuture topFut);
+
+    /**
+     * @param cctx Context.
+     * @return {@code True} if transaction is fully synchronous.
+     */
+    public boolean sync(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Context.
+     * @return {@code True} is tx has active near cache.
+     */
+    public boolean hasNearCache(GridCacheSharedContext cctx);
+
+    /**
+     * @param cacheCtx Ccntext.
+     * @param tx Transaction.
+     * @throws IgniteCheckedException If cache check failed.
+     */
+    public void addActiveCache(GridCacheContext cacheCtx, IgniteTxLocalAdapter tx) throws IgniteCheckedException;
+
+    /**
+     * @param cctx Context.
+     * @param fut Future to finish with error if some cache is stopping.
+     * @return Topology future.
+     */
+    public GridDhtTopologyFuture topologyReadLock(GridCacheSharedContext cctx, GridFutureAdapter<?> fut);
+
+    /**
+     * @param cctx Context.
+     */
+    public void topologyReadUnlock(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Context.
+     * @return {@code True} if transaction is allowed to use store and transactions spans one or more caches with
+     *      store enabled.
+     */
+    public boolean storeUsed(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Context.
+     * @return Configured stores for active caches.
+     */
+    public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Context.
+     * @param tx Transaction.
+     * @param commit Commit flag.
+     */
+    public void onTxEnd(GridCacheSharedContext cctx, IgniteInternalTx tx, boolean commit);
+
+    /**
+     * @param key Key.
+     * @return Entry.
+     */
+    @Nullable public IgniteTxEntry entry(IgniteTxKey key);
+
+    /**
+     * @param key Key.
+     * @return {@code True} if tx has write key.
+     */
+    public boolean hasWriteKey(IgniteTxKey key);
+
+    /**
+     * @return Read entries keys.
+     */
+    public Set<IgniteTxKey> readSet();
+
+    /**
+     * @return Write entries keys.
+     */
+    public Set<IgniteTxKey> writeSet();
+
+    /**
+     * @return Write entries.
+     */
+    public Collection<IgniteTxEntry> writeEntries();
+
+    /**
+     * @return Read entries.
+     */
+    public Collection<IgniteTxEntry> readEntries();
+
+    /**
+     * @return Write entries map.
+     */
+    public Map<IgniteTxKey, IgniteTxEntry> writeMap();
+
+    /**
+     * @return Read entries map.
+     */
+    public Map<IgniteTxKey, IgniteTxEntry> readMap();
+
+    /**
+     * @return All entries.
+     */
+    public Collection<IgniteTxEntry> allEntries();
+
+    /**
+     * @return Non-null entry if tx has only one write entry.
+     */
+    @Nullable public IgniteTxEntry singleWrite();
+
+    /**
+     * @return {@code True} if transaction is empty.
+     */
+    public boolean empty();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/3ff71fd7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
new file mode 100644
index 0000000..c95fb19
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
@@ -0,0 +1,375 @@
+/*
+ * 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.transactions;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
+import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+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.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
+    /** Active cache IDs. */
+    private Set<Integer> activeCacheIds = new HashSet<>();
+    /** Per-transaction read map. */
+
+    @GridToStringInclude
+    protected Map<IgniteTxKey, IgniteTxEntry> txMap;
+
+    /** Read view on transaction map. */
+    @GridToStringExclude
+    protected IgniteTxMap readView;
+
+    /** Write view on transaction map. */
+    @GridToStringExclude
+    protected IgniteTxMap writeView;
+
+    /** {@inheritDoc} */
+    @Override public boolean implicitSingle() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Integer firstCacheId() {
+        return F.first(activeCacheIds);
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public GridCacheContext singleCacheContext(GridCacheSharedContext cctx) {
+        if (activeCacheIds.size() == 1) {
+            int cacheId = F.first(activeCacheIds);
+
+            return cctx.cacheContext(cacheId);
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void awaitLastFut(GridCacheSharedContext cctx) {
+        for (Integer cacheId : activeCacheIds)
+            cctx.cacheContext(cacheId).cache().awaitLastFut();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCheckedException validateTopology(GridCacheSharedContext cctx,
+        GridDhtTopologyFuture topFut) {
+        StringBuilder invalidCaches = null;
+
+        for (Integer cacheId : activeCacheIds) {
+            GridCacheContext ctx = cctx.cacheContext(cacheId);
+
+            assert ctx != null : cacheId;
+
+            Throwable err = topFut.validateCache(ctx);
+
+            if (err != null) {
+                if (invalidCaches != null)
+                    invalidCaches.append(", ");
+                else
+                    invalidCaches = new StringBuilder();
+
+                invalidCaches.append(U.maskName(ctx.name()));
+            }
+        }
+
+        if (invalidCaches != null) {
+            return new IgniteCheckedException("Failed to perform cache operation (cache topology is not valid): " +
+                invalidCaches.toString());
+        }
+
+        for (int cacheId : activeCacheIds) {
+            GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
+
+            if (CU.affinityNodes(cacheCtx, topFut.topologyVersion()).isEmpty()) {
+                return new ClusterTopologyServerNotFoundException("Failed to map keys for cache (all " +
+                    "partition nodes left the grid): " + cacheCtx.name());
+            }
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean sync(GridCacheSharedContext cctx) {
+        for (int cacheId : activeCacheIds) {
+            if (cctx.cacheContext(cacheId).config().getWriteSynchronizationMode() == FULL_SYNC)
+                return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasNearCache(GridCacheSharedContext cctx) {
+        for (Integer cacheId : activeCacheIds) {
+            GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
+
+            if (cacheCtx.isNear())
+                return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addActiveCache(GridCacheContext cacheCtx, IgniteTxLocalAdapter tx)
+        throws IgniteCheckedException {
+        GridCacheSharedContext cctx = cacheCtx.shared();
+
+        int cacheId = cacheCtx.cacheId();
+
+        // Check if we can enlist new cache to transaction.
+        if (!activeCacheIds.contains(cacheId)) {
+            String err = cctx.verifyTxCompatibility(tx, activeCacheIds, cacheCtx);
+
+            if (err != null) {
+                StringBuilder cacheNames = new StringBuilder();
+
+                int idx = 0;
+
+                for (Integer activeCacheId : activeCacheIds) {
+                    cacheNames.append(cctx.cacheContext(activeCacheId).name());
+
+                    if (idx++ < activeCacheIds.size() - 1)
+                        cacheNames.append(", ");
+                }
+
+                throw new IgniteCheckedException("Failed to enlist new cache to existing transaction (" +
+                    err +
+                    ") [activeCaches=[" + cacheNames + "]" +
+                    ", cacheName=" + cacheCtx.name() +
+                    ", cacheSystem=" + cacheCtx.systemTx() +
+                    ", txSystem=" + tx.system() + ']');
+            }
+            else
+                activeCacheIds.add(cacheId);
+
+            if (activeCacheIds.size() == 1)
+                tx.activeCachesDeploymentEnabled(cacheCtx.deploymentEnabled());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridDhtTopologyFuture topologyReadLock(GridCacheSharedContext cctx, GridFutureAdapter<?> fut) {
+        if (activeCacheIds.isEmpty())
+            return cctx.exchange().lastTopologyFuture();
+
+        GridCacheContext<?, ?> nonLocCtx = null;
+
+        for (int cacheId : activeCacheIds) {
+            GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
+
+            if (!cacheCtx.isLocal()) {
+                nonLocCtx = cacheCtx;
+
+                break;
+            }
+        }
+
+        if (nonLocCtx == null)
+            return cctx.exchange().lastTopologyFuture();
+
+        nonLocCtx.topology().readLock();
+
+        if (nonLocCtx.topology().stopping()) {
+            fut.onDone(new IgniteCheckedException("Failed to perform cache operation (cache is stopped): " +
+                nonLocCtx.name()));
+
+            return null;
+        }
+
+        return nonLocCtx.topology().topologyVersionFuture();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void topologyReadUnlock(GridCacheSharedContext cctx) {
+        if (!activeCacheIds.isEmpty()) {
+            GridCacheContext<?, ?> nonLocCtx = null;
+
+            for (int cacheId : activeCacheIds) {
+                GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
+
+                if (!cacheCtx.isLocal()) {
+                    nonLocCtx = cacheCtx;
+
+                    break;
+                }
+            }
+
+            if (nonLocCtx != null)
+                nonLocCtx.topology().readUnlock();
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean storeUsed(GridCacheSharedContext cctx) {
+        if (!activeCacheIds.isEmpty()) {
+            for (int cacheId : activeCacheIds) {
+                CacheStoreManager store = cctx.cacheContext(cacheId).store();
+
+                if (store.configured())
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
+        Collection<Integer> cacheIds = activeCacheIds;
+
+        if (!cacheIds.isEmpty()) {
+            Collection<CacheStoreManager> stores = new ArrayList<>(cacheIds.size());
+
+            for (int cacheId : cacheIds) {
+                CacheStoreManager store = cctx.cacheContext(cacheId).store();
+
+                if (store.configured())
+                    stores.add(store);
+            }
+
+            return stores;
+        }
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void onTxEnd(GridCacheSharedContext cctx, IgniteInternalTx tx, boolean commit) {
+        for (int cacheId : activeCacheIds) {
+            GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
+
+            onTxEnd(cacheCtx, tx, commit);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean init(int txSize) {
+        if (txMap == null) {
+            txMap = U.newLinkedHashMap(txSize > 0 ? txSize : 16);
+
+            readView = new IgniteTxMap(txMap, CU.reads());
+            writeView = new IgniteTxMap(txMap, CU.writes());
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean initialized() {
+        return txMap != null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> allEntries() {
+        return txMap == null ? Collections.<IgniteTxEntry>emptySet() : txMap.values();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry entry(IgniteTxKey key) {
+        return txMap == null ? null : txMap.get(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean hasWriteKey(IgniteTxKey key) {
+        return writeView.containsKey(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> readSet() {
+        return txMap == null ? Collections.<IgniteTxKey>emptySet() : readView.keySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<IgniteTxKey> writeSet() {
+        return txMap == null ? Collections.<IgniteTxKey>emptySet() : writeView.keySet();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> writeEntries() {
+        return writeView == null ? Collections.<IgniteTxEntry>emptyList() : writeView.values();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteTxEntry> readEntries() {
+        return readView == null ? Collections.<IgniteTxEntry>emptyList() : readView.values();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
+        return writeView == null ? Collections.<IgniteTxKey, IgniteTxEntry>emptyMap() : writeView;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
+        return readView == null ? Collections.<IgniteTxKey, IgniteTxEntry>emptyMap() : readView;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean empty() {
+        return txMap.isEmpty();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void addEntry(IgniteTxEntry entry) {
+        txMap.put(entry.txKey(), entry);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void seal() {
+        if (readView != null)
+            readView.seal();
+
+        if (writeView != null)
+            writeView.seal();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTxEntry singleWrite() {
+        return writeView != null && writeView.size() == 1 ? F.firstValue(writeView) : null;
+    }
+
+    /** {@inheritDoc} */
+    public String toString() {
+        return S.toString(IgniteTxStateImpl.class, this);
+    }
+}


[22/37] ignite git commit: Fix existing typos and coding guidelines violations.

Posted by ag...@apache.org.
Fix existing typos and coding guidelines violations.


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

Branch: refs/heads/ignite-1282
Commit: f0db0d9fa579dda394a470aa1a314ed2b5c60a2d
Parents: 1f10306
Author: Raul Kripalani <ra...@apache.org>
Authored: Thu Nov 19 14:35:42 2015 +0000
Committer: Raul Kripalani <ra...@apache.org>
Committed: Thu Nov 19 14:35:49 2015 +0000

----------------------------------------------------------------------
 modules/core/src/main/java/org/apache/ignite/IgniteCache.java    | 3 ++-
 modules/core/src/main/java/org/apache/ignite/IgniteCompute.java  | 3 ++-
 .../core/src/main/java/org/apache/ignite/compute/ComputeJob.java | 2 +-
 .../java/org/apache/ignite/marshaller/MarshallerExclusions.java  | 4 ++--
 4 files changed, 7 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f0db0d9f/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
index 6c4b507..0b7f368 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
@@ -325,7 +325,8 @@ public interface IgniteCache<K, V> extends javax.cache.Cache<K, V>, IgniteAsyncS
      * <code>null</code> value for a key.
      */
     @IgniteAsyncSupported
-    <T> Map<K, EntryProcessorResult<T>> invokeAll(Map<? extends K, ? extends EntryProcessor<K, V, T>> map, Object... args);
+    <T> Map<K, EntryProcessorResult<T>> invokeAll(Map<? extends K, ? extends EntryProcessor<K, V, T>> map,
+        Object... args);
 
     /** {@inheritDoc} */
     @IgniteAsyncSupported

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0db0d9f/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java b/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
index 9aa4b87..f7d4bc5 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteCompute.java
@@ -272,7 +272,8 @@ public interface IgniteCompute extends IgniteAsyncSupport {
      * @throws IgniteException If execution failed.
      */
     @IgniteAsyncSupported
-    public <R1, R2> R2 call(Collection<? extends IgniteCallable<R1>> jobs, IgniteReducer<R1, R2> rdc) throws IgniteException;
+    public <R1, R2> R2 call(Collection<? extends IgniteCallable<R1>> jobs, IgniteReducer<R1, R2> rdc)
+        throws IgniteException;
 
     /**
      * Executes provided closure job on a node within the underlying cluster group. This method is different

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0db0d9f/modules/core/src/main/java/org/apache/ignite/compute/ComputeJob.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/compute/ComputeJob.java b/modules/core/src/main/java/org/apache/ignite/compute/ComputeJob.java
index d8664e8..9558255 100644
--- a/modules/core/src/main/java/org/apache/ignite/compute/ComputeJob.java
+++ b/modules/core/src/main/java/org/apache/ignite/compute/ComputeJob.java
@@ -142,7 +142,7 @@ public interface ComputeJob extends Serializable {
      * {@link ComputeTaskFuture#cancel()} is called.
      * <p>
      * Note that job cancellation is only a hint, and just like with
-     * {@link Thread#interrupt()}  method, it is really up to the actual job
+     * {@link Thread#interrupt()} method, it is really up to the actual job
      * instance to gracefully finish execution and exit.
      */
     public void cancel();

http://git-wip-us.apache.org/repos/asf/ignite/blob/f0db0d9f/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerExclusions.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerExclusions.java b/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerExclusions.java
index 2701ead..fba35e2 100644
--- a/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerExclusions.java
+++ b/modules/core/src/main/java/org/apache/ignite/marshaller/MarshallerExclusions.java
@@ -41,7 +41,7 @@ public final class MarshallerExclusions {
      * Classes that must be included in serialization. All marshallers must
      * included these classes.
      * <p>
-     * Note that this list supercedes {@link #EXCL_CLASSES}.
+     * Note that this list supersedes {@link #EXCL_CLASSES}.
      */
     private static final Class<?>[] INCL_CLASSES = new Class[] {
         // Ignite classes.
@@ -57,7 +57,7 @@ public final class MarshallerExclusions {
      * Excluded grid classes from serialization. All marshallers must omit
      * these classes. Fields of these types should be serialized as {@code null}.
      * <p>
-     * Note that {@link #INCL_CLASSES} supercedes this list.
+     * Note that {@link #INCL_CLASSES} supersedes this list.
      */
     private static final Class<?>[] EXCL_CLASSES;
 


[20/37] ignite git commit: Optimization for single key cache 'get' operation.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
new file mode 100644
index 0000000..8f2357b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridPartitionedSingleGetFuture.java
@@ -0,0 +1,697 @@
+/*
+ * 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.distributed.dht;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
+import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryInfo;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
+import org.apache.ignite.internal.processors.cache.GridCacheFuture;
+import org.apache.ignite.internal.processors.cache.GridCacheMessage;
+import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
+import org.apache.ignite.internal.processors.cache.distributed.near.CacheVersionedValue;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
+import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.apache.ignite.internal.util.typedef.CI1;
+import org.apache.ignite.internal.util.typedef.CIX1;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.CU;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteProductVersion;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class GridPartitionedSingleGetFuture extends GridFutureAdapter<Object> implements GridCacheFuture<Object>,
+    CacheGetFuture {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    public static final IgniteProductVersion SINGLE_GET_MSG_SINCE = IgniteProductVersion.fromString("1.5.0");
+
+    /** Logger reference. */
+    private static final AtomicReference<IgniteLogger> logRef = new AtomicReference<>();
+
+    /** Logger. */
+    private static IgniteLogger log;
+
+    /** Topology version. */
+    private AffinityTopologyVersion topVer;
+
+    /** Context. */
+    private final GridCacheContext cctx;
+
+    /** Key. */
+    private final KeyCacheObject key;
+
+    /** Read through flag. */
+    private final boolean readThrough;
+
+    /** Force primary flag. */
+    private final boolean forcePrimary;
+
+    /** Future ID. */
+    private final IgniteUuid futId;
+
+    /** Trackable flag. */
+    private boolean trackable;
+
+    /** Subject ID. */
+    private final UUID subjId;
+
+    /** Task name. */
+    private final String taskName;
+
+    /** Whether to deserialize portable objects. */
+    private boolean deserializePortable;
+
+    /** Skip values flag. */
+    private boolean skipVals;
+
+    /** Expiry policy. */
+    private IgniteCacheExpiryPolicy expiryPlc;
+
+    /** Flag indicating that get should be done on a locked topology version. */
+    private final boolean canRemap;
+
+    /** */
+    private final boolean needVer;
+
+    /** */
+    private final boolean keepCacheObjects;
+
+    /** */
+    private ClusterNode node;
+
+    /**
+     * @param cctx Context.
+     * @param key Key.
+     * @param topVer Topology version.
+     * @param readThrough Read through flag.
+     * @param forcePrimary If {@code true} then will force network trip to primary node even if called on backup node.
+     * @param subjId Subject ID.
+     * @param taskName Task name.
+     * @param deserializePortable Deserialize portable flag.
+     * @param expiryPlc Expiry policy.
+     * @param skipVals Skip values flag.
+     * @param canRemap Flag indicating whether future can be remapped on a newer topology version.
+     * @param needVer If {@code true} returns values as tuples containing value and version.
+     * @param keepCacheObjects Keep cache objects flag.
+     */
+    public GridPartitionedSingleGetFuture(
+        GridCacheContext cctx,
+        KeyCacheObject key,
+        AffinityTopologyVersion topVer,
+        boolean readThrough,
+        boolean forcePrimary,
+        @Nullable UUID subjId,
+        String taskName,
+        boolean deserializePortable,
+        @Nullable IgniteCacheExpiryPolicy expiryPlc,
+        boolean skipVals,
+        boolean canRemap,
+        boolean needVer,
+        boolean keepCacheObjects
+    ) {
+        assert key != null;
+
+        this.cctx = cctx;
+        this.key = key;
+        this.readThrough = readThrough;
+        this.forcePrimary = forcePrimary;
+        this.subjId = subjId;
+        this.taskName = taskName;
+        this.deserializePortable = deserializePortable;
+        this.expiryPlc = expiryPlc;
+        this.skipVals = skipVals;
+        this.canRemap = canRemap;
+        this.needVer = needVer;
+        this.keepCacheObjects = keepCacheObjects;
+        this.topVer = topVer;
+
+        futId = IgniteUuid.randomUuid();
+
+        if (log == null)
+            log = U.logger(cctx.kernalContext(), logRef, GridPartitionedSingleGetFuture.class);
+    }
+
+    /**
+     *
+     */
+    public void init() {
+        AffinityTopologyVersion topVer = this.topVer.topologyVersion() > 0 ? this.topVer :
+            canRemap ? cctx.affinity().affinityTopologyVersion() : cctx.shared().exchange().readyAffinityVersion();
+
+        map(topVer);
+    }
+
+    /**
+     * @param topVer Topology version.
+     */
+    @SuppressWarnings("unchecked")
+    private void map(AffinityTopologyVersion topVer) {
+        this.topVer = topVer;
+
+        ClusterNode node = mapKeyToNode(topVer);
+
+        if (node == null) {
+            assert isDone() : this;
+
+            return;
+        }
+
+        if (node.isLocal()) {
+            LinkedHashMap<KeyCacheObject, Boolean> map = U.newLinkedHashMap(1);
+
+            map.put(key, false);
+
+            final GridDhtFuture<Collection<GridCacheEntryInfo>> fut = cctx.dht().getDhtAsync(node.id(),
+                -1,
+                map,
+                readThrough,
+                topVer,
+                subjId,
+                taskName == null ? 0 : taskName.hashCode(),
+                expiryPlc,
+                skipVals);
+
+            final Collection<Integer> invalidParts = fut.invalidPartitions();
+
+            if (!F.isEmpty(invalidParts)) {
+                AffinityTopologyVersion updTopVer = cctx.discovery().topologyVersionEx();
+
+                assert updTopVer.compareTo(topVer) > 0 : "Got invalid partitions for local node but topology " +
+                    "version did not change [topVer=" + topVer + ", updTopVer=" + updTopVer +
+                    ", invalidParts=" + invalidParts + ']';
+
+                // Remap recursively.
+                map(updTopVer);
+            }
+            else {
+                fut.listen(new CI1<IgniteInternalFuture<Collection<GridCacheEntryInfo>>>() {
+                    @Override public void apply(IgniteInternalFuture<Collection<GridCacheEntryInfo>> fut) {
+                        try {
+                            Collection<GridCacheEntryInfo> infos = fut.get();
+
+                            assert F.isEmpty(infos) || infos.size() == 1 : infos;
+
+                            setResult(F.first(infos));
+                        }
+                        catch (Exception e) {
+                            U.error(log, "Failed to get values from dht cache [fut=" + fut + "]", e);
+
+                            onDone(e);
+                        }
+                    }
+                });
+            }
+        }
+        else {
+            synchronized (this) {
+                this.node = node;
+            }
+
+            if (!trackable) {
+                trackable = true;
+
+                cctx.mvcc().addFuture(this, futId);
+            }
+
+            GridCacheMessage req;
+
+            if (node.version().compareTo(SINGLE_GET_MSG_SINCE) >= 0) {
+                req = new GridNearSingleGetRequest(cctx.cacheId(),
+                    futId,
+                    key,
+                    readThrough,
+                    topVer,
+                    subjId,
+                    taskName == null ? 0 : taskName.hashCode(),
+                    expiryPlc != null ? expiryPlc.forAccess() : -1L,
+                    skipVals,
+                    /**add reader*/false,
+                    needVer,
+                    cctx.deploymentEnabled());
+            }
+            else {
+                LinkedHashMap<KeyCacheObject, Boolean> map = U.newLinkedHashMap(1);
+
+                map.put(key, false);
+
+                req = new GridNearGetRequest(
+                    cctx.cacheId(),
+                    futId,
+                    futId,
+                    cctx.versions().next(),
+                    map,
+                    readThrough,
+                    topVer,
+                    subjId,
+                    taskName == null ? 0 : taskName.hashCode(),
+                    expiryPlc != null ? expiryPlc.forAccess() : -1L,
+                    skipVals,
+                    cctx.deploymentEnabled());
+            }
+
+            try {
+                cctx.io().send(node, req, cctx.ioPolicy());
+            }
+            catch (IgniteCheckedException e) {
+                if (e instanceof ClusterTopologyCheckedException)
+                    onNodeLeft(node.id());
+                else
+                    onDone(e);
+            }
+        }
+    }
+
+    /**
+     * @param topVer Topology version.
+     * @return Primary node or {@code null} if future was completed.
+     */
+    @Nullable private ClusterNode mapKeyToNode(AffinityTopologyVersion topVer) {
+        ClusterNode primary = affinityNode(key, topVer);
+
+        if (primary == null) {
+            onDone(new ClusterTopologyServerNotFoundException("Failed to map keys for cache " +
+                "(all partition nodes left the grid) [topVer=" + topVer + ", cache=" + cctx.name() + ']'));
+
+            return null;
+        }
+
+        boolean allowLocRead = (cctx.affinityNode() && !forcePrimary) || primary.isLocal();
+
+        if (allowLocRead) {
+            GridDhtCacheAdapter colocated = cctx.dht();
+
+            while (true) {
+                GridCacheEntryEx entry;
+
+                try {
+                    entry = colocated.context().isSwapOrOffheapEnabled() ? colocated.entryEx(key) :
+                        colocated.peekEx(key);
+
+                    // If our DHT cache do has value, then we peek it.
+                    if (entry != null) {
+                        boolean isNew = entry.isNewLocked();
+
+                        CacheObject v = null;
+                        GridCacheVersion ver = null;
+
+                        if (needVer) {
+                            T2<CacheObject, GridCacheVersion> res = entry.innerGetVersioned(
+                                null,
+                                /*swap*/true,
+                                /*unmarshal*/true,
+                                /**update-metrics*/false,
+                                /*event*/!skipVals,
+                                subjId,
+                                null,
+                                taskName,
+                                expiryPlc);
+
+                            if (res != null) {
+                                v = res.get1();
+                                ver = res.get2();
+                            }
+                        }
+                        else {
+                            v = entry.innerGet(null,
+                                /*swap*/true,
+                                /*read-through*/false,
+                                /*fail-fast*/true,
+                                /*unmarshal*/true,
+                                /**update-metrics*/false,
+                                /*event*/!skipVals,
+                                /*temporary*/false,
+                                subjId,
+                                null,
+                                taskName,
+                                expiryPlc);
+                        }
+
+                        colocated.context().evicts().touch(entry, topVer);
+
+                        // Entry was not in memory or in swap, so we remove it from cache.
+                        if (v == null) {
+                            if (isNew && entry.markObsoleteIfEmpty(ver))
+                                colocated.removeIfObsolete(key);
+                        }
+                        else {
+                            if (!skipVals && cctx.config().isStatisticsEnabled())
+                                cctx.cache().metrics0().onRead(true);
+
+                            if (!skipVals)
+                                setResult(v, ver);
+                            else
+                                setSkipValueResult(true, ver);
+
+                            return null;
+                        }
+                    }
+
+                    break;
+                }
+                catch (GridDhtInvalidPartitionException ignored) {
+                    break;
+                }
+                catch (IgniteCheckedException e) {
+                    onDone(e);
+
+                    return null;
+                }
+                catch (GridCacheEntryRemovedException ignored) {
+                    // No-op, will retry.
+                }
+            }
+        }
+
+        return primary;
+    }
+
+    /**
+     * @param nodeId Node ID.
+     * @param res Result.
+     */
+    public void onResult(UUID nodeId, GridNearSingleGetResponse res) {
+        if (!processResponse(nodeId) || !checkError(res.error(), res.invalidPartitions(), res.topologyVersion()))
+            return;
+
+        Message res0 = res.result();
+
+        if (needVer) {
+            CacheVersionedValue verVal = (CacheVersionedValue)res0;
+
+            if (verVal != null) {
+                if (skipVals)
+                    setSkipValueResult(true, verVal.version());
+                else
+                    setResult(verVal.value() , verVal.version());
+            }
+            else {
+                if (skipVals)
+                    setSkipValueResult(false, null);
+                else
+                    setResult(null , null);
+            }
+        }
+        else {
+            if (skipVals)
+                setSkipValueResult(res.containsValue(), null);
+            else
+                setResult((CacheObject)res0, null);
+        }
+    }
+
+    /**
+     * @param nodeId Node ID.
+     * @param res Result.
+     */
+    public void onResult(UUID nodeId, GridNearGetResponse res) {
+        if (!processResponse(nodeId) ||
+            !checkError(res.error(), !F.isEmpty(res.invalidPartitions()), res.topologyVersion()))
+            return;
+
+        Collection<GridCacheEntryInfo> infos = res.entries();
+
+        assert F.isEmpty(infos) || infos.size() == 1 : infos;
+
+        setResult(F.first(infos));
+    }
+
+    /**
+     * @param nodeId Node ID.
+     * @return {@code True} if should process received response.
+     */
+    private boolean processResponse(UUID nodeId) {
+        synchronized (this) {
+            if (node != null && node.id().equals(nodeId)) {
+                node = null;
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * @param err Error.
+     * @param invalidParts Invalid partitions error flag.
+     * @param rmtTopVer Received topology version.
+     */
+    private boolean checkError(@Nullable IgniteCheckedException err,
+        boolean invalidParts,
+        AffinityTopologyVersion rmtTopVer) {
+        if (err != null) {
+            onDone(err);
+
+            return false;
+        }
+
+        if (invalidParts) {
+            assert !rmtTopVer.equals(AffinityTopologyVersion.ZERO);
+
+            if (rmtTopVer.compareTo(topVer) <= 0) {
+                // Fail the whole get future.
+                onDone(new IgniteCheckedException("Failed to process invalid partitions response (remote node reported " +
+                    "invalid partitions but remote topology version does not differ from local) " +
+                    "[topVer=" + topVer + ", rmtTopVer=" + rmtTopVer + ", part=" + cctx.affinity().partition(key) +
+                    ", nodeId=" + node.id() + ']'));
+
+                return false;
+            }
+
+            if (canRemap) {
+                IgniteInternalFuture<Long> topFut = cctx.discovery().topologyFuture(rmtTopVer.topologyVersion());
+
+                topFut.listen(new CIX1<IgniteInternalFuture<Long>>() {
+                    @Override public void applyx(IgniteInternalFuture<Long> fut) {
+                        try {
+                            AffinityTopologyVersion topVer = new AffinityTopologyVersion(fut.get());
+
+                            remap(topVer);
+                        }
+                        catch (IgniteCheckedException e) {
+                            onDone(e);
+                        }
+                    }
+                });
+
+            }
+            else
+                map(topVer);
+
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * @param info Entry info.
+     */
+    private void setResult(@Nullable GridCacheEntryInfo info) {
+        assert info == null || skipVals == (info.value() == null);
+
+        if (skipVals) {
+            if (info != null)
+                setSkipValueResult(true, info.version());
+            else
+                setSkipValueResult(false, null);
+        }
+        else {
+            if (info != null)
+                setResult(info.value(), info.version());
+            else
+                setResult(null, null);
+        }
+    }
+
+    /**
+     * @param res Result.
+     * @param ver Version.
+     */
+    private void setSkipValueResult(boolean res, @Nullable GridCacheVersion ver) {
+        assert skipVals;
+
+        if (needVer) {
+            assert ver != null || !res;
+
+            onDone(new T2<>(res, ver));
+        }
+        else
+            onDone(res);
+    }
+
+    /**
+     * @param val Value.
+     * @param ver Version.
+     */
+    private void setResult(@Nullable CacheObject val, @Nullable GridCacheVersion ver) {
+        try {
+            assert !skipVals;
+
+            if (val != null) {
+                if (needVer) {
+                    assert ver != null;
+
+                    onDone(new T2<>(val, ver));
+                }
+                else {
+                    if (!keepCacheObjects) {
+                        Object res = CU.value(val, cctx, true);
+
+                        if (deserializePortable && !skipVals)
+                            res = cctx.unwrapPortableIfNeeded(res, false);
+
+                        onDone(res);
+                    }
+                    else
+                        onDone(val);
+                }
+            }
+            else
+                onDone(null);
+        }
+        catch (Exception e) {
+            onDone(e);
+        }
+    }
+
+    /**
+     * Affinity node to send get request to.
+     *
+     * @param key Key to get.
+     * @param topVer Topology version.
+     * @return Affinity node to get key from.
+     */
+    private ClusterNode affinityNode(KeyCacheObject key, AffinityTopologyVersion topVer) {
+        if (!canRemap) {
+            List<ClusterNode> affNodes = cctx.affinity().nodes(key, topVer);
+
+            for (ClusterNode node : affNodes) {
+                if (cctx.discovery().alive(node))
+                    return node;
+            }
+
+            return null;
+        }
+        else
+            return cctx.affinity().primary(key, topVer);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid futureId() {
+        return futId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean onNodeLeft(UUID nodeId) {
+        if (!processResponse(nodeId))
+            return false;
+
+        if (canRemap) {
+            final AffinityTopologyVersion updTopVer = new AffinityTopologyVersion(
+                Math.max(topVer.topologyVersion() + 1, cctx.discovery().topologyVersion()));
+
+            cctx.affinity().affinityReadyFuture(updTopVer).listen(
+                new CI1<IgniteInternalFuture<AffinityTopologyVersion>>() {
+                    @Override public void apply(IgniteInternalFuture<AffinityTopologyVersion> fut) {
+                        try {
+                            fut.get();
+
+                            remap(updTopVer);
+                        }
+                        catch (IgniteCheckedException e) {
+                            onDone(e);
+                        }
+                    }
+                });
+        }
+        else
+            remap(topVer);
+
+        return true;
+    }
+
+    /**
+     * @param topVer Topology version.
+     */
+    private void remap(final AffinityTopologyVersion topVer) {
+        cctx.closures().runLocalSafe(new Runnable() {
+            @Override public void run() {
+                map(topVer);
+            }
+        });
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean onDone(Object res, Throwable err) {
+        if (super.onDone(res, err)) {
+            // Don't forget to clean up.
+            if (trackable)
+                cctx.mvcc().removeFuture(futId);
+
+            cctx.dht().sendTtlUpdateRequest(expiryPlc);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean trackable() {
+        return trackable;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void markNotTrackable() {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(GridPartitionedSingleGetFuture.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index 7f9edb2..75f8c2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -65,11 +65,14 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheE
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtInvalidPartitionException;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedGetFuture;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedSingleGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPreloader;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearAtomicCache;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheAdapter;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
 import org.apache.ignite.internal.processors.cache.dr.GridCacheDrExpirationInfo;
 import org.apache.ignite.internal.processors.cache.dr.GridCacheDrInfo;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteTxLocalEx;
@@ -242,6 +245,12 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
             }
         });
 
+        ctx.io().addHandler(ctx.cacheId(), GridNearSingleGetRequest.class, new CI2<UUID, GridNearSingleGetRequest>() {
+            @Override public void apply(UUID nodeId, GridNearSingleGetRequest req) {
+                processNearSingleGetRequest(nodeId, req);
+            }
+        });
+
         ctx.io().addHandler(ctx.cacheId(), GridNearAtomicUpdateRequest.class, new CI2<UUID, GridNearAtomicUpdateRequest>() {
             @Override public void apply(UUID nodeId, GridNearAtomicUpdateRequest req) {
                 processNearAtomicUpdateRequest(nodeId, req);
@@ -279,6 +288,12 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
                     processNearGetResponse(nodeId, res);
                 }
             });
+
+            ctx.io().addHandler(ctx.cacheId(), GridNearSingleGetResponse.class, new CI2<UUID, GridNearSingleGetResponse>() {
+                @Override public void apply(UUID nodeId, GridNearSingleGetResponse res) {
+                    processNearSingleGetResponse(nodeId, res);
+                }
+            });
         }
     }
 
@@ -301,6 +316,45 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override protected IgniteInternalFuture<V> getAsync(final K key,
+        final boolean forcePrimary,
+        final boolean skipTx,
+        @Nullable UUID subjId,
+        final String taskName,
+        final boolean deserializePortable,
+        final boolean skipVals,
+        final boolean canRemap) {
+        ctx.checkSecurity(SecurityPermission.CACHE_READ);
+
+        if (keyCheck)
+            validateCacheKey(key);
+
+        CacheOperationContext opCtx = ctx.operationContextPerCall();
+
+        subjId = ctx.subjectIdPerCall(null, opCtx);
+
+        final UUID subjId0 = subjId;
+
+        final ExpiryPolicy expiryPlc = skipVals ? null : opCtx != null ? opCtx.expiry() : null;
+
+        final boolean skipStore = opCtx != null && opCtx.skipStore();
+
+        return asyncOp(new CO<IgniteInternalFuture<V>>() {
+            @Override public IgniteInternalFuture<V> apply() {
+                return getAsync0(ctx.toCacheKeyObject(key),
+                    forcePrimary,
+                    subjId0,
+                    taskName,
+                    deserializePortable,
+                    expiryPlc,
+                    skipVals,
+                    skipStore,
+                    canRemap);
+            }
+        });
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteInternalFuture<Map<K, V>> getAllAsync(
         @Nullable final Collection<? extends K> keys,
         final boolean forcePrimary,
@@ -914,9 +968,57 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
     }
 
     /**
+     * Entry point to all public API single get methods.
+     *
+     * @param key Key.
+     * @param forcePrimary Force primary flag.
+     * @param subjId Subject ID.
+     * @param taskName Task name.
+     * @param deserializePortable Deserialize portable flag.
+     * @param expiryPlc Expiry policy.
+     * @param skipVals Skip values flag.
+     * @param skipStore Skip store flag.
+     * @param canRemap Can remap flag.
+     * @return Get future.
+     */
+    private IgniteInternalFuture<V> getAsync0(KeyCacheObject key,
+        boolean forcePrimary,
+        UUID subjId,
+        String taskName,
+        boolean deserializePortable,
+        @Nullable ExpiryPolicy expiryPlc,
+        boolean skipVals,
+        boolean skipStore,
+        boolean canRemap
+    ) {
+        AffinityTopologyVersion topVer = canRemap ? ctx.affinity().affinityTopologyVersion() :
+            ctx.shared().exchange().readyAffinityVersion();
+
+        IgniteCacheExpiryPolicy expiry = skipVals ? null : expiryPolicy(expiryPlc);
+
+        GridPartitionedSingleGetFuture fut = new GridPartitionedSingleGetFuture(ctx,
+            key,
+            topVer,
+            !skipStore,
+            forcePrimary,
+            subjId,
+            taskName,
+            deserializePortable,
+            expiry,
+            skipVals,
+            canRemap,
+            false,
+            false);
+
+        fut.init();
+
+        return (IgniteInternalFuture<V>)fut;
+    }
+
+    /**
      * Entry point to all public API get methods.
      *
-     * @param keys Keys to remove.
+     * @param keys Keys.
      * @param forcePrimary Force primary flag.
      * @param subjId Subject ID.
      * @param taskName Task name.
@@ -942,7 +1044,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
         final IgniteCacheExpiryPolicy expiry = skipVals ? null : expiryPolicy(expiryPlc);
 
         // Optimisation: try to resolve value locally and escape 'get future' creation.
-        if (!forcePrimary) {
+        if (!forcePrimary && ctx.affinityNode()) {
             Map<K, V> locVals = U.newHashMap(keys.size());
 
             boolean success = true;
@@ -2409,27 +2511,6 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
 
     /**
      * @param nodeId Sender node ID.
-     * @param res Near get response.
-     */
-    private void processNearGetResponse(UUID nodeId, GridNearGetResponse res) {
-        if (log.isDebugEnabled())
-            log.debug("Processing near get response [nodeId=" + nodeId + ", res=" + res + ']');
-
-        GridPartitionedGetFuture<K, V> fut = (GridPartitionedGetFuture<K, V>)ctx.mvcc().<Map<K, V>>future(
-            res.version(), res.futureId());
-
-        if (fut == null) {
-            if (log.isDebugEnabled())
-                log.debug("Failed to find future for get response [sender=" + nodeId + ", res=" + res + ']');
-
-            return;
-        }
-
-        fut.onResult(nodeId, res);
-    }
-
-    /**
-     * @param nodeId Sender node ID.
      * @param req Near atomic update request.
      */
     private void processNearAtomicUpdateRequest(UUID nodeId, GridNearAtomicUpdateRequest req) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
index 4ace5c4..c34dcfd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateFuture.java
@@ -22,7 +22,6 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
-import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.cache.processor.EntryProcessor;
 import org.apache.ignite.IgniteCheckedException;
@@ -48,7 +47,6 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteUuid;
 import org.jetbrains.annotations.Nullable;
-import org.jsr166.ConcurrentHashMap8;
 
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 
@@ -67,39 +65,42 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
     protected static IgniteLogger log;
 
     /** Cache context. */
-    private GridCacheContext cctx;
+    private final GridCacheContext cctx;
 
     /** Future version. */
-    private GridCacheVersion futVer;
+    private final GridCacheVersion futVer;
 
     /** Write version. */
-    private GridCacheVersion writeVer;
+    private final GridCacheVersion writeVer;
 
     /** Force transform backup flag. */
     private boolean forceTransformBackups;
 
     /** Completion callback. */
     @GridToStringExclude
-    private CI2<GridNearAtomicUpdateRequest, GridNearAtomicUpdateResponse> completionCb;
+    private final CI2<GridNearAtomicUpdateRequest, GridNearAtomicUpdateResponse> completionCb;
 
     /** Mappings. */
     @GridToStringInclude
-    private ConcurrentMap<UUID, GridDhtAtomicUpdateRequest> mappings = new ConcurrentHashMap8<>();
+    private final Map<UUID, GridDhtAtomicUpdateRequest> mappings;
 
     /** Entries with readers. */
     private Map<KeyCacheObject, GridDhtCacheEntry> nearReadersEntries;
 
     /** Update request. */
-    private GridNearAtomicUpdateRequest updateReq;
+    private final GridNearAtomicUpdateRequest updateReq;
 
     /** Update response. */
-    private GridNearAtomicUpdateResponse updateRes;
+    private final GridNearAtomicUpdateResponse updateRes;
 
     /** Future keys. */
-    private Collection<KeyCacheObject> keys;
+    private final Collection<KeyCacheObject> keys;
 
     /** */
-    private boolean waitForExchange;
+    private final boolean waitForExchange;
+
+    /** Response count. */
+    private volatile int resCnt;
 
     /**
      * @param cctx Cache context.
@@ -128,6 +129,7 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
             log = U.logger(cctx.kernalContext(), logRef, GridDhtAtomicUpdateFuture.class);
 
         keys = new ArrayList<>(updateReq.keys().size());
+        mappings = U.newHashMap(updateReq.keys().size());
 
         boolean topLocked = updateReq.topologyLocked() || (updateReq.fastMap() && !updateReq.clientRequest());
 
@@ -145,22 +147,37 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.view(F.viewReadOnly(mappings.keySet(), U.id2Node(cctx.kernalContext())), F.notNull());
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         if (log.isDebugEnabled())
             log.debug("Processing node leave event [fut=" + this + ", nodeId=" + nodeId + ']');
 
+        return registerResponse(nodeId);
+    }
+
+    /**
+     * @param nodeId Node ID.
+     * @return {@code True} if request found.
+     */
+    private boolean registerResponse(UUID nodeId) {
+        int resCnt0;
+
         GridDhtAtomicUpdateRequest req = mappings.get(nodeId);
 
         if (req != null) {
-            // Remove only after added keys to failed set.
-            mappings.remove(nodeId);
+            synchronized (this) {
+                if (req.onResponse()) {
+                    resCnt0 = resCnt;
+
+                    resCnt0 += 1;
+
+                    resCnt = resCnt0;
+                }
+                else
+                    return false;
+            }
 
-            checkComplete();
+            if (resCnt0 == mappings.size())
+                onDone();
 
             return true;
         }
@@ -343,18 +360,18 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
                     U.warn(log, "Failed to send update request to backup node because it left grid: " +
                         req.nodeId());
 
-                    mappings.remove(req.nodeId());
+                    registerResponse(req.nodeId());
                 }
                 catch (IgniteCheckedException e) {
                     U.error(log, "Failed to send update request to backup node (did node leave the grid?): "
                         + req.nodeId(), e);
 
-                    mappings.remove(req.nodeId());
+                    registerResponse(req.nodeId());
                 }
             }
         }
-
-        checkComplete();
+        else
+            onDone();
 
         // Send response right away if no ACKs from backup is required.
         // Backups will send ACKs anyway, future will be completed after all backups have replied.
@@ -389,9 +406,7 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
             }
         }
 
-        mappings.remove(nodeId);
-
-        checkComplete();
+        registerResponse(nodeId);
     }
 
     /**
@@ -403,22 +418,7 @@ public class GridDhtAtomicUpdateFuture extends GridFutureAdapter<Void>
         if (log.isDebugEnabled())
             log.debug("Received deferred DHT atomic update future result [nodeId=" + nodeId + ']');
 
-        mappings.remove(nodeId);
-
-        checkComplete();
-    }
-
-    /**
-     * Checks if all required responses are received.
-     */
-    private void checkComplete() {
-        // Always wait for replies from all backups.
-        if (mappings.isEmpty()) {
-            if (log.isDebugEnabled())
-                log.debug("Completing DHT atomic update future: " + this);
-
-            onDone();
-        }
+        registerResponse(nodeId);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
index e55cac9..1219f2f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicUpdateRequest.java
@@ -139,6 +139,10 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
     /** Task name hash. */
     private int taskNameHash;
 
+    /** On response flag. Access should be synced on future. */
+    @GridDirectTransient
+    private boolean onRes;
+
     /**
      * Empty constructor required by {@link Externalizable}.
      */
@@ -527,6 +531,13 @@ public class GridDhtAtomicUpdateRequest extends GridCacheMessage implements Grid
     }
 
     /**
+     * @return {@code True} if on response flag changed.
+     */
+    public boolean onResponse() {
+        return !onRes && (onRes = true);
+    }
+
+    /**
      * @return Optional arguments for entry processor.
      */
     @Nullable public Object[] invokeArguments() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
index ae662c8..a786803 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
@@ -238,11 +238,6 @@ public class GridNearAtomicUpdateFuture extends GridFutureAdapter<Object>
         return state.futureVersion();
     }
 
-    /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        throw new UnsupportedOperationException();
-    }
-
     /**
      * @return {@code True} if this future should block partition map exchange.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
index 7131aa5..47b7aea 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedCache.java
@@ -53,8 +53,10 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtInvali
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLockFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTransactionalCacheAdapter;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedGetFuture;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridPartitionedSingleGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTransactionalCache;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearUnlockRequest;
@@ -67,6 +69,7 @@ import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.lang.IgnitePair;
 import org.apache.ignite.internal.util.typedef.C2;
 import org.apache.ignite.internal.util.typedef.CI2;
+import org.apache.ignite.internal.util.typedef.CX1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.internal.util.typedef.internal.CU;
@@ -138,7 +141,13 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
 
         ctx.io().addHandler(ctx.cacheId(), GridNearGetResponse.class, new CI2<UUID, GridNearGetResponse>() {
             @Override public void apply(UUID nodeId, GridNearGetResponse res) {
-                processGetResponse(nodeId, res);
+                processNearGetResponse(nodeId, res);
+            }
+        });
+
+        ctx.io().addHandler(ctx.cacheId(), GridNearSingleGetResponse.class, new CI2<UUID, GridNearSingleGetResponse>() {
+            @Override public void apply(UUID nodeId, GridNearSingleGetResponse res) {
+                processNearSingleGetResponse(nodeId, res);
             }
         });
 
@@ -185,6 +194,80 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
     }
 
     /** {@inheritDoc} */
+    @Override protected IgniteInternalFuture<V> getAsync(final K key,
+        boolean forcePrimary,
+        boolean skipTx,
+        @Nullable UUID subjId,
+        String taskName,
+        final boolean deserializePortable,
+        final boolean skipVals,
+        boolean canRemap) {
+        ctx.checkSecurity(SecurityPermission.CACHE_READ);
+
+        if (keyCheck)
+            validateCacheKey(key);
+
+        IgniteTxLocalAdapter tx = ctx.tm().threadLocalTx(ctx);
+
+        final CacheOperationContext opCtx = ctx.operationContextPerCall();
+
+        if (tx != null && !tx.implicit() && !skipTx) {
+            return asyncOp(tx, new AsyncOp<V>() {
+                @Override public IgniteInternalFuture<V> op(IgniteTxLocalAdapter tx) {
+                    IgniteInternalFuture<Map<Object, Object>>  fut = tx.getAllAsync(ctx,
+                        Collections.singleton(ctx.toCacheKeyObject(key)),
+                        deserializePortable,
+                        skipVals,
+                        false,
+                        opCtx != null && opCtx.skipStore());
+
+                    return fut.chain(new CX1<IgniteInternalFuture<Map<Object, Object>>, V>() {
+                        @SuppressWarnings("unchecked")
+                        @Override public V applyx(IgniteInternalFuture<Map<Object, Object>> e)
+                            throws IgniteCheckedException {
+                            Map<Object, Object> map = e.get();
+
+                            assert map.isEmpty() || map.size() == 1 : map.size();
+
+                            if (skipVals) {
+                                Boolean val = map.isEmpty() ? false : (Boolean)F.firstValue(map);
+
+                                return (V)(val);
+                            }
+
+                            return (V)map.get(key);
+                        }
+                    });
+                }
+            });
+        }
+
+        AffinityTopologyVersion topVer = tx == null ?
+                (canRemap ? ctx.affinity().affinityTopologyVersion() : ctx.shared().exchange().readyAffinityVersion()) :
+                tx.topologyVersion();
+
+        subjId = ctx.subjectIdPerCall(subjId, opCtx);
+
+        GridPartitionedSingleGetFuture fut = new GridPartitionedSingleGetFuture(ctx,
+            ctx.toCacheKeyObject(key),
+            topVer,
+            opCtx == null || !opCtx.skipStore(),
+            forcePrimary,
+            subjId,
+            taskName,
+            deserializePortable,
+            skipVals ? null : expiryPolicy(opCtx != null ? opCtx.expiry() : null),
+            skipVals,
+            canRemap,
+            /*needVer*/false,
+            /*keepCacheObjects*/false);
+
+        fut.init();
+
+        return (IgniteInternalFuture<V>)fut;
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteInternalFuture<Map<K, V>> getAllAsync(
         @Nullable final Collection<? extends K> keys,
         boolean forcePrimary,
@@ -290,6 +373,54 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
     }
 
     /**
+     * @param key Key to load.
+     * @param readThrough Read through flag.
+     * @param forcePrimary Force get from primary node flag.
+     * @param topVer Topology version.
+     * @param subjId Subject ID.
+     * @param taskName Task name.
+     * @param deserializePortable Deserialize portable flag.
+     * @param expiryPlc Expiry policy.
+     * @param skipVals Skip values flag.
+     * @param canRemap Flag indicating whether future can be remapped on a newer topology version.
+     * @param needVer If {@code true} returns values as tuples containing value and version.
+     * @param keepCacheObj Keep cache objects flag.
+     * @return Load future.
+     */
+    public final IgniteInternalFuture<Object> loadAsync(
+        KeyCacheObject key,
+        boolean readThrough,
+        boolean forcePrimary,
+        AffinityTopologyVersion topVer,
+        @Nullable UUID subjId,
+        String taskName,
+        boolean deserializePortable,
+        @Nullable IgniteCacheExpiryPolicy expiryPlc,
+        boolean skipVals,
+        boolean canRemap,
+        boolean needVer,
+        boolean keepCacheObj
+    ) {
+        GridPartitionedSingleGetFuture fut = new GridPartitionedSingleGetFuture(ctx,
+            ctx.toCacheKeyObject(key),
+            topVer,
+            readThrough,
+            forcePrimary,
+            subjId,
+            taskName,
+            deserializePortable,
+            expiryPlc,
+            skipVals,
+            canRemap,
+            needVer,
+            keepCacheObj);
+
+        fut.init();
+
+        return fut;
+    }
+
+    /**
      * @param keys Keys to load.
      * @param readThrough Read through flag.
      * @param forcePrimary Force get from primary node flag.
@@ -299,9 +430,12 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
      * @param deserializePortable Deserialize portable flag.
      * @param expiryPlc Expiry policy.
      * @param skipVals Skip values flag.
-     * @return Loaded values.
+     * @param canRemap Flag indicating whether future can be remapped on a newer topology version.
+     * @param needVer If {@code true} returns values as tuples containing value and version.
+     * @param keepCacheObj Keep cache objects flag.
+     * @return Load future.
      */
-    public IgniteInternalFuture<Map<K, V>> loadAsync(
+    public final IgniteInternalFuture<Map<K, V>> loadAsync(
         @Nullable Collection<KeyCacheObject> keys,
         boolean readThrough,
         boolean forcePrimary,
@@ -931,24 +1065,6 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
     }
 
     /**
-     * @param nodeId Sender ID.
-     * @param res Response.
-     */
-    private void processGetResponse(UUID nodeId, GridNearGetResponse res) {
-        GridPartitionedGetFuture<K, V> fut = (GridPartitionedGetFuture<K, V>)ctx.mvcc().<Map<K, V>>future(
-            res.version(), res.futureId());
-
-        if (fut == null) {
-            if (log.isDebugEnabled())
-                log.debug("Failed to find future for get response [sender=" + nodeId + ", res=" + res + ']');
-
-            return;
-        }
-
-        fut.onResult(nodeId, res);
-    }
-
-    /**
      * @param nodeId Node ID.
      * @param res Response.
      */
@@ -957,7 +1073,7 @@ public class GridDhtColocatedCache<K, V> extends GridDhtTransactionalCacheAdapte
         assert res != null;
 
         GridDhtColocatedLockFuture fut = (GridDhtColocatedLockFuture)ctx.mvcc().
-            <Boolean>future(res.version(), res.futureId());
+            <Boolean>mvccFuture(res.version(), res.futureId());
 
         if (fut != null)
             fut.onResult(nodeId, res);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
index abeb509..8245d88 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/colocated/GridDhtColocatedLockFuture.java
@@ -35,10 +35,11 @@ import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheEntryPredicate;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
-import org.apache.ignite.internal.processors.cache.GridCacheFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheLockTimeoutException;
 import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
+import org.apache.ignite.internal.processors.cache.GridCacheMvccFuture;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedCacheEntry;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
@@ -78,7 +79,7 @@ import static org.apache.ignite.events.EventType.EVT_CACHE_OBJECT_READ;
  * Colocated cache lock future.
  */
 public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture<Boolean>
-    implements GridCacheFuture<Boolean> {
+    implements GridCacheMvccFuture<Boolean> {
     /** */
     private static final long serialVersionUID = 0L;
 
@@ -198,25 +199,16 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
         valMap = new ConcurrentHashMap8<>(keys.size(), 1f);
     }
 
-    /**
-     * @return Participating nodes.
-     */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-            @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                if (isMini(f))
-                    return ((MiniFuture)f).node();
-
-                return cctx.discovery().localNode();
-            }
-        });
-    }
-
     /** {@inheritDoc} */
     @Override public GridCacheVersion version() {
         return lockVer;
     }
 
+    /** {@inheritDoc} */
+    @Override public boolean onOwnerChanged(GridCacheEntryEx entry, GridCacheMvccCandidate owner) {
+        return false;
+    }
+
     /**
      * @return Future ID.
      */
@@ -538,7 +530,7 @@ public final class GridDhtColocatedLockFuture extends GridCompoundIdentityFuture
                 log.debug("Completing future: " + this);
 
             // Clean up.
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             if (timeoutObj != null)
                 cctx.time().removeTimeoutObject(timeoutObj);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/CacheVersionedValue.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/CacheVersionedValue.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/CacheVersionedValue.java
index 1559a91..c14621a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/CacheVersionedValue.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/CacheVersionedValue.java
@@ -53,7 +53,7 @@ public class CacheVersionedValue implements Message {
      * @param val Cache value.
      * @param ver Cache version.
      */
-    CacheVersionedValue(CacheObject val, GridCacheVersion ver) {
+    public CacheVersionedValue(CacheObject val, GridCacheVersion ver) {
         this.val = val;
         this.ver = ver;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearCacheAdapter.java
index 3c3527a..eb0b637 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearCacheAdapter.java
@@ -52,6 +52,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheValueCollection;
 import org.apache.ignite.internal.processors.cache.IgniteCacheExpiryPolicy;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedCacheAdapter;
+import org.apache.ignite.internal.processors.cache.distributed.dht.CacheGetFuture;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheEntry;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
@@ -292,8 +293,7 @@ public abstract class GridNearCacheAdapter<K, V> extends GridDistributedCacheAda
      * @param res Response.
      */
     protected void processGetResponse(UUID nodeId, GridNearGetResponse res) {
-        GridNearGetFuture<K, V> fut = (GridNearGetFuture<K, V>)ctx.mvcc().<Map<K, V>>future(
-            res.version(), res.futureId());
+        CacheGetFuture fut = (CacheGetFuture)ctx.mvcc().future(res.futureId());
 
         if (fut == null) {
             if (log.isDebugEnabled())

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
index ae1d43c..dfaa44e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetFuture.java
@@ -170,24 +170,6 @@ public final class GridNearGetFuture<K, V> extends CacheDistributedGetFutureAdap
     }
 
     /** {@inheritDoc} */
-    @Override public GridCacheVersion version() {
-        return ver;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return
-            F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<Map<K, V>>, ClusterNode>() {
-                @Nullable @Override public ClusterNode apply(IgniteInternalFuture<Map<K, V>> f) {
-                    if (isMini(f))
-                        return ((MiniFuture)f).node();
-
-                    return cctx.discovery().localNode();
-                }
-            });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         boolean found = false;
 
@@ -227,7 +209,7 @@ public final class GridNearGetFuture<K, V> extends CacheDistributedGetFutureAdap
         if (super.onDone(res, err)) {
             // Don't forget to clean up.
             if (trackable)
-                cctx.mvcc().removeFuture(this);
+                cctx.mvcc().removeFuture(futId);
 
             cache().dht().sendTtlUpdateRequest(expiryPlc);
 
@@ -343,7 +325,7 @@ public final class GridNearGetFuture<K, V> extends CacheDistributedGetFutureAdap
                 if (!trackable) {
                     trackable = true;
 
-                    cctx.mvcc().addFuture(this);
+                    cctx.mvcc().addFuture(this, futId);
                 }
 
                 MiniFuture fut = new MiniFuture(n, mappedKeys, saved, topVer);
@@ -386,6 +368,7 @@ public final class GridNearGetFuture<K, V> extends CacheDistributedGetFutureAdap
      * @param saved Reserved near cache entries.
      * @return Map.
      */
+    @SuppressWarnings("unchecked")
     private Map<KeyCacheObject, GridNearCacheEntry> map(
         KeyCacheObject key,
         Map<ClusterNode, LinkedHashMap<KeyCacheObject, Boolean>> mappings,
@@ -538,11 +521,17 @@ public final class GridNearGetFuture<K, V> extends CacheDistributedGetFutureAdap
                         }
                         else {
                             K key0 = key.value(cctx.cacheObjectContext(), true);
-                            V val0 = v.value(cctx.cacheObjectContext(), true);
-
-                            val0 = (V)cctx.unwrapPortableIfNeeded(val0, !deserializePortable);
                             key0 = (K)cctx.unwrapPortableIfNeeded(key0, !deserializePortable);
 
+                            V val0;
+
+                            if (!skipVals) {
+                                val0 = v.value(cctx.cacheObjectContext(), true);
+                                val0 = (V)cctx.unwrapPortableIfNeeded(val0, !deserializePortable);
+                            }
+                            else
+                                val0 = (V)Boolean.TRUE;
+
                             add(new GridFinishedFuture<>(Collections.singletonMap(key0, val0)));
                         }
                     }
@@ -618,28 +607,6 @@ public final class GridNearGetFuture<K, V> extends CacheDistributedGetFutureAdap
     }
 
     /**
-     * Affinity node to send get request to.
-     *
-     * @param key Key to get.
-     * @param topVer Topology version.
-     * @return Affinity node to get key from.
-     */
-    private ClusterNode affinityNode(KeyCacheObject key, AffinityTopologyVersion topVer) {
-        if (!canRemap) {
-            List<ClusterNode> affNodes = cctx.affinity().nodes(key, topVer);
-
-            for (ClusterNode node : affNodes) {
-                if (cctx.discovery().alive(node))
-                    return node;
-            }
-
-            return null;
-        }
-        else
-            return cctx.affinity().primary(key, topVer);
-    }
-
-    /**
      * @return Near cache.
      */
     private GridNearCacheAdapter<K, V> cache() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java
index 8482217..6d60298 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetRequest.java
@@ -133,7 +133,6 @@ public class GridNearGetRequest extends GridCacheMessage implements GridCacheDep
     ) {
         assert futId != null;
         assert miniId != null;
-        assert ver != null;
         assert keys != null;
 
         this.cacheId = cacheId;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java
index fc06ab1..15a791f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearGetResponse.java
@@ -100,8 +100,6 @@ public class GridNearGetResponse extends GridCacheMessage implements GridCacheDe
         boolean addDepInfo
     ) {
         assert futId != null;
-        assert miniId != null;
-        assert ver != null;
 
         this.cacheId = cacheId;
         this.futId = futId;

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
index 9c3701f..76f2fbe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearLockFuture.java
@@ -209,20 +209,6 @@ public final class GridNearLockFuture extends GridCompoundIdentityFuture<Boolean
         valMap = new ConcurrentHashMap8<>(keys.size(), 1f);
     }
 
-    /**
-     * @return Participating nodes.
-     */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-            @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                if (isMini(f))
-                    return ((MiniFuture)f).node();
-
-                return cctx.discovery().localNode();
-            }
-        });
-    }
-
     /** {@inheritDoc} */
     @Override public GridCacheVersion version() {
         return lockVer;
@@ -672,7 +658,7 @@ public final class GridNearLockFuture extends GridCompoundIdentityFuture<Boolean
                 log.debug("Completing future: " + this);
 
             // Clean up.
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             if (timeoutObj != null)
                 cctx.time().removeTimeoutObject(timeoutObj);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
index 1569b14..770c47a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticSerializableTxPrepareFuture.java
@@ -73,8 +73,7 @@ import static org.apache.ignite.transactions.TransactionState.PREPARING;
 /**
  *
  */
-public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptimisticTxPrepareFutureAdapter
-    implements GridCacheMvccFuture<IgniteInternalTx> {
+public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptimisticTxPrepareFutureAdapter {
     /** */
     public static final IgniteProductVersion SER_TX_SINCE = IgniteProductVersion.fromString("1.5.0");
 
@@ -148,18 +147,6 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-            @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                if (isMini(f))
-                    return ((MiniFuture)f).node();
-
-                return cctx.discovery().localNode();
-            }
-        });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         boolean found = false;
 
@@ -287,7 +274,7 @@ public class GridNearOptimisticSerializableTxPrepareFuture extends GridNearOptim
                 tx.setRollbackOnly();
 
             // Don't forget to clean up.
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             return true;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
index 82e3868..eaf476c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearOptimisticTxPrepareFuture.java
@@ -35,7 +35,6 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
 import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
-import org.apache.ignite.internal.processors.cache.GridCacheMvccFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxMapping;
@@ -54,7 +53,6 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.transactions.TransactionTimeoutException;
 import org.jetbrains.annotations.Nullable;
@@ -66,8 +64,7 @@ import static org.apache.ignite.transactions.TransactionState.PREPARING;
 /**
  *
  */
-public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepareFutureAdapter
-    implements GridCacheMvccFuture<IgniteInternalTx> {
+public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepareFutureAdapter {
     /** */
     @GridToStringInclude
     private Collection<IgniteTxKey> lockKeys = new GridConcurrentHashSet<>();
@@ -100,18 +97,6 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-            @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                if (isMini(f))
-                    return ((MiniFuture)f).node();
-
-                return cctx.discovery().localNode();
-            }
-        });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         boolean found = false;
 
@@ -261,7 +246,7 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
 
         if (super.onDone(tx, err0)) {
             // Don't forget to clean up.
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             return true;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
index 103105e..ffe5373 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearPessimisticTxPrepareFuture.java
@@ -28,6 +28,8 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
+import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxMapping;
@@ -42,7 +44,6 @@ import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteUuid;
 import org.jetbrains.annotations.Nullable;
 
@@ -68,15 +69,6 @@ public class GridNearPessimisticTxPrepareFuture extends GridNearTxPrepareFutureA
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-            @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                return ((MiniFuture)f).node();
-            }
-        });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         boolean found = false;
 
@@ -280,6 +272,11 @@ public class GridNearPessimisticTxPrepareFuture extends GridNearTxPrepareFutureA
     }
 
     /** {@inheritDoc} */
+    @Override public boolean onOwnerChanged(GridCacheEntryEx entry, GridCacheMvccCandidate owner) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
     @Override public boolean onDone(@Nullable IgniteInternalTx res, @Nullable Throwable err) {
         if (err != null)
             this.err.compareAndSet(null, err);
@@ -290,7 +287,7 @@ public class GridNearPessimisticTxPrepareFuture extends GridNearTxPrepareFutureA
             tx.state(PREPARED);
 
         if (super.onDone(tx, err)) {
-            cctx.mvcc().removeFuture(this);
+            cctx.mvcc().removeMvccFuture(this);
 
             return true;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetRequest.java
new file mode 100644
index 0000000..a506007
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetRequest.java
@@ -0,0 +1,396 @@
+/*
+ * 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.distributed.near;
+
+import java.nio.ByteBuffer;
+import java.util.UUID;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheDeployable;
+import org.apache.ignite.internal.processors.cache.GridCacheMessage;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.jetbrains.annotations.NotNull;
+
+import static org.apache.ignite.internal.processors.cache.GridCacheUtils.SKIP_STORE_FLAG_MASK;
+
+/**
+ *
+ */
+public class GridNearSingleGetRequest extends GridCacheMessage implements GridCacheDeployable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    public static final int READ_THROUGH_FLAG_MASK = 0x01;
+
+    /** */
+    public static final int SKIP_VALS_FLAG_MASK = 0x02;
+
+    /** */
+    public static final int ADD_READER_FLAG_MASK = 0x04;
+
+    /** */
+    public static final int NEED_VER_FLAG_MASK = 0x08;
+
+    /** */
+    public static final int NEED_ENTRY_INFO_FLAG_MASK = 0x10;
+
+    /** Future ID. */
+    private IgniteUuid futId;
+
+    /** */
+    private KeyCacheObject key;
+
+    /** Flags. */
+    private byte flags;
+
+    /** Topology version. */
+    private AffinityTopologyVersion topVer;
+
+    /** Subject ID. */
+    private UUID subjId;
+
+    /** Task name hash. */
+    private int taskNameHash;
+
+    /** TTL for read operation. */
+    private long accessTtl;
+
+    /**
+     * Empty constructor required for {@link Message}.
+     */
+    public GridNearSingleGetRequest() {
+        // No-op.
+    }
+
+    /**
+     * @param cacheId Cache ID.
+     * @param futId Future ID.
+     * @param key Key.
+     * @param readThrough Read through flag.
+     * @param skipVals Skip values flag. When false, only boolean values will be returned indicating whether
+     *      cache entry has a value.
+     * @param topVer Topology version.
+     * @param subjId Subject ID.
+     * @param taskNameHash Task name hash.
+     * @param accessTtl New TTL to set after entry is accessed, -1 to leave unchanged.
+     * @param addReader Add reader flag.
+     * @param needVer {@code True} if entry version is needed.
+     * @param addDepInfo Deployment info.
+     */
+    public GridNearSingleGetRequest(
+        int cacheId,
+        IgniteUuid futId,
+        KeyCacheObject key,
+        boolean readThrough,
+        @NotNull AffinityTopologyVersion topVer,
+        UUID subjId,
+        int taskNameHash,
+        long accessTtl,
+        boolean skipVals,
+        boolean addReader,
+        boolean needVer,
+        boolean addDepInfo
+    ) {
+        assert futId != null;
+        assert key != null;
+
+        this.cacheId = cacheId;
+        this.futId = futId;
+        this.key = key;
+        this.topVer = topVer;
+        this.subjId = subjId;
+        this.taskNameHash = taskNameHash;
+        this.accessTtl = accessTtl;
+        this.addDepInfo = addDepInfo;
+
+        if (readThrough)
+            flags = (byte)(flags | READ_THROUGH_FLAG_MASK);
+
+        if (skipVals)
+            flags = (byte)(flags | SKIP_VALS_FLAG_MASK);
+
+        if (addReader)
+            flags = (byte)(flags | ADD_READER_FLAG_MASK);
+
+        if (needVer)
+            flags = (byte)(flags | NEED_VER_FLAG_MASK);
+    }
+
+    /**
+     * @return Key.
+     */
+    public KeyCacheObject key() {
+        return key;
+    }
+
+    /**
+     * @return Future ID.
+     */
+    public IgniteUuid futureId() {
+        return futId;
+    }
+
+    /**
+     * @return Subject ID.
+     */
+    public UUID subjectId() {
+        return subjId;
+    }
+
+    /**
+     * Gets task name hash.
+     *
+     * @return Task name hash.
+     */
+    public int taskNameHash() {
+        return taskNameHash;
+    }
+
+    /**
+     * @return Topology version.
+     */
+    @Override public AffinityTopologyVersion topologyVersion() {
+        return topVer;
+    }
+
+    /**
+     * @return New TTL to set after entry is accessed, -1 to leave unchanged.
+     */
+    public long accessTtl() {
+        return accessTtl;
+    }
+
+    /**
+     * @return Read through flag.
+     */
+    public boolean readThrough() {
+        return (flags & SKIP_STORE_FLAG_MASK) != 0;
+    }
+
+    /**
+     * @return Read through flag.
+     */
+    public boolean skipValues() {
+        return (flags & SKIP_VALS_FLAG_MASK) != 0;
+    }
+
+    /**
+     * @return Add reader flag.
+     */
+    public boolean addReader() {
+        return (flags & ADD_READER_FLAG_MASK) != 0;
+    }
+
+    /**
+     * @return {@code True} if entry version is needed.
+     */
+    public boolean needVersion() {
+        return (flags & NEED_VER_FLAG_MASK) != 0;
+    }
+
+    /**
+     * @return {@code True} if full entry information is needed.
+     */
+    public boolean needEntryInfo() {
+        return (flags & NEED_ENTRY_INFO_FLAG_MASK) != 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(GridCacheSharedContext ctx) throws IgniteCheckedException {
+        super.prepareMarshal(ctx);
+
+        assert key != null;
+
+        GridCacheContext cctx = ctx.cacheContext(cacheId);
+
+        prepareMarshalCacheObject(key, cctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(GridCacheSharedContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+        super.finishUnmarshal(ctx, ldr);
+
+        assert key != null;
+
+        GridCacheContext cctx = ctx.cacheContext(cacheId);
+
+        key.finishUnmarshal(cctx.cacheObjectContext(), ldr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        if (!super.readFrom(buf, reader))
+            return false;
+
+        switch (reader.state()) {
+            case 3:
+                accessTtl = reader.readLong("accessTtl");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 4:
+                flags = reader.readByte("flags");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 5:
+                futId = reader.readIgniteUuid("futId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 6:
+                key = reader.readMessage("key");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 7:
+                subjId = reader.readUuid("subjId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 8:
+                taskNameHash = reader.readInt("taskNameHash");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 9:
+                topVer = reader.readMessage("topVer");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(GridNearSingleGetRequest.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!super.writeTo(buf, writer))
+            return false;
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 3:
+                if (!writer.writeLong("accessTtl", accessTtl))
+                    return false;
+
+                writer.incrementState();
+
+            case 4:
+                if (!writer.writeByte("flags", flags))
+                    return false;
+
+                writer.incrementState();
+
+            case 5:
+                if (!writer.writeIgniteUuid("futId", futId))
+                    return false;
+
+                writer.incrementState();
+
+            case 6:
+                if (!writer.writeMessage("key", key))
+                    return false;
+
+                writer.incrementState();
+
+            case 7:
+                if (!writer.writeUuid("subjId", subjId))
+                    return false;
+
+                writer.incrementState();
+
+            case 8:
+                if (!writer.writeInt("taskNameHash", taskNameHash))
+                    return false;
+
+                writer.incrementState();
+
+            case 9:
+                if (!writer.writeMessage("topVer", topVer))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean addDeploymentInfo() {
+        return addDepInfo;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte directType() {
+        return 116;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 10;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(GridNearSingleGetRequest.class, this);
+    }
+}


[34/37] ignite git commit: IgniteSqlQueryPutBenchmark: print number of puts and queries.

Posted by ag...@apache.org.
IgniteSqlQueryPutBenchmark: print number of puts and queries.


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

Branch: refs/heads/ignite-1282
Commit: 900788b68c4e093606abd2f7820ca08d94763802
Parents: ce63637
Author: sboikov <sb...@gridgain.com>
Authored: Fri Nov 20 10:41:34 2015 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Nov 20 10:41:34 2015 +0300

----------------------------------------------------------------------
 .../cache/IgniteSqlQueryPutBenchmark.java       | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/900788b6/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
index 1c258a4..99b2423 100644
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryPutBenchmark.java
@@ -20,16 +20,25 @@ package org.apache.ignite.yardstick.cache;
 import java.util.Collection;
 import java.util.Map;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
 import javax.cache.Cache;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.SqlQuery;
 import org.apache.ignite.yardstick.cache.model.Person;
 import org.yardstickframework.BenchmarkConfiguration;
 
+import static org.yardstickframework.BenchmarkUtils.println;
+
 /**
  * Ignite benchmark that performs put and query operations.
  */
 public class IgniteSqlQueryPutBenchmark extends IgniteCacheAbstractBenchmark<Integer, Object> {
+    /** */
+    private AtomicInteger putCnt = new AtomicInteger();
+
+    /** */
+    private AtomicInteger qryCnt = new AtomicInteger();
+
     /** {@inheritDoc} */
     @Override public void setUp(BenchmarkConfiguration cfg) throws Exception {
         super.setUp(cfg);
@@ -53,11 +62,15 @@ public class IgniteSqlQueryPutBenchmark extends IgniteCacheAbstractBenchmark<Int
                     throw new Exception("Invalid person retrieved [min=" + salary + ", max=" + maxSalary +
                             ", person=" + p + ']');
             }
+
+            qryCnt.getAndIncrement();
         }
         else {
             int i = rnd.nextInt(args.range());
 
             cache.put(i, new Person(i, "firstName" + i, "lastName" + i, i * 1000));
+
+            putCnt.getAndIncrement();
         }
 
         return true;
@@ -81,4 +94,11 @@ public class IgniteSqlQueryPutBenchmark extends IgniteCacheAbstractBenchmark<Int
     @Override protected IgniteCache<Integer, Object> cache() {
         return ignite().cache("query");
     }
+
+    /** {@inheritDoc} */
+    @Override public void tearDown() throws Exception {
+        println(cfg, "Finished sql query put benchmark [putCnt=" + putCnt.get() + ", qryCnt=" + qryCnt.get() + ']');
+
+        super.tearDown();
+    }
 }


[31/37] ignite git commit: IGNITE-426 Implemented failover for Continuous query.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
index c7bf091..b2e7490 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
@@ -23,6 +23,7 @@ import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Map;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
@@ -46,12 +47,14 @@ import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.query.ContinuousQuery;
 import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import org.apache.ignite.internal.processors.cache.GridCacheManagerAdapter;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
+import org.apache.ignite.internal.util.typedef.CI2;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgnitePredicate;
@@ -82,6 +85,9 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
     /** */
     private static final byte EXPIRED_FLAG = 0b1000;
 
+    /** */
+    private static final long BACKUP_ACK_FREQ = 5000;
+
     /** Listeners. */
     private final ConcurrentMap<UUID, CacheContinuousQueryListener> lsnrs = new ConcurrentHashMap8<>();
 
@@ -108,6 +114,18 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
     @Override protected void start0() throws IgniteCheckedException {
         // Append cache name to the topic.
         topicPrefix = "CONTINUOUS_QUERY" + (cctx.name() == null ? "" : "_" + cctx.name());
+
+        cctx.io().addHandler(cctx.cacheId(), CacheContinuousQueryBatchAck.class,
+            new CI2<UUID, CacheContinuousQueryBatchAck>() {
+                @Override public void apply(UUID uuid, CacheContinuousQueryBatchAck msg) {
+                    CacheContinuousQueryListener lsnr = lsnrs.get(msg.routineId());
+
+                    if (lsnr != null)
+                        lsnr.cleanupBackupQueue(msg.updateCntrs());
+                }
+            });
+
+        cctx.time().schedule(new BackupCleaner(lsnrs, cctx.kernalContext()), BACKUP_ACK_FREQ, BACKUP_ACK_FREQ);
     }
 
     /** {@inheritDoc} */
@@ -137,25 +155,55 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
     }
 
     /**
-     * @param e Cache entry.
+     * @param partId Partition id.
+     * @param updCntr Updated counter.
+     * @param topVer Topology version.
+     */
+    public void skipUpdateEvent(KeyCacheObject key, int partId, long updCntr, AffinityTopologyVersion topVer) {
+        if (lsnrCnt.get() > 0) {
+            CacheContinuousQueryEntry e0 = new CacheContinuousQueryEntry(
+                cctx.cacheId(),
+                UPDATED,
+                key,
+                null,
+                null,
+                partId,
+                updCntr,
+                topVer);
+
+            CacheContinuousQueryEvent evt = new CacheContinuousQueryEvent<>(
+                    cctx.kernalContext().cache().jcache(cctx.name()), cctx, e0);
+
+            for (CacheContinuousQueryListener lsnr : lsnrs.values())
+                lsnr.skipUpdateEvent(evt, topVer);
+        }
+    }
+
+    /**
      * @param key Key.
      * @param newVal New value.
      * @param oldVal Old value.
+     * @param internal Internal entry (internal key or not user cache),
+     * @param primary {@code True} if called on primary node.
      * @param preload Whether update happened during preloading.
+     * @param updateCntr Update counter.
+     * @param topVer Topology version.
      * @throws IgniteCheckedException In case of error.
      */
-    public void onEntryUpdated(GridCacheEntryEx e,
+    public void onEntryUpdated(
         KeyCacheObject key,
         CacheObject newVal,
         CacheObject oldVal,
-        boolean preload)
+        boolean internal,
+        int partId,
+        boolean primary,
+        boolean preload,
+        long updateCntr,
+        AffinityTopologyVersion topVer)
         throws IgniteCheckedException
     {
-        assert e != null;
         assert key != null;
 
-        boolean internal = e.isInternal() || !e.context().userCache();
-
         if (preload && !internal)
             return;
 
@@ -179,8 +227,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
 
         boolean initialized = false;
 
-        boolean primary = cctx.affinity().primary(cctx.localNode(), key, AffinityTopologyVersion.NONE);
-        boolean recordIgniteEvt = !internal && cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_OBJECT_READ);
+        boolean recordIgniteEvt = primary && !internal && cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_OBJECT_READ);
 
         for (CacheContinuousQueryListener lsnr : lsnrCol.values()) {
             if (preload && !lsnr.notifyExisting())
@@ -205,7 +252,10 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                 evtType,
                 key,
                 newVal,
-                lsnr.oldValueRequired() ? oldVal : null);
+                lsnr.oldValueRequired() ? oldVal : null,
+                partId,
+                updateCntr,
+                topVer);
 
             CacheContinuousQueryEvent evt = new CacheContinuousQueryEvent<>(
                 cctx.kernalContext().cache().jcache(cctx.name()), cctx, e0);
@@ -250,12 +300,15 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                     initialized = true;
                 }
 
-               CacheContinuousQueryEntry e0 = new CacheContinuousQueryEntry(
-                   cctx.cacheId(),
-                   EXPIRED,
-                   key,
-                   null,
-                   lsnr.oldValueRequired() ? oldVal : null);
+                CacheContinuousQueryEntry e0 = new CacheContinuousQueryEntry(
+                    cctx.cacheId(),
+                    EXPIRED,
+                    key,
+                    null,
+                    lsnr.oldValueRequired() ? oldVal : null,
+                    e.partition(),
+                    -1,
+                    null);
 
                 CacheContinuousQueryEvent evt = new CacheContinuousQueryEvent(
                     cctx.kernalContext().cache().jcache(cctx.name()), cctx, e0);
@@ -373,6 +426,27 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
     }
 
     /**
+     * @param topVer Topology version.
+     */
+    public void beforeExchange(AffinityTopologyVersion topVer) {
+        for (CacheContinuousQueryListener lsnr : lsnrs.values())
+            lsnr.flushBackupQueue(cctx.kernalContext(), topVer);
+    }
+
+    /**
+     * Partition evicted callback.
+     *
+     * @param part Partition number.
+     */
+    public void onPartitionEvicted(int part) {
+        for (CacheContinuousQueryListener lsnr : lsnrs.values())
+            lsnr.onPartitionEvicted(part);
+
+        for (CacheContinuousQueryListener lsnr : intLsnrs.values())
+            lsnr.onPartitionEvicted(part);
+    }
+
+    /**
      * @param locLsnr Local listener.
      * @param rmtFilter Remote filter.
      * @param bufSize Buffer size.
@@ -417,7 +491,8 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
             sync,
             ignoreExpired,
             taskNameHash,
-            skipPrimaryCheck);
+            skipPrimaryCheck,
+            cctx.isLocal());
 
         IgnitePredicate<ClusterNode> pred = (loc || cctx.config().getCacheMode() == CacheMode.LOCAL) ?
             F.nodeForNodeId(cctx.localNodeId()) : F.<ClusterNode>alwaysTrue();
@@ -469,10 +544,19 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
 
                                 GridCacheEntryEx e = it.next();
 
+                                CacheContinuousQueryEntry entry = new CacheContinuousQueryEntry(
+                                    cctx.cacheId(),
+                                    CREATED,
+                                    e.key(),
+                                    e.rawGet(),
+                                    null,
+                                    0,
+                                    -1,
+                                    null);
+
                                 next = new CacheContinuousQueryEvent<>(
                                     cctx.kernalContext().cache().jcache(cctx.name()),
-                                    cctx,
-                                    new CacheContinuousQueryEntry(cctx.cacheId(), CREATED, e.key(), e.rawGet(), null));
+                                    cctx, entry);
 
                                 if (rmtFilter != null && !rmtFilter.evaluate(next))
                                     next = null;
@@ -590,10 +674,11 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
             CacheEntryEventFilter fltr = null;
 
             if (cfg.getCacheEntryEventFilterFactory() != null) {
-                fltr = (CacheEntryEventFilter) cfg.getCacheEntryEventFilterFactory().create();
+                fltr = (CacheEntryEventFilter)cfg.getCacheEntryEventFilterFactory().create();
 
                 if (!(fltr instanceof Serializable))
-                    throw new IgniteCheckedException("Cache entry event filter must implement java.io.Serializable: " + fltr);
+                    throw new IgniteCheckedException("Cache entry event filter must implement java.io.Serializable: "
+                        + fltr);
             }
 
             CacheEntryEventSerializableFilter rmtFilter = new JCacheQueryRemoteFilter(fltr, types);
@@ -637,6 +722,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
 
         /**
          * @param impl Listener.
+         * @param log Logger.
          */
         JCacheQueryLocalListener(CacheEntryListener<K, V> impl, IgniteLogger log) {
             assert impl != null;
@@ -789,4 +875,29 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
             }
         }
     }
+
+    /**
+     * Task flash backup queue.
+     */
+    private static final class BackupCleaner implements Runnable {
+        /** Listeners. */
+        private final Map<UUID, CacheContinuousQueryListener> lsnrs;
+
+        /** Context. */
+        private final GridKernalContext ctx;
+
+        /**
+         * @param lsnrs Listeners.
+         */
+        public BackupCleaner(Map<UUID, CacheContinuousQueryListener> lsnrs, GridKernalContext ctx) {
+            this.lsnrs = lsnrs;
+            this.ctx = ctx;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void run() {
+            for (CacheContinuousQueryListener lsnr : lsnrs.values())
+                lsnr.acknowledgeBackupOnTimeout(ctx);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
index 23f83be..ff413d3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
@@ -181,6 +181,10 @@ public class IgniteTxEntry implements GridPeerDeployAware, Message {
      */
     private byte flags;
 
+    /** Partition update counter. */
+    @GridDirectTransient
+    private long partUpdateCntr;
+
     /** */
     private GridCacheVersion serReadVer;
 
@@ -373,6 +377,22 @@ public class IgniteTxEntry implements GridPeerDeployAware, Message {
     }
 
     /**
+     * Sets partition counter.
+     *
+     * @param partCntr Partition counter.
+     */
+    public void updateCounter(long partCntr) {
+        this.partUpdateCntr = partCntr;
+    }
+
+    /**
+     * @return Partition index.
+     */
+    public long updateCounter() {
+        return partUpdateCntr;
+    }
+
+    /**
      * @param val Value to set.
      */
     void setAndMarkValid(CacheObject val) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
index a9846ef..63a4cbe 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
@@ -964,6 +964,9 @@ public class IgniteTxHandler {
                 // Complete remote candidates.
                 tx.doneRemote(req.baseVersion(), null, null, null);
 
+                tx.setPartitionUpdateCounters(
+                    req.partUpdateCounters() != null ? req.partUpdateCounters().array() : null);
+
                 tx.commit();
             }
             else {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index ecb0595..cff62d9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -1012,7 +1012,11 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                             cached.isNear() ? null : explicitVer,
                                             CU.subjectId(this, cctx),
                                             resolveTaskName(),
-                                            dhtVer);
+                                            dhtVer,
+                                            null);
+
+                                        if (updRes.success())
+                                            txEntry.updateCounter(updRes.updatePartitionCounter());
 
                                         if (nearCached != null && updRes.success()) {
                                             nearCached.innerSet(
@@ -1032,7 +1036,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                                 null,
                                                 CU.subjectId(this, cctx),
                                                 resolveTaskName(),
-                                                dhtVer);
+                                                dhtVer,
+                                                null);
                                         }
                                     }
                                     else if (op == DELETE) {
@@ -1049,7 +1054,11 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                             cached.isNear() ? null : explicitVer,
                                             CU.subjectId(this, cctx),
                                             resolveTaskName(),
-                                            dhtVer);
+                                            dhtVer,
+                                            null);
+
+                                        if (updRes.success())
+                                            txEntry.updateCounter(updRes.updatePartitionCounter());
 
                                         if (nearCached != null && updRes.success()) {
                                             nearCached.innerRemove(
@@ -1065,7 +1074,8 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
                                                 null,
                                                 CU.subjectId(this, cctx),
                                                 resolveTaskName(),
-                                                dhtVer);
+                                                dhtVer,
+                                                null);
                                         }
                                     }
                                     else if (op == RELOAD) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
index b80909f..8ceca3f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteEx.java
@@ -34,4 +34,9 @@ public interface IgniteTxRemoteEx extends IgniteInternalTx {
         Collection<GridCacheVersion> committedVers,
         Collection<GridCacheVersion> rolledbackVers,
         Collection<GridCacheVersion> pendingVers);
-}
\ No newline at end of file
+
+    /**
+     * @param cntrs Partition update indexes.
+     */
+    public void setPartitionUpdateCounters(long[] cntrs);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatch.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatch.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatch.java
new file mode 100644
index 0000000..67b8c82
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatch.java
@@ -0,0 +1,44 @@
+/*
+ * 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.continuous;
+
+import java.util.Collection;
+
+/**
+ * Continuous routine batch.
+ */
+public interface GridContinuousBatch {
+    /**
+     * Adds element to this batch.
+     *
+     * @param obj Element to add.
+     */
+    public void add(Object obj);
+
+    /**
+     * Collects elements that are currently in this batch.
+     *
+     * @return Elements in this batch.
+     */
+    public Collection<Object> collect();
+
+    /**
+     * @return Current batch size.
+     */
+    public int size();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatchAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatchAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatchAdapter.java
new file mode 100644
index 0000000..4540de1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousBatchAdapter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.continuous;
+
+import java.util.Collection;
+import org.jsr166.ConcurrentLinkedDeque8;
+
+/**
+ * Continuous routine batch adapter.
+ */
+public class GridContinuousBatchAdapter implements GridContinuousBatch {
+    /** Buffer. */
+    private final ConcurrentLinkedDeque8<Object> buf = new ConcurrentLinkedDeque8<>();
+
+    /** {@inheritDoc} */
+    @Override public void add(Object obj) {
+        assert obj != null;
+
+        buf.add(obj);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<Object> collect() {
+        return buf;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        return buf.sizex();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousHandler.java
index 30e596a..d8698b3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousHandler.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.continuous;
 
 import java.io.Externalizable;
 import java.util.Collection;
+import java.util.Map;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.GridKernalContext;
@@ -98,6 +99,22 @@ public interface GridContinuousHandler extends Externalizable, Cloneable {
     public void p2pUnmarshal(UUID nodeId, GridKernalContext ctx) throws IgniteCheckedException;
 
     /**
+     * Creates new batch.
+     *
+     * @return New batch.
+     */
+    public GridContinuousBatch createBatch();
+
+    /**
+     * Called when ack for a batch is received from client.
+     *
+     * @param routineId Routine ID.
+     * @param batch Acknowledged batch.
+     * @param ctx Kernal context.
+     */
+    public void onBatchAcknowledged(UUID routineId, GridContinuousBatch batch, GridKernalContext ctx);
+
+    /**
      * @return Topic for ordered notifications. If {@code null}, notifications
      * will be sent in non-ordered messages.
      */
@@ -129,4 +146,9 @@ public interface GridContinuousHandler extends Externalizable, Cloneable {
      * @return Cache name if this is a continuous query handler.
      */
     public String cacheName();
+
+    /**
+     * @param cntrs Init state for partition counters.
+     */
+    public void updateCounters(Map<Integer, Long> cntrs);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
index d1cb3a9..c07cc13 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/GridContinuousProcessor.java
@@ -35,6 +35,7 @@ import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.events.DiscoveryEvent;
 import org.apache.ignite.events.Event;
@@ -52,17 +53,21 @@ import org.apache.ignite.internal.managers.discovery.CustomEventListener;
 import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObject;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.CI1;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.internal.util.worker.GridWorker;
 import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.marshaller.Marshaller;
@@ -70,7 +75,6 @@ import org.apache.ignite.plugin.extensions.communication.Message;
 import org.apache.ignite.thread.IgniteThread;
 import org.jetbrains.annotations.Nullable;
 import org.jsr166.ConcurrentHashMap8;
-import org.jsr166.ConcurrentLinkedDeque8;
 
 import static org.apache.ignite.events.EventType.EVT_NODE_FAILED;
 import static org.apache.ignite.events.EventType.EVT_NODE_LEFT;
@@ -203,8 +207,38 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                     StartFuture fut = startFuts.remove(msg.routineId());
 
                     if (fut != null) {
-                        if (msg.errs().isEmpty())
+                        if (msg.errs().isEmpty()) {
+                            LocalRoutineInfo routine = locInfos.get(msg.routineId());
+
+                            if (routine != null) {
+                                try {
+                                    Map<Integer, Long> cntrs = msg.updateCounters();
+
+                                    GridCacheAdapter<Object, Object> interCache =
+                                        ctx.cache().internalCache(routine.handler().cacheName());
+
+                                    if (interCache != null && cntrs != null && interCache.context() != null
+                                        && !interCache.isLocal() && !CU.clientNode(ctx.grid().localNode())) {
+                                        Map<Integer, Long> map = interCache.context().topology().updateCounters();
+
+                                        for (Map.Entry<Integer, Long> e : map.entrySet()) {
+                                            Long cntr0 = cntrs.get(e.getKey());
+                                            Long cntr1 = e.getValue();
+
+                                            if (cntr0 == null || cntr1 > cntr0)
+                                                cntrs.put(e.getKey(), cntr1);
+                                        }
+                                    }
+                                }
+                                catch (Exception e) {
+                                    U.warn(log, "Failed to load update counters.", e);
+                                }
+
+                                routine.handler().updateCounters(msg.updateCounters());
+                            }
+
                             fut.onRemoteRegistered();
+                        }
                         else {
                             IgniteCheckedException firstEx = F.first(msg.errs().values());
 
@@ -651,6 +685,30 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
     /**
      * @param nodeId ID of the node that started routine.
      * @param routineId Routine ID.
+     * @param objs Notification objects.
+     * @param orderedTopic Topic for ordered notifications. If {@code null}, non-ordered message will be sent.
+     * @throws IgniteCheckedException In case of error.
+     */
+    public void addBackupNotification(UUID nodeId,
+        final UUID routineId,
+        Collection<?> objs,
+        @Nullable Object orderedTopic)
+        throws IgniteCheckedException {
+        if (processorStopped)
+            return;
+
+        final RemoteRoutineInfo info = rmtInfos.get(routineId);
+
+        if (info != null) {
+            final GridContinuousBatch batch = info.addAll(objs);
+
+            sendNotification(nodeId, routineId, null, batch.collect(), orderedTopic, true, null);
+        }
+    }
+
+    /**
+     * @param nodeId ID of the node that started routine.
+     * @param routineId Routine ID.
      * @param obj Notification object.
      * @param orderedTopic Topic for ordered notifications. If {@code null}, non-ordered message will be sent.
      * @param sync If {@code true} then waits for event acknowledgment.
@@ -658,7 +716,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
      * @throws IgniteCheckedException In case of error.
      */
     public void addNotification(UUID nodeId,
-        UUID routineId,
+        final UUID routineId,
         @Nullable Object obj,
         @Nullable Object orderedTopic,
         boolean sync,
@@ -673,7 +731,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
         if (processorStopped)
             return;
 
-        RemoteRoutineInfo info = rmtInfos.get(routineId);
+        final RemoteRoutineInfo info = rmtInfos.get(routineId);
 
         if (info != null) {
             assert info.interval == 0 || !sync;
@@ -686,7 +744,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                 syncMsgFuts.put(futId, fut);
 
                 try {
-                    sendNotification(nodeId, routineId, futId, F.asList(obj), orderedTopic, msg);
+                    sendNotification(nodeId, routineId, futId, F.asList(obj), orderedTopic, msg, null);
                 }
                 catch (IgniteCheckedException e) {
                     syncMsgFuts.remove(futId);
@@ -697,10 +755,18 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                 fut.get();
             }
             else {
-                Collection<Object> toSnd = info.add(obj);
+                final GridContinuousBatch batch = info.add(obj);
+
+                if (batch != null) {
+                    CI1<IgniteException> ackC = new CI1<IgniteException>() {
+                        @Override public void apply(IgniteException e) {
+                            if (e == null)
+                                info.hnd.onBatchAcknowledged(routineId, batch, ctx);
+                        }
+                    };
 
-                if (toSnd != null)
-                    sendNotification(nodeId, routineId, null, toSnd, orderedTopic, msg);
+                    sendNotification(nodeId, routineId, null, batch.collect(), orderedTopic, msg, ackC);
+                }
             }
         }
     }
@@ -725,6 +791,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
      * @param orderedTopic Topic for ordered notifications.
      *      If {@code null}, non-ordered message will be sent.
      * @param msg If {@code true} then sent data is collection of messages.
+     * @param ackC Ack closure.
      * @throws IgniteCheckedException In case of error.
      */
     private void sendNotification(UUID nodeId,
@@ -732,7 +799,8 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
         @Nullable IgniteUuid futId,
         Collection<Object> toSnd,
         @Nullable Object orderedTopic,
-        boolean msg) throws IgniteCheckedException {
+        boolean msg,
+        IgniteInClosure<IgniteException> ackC) throws IgniteCheckedException {
         assert nodeId != null;
         assert routineId != null;
         assert toSnd != null;
@@ -740,7 +808,8 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
 
         sendWithRetries(nodeId,
             new GridContinuousMessage(MSG_EVT_NOTIFICATION, routineId, futId, toSnd, msg),
-            orderedTopic);
+            orderedTopic,
+            ackC);
     }
 
     /**
@@ -819,6 +888,18 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
             }
         }
 
+        try {
+            if (ctx.cache() != null && ctx.cache().internalCache(hnd.cacheName()) != null) {
+                Map<Integer, Long> cntrs = ctx.cache().internalCache(hnd.cacheName())
+                    .context().topology().updateCounters();
+
+                req.addUpdateCounters(cntrs);
+            }
+        }
+        catch (Exception e) {
+            U.warn(log, "Failed to load partition counters.");
+        }
+
         if (err != null)
             req.addError(ctx.localNodeId(), err);
 
@@ -859,6 +940,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                 try {
                     sendWithRetries(nodeId,
                         new GridContinuousMessage(MSG_EVT_ACK, null, msg.futureId(), null, false),
+                        null,
                         null);
                 }
                 catch (IgniteCheckedException e) {
@@ -922,15 +1004,30 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                                 break;
                             }
 
-                            IgniteBiTuple<Collection<Object>, Long> t = info.checkInterval();
+                            IgniteBiTuple<GridContinuousBatch, Long> t = info.checkInterval();
 
-                            Collection<Object> toSnd = t.get1();
+                            final GridContinuousBatch batch = t.get1();
 
-                            if (toSnd != null && !toSnd.isEmpty()) {
+                            if (batch != null && batch.size() > 0) {
                                 try {
+                                    Collection<Object> toSnd = batch.collect();
+
                                     boolean msg = toSnd.iterator().next() instanceof Message;
 
-                                    sendNotification(nodeId, routineId, null, toSnd, hnd.orderedTopic(), msg);
+                                    CI1<IgniteException> ackC = new CI1<IgniteException>() {
+                                        @Override public void apply(IgniteException e) {
+                                            if (e == null)
+                                                info.hnd.onBatchAcknowledged(routineId, batch, ctx);
+                                        }
+                                    };
+
+                                    sendNotification(nodeId,
+                                        routineId,
+                                        null,
+                                        toSnd,
+                                        hnd.orderedTopic(),
+                                        msg,
+                                        ackC);
                                 }
                                 catch (ClusterTopologyCheckedException ignored) {
                                     if (log.isDebugEnabled())
@@ -1013,9 +1110,11 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
      * @param msg Message.
      * @param orderedTopic Topic for ordered notifications.
      *      If {@code null}, non-ordered message will be sent.
+     * @param ackC Ack closure.
      * @throws IgniteCheckedException In case of error.
      */
-    private void sendWithRetries(UUID nodeId, GridContinuousMessage msg, @Nullable Object orderedTopic)
+    private void sendWithRetries(UUID nodeId, GridContinuousMessage msg, @Nullable Object orderedTopic,
+        IgniteInClosure<IgniteException> ackC)
         throws IgniteCheckedException {
         assert nodeId != null;
         assert msg != null;
@@ -1023,7 +1122,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
         ClusterNode node = ctx.discovery().node(nodeId);
 
         if (node != null)
-            sendWithRetries(node, msg, orderedTopic);
+            sendWithRetries(node, msg, orderedTopic, ackC);
         else
             throw new ClusterTopologyCheckedException("Node for provided ID doesn't exist (did it leave the grid?): " + nodeId);
     }
@@ -1033,14 +1132,15 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
      * @param msg Message.
      * @param orderedTopic Topic for ordered notifications.
      *      If {@code null}, non-ordered message will be sent.
+     * @param ackC Ack closure.
      * @throws IgniteCheckedException In case of error.
      */
-    private void sendWithRetries(ClusterNode node, GridContinuousMessage msg, @Nullable Object orderedTopic)
-        throws IgniteCheckedException {
+    private void sendWithRetries(ClusterNode node, GridContinuousMessage msg, @Nullable Object orderedTopic,
+        IgniteInClosure<IgniteException> ackC) throws IgniteCheckedException {
         assert node != null;
         assert msg != null;
 
-        sendWithRetries(F.asList(node), msg, orderedTopic);
+        sendWithRetries(F.asList(node), msg, orderedTopic, ackC);
     }
 
     /**
@@ -1048,10 +1148,11 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
      * @param msg Message.
      * @param orderedTopic Topic for ordered notifications.
      *      If {@code null}, non-ordered message will be sent.
+     * @param ackC Ack closure.
      * @throws IgniteCheckedException In case of error.
      */
     private void sendWithRetries(Collection<? extends ClusterNode> nodes, GridContinuousMessage msg,
-        @Nullable Object orderedTopic) throws IgniteCheckedException {
+        @Nullable Object orderedTopic, IgniteInClosure<IgniteException> ackC) throws IgniteCheckedException {
         assert !F.isEmpty(nodes);
         assert msg != null;
 
@@ -1074,10 +1175,11 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                             msg,
                             SYSTEM_POOL,
                             0,
-                            true);
+                            true,
+                            ackC);
                     }
                     else
-                        ctx.io().send(node, TOPIC_CONTINUOUS, msg, SYSTEM_POOL);
+                        ctx.io().send(node, TOPIC_CONTINUOUS, msg, SYSTEM_POOL, ackC);
 
                     break;
                 }
@@ -1178,8 +1280,8 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
         /** Lock. */
         private final ReadWriteLock lock = new ReentrantReadWriteLock();
 
-        /** Buffer. */
-        private ConcurrentLinkedDeque8<Object> buf;
+        /** Batch. */
+        private GridContinuousBatch batch;
 
         /** Last send time. */
         private long lastSndTime = U.currentTimeMillis();
@@ -1210,7 +1312,7 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
             this.interval = interval;
             this.autoUnsubscribe = autoUnsubscribe;
 
-            buf = new ConcurrentLinkedDeque8<>();
+            batch = hnd.createBatch();
         }
 
         /**
@@ -1238,21 +1340,53 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
         }
 
         /**
+         * @param objs Objects to add.
+         * @return Batch to send.
+         */
+        GridContinuousBatch addAll(Collection<?> objs) {
+            assert objs != null;
+            assert objs.size() > 0;
+
+            GridContinuousBatch toSnd = null;
+
+            lock.writeLock().lock();
+
+            try {
+                for (Object obj : objs)
+                    batch.add(obj);
+
+                toSnd = batch;
+
+                batch = hnd.createBatch();
+
+                if (interval > 0)
+                    lastSndTime = U.currentTimeMillis();
+            }
+            finally {
+                lock.writeLock().unlock();
+            }
+
+            return toSnd;
+        }
+
+        /**
          * @param obj Object to add.
-         * @return Object to send or {@code null} if there is nothing to send for now.
+         * @return Batch to send or {@code null} if there is nothing to send for now.
          */
-        @Nullable Collection<Object> add(@Nullable Object obj) {
-            ConcurrentLinkedDeque8 buf0 = null;
+        @Nullable GridContinuousBatch add(Object obj) {
+            assert obj != null;
+
+            GridContinuousBatch toSnd = null;
 
-            if (buf.sizex() >= bufSize - 1) {
+            if (batch.size() >= bufSize - 1) {
                 lock.writeLock().lock();
 
                 try {
-                    buf.add(obj);
+                    batch.add(obj);
 
-                    buf0 = buf;
+                    toSnd = batch;
 
-                    buf = new ConcurrentLinkedDeque8<>();
+                    batch = hnd.createBatch();
 
                     if (interval > 0)
                         lastSndTime = U.currentTimeMillis();
@@ -1265,34 +1399,25 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
                 lock.readLock().lock();
 
                 try {
-                    buf.add(obj);
+                    batch.add(obj);
                 }
                 finally {
                     lock.readLock().unlock();
                 }
             }
 
-            Collection<Object> toSnd = null;
-
-            if (buf0 != null) {
-                toSnd = new ArrayList<>(buf0.sizex());
-
-                for (Object o : buf0)
-                    toSnd.add(o);
-            }
-
             return toSnd;
         }
 
         /**
-         * @return Tuple with objects to sleep (or {@code null} if there is nothing to
+         * @return Tuple with batch to send (or {@code null} if there is nothing to
          *      send for now) and time interval after next check is needed.
          */
         @SuppressWarnings("TooBroadScope")
-        IgniteBiTuple<Collection<Object>, Long> checkInterval() {
+        IgniteBiTuple<GridContinuousBatch, Long> checkInterval() {
             assert interval > 0;
 
-            Collection<Object> toSnd = null;
+            GridContinuousBatch toSnd = null;
             long diff;
 
             long now = U.currentTimeMillis();
@@ -1302,10 +1427,10 @@ public class GridContinuousProcessor extends GridProcessorAdapter {
             try {
                 diff = now - lastSndTime;
 
-                if (diff >= interval && !buf.isEmpty()) {
-                    toSnd = buf;
+                if (diff >= interval && batch.size() > 0) {
+                    toSnd = batch;
 
-                    buf = new ConcurrentLinkedDeque8<>();
+                    batch = hnd.createBatch();
 
                     lastSndTime = now;
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineAckDiscoveryMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineAckDiscoveryMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineAckDiscoveryMessage.java
index bd4aae3..9644372 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineAckDiscoveryMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineAckDiscoveryMessage.java
@@ -35,14 +35,19 @@ public class StartRoutineAckDiscoveryMessage extends AbstractContinuousMessage {
     /** */
     private final Map<UUID, IgniteCheckedException> errs;
 
+    /** */
+    private final Map<Integer, Long> updateCntrs;
+
     /**
      * @param routineId Routine id.
      * @param errs Errs.
      */
-    public StartRoutineAckDiscoveryMessage(UUID routineId, Map<UUID, IgniteCheckedException> errs) {
+    public StartRoutineAckDiscoveryMessage(UUID routineId, Map<UUID, IgniteCheckedException> errs,
+        Map<Integer, Long> cntrs) {
         super(routineId);
 
         this.errs = new HashMap<>(errs);
+        this.updateCntrs = cntrs;
     }
 
     /** {@inheritDoc} */
@@ -51,6 +56,13 @@ public class StartRoutineAckDiscoveryMessage extends AbstractContinuousMessage {
     }
 
     /**
+     * @return Update counters for partitions.
+     */
+    public Map<Integer, Long> updateCounters() {
+        return updateCntrs;
+    }
+
+    /**
      * @return Errs.
      */
     public Map<UUID, IgniteCheckedException> errs() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineDiscoveryMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineDiscoveryMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineDiscoveryMessage.java
index 892adac..82c0377 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineDiscoveryMessage.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/continuous/StartRoutineDiscoveryMessage.java
@@ -37,6 +37,9 @@ public class StartRoutineDiscoveryMessage extends AbstractContinuousMessage {
     /** */
     private final Map<UUID, IgniteCheckedException> errs = new HashMap<>();
 
+    /** */
+    private Map<Integer, Long> updateCntrs;
+
     /**
      * @param routineId Routine id.
      * @param startReqData Start request data.
@@ -63,6 +66,22 @@ public class StartRoutineDiscoveryMessage extends AbstractContinuousMessage {
     }
 
     /**
+     * @param cntrs Update counters.
+     */
+    public void addUpdateCounters(Map<Integer, Long> cntrs) {
+        if (updateCntrs == null)
+            updateCntrs = new HashMap<>();
+
+        for (Map.Entry<Integer, Long> e : cntrs.entrySet()) {
+            Long cntr0 = updateCntrs.get(e.getKey());
+            Long cntr1 = e.getValue();
+
+            if (cntr0 == null || cntr1 > cntr0)
+                updateCntrs.put(e.getKey(), cntr1);
+        }
+    }
+
+    /**
      * @return Errs.
      */
     public Map<UUID, IgniteCheckedException> errs() {
@@ -76,7 +95,7 @@ public class StartRoutineDiscoveryMessage extends AbstractContinuousMessage {
 
     /** {@inheritDoc} */
     @Override public DiscoveryCustomMessage ackMessage() {
-        return new StartRoutineAckDiscoveryMessage(routineId, errs);
+        return new StartRoutineAckDiscoveryMessage(routineId, errs, updateCntrs);
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
index b93acf5..97696bb 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheTestEntryEx.java
@@ -479,7 +479,8 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
         @Nullable GridCacheVersion drVer,
         UUID subjId,
         String taskName,
-        @Nullable GridCacheVersion dhtVer)
+        @Nullable GridCacheVersion dhtVer,
+        @Nullable Long updateCntr)
         throws IgniteCheckedException, GridCacheEntryRemovedException {
         return new GridCacheUpdateTxResult(true, rawPut(val, ttl));
     }
@@ -529,7 +530,9 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
         boolean conflictResolve,
         boolean intercept,
         UUID subjId,
-        String taskName) throws IgniteCheckedException,
+        String taskName,
+        @Nullable CacheObject prevVal,
+        @Nullable Long updateCntr) throws IgniteCheckedException,
         GridCacheEntryRemovedException {
         assert false;
 
@@ -550,7 +553,8 @@ public class GridCacheTestEntryEx extends GridMetadataAwareAdapter implements Gr
         @Nullable GridCacheVersion drVer,
         UUID subjId,
         String taskName,
-        @Nullable GridCacheVersion dhtVer
+        @Nullable GridCacheVersion dhtVer,
+        @Nullable Long updateCntr
         ) throws IgniteCheckedException, GridCacheEntryRemovedException {
         obsoleteVer = ver;
 


[30/37] ignite git commit: IGNITE-426 Implemented failover for Continuous query.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
new file mode 100644
index 0000000..b311272
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAbstractSelfTest.java
@@ -0,0 +1,2235 @@
+/*
+ * 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.query.continuous;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.cache.Cache;
+import javax.cache.CacheException;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.MutableEntry;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cache.CacheAtomicWriteOrderMode;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
+import org.apache.ignite.cache.CacheEntryProcessor;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.cluster.ClusterTopologyException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.managers.communication.GridIoMessage;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionTopology;
+import org.apache.ignite.internal.processors.continuous.GridContinuousHandler;
+import org.apache.ignite.internal.processors.continuous.GridContinuousMessage;
+import org.apache.ignite.internal.processors.continuous.GridContinuousProcessor;
+import org.apache.ignite.internal.util.GridConcurrentHashSet;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.C1;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.PA;
+import org.apache.ignite.internal.util.typedef.PAX;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.T3;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.lang.IgniteOutClosure;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.resources.LoggerResource;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+
+import static java.util.concurrent.TimeUnit.MINUTES;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public abstract class CacheContinuousQueryFailoverAbstractSelfTest extends GridCommonAbstractTest {
+    /** */
+    private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final int BACKUP_ACK_THRESHOLD = 100;
+
+    /** */
+    private static volatile boolean err;
+
+    /** */
+    private boolean client;
+
+    /** */
+    private int backups = 1;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setForceServerMode(true);
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+
+        TestCommunicationSpi commSpi = new TestCommunicationSpi();
+
+        commSpi.setSharedMemoryPort(-1);
+        commSpi.setIdleConnectionTimeout(100);
+
+        cfg.setCommunicationSpi(commSpi);
+
+        CacheConfiguration ccfg = new CacheConfiguration();
+
+        ccfg.setCacheMode(cacheMode());
+        ccfg.setAtomicityMode(atomicityMode());
+        ccfg.setAtomicWriteOrderMode(writeOrderMode());
+        ccfg.setBackups(backups);
+        ccfg.setWriteSynchronizationMode(FULL_SYNC);
+        ccfg.setNearConfiguration(nearCacheConfiguration());
+
+        cfg.setCacheConfiguration(ccfg);
+
+        cfg.setClientMode(client);
+
+        return cfg;
+    }
+
+    /**
+     * @return Near cache configuration.
+     */
+    protected NearCacheConfiguration nearCacheConfiguration() {
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long getTestTimeout() {
+        return 5 * 60_000;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        super.beforeTest();
+
+        err = false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        super.afterTest();
+
+        stopAllGrids();
+    }
+
+    /**
+     * @return Cache mode.
+     */
+    protected abstract CacheMode cacheMode();
+
+    /**
+     * @return Atomicity mode.
+     */
+    protected abstract CacheAtomicityMode atomicityMode();
+
+    /**
+     * @return Write order mode for atomic cache.
+     */
+    protected CacheAtomicWriteOrderMode writeOrderMode() {
+        return PRIMARY;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFirstFilteredEvent() throws Exception {
+        this.backups = 2;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        IgniteCache<Object, Object> qryClnCache = qryClient.cache(null);
+
+        final CacheEventListener3 lsnr = new CacheEventListener3();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        qry.setRemoteFilter(new CacheEventFilter());
+
+        try (QueryCursor<?> cur = qryClnCache.query(qry)) {
+            List<Integer> keys = testKeys(grid(0).cache(null), 1);
+
+            for (Integer key : keys)
+                qryClnCache.put(key, -1);
+
+            qryClnCache.put(keys.get(0), 100);
+        }
+
+        assertEquals(lsnr.evts.size(), 1);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRebalanceVersion() throws Exception {
+        Ignite ignite0 = startGrid(0);
+        GridDhtPartitionTopology top0 = ((IgniteKernal)ignite0).context().cache().context().cacheContext(1).topology();
+
+        assertTrue(top0.rebalanceFinished(new AffinityTopologyVersion(1)));
+        assertFalse(top0.rebalanceFinished(new AffinityTopologyVersion(2)));
+
+        Ignite ignite1 = startGrid(1);
+        GridDhtPartitionTopology top1 = ((IgniteKernal)ignite1).context().cache().context().cacheContext(1).topology();
+
+        waitRebalanceFinished(ignite0, 2);
+        waitRebalanceFinished(ignite1, 2);
+
+        assertFalse(top0.rebalanceFinished(new AffinityTopologyVersion(3)));
+        assertFalse(top1.rebalanceFinished(new AffinityTopologyVersion(3)));
+
+        Ignite ignite2 = startGrid(2);
+        GridDhtPartitionTopology top2 = ((IgniteKernal)ignite2).context().cache().context().cacheContext(1).topology();
+
+        waitRebalanceFinished(ignite0, 3);
+        waitRebalanceFinished(ignite1, 3);
+        waitRebalanceFinished(ignite2, 3);
+
+        assertFalse(top0.rebalanceFinished(new AffinityTopologyVersion(4)));
+        assertFalse(top1.rebalanceFinished(new AffinityTopologyVersion(4)));
+        assertFalse(top2.rebalanceFinished(new AffinityTopologyVersion(4)));
+
+        client = true;
+
+        Ignite ignite3 = startGrid(3);
+        GridDhtPartitionTopology top3 = ((IgniteKernal)ignite3).context().cache().context().cacheContext(1).topology();
+
+        assertTrue(top0.rebalanceFinished(new AffinityTopologyVersion(4)));
+        assertTrue(top1.rebalanceFinished(new AffinityTopologyVersion(4)));
+        assertTrue(top2.rebalanceFinished(new AffinityTopologyVersion(4)));
+        assertTrue(top3.rebalanceFinished(new AffinityTopologyVersion(4)));
+
+        stopGrid(1);
+
+        waitRebalanceFinished(ignite0, 5);
+        waitRebalanceFinished(ignite2, 5);
+        waitRebalanceFinished(ignite3, 5);
+    }
+
+    /**
+     * @param ignite Ignite.
+     * @param topVer Topology version.
+     * @throws Exception If failed.
+     */
+    private void waitRebalanceFinished(Ignite ignite, long topVer) throws Exception {
+        final AffinityTopologyVersion topVer0 = new AffinityTopologyVersion(topVer);
+
+        final GridDhtPartitionTopology top =
+            ((IgniteKernal)ignite).context().cache().context().cacheContext(1).topology();
+
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return top.rebalanceFinished(topVer0);
+            }
+        }, 5000);
+
+        assertTrue(top.rebalanceFinished(topVer0));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testOneBackup() throws Exception {
+        checkBackupQueue(1, false);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testOneBackupClientUpdate() throws Exception {
+        checkBackupQueue(1, true);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testUpdatePartitionCounter() throws Exception {
+        this.backups = 2;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        final Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        Map<Integer, Long> updateCntrs = new HashMap<>();
+
+        ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+        int killedNode = rnd.nextInt(SRV_NODES);
+
+        for (int i = 0; i < 10; i++) {
+            List<Integer> keys = testKeys(grid(0).cache(null), 10);
+
+            for (Integer key : keys) {
+                IgniteCache cache = null;
+
+                if (rnd.nextBoolean())
+                    cache = qryClient.cache(null);
+                else {
+                    for (int j = 0; j < 10; j++) {
+                        int nodeIdx = rnd.nextInt(SRV_NODES);
+
+                        if (killedNode != nodeIdx) {
+                            cache = grid(nodeIdx).cache(null);
+
+                            break;
+                        }
+                    }
+
+                    if (cache == null)
+                        throw new Exception("Failed to find a server node.");
+                }
+
+                cache.put(key, key);
+
+                int part = qryClient.affinity(null).partition(key);
+
+                Long cntr = updateCntrs.get(part);
+
+                if (cntr == null)
+                    cntr = 0L;
+
+                updateCntrs.put(part, ++cntr);
+            }
+
+            checkPartCounter(SRV_NODES, killedNode, updateCntrs);
+
+            stopGrid(killedNode);
+
+            awaitPartitionMapExchange();
+
+            checkPartCounter(SRV_NODES, killedNode, updateCntrs);
+
+            startGrid(killedNode);
+
+            awaitPartitionMapExchange();
+
+            checkPartCounter(SRV_NODES, killedNode, updateCntrs);
+
+            killedNode = rnd.nextInt(SRV_NODES);
+        }
+    }
+
+    /**
+     * @param nodes Count nodes.
+     * @param killedNodeIdx Killed node index.
+     * @param updCntrs Update counters.
+     * @return {@code True} if counters matches.
+     */
+    private boolean checkPartCounter(int nodes, int killedNodeIdx, Map<Integer, Long> updCntrs) {
+        for (int i = 0; i < nodes; i++) {
+            if (i == killedNodeIdx)
+                continue;
+
+            Affinity<Object> aff = grid(i).affinity(null);
+
+            Map<Integer, Long> act = grid(i).cachex(null).context().topology().updateCounters();
+
+            for (Map.Entry<Integer, Long> e : updCntrs.entrySet()) {
+                if (aff.mapPartitionToPrimaryAndBackups(e.getKey()).contains(grid(i).localNode()))
+                    assertEquals(e.getValue(), act.get(e.getKey()));
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testStartStopQuery() throws Exception {
+        this.backups = 1;
+
+        final int SRV_NODES = 3;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        final Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        IgniteCache<Object, Object> clnCache = qryClient.cache(null);
+
+        IgniteOutClosure<IgniteCache<Integer, Integer>> rndCache =
+            new IgniteOutClosure<IgniteCache<Integer, Integer>>() {
+                int cnt = 0;
+
+                @Override public IgniteCache<Integer, Integer> apply() {
+                    ++cnt;
+
+                    return grid(cnt % SRV_NODES + 1).cache(null);
+                }
+            };
+
+        Ignite igniteSrv = ignite(0);
+
+        IgniteCache<Object, Object> srvCache = igniteSrv.cache(null);
+
+        List<Integer> keys = testKeys(srvCache, 3);
+
+        int keyCnt = keys.size();
+
+        for (int j = 0; j < 50; ++j) {
+            ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+            final CacheEventListener3 lsnr = new CacheEventListener3();
+
+            qry.setLocalListener(lsnr);
+
+            qry.setRemoteFilter(lsnr);
+
+            int keyIter = 0;
+
+            for (; keyIter < keyCnt / 2; keyIter++) {
+                int key = keys.get(keyIter);
+
+                rndCache.apply().put(key, key);
+            }
+
+            assert lsnr.evts.isEmpty();
+
+            QueryCursor<Cache.Entry<Object, Object>> query = clnCache.query(qry);
+
+            Map<Object, T2<Object, Object>> updates = new HashMap<>();
+
+            final List<T3<Object, Object, Object>> expEvts = new ArrayList<>();
+
+            Affinity<Object> aff = affinity(srvCache);
+
+            boolean filtered = false;
+
+            for (; keyIter < keys.size(); keyIter++) {
+                int key = keys.get(keyIter);
+
+                int val = filtered ? 1 : 2;
+
+                log.info("Put [key=" + key + ", val=" + val + ", part=" + aff.partition(key) + ']');
+
+                T2<Object, Object> t = updates.get(key);
+
+                if (t == null) {
+                    // Check filtered.
+                    if (!filtered) {
+                        updates.put(key, new T2<>((Object)val, null));
+
+                        expEvts.add(new T3<>((Object)key, (Object)val, null));
+                    }
+                }
+                else {
+                    // Check filtered.
+                    if (!filtered) {
+                        updates.put(key, new T2<>((Object)val, (Object)t.get1()));
+
+                        expEvts.add(new T3<>((Object)key, (Object)val, (Object)t.get1()));
+                    }
+                }
+
+                rndCache.apply().put(key, val);
+
+                filtered = !filtered;
+            }
+
+            checkEvents(expEvts, lsnr, false);
+
+            query.close();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testLeftPrimaryAndBackupNodes() throws Exception {
+        if (cacheMode() == REPLICATED)
+            return;
+
+        this.backups = 1;
+
+        final int SRV_NODES = 3;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        final Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        final CacheEventListener3 lsnr = new CacheEventListener3();
+
+        qry.setLocalListener(lsnr);
+
+        qry.setRemoteFilter(lsnr);
+
+        IgniteCache<Object, Object> clnCache = qryClient.cache(null);
+
+        QueryCursor<Cache.Entry<Object, Object>> query = clnCache.query(qry);
+
+        Ignite igniteSrv = ignite(0);
+
+        IgniteCache<Object, Object> srvCache = igniteSrv.cache(null);
+
+        Affinity<Object> aff = affinity(srvCache);
+
+        List<Integer> keys = testKeys(srvCache, 1);
+
+        Collection<ClusterNode> nodes = aff.mapPartitionToPrimaryAndBackups(keys.get(0));
+
+        Collection<UUID> ids = F.transform(nodes, new C1<ClusterNode, UUID>() {
+            @Override public UUID apply(ClusterNode node) {
+                return node.id();
+            }
+        });
+
+        int keyIter = 0;
+
+        boolean filtered = false;
+
+        Map<Object, T2<Object, Object>> updates = new HashMap<>();
+
+        final List<T3<Object, Object, Object>> expEvts = new ArrayList<>();
+
+        for (; keyIter < keys.size() / 2; keyIter++) {
+            int key = keys.get(keyIter);
+
+            log.info("Put [key=" + key + ", part=" + aff.partition(key)
+                + ", filtered=" + filtered + ']');
+
+            T2<Object, Object> t = updates.get(key);
+
+            Integer val = filtered ?
+                (key % 2 == 0 ? key + 1 : key) :
+                key * 2;
+
+            if (t == null) {
+                updates.put(key, new T2<>((Object)val, null));
+
+                if (!filtered)
+                    expEvts.add(new T3<>((Object)key, (Object)val, null));
+            }
+            else {
+                updates.put(key, new T2<>((Object)val, (Object)key));
+
+                if (!filtered)
+                    expEvts.add(new T3<>((Object)key, (Object)val, (Object)key));
+            }
+
+            srvCache.put(key, val);
+
+            filtered = !filtered;
+        }
+
+        checkEvents(expEvts, lsnr, false);
+
+        List<Thread> stopThreads = new ArrayList<>(3);
+
+        // Stop nodes which owning this partition.
+        for (int i = 0; i < SRV_NODES; i++) {
+            Ignite ignite = ignite(i);
+
+            if (ids.contains(ignite.cluster().localNode().id())) {
+                final int i0 = i;
+
+                TestCommunicationSpi spi = (TestCommunicationSpi)ignite.configuration().getCommunicationSpi();
+
+                spi.skipAllMsg = true;
+
+                stopThreads.add(new Thread() {
+                    @Override public void run() {
+                        stopGrid(i0, true);
+                    }
+                });
+            }
+        }
+
+        // Stop and join threads.
+        for (Thread t : stopThreads)
+            t.start();
+
+        for (Thread t : stopThreads)
+            t.join();
+
+        assert GridTestUtils.waitForCondition(new PA() {
+            @Override public boolean apply() {
+                // (SRV_NODES + 1 client node) - 1 primary - backup nodes.
+                return qryClient.cluster().nodes().size() == (SRV_NODES + 1 /** client node */)
+                    - 1 /** Primary node */ - backups;
+            }
+        }, 5000L);
+
+        for (; keyIter < keys.size(); keyIter++) {
+            int key = keys.get(keyIter);
+
+            log.info("Put [key=" + key + ", filtered=" + filtered + ']');
+
+            T2<Object, Object> t = updates.get(key);
+
+            Integer val = filtered ?
+                (key % 2 == 0 ? key + 1 : key) :
+                key * 2;
+
+            if (t == null) {
+                updates.put(key, new T2<>((Object)val, null));
+
+                if (!filtered)
+                    expEvts.add(new T3<>((Object)key, (Object)val, null));
+            }
+            else {
+                updates.put(key, new T2<>((Object)val, (Object)key));
+
+                if (!filtered)
+                    expEvts.add(new T3<>((Object)key, (Object)val, (Object)key));
+            }
+
+            clnCache.put(key, val);
+
+            filtered = !filtered;
+        }
+
+        checkEvents(expEvts, lsnr, false);
+
+        query.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testRemoteFilter() throws Exception {
+        this.backups = 2;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        IgniteCache<Object, Object> qryClientCache = qryClient.cache(null);
+
+        if (cacheMode() != REPLICATED)
+            assertEquals(backups, qryClientCache.getConfiguration(CacheConfiguration.class).getBackups());
+
+        Affinity<Object> aff = qryClient.affinity(null);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        final CacheEventListener3 lsnr = new CacheEventListener3();
+
+        qry.setLocalListener(lsnr);
+
+        qry.setRemoteFilter(lsnr);
+
+        int PARTS = 10;
+
+        QueryCursor<?> cur = qryClientCache.query(qry);
+
+        Map<Object, T2<Object, Object>> updates = new HashMap<>();
+
+        final List<T3<Object, Object, Object>> expEvts = new ArrayList<>();
+
+        for (int i = 0; i < (atomicityMode() == CacheAtomicityMode.ATOMIC ? SRV_NODES - 1 : SRV_NODES - 2); i++) {
+            log.info("Stop iteration: " + i);
+
+            TestCommunicationSpi spi = (TestCommunicationSpi)ignite(i).configuration().getCommunicationSpi();
+
+            Ignite ignite = ignite(i);
+
+            IgniteCache<Object, Object> cache = ignite.cache(null);
+
+            List<Integer> keys = testKeys(cache, PARTS);
+
+            boolean first = true;
+
+            boolean filtered = false;
+
+            for (Integer key : keys) {
+                log.info("Put [node=" + ignite.name() + ", key=" + key + ", part=" + aff.partition(key)
+                    + ", filtered=" + filtered + ']');
+
+                T2<Object, Object> t = updates.get(key);
+
+                Integer val = filtered ?
+                    (key % 2 == 0 ? key + 1 : key) :
+                    key * 2;
+
+                if (t == null) {
+                    updates.put(key, new T2<>((Object)val, null));
+
+                    if (!filtered)
+                        expEvts.add(new T3<>((Object)key, (Object)val, null));
+                }
+                else {
+                    updates.put(key, new T2<>((Object)val, (Object)key));
+
+                    if (!filtered)
+                        expEvts.add(new T3<>((Object)key, (Object)val, (Object)key));
+                }
+
+                cache.put(key, val);
+
+                if (first) {
+                    spi.skipMsg = true;
+
+                    first = false;
+                }
+
+                filtered = !filtered;
+            }
+
+            stopGrid(i);
+
+            boolean check = GridTestUtils.waitForCondition(new PAX() {
+                @Override public boolean applyx() throws IgniteCheckedException {
+                    return expEvts.size() == lsnr.keys.size();
+                }
+            }, 5000L);
+
+            if (!check) {
+                Set<Integer> keys0 = new HashSet<>(keys);
+
+                keys0.removeAll(lsnr.keys);
+
+                log.info("Missed events for keys: " + keys0);
+
+                fail("Failed to wait for notifications [exp=" + keys.size() + ", left=" + keys0.size() + ']');
+            }
+
+            checkEvents(expEvts, lsnr, false);
+        }
+
+        cur.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testThreeBackups() throws Exception {
+        if (cacheMode() == REPLICATED)
+            return;
+
+        checkBackupQueue(3, false);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDebug() {
+        return true;
+    }
+
+    /**
+     * @param backups Number of backups.
+     * @param updateFromClient If {@code true} executes cache update from client node.
+     * @throws Exception If failed.
+     */
+    private void checkBackupQueue(int backups, boolean updateFromClient) throws Exception {
+        this.backups = atomicityMode() == CacheAtomicityMode.ATOMIC ? backups :
+            backups < 2 ? 2 : backups;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        IgniteCache<Object, Object> qryClientCache = qryClient.cache(null);
+
+        Affinity<Object> aff = qryClient.affinity(null);
+
+        CacheEventListener1 lsnr = new CacheEventListener1(false);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        QueryCursor<?> cur = qryClientCache.query(qry);
+
+        int PARTS = 10;
+
+        Map<Object, T2<Object, Object>> updates = new HashMap<>();
+
+        List<T3<Object, Object, Object>> expEvts = new ArrayList<>();
+
+        for (int i = 0; i < (atomicityMode() == CacheAtomicityMode.ATOMIC ? SRV_NODES - 1 : SRV_NODES - 2); i++) {
+            log.info("Stop iteration: " + i);
+
+            TestCommunicationSpi spi = (TestCommunicationSpi)ignite(i).configuration().getCommunicationSpi();
+
+            Ignite ignite = ignite(i);
+
+            IgniteCache<Object, Object> cache = ignite.cache(null);
+
+            List<Integer> keys = testKeys(cache, PARTS);
+
+            CountDownLatch latch = new CountDownLatch(keys.size());
+
+            lsnr.latch = latch;
+
+            boolean first = true;
+
+            for (Integer key : keys) {
+                log.info("Put [node=" + ignite.name() + ", key=" + key + ", part=" + aff.partition(key) + ']');
+
+                T2<Object, Object> t = updates.get(key);
+
+                if (updateFromClient) {
+                    if (atomicityMode() == CacheAtomicityMode.TRANSACTIONAL) {
+                        try (Transaction tx = qryClient.transactions().txStart()) {
+                            qryClientCache.put(key, key);
+
+                            tx.commit();
+                        }
+                        catch (CacheException | ClusterTopologyException e) {
+                            log.warning("Failed put. [Key=" + key + ", val=" + key + "]");
+
+                            continue;
+                        }
+                    }
+                    else
+                        qryClientCache.put(key, key);
+                }
+                else {
+                    if (atomicityMode() == CacheAtomicityMode.TRANSACTIONAL) {
+                        try (Transaction tx = ignite.transactions().txStart()) {
+                            cache.put(key, key);
+
+                            tx.commit();
+                        }
+                        catch (CacheException | ClusterTopologyException e) {
+                            log.warning("Failed put. [Key=" + key + ", val=" + key + "]");
+
+                            continue;
+                        }
+                    }
+                    else
+                        cache.put(key, key);
+                }
+
+                if (t == null) {
+                    updates.put(key, new T2<>((Object)key, null));
+
+                    expEvts.add(new T3<>((Object)key, (Object)key, null));
+                }
+                else {
+                    updates.put(key, new T2<>((Object)key, (Object)key));
+
+                    expEvts.add(new T3<>((Object)key, (Object)key, (Object)key));
+                }
+
+                if (first) {
+                    spi.skipMsg = true;
+
+                    first = false;
+                }
+            }
+
+            stopGrid(i);
+
+            if (!latch.await(5, SECONDS)) {
+                Set<Integer> keys0 = new HashSet<>(keys);
+
+                keys0.removeAll(lsnr.keys);
+
+                log.info("Missed events for keys: " + keys0);
+
+                fail("Failed to wait for notifications [exp=" + keys.size() + ", left=" + lsnr.latch.getCount() + ']');
+            }
+
+            checkEvents(expEvts, lsnr);
+        }
+
+        for (int i = 0; i < (atomicityMode() == CacheAtomicityMode.ATOMIC ? SRV_NODES - 1 : SRV_NODES - 2); i++) {
+            log.info("Start iteration: " + i);
+
+            Ignite ignite = startGrid(i);
+
+            IgniteCache<Object, Object> cache = ignite.cache(null);
+
+            List<Integer> keys = testKeys(cache, PARTS);
+
+            CountDownLatch latch = new CountDownLatch(keys.size());
+
+            lsnr.latch = latch;
+
+            for (Integer key : keys) {
+                log.info("Put [node=" + ignite.name() + ", key=" + key + ", part=" + aff.partition(key) + ']');
+
+                T2<Object, Object> t = updates.get(key);
+
+                if (t == null) {
+                    updates.put(key, new T2<>((Object)key, null));
+
+                    expEvts.add(new T3<>((Object)key, (Object)key, null));
+                }
+                else {
+                    updates.put(key, new T2<>((Object)key, (Object)key));
+
+                    expEvts.add(new T3<>((Object)key, (Object)key, (Object)key));
+                }
+
+                if (updateFromClient)
+                    qryClientCache.put(key, key);
+                else
+                    cache.put(key, key);
+            }
+
+            if (!latch.await(10, SECONDS)) {
+                Set<Integer> keys0 = new HashSet<>(keys);
+
+                keys0.removeAll(lsnr.keys);
+
+                log.info("Missed events for keys: " + keys0);
+
+                fail("Failed to wait for notifications [exp=" + keys.size() + ", left=" + lsnr.latch.getCount() + ']');
+            }
+
+            checkEvents(expEvts, lsnr);
+        }
+
+        cur.close();
+
+        assertFalse("Unexpected error during test, see log for details.", err);
+    }
+
+    /**
+     * @param expEvts Expected events.
+     * @param lsnr Listener.
+     */
+    private void checkEvents(List<T3<Object, Object, Object>> expEvts, CacheEventListener1 lsnr) {
+        for (T3<Object, Object, Object> exp : expEvts) {
+            CacheEntryEvent<?, ?> e = lsnr.evts.get(exp.get1());
+
+            assertNotNull("No event for key: " + exp.get1(), e);
+            assertEquals("Unexpected value: " + e, exp.get2(), e.getValue());
+        }
+
+        expEvts.clear();
+
+        lsnr.evts.clear();
+    }
+
+    /**
+     * @param expEvts Expected events.
+     * @param lsnr Listener.
+     * @param lostAllow If {@code true} than won't assert on lost events.
+     */
+    private void checkEvents(final List<T3<Object, Object, Object>> expEvts, final CacheEventListener2 lsnr,
+        boolean lostAllow) throws Exception {
+        checkEvents(expEvts, lsnr, lostAllow, true);
+    }
+
+    /**
+     * @param expEvts Expected events.
+     * @param lsnr Listener.
+     * @param lostAllow If {@code true} than won't assert on lost events.
+     */
+    private void checkEvents(final List<T3<Object, Object, Object>> expEvts, final CacheEventListener2 lsnr,
+        boolean lostAllow, boolean wait) throws Exception {
+        if (wait)
+            GridTestUtils.waitForCondition(new PA() {
+                @Override public boolean apply() {
+                    return expEvts.size() == lsnr.size();
+                }
+            }, 2000L);
+
+        Map<Integer, List<CacheEntryEvent<?, ?>>> prevMap = new HashMap<>(lsnr.evts.size());
+
+        for (Map.Entry<Integer, List<CacheEntryEvent<?, ?>>> e : lsnr.evts.entrySet())
+            prevMap.put(e.getKey(), new ArrayList<>(e.getValue()));
+
+        List<T3<Object, Object, Object>> lostEvents = new ArrayList<>();
+
+        for (T3<Object, Object, Object> exp : expEvts) {
+            List<CacheEntryEvent<?, ?>> rcvdEvts = lsnr.evts.get(exp.get1());
+
+            if (F.eq(exp.get2(), exp.get3()))
+                continue;
+
+            if (rcvdEvts == null || rcvdEvts.isEmpty()) {
+                lostEvents.add(exp);
+
+                continue;
+            }
+
+            Iterator<CacheEntryEvent<?, ?>> iter = rcvdEvts.iterator();
+
+            boolean found = false;
+
+            while (iter.hasNext()) {
+                CacheEntryEvent<?, ?> e = iter.next();
+
+                if ((exp.get2() != null && e.getValue() != null && exp.get2().equals(e.getValue()))
+                    && equalOldValue(e, exp)) {
+                    found = true;
+
+                    iter.remove();
+
+                    break;
+                }
+            }
+
+            // Lost event is acceptable.
+            if (!found)
+                lostEvents.add(exp);
+        }
+
+        boolean dup = false;
+
+        // Check duplicate.
+        if (!lsnr.evts.isEmpty()) {
+            for (List<CacheEntryEvent<?, ?>> evts : lsnr.evts.values()) {
+                if (!evts.isEmpty()) {
+                    for (CacheEntryEvent<?, ?> e : evts) {
+                        boolean found = false;
+
+                        for (T3<Object, Object, Object> lostEvt : lostEvents) {
+                            if (e.getKey().equals(lostEvt.get1()) && e.getValue().equals(lostEvt.get2())) {
+                                found = true;
+
+                                lostEvents.remove(lostEvt);
+
+                                break;
+                            }
+                        }
+
+                        if (!found) {
+                            dup = true;
+
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (dup) {
+                for (List<CacheEntryEvent<?, ?>> e : lsnr.evts.values()) {
+                    if (!e.isEmpty()) {
+                        for (CacheEntryEvent<?, ?> event : e)
+                            log.error("Got duplicate event: " + event);
+                    }
+                }
+            }
+        }
+
+        if (!lostAllow && lostEvents.size() > 100) {
+            log.error("Lost event cnt: " + lostEvents.size());
+
+            for (T3<Object, Object, Object> e : lostEvents)
+                log.error("Lost event: " + e);
+
+            fail("Lose events, see log for details.");
+        }
+
+        log.error("Lost event cnt: " + lostEvents.size());
+
+        expEvts.clear();
+
+        lsnr.evts.clear();
+        lsnr.vals.clear();
+    }
+
+    /**
+     * @param e Event
+     * @param expVals expected value
+     * @return {@code True} if entries has the same key, value and oldValue. If cache start without backups
+     *          than oldValue ignoring in comparison.
+     */
+    private boolean equalOldValue(CacheEntryEvent<?, ?> e, T3<Object, Object, Object> expVals) {
+        return (e.getOldValue() == null && expVals.get3() == null) // Both null
+            || (e.getOldValue() != null && expVals.get3() != null  // Equals
+                && e.getOldValue().equals(expVals.get3()))
+            || (backups == 0); // If we start without backup than oldValue might be lose.
+    }
+
+    /**
+     * @param expEvts Expected events.
+     * @param lsnr Listener.
+     */
+    private void checkEvents(final List<T3<Object, Object, Object>> expEvts, final CacheEventListener3 lsnr,
+        boolean allowLoseEvent) throws Exception {
+        if (!allowLoseEvent)
+            assert GridTestUtils.waitForCondition(new PA() {
+                @Override public boolean apply() {
+                    return lsnr.evts.size() == expEvts.size();
+                }
+            }, 2000L);
+
+        for (T3<Object, Object, Object> exp : expEvts) {
+            CacheEntryEvent<?, ?> e = lsnr.evts.get(exp.get1());
+
+            assertNotNull("No event for key: " + exp.get1(), e);
+            assertEquals("Unexpected value: " + e, exp.get2(), e.getValue());
+
+            if (allowLoseEvent)
+                lsnr.evts.remove(exp.get1());
+        }
+
+        if (allowLoseEvent)
+            assert lsnr.evts.isEmpty();
+
+        expEvts.clear();
+
+        lsnr.evts.clear();
+        lsnr.keys.clear();
+    }
+
+    /**
+     * @param cache Cache.
+     * @param parts Number of partitions.
+     * @return Keys.
+     */
+    private List<Integer> testKeys(IgniteCache<Object, Object> cache, int parts) {
+        Ignite ignite = cache.unwrap(Ignite.class);
+
+        List<Integer> res = new ArrayList<>();
+
+        Affinity<Object> aff = ignite.affinity(cache.getName());
+
+        ClusterNode node = ignite.cluster().localNode();
+
+        int[] nodeParts = aff.primaryPartitions(node);
+
+        final int KEYS_PER_PART = 50;
+
+        for (int i = 0; i < parts; i++) {
+            int part = nodeParts[i];
+
+            int cnt = 0;
+
+            for (int key = 0; key < 100_000; key++) {
+                if (aff.partition(key) == part && aff.isPrimary(node, key)) {
+                    res.add(key);
+
+                    if (++cnt == KEYS_PER_PART)
+                        break;
+                }
+            }
+
+            assertEquals(KEYS_PER_PART, cnt);
+        }
+
+        assertEquals(parts * KEYS_PER_PART, res.size());
+
+        return res;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBackupQueueCleanupClientQuery() throws Exception {
+        startGridsMultiThreaded(2);
+
+        client = true;
+
+        Ignite qryClient = startGrid(2);
+
+        CacheEventListener1 lsnr = new CacheEventListener1(false);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        QueryCursor<?> cur = qryClient.cache(null).query(qry);
+
+        final Collection<Object> backupQueue = backupQueue(ignite(1));
+
+        assertEquals(0, backupQueue.size());
+
+        IgniteCache<Object, Object> cache0 = ignite(0).cache(null);
+
+        List<Integer> keys = primaryKeys(cache0, BACKUP_ACK_THRESHOLD);
+
+        CountDownLatch latch = new CountDownLatch(keys.size());
+
+        lsnr.latch = latch;
+
+        for (Integer key : keys) {
+            log.info("Put: " + key);
+
+            cache0.put(key, key);
+        }
+
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return backupQueue.isEmpty();
+            }
+        }, 2000);
+
+        assertTrue("Backup queue is not cleared: " + backupQueue, backupQueue.size() < BACKUP_ACK_THRESHOLD);
+
+        if (!latch.await(5, SECONDS))
+            fail("Failed to wait for notifications [exp=" + keys.size() + ", left=" + lsnr.latch.getCount() + ']');
+
+        keys = primaryKeys(cache0, BACKUP_ACK_THRESHOLD / 2);
+
+        latch = new CountDownLatch(keys.size());
+
+        lsnr.latch = latch;
+
+        for (Integer key : keys)
+            cache0.put(key, key);
+
+        final long ACK_FREQ = 5000;
+
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return backupQueue.isEmpty();
+            }
+        }, ACK_FREQ + 2000);
+
+        assertTrue("Backup queue is not cleared: " + backupQueue, backupQueue.isEmpty());
+
+        if (!latch.await(5, SECONDS))
+            fail("Failed to wait for notifications [exp=" + keys.size() + ", left=" + lsnr.latch.getCount() + ']');
+
+        cur.close();
+
+        assertFalse("Unexpected error during test, see log for details.", err);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBackupQueueCleanupServerQuery() throws Exception {
+        Ignite qryClient = startGridsMultiThreaded(2);
+
+        CacheEventListener1 lsnr = new CacheEventListener1(false);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        IgniteCache<Object, Object> cache = qryClient.cache(null);
+
+        QueryCursor<?> cur = cache.query(qry);
+
+        final Collection<Object> backupQueue = backupQueue(ignite(1));
+
+        assertEquals(0, backupQueue.size());
+
+        List<Integer> keys = primaryKeys(cache, BACKUP_ACK_THRESHOLD);
+
+        CountDownLatch latch = new CountDownLatch(keys.size());
+
+        lsnr.latch = latch;
+
+        for (Integer key : keys) {
+            log.info("Put: " + key);
+
+            cache.put(key, key);
+        }
+
+        GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return backupQueue.isEmpty();
+            }
+        }, 3000);
+
+        assertTrue("Backup queue is not cleared: " + backupQueue, backupQueue.size() < BACKUP_ACK_THRESHOLD);
+
+        if (!latch.await(5, SECONDS))
+            fail("Failed to wait for notifications [exp=" + keys.size() + ", left=" + lsnr.latch.getCount() + ']');
+
+        cur.close();
+    }
+
+    /**
+     * @param ignite Ignite.
+     * @return Backup queue for test query.
+     */
+    private Collection<Object> backupQueue(Ignite ignite) {
+        GridContinuousProcessor proc = ((IgniteKernal)ignite).context().continuous();
+
+        ConcurrentMap<Object, Object> infos = GridTestUtils.getFieldValue(proc, "rmtInfos");
+
+        Collection<Object> backupQueue = null;
+
+        for (Object info : infos.values()) {
+            GridContinuousHandler hnd = GridTestUtils.getFieldValue(info, "hnd");
+
+            if (hnd.isForQuery() && hnd.cacheName() == null) {
+                backupQueue = GridTestUtils.getFieldValue(hnd, "backupQueue");
+
+                break;
+            }
+        }
+
+        assertNotNull(backupQueue);
+
+        return backupQueue;
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFailoverStartStopBackup() throws Exception {
+        failoverStartStopFilter(2);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testStartStop() throws Exception {
+        this.backups = 2;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        IgniteCache<Object, Object> qryClnCache = qryClient.cache(null);
+
+        Affinity<Object> aff = qryClient.affinity(null);
+
+        final CacheEventListener2 lsnr = new CacheEventListener2();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        qry.setRemoteFilter(new CacheEventFilter());
+
+        QueryCursor<?> cur = qryClnCache.query(qry);
+
+        for (int i = 0; i < 10; i++) {
+            final int idx = i % (SRV_NODES - 1);
+
+            log.info("Stop node: " + idx);
+
+            stopGrid(idx);
+
+            awaitPartitionMapExchange();
+
+            List<T3<Object, Object, Object>> afterRestEvents = new ArrayList<>();
+
+            for (int j = 0; j < aff.partitions(); j++) {
+                Integer oldVal = (Integer)qryClnCache.get(j);
+
+                qryClnCache.put(j, i);
+
+                afterRestEvents.add(new T3<>((Object)j, (Object)i, (Object)oldVal));
+            }
+
+            checkEvents(new ArrayList<>(afterRestEvents), lsnr, false);
+
+            log.info("Start node: " + idx);
+
+            startGrid(idx);
+        }
+
+        cur.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void failoverStartStopFilter(int backups) throws Exception {
+        this.backups = backups;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        Ignite qryClient = startGrid(SRV_NODES);
+
+        client = false;
+
+        IgniteCache<Object, Object> qryClnCache = qryClient.cache(null);
+
+        final CacheEventListener2 lsnr = new CacheEventListener2();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        qry.setRemoteFilter(new CacheEventFilter());
+
+        QueryCursor<?> cur = qryClnCache.query(qry);
+
+        CacheEventListener2 dinLsnr = null;
+
+        QueryCursor<?> dinQry = null;
+
+        final AtomicBoolean stop = new AtomicBoolean();
+
+        final AtomicReference<CountDownLatch> checkLatch = new AtomicReference<>();
+
+        IgniteInternalFuture<?> restartFut = GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                while (!stop.get() && !err) {
+                    final int idx = ThreadLocalRandom.current().nextInt(SRV_NODES - 1);
+
+                    log.info("Stop node: " + idx);
+
+                    awaitPartitionMapExchange();
+
+                    Thread.sleep(400);
+
+                    stopGrid(idx);
+
+                    awaitPartitionMapExchange();
+
+                    Thread.sleep(400);
+
+                    log.info("Start node: " + idx);
+
+                    startGrid(idx);
+
+                    Thread.sleep(200);
+
+                    CountDownLatch latch = new CountDownLatch(1);
+
+                    assertTrue(checkLatch.compareAndSet(null, latch));
+
+                    if (!stop.get()) {
+                        log.info("Wait for event check.");
+
+                        assertTrue(latch.await(1, MINUTES));
+                    }
+                }
+
+                return null;
+            }
+        });
+
+        final Map<Integer, Integer> vals = new HashMap<>();
+
+        final Map<Integer, List<T2<Integer, Integer>>> expEvts = new HashMap<>();
+
+        final List<T3<Object, Object, Object>> expEvtsNewLsnr = new ArrayList<>();
+
+        final List<T3<Object, Object, Object>> expEvtsLsnr = new ArrayList<>();
+
+        try {
+            long stopTime = System.currentTimeMillis() + 60_000;
+
+            // Start new filter each 5 sec.
+            long startFilterTime = System.currentTimeMillis() + 5_000;
+
+            final int PARTS = qryClient.affinity(null).partitions();
+
+            ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+            boolean filtered = false;
+
+            boolean processorPut = false;
+
+            while (System.currentTimeMillis() < stopTime) {
+                Integer key = rnd.nextInt(PARTS);
+
+                Integer prevVal = vals.get(key);
+                Integer val = vals.get(key);
+
+                if (System.currentTimeMillis() > startFilterTime) {
+                    // Stop filter and check events.
+                    if (dinQry != null) {
+                        dinQry.close();
+
+                        log.info("Continuous query listener closed. Await events: " + expEvtsNewLsnr.size());
+
+                        checkEvents(expEvtsNewLsnr, dinLsnr, backups == 0);
+                    }
+
+                    dinLsnr = new CacheEventListener2();
+
+                    ContinuousQuery<Object, Object> newQry = new ContinuousQuery<>();
+
+                    newQry.setLocalListener(dinLsnr);
+
+                    newQry.setRemoteFilter(new CacheEventFilter());
+
+                    dinQry = qryClnCache.query(newQry);
+
+                    log.info("Continuous query listener started.");
+
+                    startFilterTime = System.currentTimeMillis() + 5_000;
+                }
+
+                if (val == null)
+                    val = 0;
+                else
+                    val = Math.abs(val) + 1;
+
+                if (filtered)
+                    val = -val;
+
+                if (processorPut && prevVal != null) {
+                    qryClnCache.invoke(key, new CacheEntryProcessor<Object, Object, Void>() {
+                        @Override public Void process(MutableEntry<Object, Object> entry,
+                            Object... arguments) throws EntryProcessorException {
+                            entry.setValue(arguments[0]);
+
+                            return null;
+                        }
+                    }, val);
+                }
+                else
+                    qryClnCache.put(key, val);
+
+                processorPut = !processorPut;
+
+                vals.put(key, val);
+
+                if (val >= 0) {
+                    List<T2<Integer, Integer>> keyEvts = expEvts.get(key);
+
+                    if (keyEvts == null) {
+                        keyEvts = new ArrayList<>();
+
+                        expEvts.put(key, keyEvts);
+                    }
+
+                    keyEvts.add(new T2<>(val, prevVal));
+
+                    T3<Object, Object, Object> tupVal = new T3<>((Object)key, (Object)val, (Object)prevVal);
+
+                    expEvtsLsnr.add(tupVal);
+
+                    if (dinQry != null)
+                        expEvtsNewLsnr.add(tupVal);
+                }
+
+                filtered = !filtered;
+
+                CountDownLatch latch = checkLatch.get();
+
+                if (latch != null) {
+                    log.info("Check events.");
+
+                    checkLatch.set(null);
+
+                    boolean success = false;
+
+                    try {
+                        if (err)
+                            break;
+
+                        checkEvents(expEvtsLsnr, lsnr, backups == 0);
+
+                        success = true;
+
+                        log.info("Events checked.");
+                    }
+                    finally {
+                        if (!success)
+                            err = true;
+
+                        latch.countDown();
+                    }
+                }
+            }
+        }
+        finally {
+            stop.set(true);
+        }
+
+        CountDownLatch latch = checkLatch.get();
+
+        if (latch != null)
+            latch.countDown();
+
+        restartFut.get();
+
+        checkEvents(expEvtsLsnr, lsnr, backups == 0);
+
+        lsnr.evts.clear();
+        lsnr.vals.clear();
+
+        if (dinQry != null) {
+            checkEvents(expEvtsNewLsnr, dinLsnr, backups == 0);
+
+            dinLsnr.evts.clear();
+            dinLsnr.vals.clear();
+        }
+
+        List<T3<Object, Object, Object>> afterRestEvents = new ArrayList<>();
+
+        for (int i = 0; i < qryClient.affinity(null).partitions(); i++) {
+            Integer oldVal = (Integer)qryClnCache.get(i);
+
+            qryClnCache.put(i, i);
+
+            afterRestEvents.add(new T3<>((Object)i, (Object)i, (Object)oldVal));
+        }
+
+        checkEvents(new ArrayList<>(afterRestEvents), lsnr, false);
+
+        cur.close();
+
+        if (dinQry != null) {
+            checkEvents(new ArrayList<>(afterRestEvents), dinLsnr, false);
+
+            dinQry.close();
+        }
+
+        assertFalse("Unexpected error during test, see log for details.", err);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMultiThreadedFailover() throws Exception {
+        this.backups = 2;
+
+        final int SRV_NODES = 4;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        final Ignite qryCln = startGrid(SRV_NODES);
+
+        client = false;
+
+        final IgniteCache<Object, Object> qryClnCache = qryCln.cache(null);
+
+        final CacheEventListener2 lsnr = new CacheEventListener2();
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        QueryCursor<?> cur = qryClnCache.query(qry);
+
+        final AtomicBoolean stop = new AtomicBoolean();
+
+        final int THREAD = 4;
+
+        final int PARTS = THREAD;
+
+        final List<List<T3<Object, Object, Object>>> expEvts = new ArrayList<>(THREAD + 5);
+
+        for (int i = 0; i < THREAD; i++)
+            expEvts.add(i, new ArrayList<T3<Object, Object, Object>>());
+
+        final AtomicReference<CyclicBarrier> checkBarrier = new AtomicReference<>();
+
+        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+        IgniteInternalFuture<?> restartFut = GridTestUtils.runAsync(new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                while (!stop.get() && !err) {
+                    final int idx = rnd.nextInt(SRV_NODES);
+
+                    log.info("Stop node: " + idx);
+
+                    stopGrid(idx);
+
+                    Thread.sleep(300);
+
+                    GridTestUtils.waitForCondition(new PA() {
+                        @Override public boolean apply() {
+                            return qryCln.cluster().nodes().size() == SRV_NODES;
+                        }
+                    }, 5000L);
+
+                    try {
+                        log.info("Start node: " + idx);
+
+                        startGrid(idx);
+
+                        Thread.sleep(300);
+
+                        GridTestUtils.waitForCondition(new PA() {
+                            @Override public boolean apply() {
+                                return qryCln.cluster().nodes().size() == SRV_NODES + 1;
+                            }
+                        }, 5000L);
+                    }
+                    catch (Exception e) {
+                        log.warning("Failed to stop nodes.", e);
+                    }
+
+                    CyclicBarrier bar = new CyclicBarrier(THREAD + 1 /* plus start/stop thread */, new Runnable() {
+                        @Override public void run() {
+                            try {
+                                int size0 = 0;
+
+                                for (List<T3<Object, Object, Object>> evt : expEvts)
+                                    size0 += evt.size();
+
+                                final int size = size0;
+
+                                GridTestUtils.waitForCondition(new PA() {
+                                    @Override public boolean apply() {
+                                        return lsnr.size() <= size;
+                                    }
+                                }, 2000L);
+
+                                List<T3<Object, Object, Object>> expEvts0 = new ArrayList<>();
+
+                                for (List<T3<Object, Object, Object>> evt : expEvts)
+                                    expEvts0.addAll(evt);
+
+                                checkEvents(expEvts0, lsnr, false, false);
+
+                                for (List<T3<Object, Object, Object>> evt : expEvts)
+                                    evt.clear();
+                            }
+                            catch (Exception e) {
+                                log.error("Failed.", e);
+
+                                err = true;
+
+                                stop.set(true);
+                            }
+                            finally {
+                                checkBarrier.set(null);
+                            }
+                        }
+                    });
+
+                    assertTrue(checkBarrier.compareAndSet(null, bar));
+
+                    if (!stop.get() && !err)
+                        bar.await(1, MINUTES);
+                }
+
+                return null;
+            }
+        });
+
+        final long stopTime = System.currentTimeMillis() + 60_000;
+
+        final AtomicInteger valCntr = new AtomicInteger(0);
+
+        final AtomicInteger threadSeq = new AtomicInteger(0);
+
+        GridTestUtils.runMultiThreaded(new Runnable() {
+            @Override public void run() {
+                try {
+                    final ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+                    final int threadId = threadSeq.getAndIncrement();
+
+                    log.error("Thread id: " + threadId);
+
+                    while (System.currentTimeMillis() < stopTime && !stop.get() && !err) {
+                        Integer key = rnd.nextInt(PARTS);
+
+                        Integer val = valCntr.incrementAndGet();
+
+                        Integer prevVal = (Integer)qryClnCache.getAndPut(key, val);
+
+                        expEvts.get(threadId).add(new T3<>((Object)key, (Object)val, (Object)prevVal));
+
+                        CyclicBarrier bar = checkBarrier.get();
+
+                        if (bar != null)
+                            bar.await();
+                    }
+                }
+                catch (Exception e){
+                    log.error("Failed.", e);
+
+                    err = true;
+
+                    stop.set(true);
+                }
+                finally {
+                    stop.set(true);
+                }
+            }
+        }, THREAD, "update-thread");
+
+        restartFut.get();
+
+        List<T3<Object, Object, Object>> expEvts0 = new ArrayList<>();
+
+        for (List<T3<Object, Object, Object>> evt : expEvts) {
+            expEvts0.addAll(evt);
+
+            evt.clear();
+        }
+
+        if (!expEvts0.isEmpty())
+            checkEvents(expEvts0, lsnr, true);
+
+        cur.close();
+
+        assertFalse("Unexpected error during test, see log for details.", err);
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testMultiThreaded() throws Exception {
+        this.backups = 2;
+
+        final int SRV_NODES = 3;
+
+        startGridsMultiThreaded(SRV_NODES);
+
+        client = true;
+
+        Ignite qryClient = startGrid(SRV_NODES);
+
+        final IgniteCache<Object, Object> cache = qryClient.cache(null);
+
+        CacheEventListener1 lsnr = new CacheEventListener1(true);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setLocalListener(lsnr);
+
+        QueryCursor<?> cur = cache.query(qry);
+
+        client = false;
+
+        final int SRV_IDX = SRV_NODES - 1;
+
+        List<Integer> keys = primaryKeys(ignite(SRV_IDX).cache(null), 10);
+
+        final int THREADS = 10;
+
+        for (int i = 0; i < keys.size(); i++) {
+            log.info("Iteration: " + i);
+
+            Ignite srv = ignite(SRV_IDX);
+
+            TestCommunicationSpi spi = (TestCommunicationSpi)srv.configuration().getCommunicationSpi();
+
+            spi.sndFirstOnly = new AtomicBoolean(false);
+
+            final Integer key = keys.get(i);
+
+            final AtomicInteger val = new AtomicInteger();
+
+            CountDownLatch latch = new CountDownLatch(THREADS);
+
+            lsnr.latch = latch;
+
+            IgniteInternalFuture<?> fut = GridTestUtils.runMultiThreadedAsync(new Callable<Object>() {
+                @Override public Object call() throws Exception {
+                    Integer val0 = val.getAndIncrement();
+
+                    cache.put(key, val0);
+
+                    return null;
+                }
+            }, THREADS, "update-thread");
+
+            fut.get();
+
+            stopGrid(SRV_IDX);
+
+            if (!latch.await(5, SECONDS))
+                fail("Failed to wait for notifications [exp=" + THREADS + ", left=" + lsnr.latch.getCount() + ']');
+
+            assertEquals(THREADS, lsnr.allEvts.size());
+
+            Set<Integer> vals = new HashSet<>();
+
+            boolean err = false;
+
+            for (CacheEntryEvent<?, ?> evt : lsnr.allEvts) {
+                assertEquals(key, evt.getKey());
+                assertNotNull(evt.getValue());
+
+                if (!vals.add((Integer)evt.getValue())) {
+                    err = true;
+
+                    log.info("Extra event: " + evt);
+                }
+            }
+
+            for (int v = 0; v < THREADS; v++) {
+                if (!vals.contains(v)) {
+                    err = true;
+
+                    log.info("Event for value not received: " + v);
+                }
+            }
+
+            assertFalse("Invalid events, see log for details.", err);
+
+            lsnr.allEvts.clear();
+
+            startGrid(SRV_IDX);
+        }
+
+        cur.close();
+    }
+
+    /**
+     * @param logAll If {@code true} logs all unexpected values.
+     * @param expEvts Expected values.
+     * @param lsnr Listener.
+     * @return Check status.
+     */
+    @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter")
+    private boolean checkEvents(boolean logAll,
+        Map<Integer, List<T2<Integer, Integer>>> expEvts,
+        CacheEventListener2 lsnr) {
+        assertTrue(!expEvts.isEmpty());
+
+        boolean pass = true;
+
+        for (Map.Entry<Integer, List<T2<Integer, Integer>>> e : expEvts.entrySet()) {
+            Integer key = e.getKey();
+            List<T2<Integer, Integer>> exp = e.getValue();
+
+            List<CacheEntryEvent<?, ?>> rcvdEvts = lsnr.evts.get(key);
+
+            if (rcvdEvts == null) {
+                pass = false;
+
+                log.info("No events for key [key=" + key + ", exp=" + e.getValue() + ']');
+
+                if (!logAll)
+                    return false;
+            }
+            else {
+                synchronized (rcvdEvts) {
+                    if (rcvdEvts.size() != exp.size()) {
+                        pass = false;
+
+                        log.info("Missed or extra events for key [key=" + key +
+                            ", exp=" + e.getValue() +
+                            ", rcvd=" + rcvdEvts + ']');
+
+                        if (!logAll)
+                            return false;
+                    }
+
+                    int cnt = Math.min(rcvdEvts.size(), exp.size());
+
+                    for (int i = 0; i < cnt; i++) {
+                        T2<Integer, Integer> expEvt = exp.get(i);
+                        CacheEntryEvent<?, ?> rcvdEvt = rcvdEvts.get(i);
+
+                        if (pass) {
+                            assertEquals(key, rcvdEvt.getKey());
+                            assertEquals(expEvt.get1(), rcvdEvt.getValue());
+                        }
+                        else {
+                            if (!key.equals(rcvdEvt.getKey()) || !expEvt.get1().equals(rcvdEvt.getValue()))
+                                log.warning("Missed events. [key=" + key + ", actKey=" + rcvdEvt.getKey()
+                                    + ", expVal=" + expEvt.get1() + ", actVal=" + rcvdEvt.getValue() + "]");
+                        }
+                    }
+
+                    if (!pass) {
+                        for (int i = cnt; i < exp.size(); i++) {
+                            T2<Integer, Integer> val = exp.get(i);
+
+                            log.warning("Missed events. [key=" + key + ", expVal=" + val.get1()
+                                + ", prevVal=" + val.get2() + "]");
+                        }
+                    }
+                }
+            }
+        }
+
+        if (pass) {
+            expEvts.clear();
+            lsnr.evts.clear();
+        }
+
+        return pass;
+    }
+
+    /**
+     *
+     */
+    private static class CacheEventListener1 implements CacheEntryUpdatedListener<Object, Object> {
+        /** */
+        private volatile CountDownLatch latch;
+
+        /** */
+        private GridConcurrentHashSet<Integer> keys = new GridConcurrentHashSet<>();
+
+        /** */
+        private ConcurrentHashMap<Object, CacheEntryEvent<?, ?>> evts = new ConcurrentHashMap<>();
+
+        /** */
+        private List<CacheEntryEvent<?, ?>> allEvts;
+
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /**
+         * @param saveAll Save all events flag.
+         */
+        CacheEventListener1(boolean saveAll) {
+            if (saveAll)
+                allEvts = new ArrayList<>();
+        }
+
+        /** {@inheritDoc} */
+        @Override public void onUpdated(Iterable<CacheEntryEvent<?, ?>> evts) {
+            try {
+                for (CacheEntryEvent<?, ?> evt : evts) {
+                    CountDownLatch latch = this.latch;
+
+                    log.info("Received cache event [evt=" + evt +
+                        ", left=" + (latch != null ? latch.getCount() : null) + ']');
+
+                    this.evts.put(evt.getKey(), evt);
+
+                    keys.add((Integer)evt.getKey());
+
+                    if (allEvts != null)
+                        allEvts.add(evt);
+
+                    assertTrue(latch != null);
+                    assertTrue(latch.getCount() > 0);
+
+                    latch.countDown();
+
+                    if (latch.getCount() == 0) {
+                        this.latch = null;
+
+                        keys.clear();
+                    }
+                }
+            }
+            catch (Throwable e) {
+                err = true;
+
+                log.error("Unexpected error", e);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    private static class CacheEventListener2 implements CacheEntryUpdatedListener<Object, Object> {
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /** */
+        private final ConcurrentHashMap<Integer, Integer> vals = new ConcurrentHashMap<>();
+
+        /** */
+        private final ConcurrentHashMap<Integer, List<CacheEntryEvent<?, ?>>> evts = new ConcurrentHashMap<>();
+
+        /**
+         * @return Count events.
+         */
+        public int size() {
+            int size = 0;
+
+            for (List<CacheEntryEvent<?, ?>> e : evts.values())
+                size += e.size();
+
+            return size;
+        }
+
+        /** {@inheritDoc} */
+        @Override public synchronized void onUpdated(Iterable<CacheEntryEvent<?, ?>> evts)
+            throws CacheEntryListenerException  {
+            try {
+                for (CacheEntryEvent<?, ?> evt : evts) {
+                    Integer key = (Integer)evt.getKey();
+                    Integer val = (Integer)evt.getValue();
+
+                    assertNotNull(key);
+                    assertNotNull(val);
+
+                    Integer prevVal = vals.get(key);
+
+                    boolean dup = false;
+
+                    if (prevVal != null && prevVal.equals(val))
+                        dup = true;
+
+                    if (!dup) {
+                        vals.put(key, val);
+
+                        List<CacheEntryEvent<?, ?>> keyEvts = this.evts.get(key);
+
+                        if (keyEvts == null) {
+                            keyEvts = Collections.synchronizedList(new ArrayList<CacheEntryEvent<?, ?>>());
+
+                            this.evts.put(key, keyEvts);
+                        }
+
+                        keyEvts.add(evt);
+                    }
+                }
+            }
+            catch (Throwable e) {
+                err = true;
+
+                log.error("Unexpected error", e);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    public static class CacheEventListener3 implements CacheEntryUpdatedListener<Object, Object>,
+        CacheEntryEventSerializableFilter<Object, Object> {
+        /** Keys. */
+        GridConcurrentHashSet<Integer> keys = new GridConcurrentHashSet<>();
+
+        /** Events. */
+        private final ConcurrentHashMap<Object, CacheEntryEvent<?, ?>> evts = new ConcurrentHashMap<>();
+
+        /** {@inheritDoc} */
+        @Override public void onUpdated(Iterable<CacheEntryEvent<?, ?>> events) throws CacheEntryListenerException {
+            for (CacheEntryEvent<?, ?> e : events) {
+                Integer key = (Integer)e.getKey();
+
+                keys.add(key);
+
+                assert evts.put(key, e) == null;
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean evaluate(CacheEntryEvent<?, ?> e) throws CacheEntryListenerException {
+            return (Integer)e.getValue() % 2 == 0;
+        }
+    }
+
+    /**
+     *
+     */
+    public static class CacheEventFilter implements CacheEntryEventSerializableFilter<Object, Object> {
+        /** {@inheritDoc} */
+        @Override public boolean evaluate(CacheEntryEvent<?, ?> event) throws CacheEntryListenerException {
+            return ((Integer)event.getValue()) >= 0;
+        }
+    }
+
+    /**
+     *
+     */
+    private static class TestCommunicationSpi extends TcpCommunicationSpi {
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
+        /** */
+        private volatile boolean skipMsg;
+
+        /** */
+        private volatile boolean skipAllMsg;
+
+        /** */
+        private volatile AtomicBoolean sndFirstOnly;
+
+        /** {@inheritDoc} */
+        @Override public void sendMessage(ClusterNode node, Message msg, IgniteInClosure<IgniteException> ackC)
+            throws IgniteSpiException {
+            Object msg0 = ((GridIoMessage)msg).message();
+
+            if (skipAllMsg)
+                return;
+
+            if (msg0 instanceof GridContinuousMessage) {
+                if (skipMsg) {
+                    if (log.isDebugEnabled())
+                        log.debug("Skip continuous message: " + msg0);
+
+                    return;
+                }
+                else {
+                    AtomicBoolean sndFirstOnly = this.sndFirstOnly;
+
+                    if (sndFirstOnly != null && !sndFirstOnly.compareAndSet(false, true)) {
+                        if (log.isDebugEnabled())
+                            log.debug("Skip continuous message: " + msg0);
+
+                        return;
+                    }
+                }
+            }
+
+            super.sendMessage(node, msg, ackC);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicNearEnabledSelfSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicNearEnabledSelfSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicNearEnabledSelfSelfTest.java
new file mode 100644
index 0000000..b3c18a9
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicNearEnabledSelfSelfTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicWriteOrderMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFailoverAtomicNearEnabledSelfSelfTest
+    extends CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicWriteOrderMode writeOrderMode() {
+        return PRIMARY;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected NearCacheConfiguration nearCacheConfiguration() {
+        return super.nearCacheConfiguration();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest.java
new file mode 100644
index 0000000..e33db45
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicWriteOrderMode;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest extends CacheContinuousQueryFailoverAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicWriteOrderMode writeOrderMode() {
+        return PRIMARY;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return CacheMode.PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return CacheAtomicityMode.ATOMIC;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicReplicatedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicReplicatedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicReplicatedSelfTest.java
new file mode 100644
index 0000000..84c9131
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverAtomicReplicatedSelfTest.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.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicWriteOrderMode;
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFailoverAtomicReplicatedSelfTest
+    extends CacheContinuousQueryFailoverAtomicPrimaryWriteOrderSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return REPLICATED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicWriteOrderMode writeOrderMode() {
+        return PRIMARY;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxReplicatedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxReplicatedSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxReplicatedSelfTest.java
new file mode 100644
index 0000000..7c4f180
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxReplicatedSelfTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.query.continuous;
+
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFailoverTxReplicatedSelfTest extends CacheContinuousQueryFailoverTxSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return REPLICATED;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ce636372/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxSelfTest.java
new file mode 100644
index 0000000..789a105
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryFailoverTxSelfTest.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.query.continuous;
+
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+
+/**
+ *
+ */
+public class CacheContinuousQueryFailoverTxSelfTest extends CacheContinuousQueryFailoverAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected CacheMode cacheMode() {
+        return PARTITIONED;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected CacheAtomicityMode atomicityMode() {
+        return TRANSACTIONAL;
+    }
+}


[11/37] ignite git commit: Performance optimizations - reviewed by Yakov.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
index e8546ef..1a26028 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
@@ -273,7 +273,7 @@ public class GridNearTransactionalCache<K, V> extends GridNearCacheAdapter<K, V>
      * @throws IgniteCheckedException If failed.
      * @throws GridDistributedLockCancelledException If lock has been cancelled.
      */
-    @SuppressWarnings({"RedundantTypeArguments"})
+    @SuppressWarnings({"RedundantTypeArguments", "ForLoopReplaceableByForEach"})
     @Nullable public GridNearTxRemote startRemoteTx(UUID nodeId, GridDhtLockRequest req)
         throws IgniteCheckedException, GridDistributedLockCancelledException {
         List<KeyCacheObject> nearKeys = req.nearKeys();
@@ -285,6 +285,7 @@ public class GridNearTransactionalCache<K, V> extends GridNearCacheAdapter<K, V>
         if (ldr != null) {
             Collection<IgniteTxKey> evicted = null;
 
+            // Avoid iterator creation.
             for (int i = 0; i < nearKeys.size(); i++) {
                 KeyCacheObject key = nearKeys.get(i);
 
@@ -293,8 +294,6 @@ public class GridNearTransactionalCache<K, V> extends GridNearCacheAdapter<K, V>
 
                 IgniteTxKey txKey = ctx.txKey(key);
 
-                Collection<GridCacheMvccCandidate> cands = req.candidatesByIndex(i);
-
                 if (log.isDebugEnabled())
                     log.debug("Unmarshalled key: " + key);
 
@@ -356,8 +355,6 @@ public class GridNearTransactionalCache<K, V> extends GridNearCacheAdapter<K, V>
                                 req.owned(entry.key())
                             );
 
-                            assert cands.isEmpty() : "Received non-empty candidates in dht lock request: " + cands;
-
                             if (!req.inTx())
                                 ctx.evicts().touch(entry, req.topologyVersion());
                         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
index 31aa8c3..9c022b2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
@@ -40,6 +40,7 @@ import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridCompoundIdentityFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
@@ -332,6 +333,7 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
     /**
      * Initializes future.
      */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
     void finish() {
         if (tx.onNeedCheckBackup()) {
             assert tx.onePhaseCommit();
@@ -363,10 +365,18 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
                 if (!isSync() && !isDone()) {
                     boolean complete = true;
 
-                    for (IgniteInternalFuture<?> f : pending())
-                        // Mini-future in non-sync mode gets done when message gets sent.
-                        if (isMini(f) && !f.isDone())
-                            complete = false;
+                    synchronized (futs) {
+                        // Avoid collection copy and iterator creation.
+                        for (int i = 0; i < futs.size(); i++) {
+                            IgniteInternalFuture<IgniteInternalTx> f = futs.get(i);
+
+                            if (isMini(f) && !f.isDone()) {
+                                complete = false;
+
+                                break;
+                            }
+                        }
+                    }
 
                     if (complete)
                         onComplete();

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index 434b6c7..b92be31 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -461,21 +461,6 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
     }
 
     /**
-     * @param nodeId Node ID.
-     * @param dhtVer DHT version.
-     * @param writeVer Write version.
-     */
-    void addDhtVersion(UUID nodeId, GridCacheVersion dhtVer, GridCacheVersion writeVer) {
-        // This step is very important as near and DHT versions grow separately.
-        cctx.versions().onReceived(nodeId, dhtVer);
-
-        GridDistributedTxMapping m = mappings.get(nodeId);
-
-        if (m != null)
-            m.dhtVersion(dhtVer, writeVer);
-    }
-
-    /**
      * @param nodeId Undo mapping.
      */
     @Override public boolean removeMapping(UUID nodeId) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
index 45477a0..cfaadc9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
@@ -172,6 +172,8 @@ public abstract class GridNearTxPrepareFutureAdapter extends GridCompoundFuture<
         assert res.error() == null : res;
         assert F.isEmpty(res.invalidPartitions()) : res;
 
+        UUID nodeId = m.node().id();
+
         for (Map.Entry<IgniteTxKey, CacheVersionedValue> entry : res.ownedValues().entrySet()) {
             IgniteTxEntry txEntry = tx.entry(entry.getKey());
 
@@ -187,7 +189,7 @@ public abstract class GridNearTxPrepareFutureAdapter extends GridCompoundFuture<
                         CacheVersionedValue tup = entry.getValue();
 
                         nearEntry.resetFromPrimary(tup.value(), tx.xidVersion(),
-                            tup.version(), m.node().id(), tx.topologyVersion());
+                            tup.version(), nodeId, tx.topologyVersion());
                     }
                     else if (txEntry.cached().detached()) {
                         GridDhtDetachedCacheEntry detachedEntry = (GridDhtDetachedCacheEntry)txEntry.cached();
@@ -229,11 +231,17 @@ public abstract class GridNearTxPrepareFutureAdapter extends GridCompoundFuture<
             if (writeVer == null)
                 writeVer = res.dhtVersion();
 
-            // Register DHT version.
-            tx.addDhtVersion(m.node().id(), res.dhtVersion(), writeVer);
+            // This step is very important as near and DHT versions grow separately.
+            cctx.versions().onReceived(nodeId, res.dhtVersion());
 
+            // Register DHT version.
             m.dhtVersion(res.dhtVersion(), writeVer);
 
+            GridDistributedTxMapping map = tx.mappings().get(nodeId);
+
+            if (map != null)
+                map.dhtVersion(res.dhtVersion(), writeVer);
+
             if (m.near())
                 tx.readyNearLocks(m, res.pending(), res.committedVersions(), res.rolledbackVersions());
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
index 798635a..9dfdb43 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareRequest.java
@@ -71,7 +71,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
     /** Implicit single flag. */
     private boolean implicitSingle;
 
-    /** Explicit lock flag. Set to true if at leat one entry was explicitly locked. */
+    /** Explicit lock flag. Set to true if at least one entry was explicitly locked. */
     private boolean explicitLock;
 
     /** Subject ID. */
@@ -282,73 +282,73 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
         }
 
         switch (writer.state()) {
-            case 22:
+            case 23:
                 if (!writer.writeBoolean("explicitLock", explicitLock))
                     return false;
 
                 writer.incrementState();
 
-            case 23:
+            case 24:
                 if (!writer.writeBoolean("firstClientReq", firstClientReq))
                     return false;
 
                 writer.incrementState();
 
-            case 24:
+            case 25:
                 if (!writer.writeIgniteUuid("futId", futId))
                     return false;
 
                 writer.incrementState();
 
-            case 25:
+            case 26:
                 if (!writer.writeBoolean("implicitSingle", implicitSingle))
                     return false;
 
                 writer.incrementState();
 
-            case 26:
+            case 27:
                 if (!writer.writeBoolean("last", last))
                     return false;
 
                 writer.incrementState();
 
-            case 27:
+            case 28:
                 if (!writer.writeCollection("lastBackups", lastBackups, MessageCollectionItemType.UUID))
                     return false;
 
                 writer.incrementState();
 
-            case 28:
+            case 29:
                 if (!writer.writeIgniteUuid("miniId", miniId))
                     return false;
 
                 writer.incrementState();
 
-            case 29:
+            case 30:
                 if (!writer.writeBoolean("near", near))
                     return false;
 
                 writer.incrementState();
 
-            case 30:
+            case 31:
                 if (!writer.writeBoolean("retVal", retVal))
                     return false;
 
                 writer.incrementState();
 
-            case 31:
+            case 32:
                 if (!writer.writeUuid("subjId", subjId))
                     return false;
 
                 writer.incrementState();
 
-            case 32:
+            case 33:
                 if (!writer.writeInt("taskNameHash", taskNameHash))
                     return false;
 
                 writer.incrementState();
 
-            case 33:
+            case 34:
                 if (!writer.writeMessage("topVer", topVer))
                     return false;
 
@@ -370,7 +370,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
             return false;
 
         switch (reader.state()) {
-            case 22:
+            case 23:
                 explicitLock = reader.readBoolean("explicitLock");
 
                 if (!reader.isLastRead())
@@ -378,7 +378,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 23:
+            case 24:
                 firstClientReq = reader.readBoolean("firstClientReq");
 
                 if (!reader.isLastRead())
@@ -386,7 +386,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 24:
+            case 25:
                 futId = reader.readIgniteUuid("futId");
 
                 if (!reader.isLastRead())
@@ -394,7 +394,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 25:
+            case 26:
                 implicitSingle = reader.readBoolean("implicitSingle");
 
                 if (!reader.isLastRead())
@@ -402,7 +402,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 26:
+            case 27:
                 last = reader.readBoolean("last");
 
                 if (!reader.isLastRead())
@@ -410,7 +410,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 27:
+            case 28:
                 lastBackups = reader.readCollection("lastBackups", MessageCollectionItemType.UUID);
 
                 if (!reader.isLastRead())
@@ -418,7 +418,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 28:
+            case 29:
                 miniId = reader.readIgniteUuid("miniId");
 
                 if (!reader.isLastRead())
@@ -426,7 +426,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 29:
+            case 30:
                 near = reader.readBoolean("near");
 
                 if (!reader.isLastRead())
@@ -434,7 +434,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 30:
+            case 31:
                 retVal = reader.readBoolean("retVal");
 
                 if (!reader.isLastRead())
@@ -442,7 +442,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 31:
+            case 32:
                 subjId = reader.readUuid("subjId");
 
                 if (!reader.isLastRead())
@@ -450,7 +450,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 32:
+            case 33:
                 taskNameHash = reader.readInt("taskNameHash");
 
                 if (!reader.isLastRead())
@@ -458,7 +458,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
                 reader.incrementState();
 
-            case 33:
+            case 34:
                 topVer = reader.readMessage("topVer");
 
                 if (!reader.isLastRead())
@@ -478,7 +478,7 @@ public class GridNearTxPrepareRequest extends GridDistributedTxPrepareRequest {
 
     /** {@inheritDoc} */
     @Override public byte fieldsCount() {
-        return 34;
+        return 35;
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
index f5f99f5..eb0db4a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteInternalTx.java
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutObject;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.lang.GridTuple;
 import org.apache.ignite.lang.IgniteAsyncSupported;
 import org.apache.ignite.lang.IgniteUuid;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
index 6a0f8ab..3ddd909 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java
@@ -54,6 +54,7 @@ import org.apache.ignite.internal.processors.cache.version.GridCacheVersion;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersionConflictContext;
 import org.apache.ignite.internal.processors.cache.version.GridCacheVersionedEntryEx;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.lang.GridMetadataAwareAdapter;
 import org.apache.ignite.internal.util.lang.GridTuple;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
index 9eb2808..23f83be 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxEntry.java
@@ -599,20 +599,20 @@ public class IgniteTxEntry implements GridPeerDeployAware, Message {
      */
     @SuppressWarnings("unchecked")
     public CacheObject applyEntryProcessors(CacheObject cacheVal) {
-        Object val = null;
-        Object keyVal = null;
-
         GridCacheVersion ver;
 
         try {
             ver = entry.version();
         }
-        catch (GridCacheEntryRemovedException e) {
+        catch (GridCacheEntryRemovedException ignore) {
             assert tx == null || tx.optimistic() : tx;
 
             ver = null;
         }
 
+        Object val = null;
+        Object keyVal = null;
+
         for (T2<EntryProcessor<Object, Object, Object>, Object[]> t : entryProcessors()) {
             try {
                 CacheInvokeEntry<Object, Object> invokeEntry = new CacheInvokeEntry(ctx, key, keyVal, cacheVal, val,
@@ -1078,5 +1078,4 @@ public class IgniteTxEntry implements GridPeerDeployAware, Message {
     @Override public String toString() {
         return GridToStringBuilder.toString(IgniteTxEntry.class, this, "xidVer", tx == null ? "null" : tx.xidVersion());
     }
-
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
index 5f48469..c75a8f38 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxImplicitSingleStateImpl.java
@@ -147,6 +147,13 @@ public class IgniteTxImplicitSingleStateImpl extends IgniteTxLocalStateAdapter {
     }
 
     /** {@inheritDoc} */
+    @Override public boolean hasInterceptor(GridCacheSharedContext cctx) {
+        GridCacheContext ctx0 = cacheCtx;
+
+        return ctx0 != null && ctx0.config().getInterceptor() != null;
+    }
+
+    /** {@inheritDoc} */
     @Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
         if (cacheCtx == null)
             return null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index 758f82c..9e44b10 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -67,6 +67,7 @@ import org.apache.ignite.internal.transactions.IgniteTxHeuristicCheckedException
 import org.apache.ignite.internal.transactions.IgniteTxRollbackCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
 import org.apache.ignite.internal.util.GridLeanMap;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridEmbeddedFuture;
 import org.apache.ignite.internal.util.future.GridFinishedFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
@@ -74,7 +75,6 @@ import org.apache.ignite.internal.util.lang.GridClosureException;
 import org.apache.ignite.internal.util.lang.GridInClosure3;
 import org.apache.ignite.internal.util.lang.GridTuple;
 import org.apache.ignite.internal.util.tostring.GridToStringBuilder;
-import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.C1;
 import org.apache.ignite.internal.util.typedef.C2;
@@ -358,6 +358,13 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     }
 
     /**
+     * @return {@code True} if transaction participates in a cache that has an interceptor configured.
+     */
+    public boolean hasInterceptor() {
+        return txState().hasInterceptor(cctx);
+    }
+
+    /**
      * @param needRetVal Need return value flag.
      */
     public void needReturnValue(boolean needRetVal) {
@@ -3045,7 +3052,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
         try {
             Set<?> keySet = map0 != null ? map0.keySet() : invokeMap0.keySet();
 
-            final Collection<KeyCacheObject> enlisted = new ArrayList<>();
+            final Collection<KeyCacheObject> enlisted = new ArrayList<>(keySet.size());
 
             CacheOperationContext opCtx = cacheCtx.operationContextPerCall();
 
@@ -3434,7 +3441,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
      */
     public boolean init() {
         return !txState.init(txSize) || cctx.tm().onStarted(this);
-
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
index ccccca0..67bca51 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
@@ -59,6 +59,7 @@ import org.apache.ignite.internal.processors.timeout.GridTimeoutObjectAdapter;
 import org.apache.ignite.internal.transactions.IgniteTxOptimisticCheckedException;
 import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException;
 import org.apache.ignite.internal.util.GridBoundedConcurrentOrderedMap;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridCompoundFuture;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.lang.IgnitePair;

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
index e7c4c96..3e5034b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxRemoteStateAdapter.java
@@ -92,6 +92,11 @@ public abstract class IgniteTxRemoteStateAdapter implements IgniteTxRemoteState
     }
 
     /** {@inheritDoc} */
+    @Override public boolean hasInterceptor(GridCacheSharedContext cctx) {
+        return false;
+    }
+
+    /** {@inheritDoc} */
     @Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
         assert false;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
index 81707ba..18fce8d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxState.java
@@ -101,6 +101,12 @@ public interface IgniteTxState {
 
     /**
      * @param cctx Context.
+     * @return {@code True} if transaction spans one or more caches with configured interceptor.
+     */
+    public boolean hasInterceptor(GridCacheSharedContext cctx);
+
+    /**
+     * @param cctx Context.
      * @return Configured stores for active caches.
      */
     public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx);

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
index c95fb19..213c5e6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxStateImpl.java
@@ -24,11 +24,13 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheInterceptor;
 import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
 import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
+import org.apache.ignite.internal.util.GridLongList;
 import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
@@ -45,7 +47,7 @@ import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
  */
 public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
     /** Active cache IDs. */
-    private Set<Integer> activeCacheIds = new HashSet<>();
+    private GridLongList activeCacheIds = new GridLongList();
     /** Per-transaction read map. */
 
     @GridToStringInclude
@@ -66,13 +68,13 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
     /** {@inheritDoc} */
     @Nullable @Override public Integer firstCacheId() {
-        return F.first(activeCacheIds);
+        return activeCacheIds.isEmpty() ? null : (int)activeCacheIds.get(0);
     }
 
     /** {@inheritDoc} */
     @Nullable @Override public GridCacheContext singleCacheContext(GridCacheSharedContext cctx) {
         if (activeCacheIds.size() == 1) {
-            int cacheId = F.first(activeCacheIds);
+            int cacheId = (int)activeCacheIds.get(0);
 
             return cctx.cacheContext(cacheId);
         }
@@ -82,8 +84,11 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
     /** {@inheritDoc} */
     @Override public void awaitLastFut(GridCacheSharedContext cctx) {
-        for (Integer cacheId : activeCacheIds)
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             cctx.cacheContext(cacheId).cache().awaitLastFut();
+        }
     }
 
     /** {@inheritDoc} */
@@ -91,7 +96,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
         GridDhtTopologyFuture topFut) {
         StringBuilder invalidCaches = null;
 
-        for (Integer cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             GridCacheContext ctx = cctx.cacheContext(cacheId);
 
             assert ctx != null : cacheId;
@@ -113,7 +120,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
                 invalidCaches.toString());
         }
 
-        for (int cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
 
             if (CU.affinityNodes(cacheCtx, topFut.topologyVersion()).isEmpty()) {
@@ -127,7 +136,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
     /** {@inheritDoc} */
     @Override public boolean sync(GridCacheSharedContext cctx) {
-        for (int cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             if (cctx.cacheContext(cacheId).config().getWriteSynchronizationMode() == FULL_SYNC)
                 return true;
         }
@@ -137,7 +148,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
     /** {@inheritDoc} */
     @Override public boolean hasNearCache(GridCacheSharedContext cctx) {
-        for (Integer cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
 
             if (cacheCtx.isNear())
@@ -163,7 +176,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
                 int idx = 0;
 
-                for (Integer activeCacheId : activeCacheIds) {
+                for (int i = 0; i < activeCacheIds.size(); i++) {
+                    int activeCacheId = (int)activeCacheIds.get(i);
+
                     cacheNames.append(cctx.cacheContext(activeCacheId).name());
 
                     if (idx++ < activeCacheIds.size() - 1)
@@ -192,7 +207,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
         GridCacheContext<?, ?> nonLocCtx = null;
 
-        for (int cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
 
             if (!cacheCtx.isLocal()) {
@@ -222,7 +239,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
         if (!activeCacheIds.isEmpty()) {
             GridCacheContext<?, ?> nonLocCtx = null;
 
-            for (int cacheId : activeCacheIds) {
+            for (int i = 0; i < activeCacheIds.size(); i++) {
+                int cacheId = (int)activeCacheIds.get(i);
+
                 GridCacheContext<?, ?> cacheCtx = cctx.cacheContext(cacheId);
 
                 if (!cacheCtx.isLocal()) {
@@ -240,7 +259,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
     /** {@inheritDoc} */
     @Override public boolean storeUsed(GridCacheSharedContext cctx) {
         if (!activeCacheIds.isEmpty()) {
-            for (int cacheId : activeCacheIds) {
+            for (int i = 0; i < activeCacheIds.size(); i++) {
+                int cacheId = (int)activeCacheIds.get(i);
+
                 CacheStoreManager store = cctx.cacheContext(cacheId).store();
 
                 if (store.configured())
@@ -252,13 +273,29 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
     }
 
     /** {@inheritDoc} */
+    @Override public boolean hasInterceptor(GridCacheSharedContext cctx) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
+            CacheInterceptor interceptor = cctx.cacheContext(cacheId).config().getInterceptor();
+
+            if (interceptor != null)
+                return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
     @Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
-        Collection<Integer> cacheIds = activeCacheIds;
+        GridLongList cacheIds = activeCacheIds;
 
         if (!cacheIds.isEmpty()) {
             Collection<CacheStoreManager> stores = new ArrayList<>(cacheIds.size());
 
-            for (int cacheId : cacheIds) {
+            for (int i = 0; i < cacheIds.size(); i++) {
+                int cacheId = (int)cacheIds.get(i);
+
                 CacheStoreManager store = cctx.cacheContext(cacheId).store();
 
                 if (store.configured())
@@ -273,7 +310,9 @@ public class IgniteTxStateImpl extends IgniteTxLocalStateAdapter {
 
     /** {@inheritDoc} */
     @Override public void onTxEnd(GridCacheSharedContext cctx, IgniteInternalTx tx, boolean commit) {
-        for (int cacheId : activeCacheIds) {
+        for (int i = 0; i < activeCacheIds.size(); i++) {
+            int cacheId = (int)activeCacheIds.get(i);
+
             GridCacheContext cacheCtx = cctx.cacheContext(cacheId);
 
             onTxEnd(cacheCtx, tx, commit);

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/processors/clock/GridClockSyncProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/clock/GridClockSyncProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/clock/GridClockSyncProcessor.java
index 21d3fb6..b5c89cf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/clock/GridClockSyncProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/clock/GridClockSyncProcessor.java
@@ -35,6 +35,7 @@ import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener;
 import org.apache.ignite.internal.processors.GridProcessorAdapter;
 import org.apache.ignite.internal.util.GridBoundedConcurrentOrderedMap;
 import org.apache.ignite.internal.util.GridSpinReadWriteLock;
+import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.internal.util.typedef.internal.LT;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.internal.util.worker.GridWorker;
@@ -71,6 +72,9 @@ public class GridClockSyncProcessor extends GridProcessorAdapter {
     private NavigableMap<GridClockDeltaVersion, GridClockDeltaSnapshot> timeSyncHist =
         new GridBoundedConcurrentOrderedMap<>(MAX_TIME_SYNC_HISTORY);
 
+    /** Last recorded. */
+    private volatile T2<GridClockDeltaVersion, GridClockDeltaSnapshot> lastSnapshot;
+
     /** Time source. */
     private GridClockSource clockSrc;
 
@@ -99,7 +103,11 @@ public class GridClockSyncProcessor extends GridProcessorAdapter {
 
                 GridClockDeltaVersion ver = msg0.snapshotVersion();
 
-                timeSyncHist.put(ver, new GridClockDeltaSnapshot(ver, msg0.deltas()));
+                GridClockDeltaSnapshot snap = new GridClockDeltaSnapshot(ver, msg0.deltas());
+
+                lastSnapshot = new T2<>(ver, snap);
+
+                timeSyncHist.put(ver, snap);
             }
         });
 
@@ -265,11 +273,19 @@ public class GridClockSyncProcessor extends GridProcessorAdapter {
      * @return Adjusted time.
      */
     public long adjustedTime(long topVer) {
-        // Get last synchronized time on given topology version.
-        Map.Entry<GridClockDeltaVersion, GridClockDeltaSnapshot> entry = timeSyncHistory().lowerEntry(
-            new GridClockDeltaVersion(0, topVer + 1));
+        T2<GridClockDeltaVersion, GridClockDeltaSnapshot> fastSnap = lastSnapshot;
+
+        GridClockDeltaSnapshot snap;
 
-        GridClockDeltaSnapshot snap = entry == null ? null : entry.getValue();
+        if (fastSnap != null && fastSnap.get1().topologyVersion() == topVer)
+            snap = fastSnap.get2();
+        else {
+            // Get last synchronized time on given topology version.
+            Map.Entry<GridClockDeltaVersion, GridClockDeltaSnapshot> entry = timeSyncHistory().lowerEntry(
+                new GridClockDeltaVersion(0, topVer + 1));
+
+            snap = entry == null ? null : entry.getValue();
+        }
 
         long now = clockSrc.currentTimeMillis();
 
@@ -295,6 +311,8 @@ public class GridClockSyncProcessor extends GridProcessorAdapter {
             return;
 
         try {
+            lastSnapshot = new T2<>(snapshot.version(), snapshot);
+
             timeSyncHist.put(snapshot.version(), snapshot);
 
             for (ClusterNode n : top.topologyNodes()) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/util/UUIDCollectionMessage.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/UUIDCollectionMessage.java b/modules/core/src/main/java/org/apache/ignite/internal/util/UUIDCollectionMessage.java
new file mode 100644
index 0000000..25e3376
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/UUIDCollectionMessage.java
@@ -0,0 +1,114 @@
+/*
+ * 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.util;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.UUID;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ *
+ */
+public class UUIDCollectionMessage implements Message {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    @GridDirectCollection(UUID.class)
+    private Collection<UUID> uuids;
+
+    /**
+     * Empty constructor required for direct marshalling.
+     */
+    public UUIDCollectionMessage() {
+        // No-op.
+    }
+
+    /**
+     * @param uuids UUIDs to wrap.
+     */
+    public UUIDCollectionMessage(Collection<UUID> uuids) {
+        this.uuids = uuids;
+    }
+
+    /**
+     * @return The collection of UUIDs that was wrapped.
+     */
+    public Collection<UUID> uuids() {
+        return uuids;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 0:
+                if (!writer.writeCollection("uuids", uuids, MessageCollectionItemType.UUID))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        switch (reader.state()) {
+            case 0:
+                uuids = reader.readCollection("uuids", MessageCollectionItemType.UUID);
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(UUIDCollectionMessage.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte directType() {
+        return 115;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 1;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
index 31674f1..5f0d411 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/future/GridCompoundFuture.java
@@ -53,7 +53,7 @@ public class GridCompoundFuture<T, R> extends GridFutureAdapter<R> {
         AtomicIntegerFieldUpdater.newUpdater(GridCompoundFuture.class, "lsnrCalls");
 
     /** Futures. */
-    private final Collection<IgniteInternalFuture<T>> futs = new ArrayList<>();
+    protected final ArrayList<IgniteInternalFuture<T>> futs = new ArrayList<>();
 
     /** Reducer. */
     @GridToStringInclude
@@ -166,8 +166,19 @@ public class GridCompoundFuture<T, R> extends GridFutureAdapter<R> {
      *
      * @return {@code True} if there are pending futures.
      */
+    @SuppressWarnings("ForLoopReplaceableByForEach")
     public boolean hasPending() {
-        return !pending().isEmpty();
+        synchronized (futs) {
+            // Avoid iterator creation and collection copy.
+            for (int i = 0; i < futs.size(); i++) {
+                IgniteInternalFuture<T> fut = futs.get(i);
+
+                if (!fut.isDone())
+                    return true;
+            }
+        }
+
+        return false;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
index c1d91a8..8d5a8e7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
@@ -1866,6 +1866,8 @@ public class GridFunc {
 
         assert m != null;
 
+        final boolean hasPred = p != null && p.length > 0;
+
         return new GridSerializableMap<K, V1>() {
             /** Entry predicate. */
             private IgnitePredicate<Entry<K, V>> ep = new P1<Map.Entry<K, V>>() {
@@ -1911,7 +1913,7 @@ public class GridFunc {
                     }
 
                     @Override public int size() {
-                        return F.size(m.keySet(), p);
+                        return hasPred ? F.size(m.keySet(), p) : m.size();
                     }
 
                     @SuppressWarnings({"unchecked"})
@@ -1925,13 +1927,13 @@ public class GridFunc {
                     }
 
                     @Override public boolean isEmpty() {
-                        return !iterator().hasNext();
+                        return hasPred ? !iterator().hasNext() : m.isEmpty();
                     }
                 };
             }
 
             @Override public boolean isEmpty() {
-                return entrySet().isEmpty();
+                return hasPred ? entrySet().isEmpty() : m.isEmpty();
             }
 
             @SuppressWarnings({"unchecked"})

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java b/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java
index 1824339..5bd08e7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/nio/GridNioServer.java
@@ -1301,6 +1301,8 @@ public class GridNioServer<T> {
         @SuppressWarnings("unchecked")
         private void bodyInternal() throws IgniteCheckedException {
             try {
+                long lastIdleCheck = U.currentTimeMillis();
+
                 while (!closed && selector.isOpen()) {
                     NioOperationFuture req;
 
@@ -1374,11 +1376,18 @@ public class GridNioServer<T> {
                     }
 
                     // Wake up every 2 seconds to check if closed.
-                    if (selector.select(2000) > 0)
+                    if (selector.select(2000) > 0) {
                         // Walk through the ready keys collection and process network events.
                         processSelectedKeys(selector.selectedKeys());
+                    }
 
-                    checkIdle(selector.keys());
+                    long now = U.currentTimeMillis();
+
+                    if (now - lastIdleCheck > 2000) {
+                        lastIdleCheck = now;
+
+                        checkIdle(selector.keys());
+                    }
                 }
             }
             // Ignore this exception as thread interruption is equal to 'close' call.

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/integration/IgniteCacheTxStoreSessionTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/integration/IgniteCacheTxStoreSessionTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/integration/IgniteCacheTxStoreSessionTest.java
index 8957c5d..6424b8b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/integration/IgniteCacheTxStoreSessionTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/integration/IgniteCacheTxStoreSessionTest.java
@@ -285,7 +285,7 @@ public class IgniteCacheTxStoreSessionTest extends IgniteCacheStoreSessionAbstra
 
             expData.add(new ExpectedData(true, "write", new HashMap<>(), CACHE_NAME1));
             expData.add(new ExpectedData(true, "write", F.<Object, Object>asMap(0, "write"), null));
-            expData.add(new ExpectedData(true, "sessionEnd", F.<Object, Object>asMap(0, "write", 1, "write"), null));
+            expData.add(new ExpectedData(true, "sessionEnd", F.<Object, Object>asMap(0, "write", 1, "write"), CACHE_NAME1));
 
             tx.commit();
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/175b7f24/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java
index c3c3659..ea13cdd 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite3.java
@@ -51,6 +51,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.GridCachePut
 import org.apache.ignite.internal.processors.cache.distributed.near.IgniteTxReentryNearSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.rebalancing.GridCacheRebalancingAsyncSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.rebalancing.GridCacheRebalancingSyncSelfTest;
+import org.apache.ignite.internal.processors.cache.distributed.rebalancing.GridCacheRebalancingUnmarshallingFailedSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.GridCacheDaemonNodeReplicatedSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.GridCacheReplicatedAtomicGetAndTransformStoreSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.replicated.GridCacheReplicatedBasicApiTest;
@@ -138,6 +139,7 @@ public class IgniteCacheTestSuite3 extends TestSuite {
 
         suite.addTestSuite(GridCacheOrderedPreloadingSelfTest.class);
         suite.addTestSuite(GridCacheRebalancingSyncSelfTest.class);
+        suite.addTestSuite(GridCacheRebalancingUnmarshallingFailedSelfTest.class);
         suite.addTestSuite(GridCacheRebalancingAsyncSelfTest.class);
 
         // Test for byte array value special case.


[19/37] ignite git commit: Optimization for single key cache 'get' operation.

Posted by ag...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetResponse.java
new file mode 100644
index 0000000..ba0081c
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearSingleGetResponse.java
@@ -0,0 +1,321 @@
+/*
+ * 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.distributed.near;
+
+import java.nio.ByteBuffer;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.GridDirectTransient;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheDeployable;
+import org.apache.ignite.internal.processors.cache.GridCacheEntryInfo;
+import org.apache.ignite.internal.processors.cache.GridCacheMessage;
+import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class GridNearSingleGetResponse extends GridCacheMessage implements GridCacheDeployable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    public static final int INVALID_PART_FLAG_MASK = 0x1;
+
+    /** */
+    public static final int CONTAINS_VAL_FLAG_MASK = 0x2;
+
+    /** Future ID. */
+    private IgniteUuid futId;
+
+    /** */
+    private Message res;
+
+    /** */
+    private AffinityTopologyVersion topVer;
+
+    /** Error. */
+    @GridDirectTransient
+    private IgniteCheckedException err;
+
+    /** Serialized error. */
+    private byte[] errBytes;
+
+    /** */
+    private byte flags;
+
+    /**
+     * Empty constructor required for {@link Message}.
+     */
+    public GridNearSingleGetResponse() {
+        // No-op.
+    }
+
+    /**
+     * @param cacheId Cache ID.
+     * @param futId Future ID.
+     * @param topVer Topology version.
+     * @param res Result.
+     * @param invalidPartitions {@code True} if invalid partitions error occurred.
+     * @param addDepInfo Deployment info.
+     */
+    public GridNearSingleGetResponse(
+        int cacheId,
+        IgniteUuid futId,
+        AffinityTopologyVersion topVer,
+        @Nullable Message res,
+        boolean invalidPartitions,
+        boolean addDepInfo
+    ) {
+        assert futId != null;
+
+        this.cacheId = cacheId;
+        this.futId = futId;
+        this.topVer = topVer;
+        this.res = res;
+        this.addDepInfo = addDepInfo;
+
+        if (invalidPartitions)
+            flags = (byte)(flags | INVALID_PART_FLAG_MASK);
+    }
+
+    /**
+     * @param err Error.
+     */
+    public void error(IgniteCheckedException err) {
+        this.err = err;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCheckedException error() {
+        return err;
+    }
+
+    /**
+     * @return Topology version.
+     */
+    @Override public AffinityTopologyVersion topologyVersion() {
+        return topVer;
+    }
+
+    /**
+     * @return {@code True} if invalid partitions error occurred.
+     */
+    public boolean invalidPartitions() {
+        return (flags & INVALID_PART_FLAG_MASK) != 0;
+    }
+
+    /**
+     * @return Results for request with set flag {@link GridNearSingleGetRequest#skipValues()}.
+     */
+    public boolean containsValue() {
+        return (flags & CONTAINS_VAL_FLAG_MASK) != 0;
+    }
+
+    /**
+     *
+     */
+    public void setContainsValue() {
+        flags = (byte)(flags | CONTAINS_VAL_FLAG_MASK);
+    }
+
+    /**
+     * @return Result.
+     */
+    public Message result() {
+        return res;
+    }
+
+    /**
+     * @return Future ID.
+     */
+    public IgniteUuid futureId() {
+        return futId;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void prepareMarshal(GridCacheSharedContext ctx) throws IgniteCheckedException {
+        super.prepareMarshal(ctx);
+
+        if (res != null) {
+            GridCacheContext cctx = ctx.cacheContext(cacheId);
+
+            if (res instanceof CacheObject)
+                prepareMarshalCacheObject((CacheObject) res, cctx);
+            else if (res instanceof CacheVersionedValue)
+                ((CacheVersionedValue)res).prepareMarshal(cctx.cacheObjectContext());
+            else if (res instanceof GridCacheEntryInfo)
+                ((GridCacheEntryInfo)res).marshal(cctx);
+        }
+
+        if (err != null)
+            errBytes = ctx.marshaller().marshal(err);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void finishUnmarshal(GridCacheSharedContext ctx, ClassLoader ldr) throws IgniteCheckedException {
+        super.finishUnmarshal(ctx, ldr);
+
+        if (res != null) {
+            GridCacheContext cctx = ctx.cacheContext(cacheId());
+
+            if (res instanceof CacheObject)
+                ((CacheObject)res).finishUnmarshal(cctx.cacheObjectContext(), ldr);
+            else if (res instanceof CacheVersionedValue)
+                ((CacheVersionedValue)res).finishUnmarshal(cctx, ldr);
+            else if (res instanceof GridCacheEntryInfo)
+                ((GridCacheEntryInfo)res).unmarshal(cctx, ldr);
+        }
+
+        if (errBytes != null && err == null)
+            err = ctx.marshaller().unmarshal(errBytes, ldr);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+        writer.setBuffer(buf);
+
+        if (!super.writeTo(buf, writer))
+            return false;
+
+        if (!writer.isHeaderWritten()) {
+            if (!writer.writeHeader(directType(), fieldsCount()))
+                return false;
+
+            writer.onHeaderWritten();
+        }
+
+        switch (writer.state()) {
+            case 3:
+                if (!writer.writeByteArray("errBytes", errBytes))
+                    return false;
+
+                writer.incrementState();
+
+            case 4:
+                if (!writer.writeByte("flags", flags))
+                    return false;
+
+                writer.incrementState();
+
+            case 5:
+                if (!writer.writeIgniteUuid("futId", futId))
+                    return false;
+
+                writer.incrementState();
+
+            case 6:
+                if (!writer.writeMessage("res", res))
+                    return false;
+
+                writer.incrementState();
+
+            case 7:
+                if (!writer.writeMessage("topVer", topVer))
+                    return false;
+
+                writer.incrementState();
+
+        }
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+        reader.setBuffer(buf);
+
+        if (!reader.beforeMessageRead())
+            return false;
+
+        if (!super.readFrom(buf, reader))
+            return false;
+
+        switch (reader.state()) {
+            case 3:
+                errBytes = reader.readByteArray("errBytes");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 4:
+                flags = reader.readByte("flags");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 5:
+                futId = reader.readIgniteUuid("futId");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 6:
+                res = reader.readMessage("res");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+            case 7:
+                topVer = reader.readMessage("topVer");
+
+                if (!reader.isLastRead())
+                    return false;
+
+                reader.incrementState();
+
+        }
+
+        return reader.afterMessageRead(GridNearSingleGetResponse.class);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean addDeploymentInfo() {
+        return addDepInfo;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte directType() {
+        return 117;
+    }
+
+    /** {@inheritDoc} */
+    @Override public byte fieldsCount() {
+        return 8;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(GridNearSingleGetResponse.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
index 1a26028..fd3d056 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTransactionalCache.java
@@ -423,7 +423,7 @@ public class GridNearTransactionalCache<K, V> extends GridNearCacheAdapter<K, V>
         assert nodeId != null;
         assert res != null;
 
-        GridNearLockFuture fut = (GridNearLockFuture)ctx.mvcc().<Boolean>future(res.version(),
+        GridNearLockFuture fut = (GridNearLockFuture)ctx.mvcc().<Boolean>mvccFuture(res.version(),
             res.futureId());
 
         if (fut != null)

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
index 9c022b2..102cc4b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxFinishFuture.java
@@ -79,7 +79,7 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
     private GridCacheSharedContext<K, V> cctx;
 
     /** Future ID. */
-    private IgniteUuid futId;
+    private final IgniteUuid futId;
 
     /** Transaction. */
     @GridToStringInclude
@@ -125,26 +125,6 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
     }
 
     /** {@inheritDoc} */
-    @Override public GridCacheVersion version() {
-        return tx.xidVersion();
-    }
-
-    /**
-     * @return Involved nodes.
-     */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return
-            F.viewReadOnly(futures(), new IgniteClosure<IgniteInternalFuture<?>, ClusterNode>() {
-                @Nullable @Override public ClusterNode apply(IgniteInternalFuture<?> f) {
-                    if (isMini(f))
-                        return ((MiniFuture)f).node();
-
-                    return cctx.discovery().localNode();
-                }
-            });
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         for (IgniteInternalFuture<?> fut : futures())
             if (isMini(fut)) {
@@ -298,7 +278,7 @@ public final class GridNearTxFinishFuture<K, V> extends GridCompoundIdentityFutu
                     }
 
                     // Don't forget to clean up.
-                    cctx.mvcc().removeFuture(this);
+                    cctx.mvcc().removeFuture(futId);
 
                     return true;
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
index b92be31..1c01e4e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxLocal.java
@@ -332,7 +332,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         boolean readThrough,
         boolean async,
         final Collection<KeyCacheObject> keys,
-        boolean skipVals,
+        final boolean skipVals,
         final boolean needVer,
         final GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c
     ) {
@@ -361,35 +361,70 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
             });
         }
         else if (cacheCtx.isColocated()) {
-            return cacheCtx.colocated().loadAsync(
-                keys,
-                readThrough,
-                /*force primary*/needVer,
-                topologyVersion(),
-                CU.subjectId(this, cctx),
-                resolveTaskName(),
-                /*deserializePortable*/false,
-                accessPolicy(cacheCtx, keys),
-                skipVals,
-                /*can remap*/true,
-                needVer,
-                /*keepCacheObject*/true
-            ).chain(new C1<IgniteInternalFuture<Map<Object, Object>>, Void>() {
-                @Override public Void apply(IgniteInternalFuture<Map<Object, Object>> f) {
-                    try {
-                        Map<Object, Object> map = f.get();
-
-                        processLoaded(map, keys, needVer, c);
-
-                        return null;
+            if (keys.size() == 1) {
+                final KeyCacheObject key = F.first(keys);
+
+                return cacheCtx.colocated().loadAsync(
+                    key,
+                    readThrough,
+                    /*force primary*/needVer,
+                    topologyVersion(),
+                    CU.subjectId(this, cctx),
+                    resolveTaskName(),
+                    /*deserializePortable*/false,
+                    accessPolicy(cacheCtx, keys),
+                    skipVals,
+                    /*can remap*/true,
+                    needVer,
+                    /*keepCacheObject*/true
+                ).chain(new C1<IgniteInternalFuture<Object>, Void>() {
+                    @Override public Void apply(IgniteInternalFuture<Object> f) {
+                        try {
+                            Object val = f.get();
+
+                            processLoaded(key, val, needVer, skipVals, c);
+
+                            return null;
+                        }
+                        catch (Exception e) {
+                            setRollbackOnly();
+
+                            throw new GridClosureException(e);
+                        }
                     }
-                    catch (Exception e) {
-                        setRollbackOnly();
-
-                        throw new GridClosureException(e);
+                });
+            }
+            else {
+                return cacheCtx.colocated().loadAsync(
+                    keys,
+                    readThrough,
+                    /*force primary*/needVer,
+                    topologyVersion(),
+                    CU.subjectId(this, cctx),
+                    resolveTaskName(),
+                    /*deserializePortable*/false,
+                    accessPolicy(cacheCtx, keys),
+                    skipVals,
+                    /*can remap*/true,
+                    needVer,
+                    /*keepCacheObject*/true
+                ).chain(new C1<IgniteInternalFuture<Map<Object, Object>>, Void>() {
+                    @Override public Void apply(IgniteInternalFuture<Map<Object, Object>> f) {
+                        try {
+                            Map<Object, Object> map = f.get();
+
+                            processLoaded(map, keys, needVer, c);
+
+                            return null;
+                        }
+                        catch (Exception e) {
+                            setRollbackOnly();
+
+                            throw new GridClosureException(e);
+                        }
                     }
-                }
-            });
+                });
+            }
         }
         else {
             assert cacheCtx.isLocal();
@@ -409,29 +444,45 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         final Collection<KeyCacheObject> keys,
         boolean needVer,
         GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c) {
-        for (KeyCacheObject key : keys) {
-            Object val = map.get(key);
+        for (KeyCacheObject key : keys)
+            processLoaded(key, map.get(key), needVer, false, c);
+    }
 
-            if (val != null) {
-                Object v;
-                GridCacheVersion ver;
+    /**
+     * @param key Key.
+     * @param val Value.
+     * @param needVer If {@code true} version is required for loaded values.
+     * @param skipVals Skip values flag.
+     * @param c Closure.
+     */
+    private void processLoaded(
+        KeyCacheObject key,
+        @Nullable Object val,
+        boolean needVer,
+        boolean skipVals,
+        GridInClosure3<KeyCacheObject, Object, GridCacheVersion> c) {
+        if (val != null) {
+            Object v;
+            GridCacheVersion ver;
 
-                if (needVer) {
-                    T2<Object, GridCacheVersion> t = (T2)val;
+            if (needVer) {
+                T2<Object, GridCacheVersion> t = (T2)val;
 
-                    v = t.get1();
-                    ver = t.get2();
-                }
-                else {
-                    v = val;
-                    ver = null;
-                }
-
-                c.apply(key, v, ver);
+                v = t.get1();
+                ver = t.get2();
             }
-            else
+            else {
+                v = val;
+                ver = null;
+            }
+
+            if (skipVals && v == Boolean.FALSE)
                 c.apply(key, null, IgniteTxEntry.SER_READ_EMPTY_ENTRY_VER);
+            else
+                c.apply(key, v, ver);
         }
+        else
+            c.apply(key, null, IgniteTxEntry.SER_READ_EMPTY_ENTRY_VER);
     }
 
     /** {@inheritDoc} */
@@ -771,7 +822,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         if (fut == null && !commitFut.compareAndSet(null, fut = new GridNearTxFinishFuture<>(cctx, this, true)))
             return commitFut.get();
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         final IgniteInternalFuture<?> prepareFut = prepFut.get();
 
@@ -816,7 +867,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
         if (!rollbackFut.compareAndSet(null, fut = new GridNearTxFinishFuture<>(cctx, this, false)))
             return rollbackFut.get();
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         IgniteInternalFuture<?> prepFut = this.prepFut.get();
 
@@ -957,7 +1008,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
 
         final GridDhtTxFinishFuture fut = new GridDhtTxFinishFuture<>(cctx, this, /*commit*/true);
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         if (prep == null || prep.isDone()) {
             assert prep != null || optimistic();
@@ -1016,7 +1067,7 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter {
 
         final GridDhtTxFinishFuture fut = new GridDhtTxFinishFuture<>(cctx, this, /*commit*/false);
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         IgniteInternalFuture<?> prep = prepFut.get();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
index cfaadc9..52cad91 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/near/GridNearTxPrepareFutureAdapter.java
@@ -25,7 +25,7 @@ import javax.cache.expiry.ExpiryPolicy;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
-import org.apache.ignite.internal.processors.cache.GridCacheFuture;
+import org.apache.ignite.internal.processors.cache.GridCacheMvccFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
 import org.apache.ignite.internal.processors.cache.distributed.GridDistributedTxMapping;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTxMapping;
@@ -48,8 +48,8 @@ import static org.apache.ignite.internal.processors.cache.GridCacheOperation.NOO
 /**
  * Common code for tx prepare in optimistic and pessimistic modes.
  */
-public abstract class GridNearTxPrepareFutureAdapter extends GridCompoundFuture<GridNearTxPrepareResponse, IgniteInternalTx>
-    implements GridCacheFuture<IgniteInternalTx> {
+public abstract class GridNearTxPrepareFutureAdapter extends
+    GridCompoundFuture<GridNearTxPrepareResponse, IgniteInternalTx> implements GridCacheMvccFuture<IgniteInternalTx> {
     /** Logger reference. */
     protected static final AtomicReference<IgniteLogger> logRef = new AtomicReference<>();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCache.java
index 87da9a1..544d5b4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalCache.java
@@ -231,8 +231,8 @@ public class GridLocalCache<K, V> extends GridCacheAdapter<K, V> {
     /**
      * @param fut Clears future from cache.
      */
-    void onFutureDone(GridCacheFuture<?> fut) {
-        if (ctx.mvcc().removeFuture(fut)) {
+    void onFutureDone(GridLocalLockFuture fut) {
+        if (ctx.mvcc().removeMvccFuture(fut)) {
             if (log().isDebugEnabled())
                 log().debug("Explicitly removed future from map of futures: " + fut);
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalLockFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalLockFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalLockFuture.java
index cb14b4c..d392d53 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalLockFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/local/GridLocalLockFuture.java
@@ -154,11 +154,6 @@ public final class GridLocalLockFuture<K, V> extends GridFutureAdapter<Boolean>
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<? extends ClusterNode> nodes() {
-        return Collections.emptyList();
-    }
-
-    /** {@inheritDoc} */
     @Override public boolean onNodeLeft(UUID nodeId) {
         return false;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
index 0e5657b..a9846ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxHandler.java
@@ -477,7 +477,7 @@ public class IgniteTxHandler {
      */
     private void processNearTxPrepareResponse(UUID nodeId, GridNearTxPrepareResponse res) {
         GridNearTxPrepareFutureAdapter fut = (GridNearTxPrepareFutureAdapter)ctx.mvcc()
-            .<IgniteInternalTx>future(res.version(), res.futureId());
+            .<IgniteInternalTx>mvccFuture(res.version(), res.futureId());
 
         if (fut == null) {
             U.warn(log, "Failed to find future for prepare response [sender=" + nodeId + ", res=" + res + ']');
@@ -495,8 +495,7 @@ public class IgniteTxHandler {
     private void processNearTxFinishResponse(UUID nodeId, GridNearTxFinishResponse res) {
         ctx.tm().onFinishedRemote(nodeId, res.threadId());
 
-        GridNearTxFinishFuture fut = (GridNearTxFinishFuture)ctx.mvcc().<IgniteInternalTx>future(
-            res.xid(), res.futureId());
+        GridNearTxFinishFuture fut = (GridNearTxFinishFuture)ctx.mvcc().<IgniteInternalTx>future(res.futureId());
 
         if (fut == null) {
             if (log.isDebugEnabled())
@@ -513,7 +512,7 @@ public class IgniteTxHandler {
      * @param res Response.
      */
     private void processDhtTxPrepareResponse(UUID nodeId, GridDhtTxPrepareResponse res) {
-        GridDhtTxPrepareFuture fut = (GridDhtTxPrepareFuture)ctx.mvcc().future(res.version(), res.futureId());
+        GridDhtTxPrepareFuture fut = (GridDhtTxPrepareFuture)ctx.mvcc().mvccFuture(res.version(), res.futureId());
 
         if (fut == null) {
             if (log.isDebugEnabled())
@@ -534,8 +533,7 @@ public class IgniteTxHandler {
         assert res != null;
 
         if (res.checkCommitted()) {
-            GridNearTxFinishFuture fut = (GridNearTxFinishFuture)ctx.mvcc().<IgniteInternalTx>future(
-                res.xid(), res.futureId());
+            GridNearTxFinishFuture fut = (GridNearTxFinishFuture)ctx.mvcc().<IgniteInternalTx>future(res.futureId());
 
             if (fut == null) {
                 if (log.isDebugEnabled())
@@ -547,8 +545,7 @@ public class IgniteTxHandler {
             fut.onResult(nodeId, res);
         }
         else {
-            GridDhtTxFinishFuture fut = (GridDhtTxFinishFuture)ctx.mvcc().<IgniteInternalTx>future(
-                res.xid(), res.futureId());
+            GridDhtTxFinishFuture fut = (GridDhtTxFinishFuture)ctx.mvcc().<IgniteInternalTx>future(res.futureId());
 
             if (fut == null) {
                 if (log.isDebugEnabled())
@@ -566,7 +563,8 @@ public class IgniteTxHandler {
      * @param req Request.
      * @return Future.
      */
-    @Nullable public IgniteInternalFuture<IgniteInternalTx> processNearTxFinishRequest(UUID nodeId, GridNearTxFinishRequest req) {
+    @Nullable public IgniteInternalFuture<IgniteInternalTx> processNearTxFinishRequest(UUID nodeId,
+        GridNearTxFinishRequest req) {
         return finish(nodeId, null, req);
     }
 
@@ -1359,8 +1357,7 @@ public class IgniteTxHandler {
         if (log.isDebugEnabled())
             log.debug("Processing check prepared transaction response [nodeId=" + nodeId + ", res=" + res + ']');
 
-        GridCacheTxRecoveryFuture fut = (GridCacheTxRecoveryFuture)ctx.mvcc().
-            <Boolean>future(res.version(), res.futureId());
+        GridCacheTxRecoveryFuture fut = (GridCacheTxRecoveryFuture)ctx.mvcc().future(res.futureId());
 
         if (fut == null) {
             if (log.isDebugEnabled())

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
index 9e44b10..ecb0595 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java
@@ -1372,7 +1372,6 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
             if (txEntry != null) {
                 CacheObject val = txEntry.value();
 
-                // Read value from locked entry in group-lock transaction as well.
                 if (txEntry.hasValue()) {
                     if (!F.isEmpty(txEntry.entryProcessors()))
                         val = txEntry.applyEntryProcessors(val);
@@ -2224,6 +2223,7 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter
     /**
      * @param cacheCtx Cache context.
      * @param keys Keys to load.
+     * @param filter Filter.
      * @param ret Return value.
      * @param needReadVer Read version flag.
      * @param singleRmv {@code True} for single remove operation.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
index 67bca51..247ccaf 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxManager.java
@@ -1764,7 +1764,7 @@ public class IgniteTxManager extends GridCacheSharedManagerAdapter {
             tx.originatingNodeId(),
             tx.transactionNodes());
 
-        cctx.mvcc().addFuture(fut);
+        cctx.mvcc().addFuture(fut, fut.futureId());
 
         if (log.isDebugEnabled())
             log.debug("Checking optimistic transaction state on remote nodes [tx=" + tx + ", fut=" + fut + ']');

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientReconnectCacheTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientReconnectCacheTest.java b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientReconnectCacheTest.java
index 6131f54..6cf10f4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientReconnectCacheTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/IgniteClientReconnectCacheTest.java
@@ -53,6 +53,7 @@ import org.apache.ignite.internal.processors.cache.distributed.dht.atomic.GridNe
 import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsFullMessage;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearLockResponse;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxFinishResponse;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxPrepareResponse;
 import org.apache.ignite.internal.util.typedef.CI1;
@@ -765,6 +766,12 @@ public class IgniteClientReconnectCacheTest extends IgniteClientReconnectAbstrac
             }
         };
 
+        IgniteInClosure<IgniteCache<Object, Object>> getAllOp = new CI1<IgniteCache<Object, Object>>() {
+            @Override public void apply(IgniteCache<Object, Object> cache) {
+                cache.getAll(F.asSet(1, 2));
+            }
+        };
+
         int cnt = 0;
 
         for (CacheAtomicityMode atomicityMode : CacheAtomicityMode.values()) {
@@ -799,7 +806,9 @@ public class IgniteClientReconnectCacheTest extends IgniteClientReconnectAbstrac
 
                     log.info("Test cache get [atomicity=" + atomicityMode + ", syncMode=" + syncMode + ']');
 
-                    checkOperationInProgressFails(client, ccfg, GridNearGetResponse.class, getOp);
+                    checkOperationInProgressFails(client, ccfg, GridNearSingleGetResponse.class, getOp);
+
+                    checkOperationInProgressFails(client, ccfg, GridNearGetResponse.class, getAllOp);
 
                     client.destroyCache(ccfg.getName());
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
index 1d79e20..e8e86e9 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
@@ -382,6 +382,81 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     /**
      * @throws Exception If failed.
      */
+    public void testContainsKeyTx() throws Exception {
+        if (!txEnabled())
+            return;
+
+        IgniteCache<String, Integer> cache = jcache();
+
+        IgniteTransactions txs = ignite(0).transactions();
+
+        for (int i = 0; i < 10; i++) {
+            String key = String.valueOf(i);
+
+            try (Transaction tx = txs.txStart()) {
+                assertNull(key, cache.get(key));
+
+                assertFalse(cache.containsKey(key));
+
+                tx.commit();
+            }
+
+            try (Transaction tx = txs.txStart()) {
+                assertNull(key, cache.get(key));
+
+                cache.put(key, i);
+
+                assertTrue(cache.containsKey(key));
+
+                tx.commit();
+            }
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testContainsKeysTx() throws Exception {
+        if (!txEnabled())
+            return;
+
+        IgniteCache<String, Integer> cache = jcache();
+
+        IgniteTransactions txs = ignite(0).transactions();
+
+        Set<String> keys = new HashSet<>();
+
+        for (int i = 0; i < 10; i++) {
+            String key = String.valueOf(i);
+
+            keys.add(key);
+        }
+
+        try (Transaction tx = txs.txStart()) {
+            for (String key : keys)
+                assertNull(key, cache.get(key));
+
+            assertFalse(cache.containsKeys(keys));
+
+            tx.commit();
+        }
+
+        try (Transaction tx = txs.txStart()) {
+            for (String key : keys)
+                assertNull(key, cache.get(key));
+
+            for (String key : keys)
+                cache.put(key, 0);
+
+            assertTrue(cache.containsKeys(keys));
+
+            tx.commit();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testRemoveInExplicitLocks() throws Exception {
         if (lockingEnabled()) {
             IgniteCache<String, Integer> cache = jcache();

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentTxMultiNodeTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentTxMultiNodeTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentTxMultiNodeTest.java
index 1ef77f2..45c8c2c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentTxMultiNodeTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheConcurrentTxMultiNodeTest.java
@@ -613,21 +613,6 @@ public class GridCacheConcurrentTxMultiNodeTest extends GridCommonAbstractTest {
 
                                 X.println("Near entry [grid="+ g.name() + ", key=" + k + ", entry=" + nearEntry);
                                 X.println("DHT entry [grid=" + g.name() + ", key=" + k + ", entry=" + dhtEntry);
-
-                                GridCacheMvccCandidate nearCand =
-                                    nearEntry == null ? null : F.first(nearEntry.localCandidates());
-
-                                if (nearCand != null)
-                                    X.println("Near futures: " +
-                                        nearEntry.context().mvcc().futures(nearCand.version()));
-
-                                GridCacheMvccCandidate dhtCand =
-                                    dhtEntry == null ? null : F.first(dhtEntry.localCandidates());
-
-                                if (dhtCand != null)
-                                    X.println("Dht futures: " +
-                                        dhtEntry.context().mvcc().futures(dhtCand.version()));
-
                             }
                         }
                     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
index cbfc97b..2cb4a00 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCachePartitionedGetSelfTest.java
@@ -28,6 +28,7 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.managers.communication.GridMessageListener;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
 import org.apache.ignite.spi.discovery.DiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -228,7 +229,7 @@ public class GridCachePartitionedGetSelfTest extends GridCommonAbstractTest {
                         @Override public void onMessage(UUID nodeId, Object msg) {
                             info("Received message from node [nodeId=" + nodeId + ", msg=" + msg + ']');
 
-                            if (msg instanceof GridNearGetRequest) {
+                            if (msg instanceof GridNearSingleGetRequest) {
                                 info("Setting flag: " + System.identityHashCode(received));
 
                                 received.set(true);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractStopBusySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractStopBusySelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractStopBusySelfTest.java
index 8ddee0c..e5cff5a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractStopBusySelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractStopBusySelfTest.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -37,6 +38,8 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.managers.communication.GridIoMessage;
 import org.apache.ignite.internal.processors.cache.distributed.near.GridNearGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.lang.IgniteInClosure;
 import org.apache.ignite.plugin.extensions.communication.Message;
@@ -218,7 +221,7 @@ public abstract class IgniteCacheAbstractStopBusySelfTest extends GridCommonAbst
      * @throws Exception If failed.
      */
     public void testGet() throws Exception {
-        bannedMsg.set(GridNearGetRequest.class);
+        bannedMsg.set(GridNearSingleGetRequest.class);
 
         executeTest(new Callable<Integer>() {
             /** {@inheritDoc} */
@@ -235,6 +238,28 @@ public abstract class IgniteCacheAbstractStopBusySelfTest extends GridCommonAbst
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testGetAll() throws Exception {
+        bannedMsg.set(GridNearGetRequest.class);
+
+        executeTest(new Callable<Integer>() {
+            /** {@inheritDoc} */
+            @Override public Integer call() throws Exception {
+                info("Start operation.");
+
+                Set<Integer> keys = F.asSet(1, 2, 3);
+
+                clientCache().getAll(keys);
+
+                info("Stop operation.");
+
+                return null;
+            }
+        });
+    }
+
+    /**
      *
      * @param call Closure executing cache operation.
      * @throws Exception If failed.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheP2pUnmarshallingErrorTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheP2pUnmarshallingErrorTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheP2pUnmarshallingErrorTest.java
index f4423f7..9c1abc7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheP2pUnmarshallingErrorTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheP2pUnmarshallingErrorTest.java
@@ -21,6 +21,7 @@ import java.io.Externalizable;
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import javax.cache.CacheException;
 import org.apache.ignite.cache.CacheAtomicWriteOrderMode;
@@ -30,6 +31,7 @@ import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.X;
 
 /**
@@ -37,7 +39,10 @@ import org.apache.ignite.internal.util.typedef.X;
  */
 public class IgniteCacheP2pUnmarshallingErrorTest extends IgniteCacheAbstractTest {
     /** Allows to change behavior of readExternal method. */
-    protected static AtomicInteger readCnt = new AtomicInteger();
+    protected static final AtomicInteger readCnt = new AtomicInteger();
+
+    /** Allows to change behavior of readExternal method. */
+    protected static final AtomicInteger valReadCnt = new AtomicInteger();
 
     /** Iterable key. */
     protected static int key = 0;
@@ -86,71 +91,40 @@ public class IgniteCacheP2pUnmarshallingErrorTest extends IgniteCacheAbstractTes
         return cfg;
     }
 
-    /** Test key 1. */
-    protected static class TestKey implements Externalizable {
-        /** Field. */
-        @QuerySqlField(index = true)
-        private String field;
-
-        /**
-         * @param field Test key 1.
-         */
-        public TestKey(String field) {
-            this.field = field;
-        }
-
-        /** Test key 1. */
-        public TestKey() {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean equals(Object o) {
-            if (this == o)
-                return true;
-            if (o == null || getClass() != o.getClass())
-                return false;
-
-            TestKey key = (TestKey)o;
-
-            return !(field != null ? !field.equals(key.field) : key.field != null);
-        }
+    /**
+     * Sends put atomically and handles fail.
+     *
+     * @param k Key.
+     */
+    protected void failAtomicPut(int k) {
+        try {
+            jcache(0).put(new TestKey(String.valueOf(k)), "");
 
-        /** {@inheritDoc} */
-        @Override public int hashCode() {
-            return field != null ? field.hashCode() : 0;
+            assert false : "p2p marshalling failed, but error response was not sent";
         }
-
-        /** {@inheritDoc} */
-        @Override public void writeExternal(ObjectOutput out) throws IOException {
-            out.writeObject(field);
+        catch (CacheException e) {
+            assert X.hasCause(e, IOException.class);
         }
 
-        /** {@inheritDoc} */
-        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-            field = (String)in.readObject();
-
-            if (readCnt.decrementAndGet() <= 0)
-                throw new IOException("Class can not be unmarshalled.");
-        }
+        assert readCnt.get() == 0; //ensure we have read count as expected.
     }
 
     /**
-     * Sends put atomically and handles fail.
+     * Sends get atomically and handles fail.
      *
      * @param k Key.
      */
-    protected void failAtomicPut(int k) {
+    protected void failGetAll(int k) {
         try {
-            jcache(0).put(new TestKey(String.valueOf(k)), "");
+            Set<Object> keys = F.<Object>asSet(new TestKey(String.valueOf(k)));
+
+            jcache(0).getAll(keys);
 
             assert false : "p2p marshalling failed, but error response was not sent";
         }
         catch (CacheException e) {
             assert X.hasCause(e, IOException.class);
         }
-
-        assert readCnt.get() == 0; //ensure we have read count as expected.
     }
 
     /**
@@ -158,7 +132,7 @@ public class IgniteCacheP2pUnmarshallingErrorTest extends IgniteCacheAbstractTes
      *
      * @param k Key.
      */
-    protected void failAtomicGet(int k) {
+    protected void failGet(int k) {
         try {
             jcache(0).get(new TestKey(String.valueOf(k)));
 
@@ -175,38 +149,132 @@ public class IgniteCacheP2pUnmarshallingErrorTest extends IgniteCacheAbstractTes
      * @throws Exception If failed.
      */
     public void testResponseMessageOnUnmarshallingFailed() throws Exception {
-        //GridNearAtomicUpdateRequest unmarshalling failed test
+        // GridNearAtomicUpdateRequest unmarshalling failed test.
         readCnt.set(1);
 
         failAtomicPut(++key);
 
-        //Check that cache is empty.
+        // Check that cache is empty.
         readCnt.set(Integer.MAX_VALUE);
 
         assert jcache(0).get(new TestKey(String.valueOf(key))) == null;
 
-        //GridDhtAtomicUpdateRequest unmarshalling failed test
+        // GridDhtAtomicUpdateRequest unmarshalling failed test.
         readCnt.set(2);
 
         failAtomicPut(++key);
 
-        //Check that cache is not empty.
+        // Check that cache is not empty.
         readCnt.set(Integer.MAX_VALUE);
 
         assert jcache(0).get(new TestKey(String.valueOf(key))) != null;
 
-        //GridNearGetRequest unmarshalling failed test
+        // GridNearGetRequest unmarshalling failed test.
         readCnt.set(1);
 
-        failAtomicGet(++key);
+        failGetAll(++key);
 
-        //GridNearGetResponse unmarshalling failed test
+        // GridNearGetResponse unmarshalling failed test.
         readCnt.set(Integer.MAX_VALUE);
 
         jcache(0).put(new TestKey(String.valueOf(++key)), "");
 
         readCnt.set(2);
 
-        failAtomicGet(key);
+        failGetAll(key);
+
+        readCnt.set(Integer.MAX_VALUE);
+        valReadCnt.set(Integer.MAX_VALUE);
+
+        jcache(0).put(new TestKey(String.valueOf(++key)), new TestValue());
+
+        assertNotNull(new TestKey(String.valueOf(key)));
+
+        // GridNearSingleGetRequest unmarshalling failed.
+        readCnt.set(1);
+
+        failGet(key);
+
+        // GridNearSingleGetRequest unmarshalling failed.
+        valReadCnt.set(1);
+        readCnt.set(2);
+
+        failGet(key);
+    }
+
+    /**
+     * Test key.
+     */
+    protected static class TestKey implements Externalizable {
+        /** Field. */
+        @QuerySqlField(index = true)
+        private String field;
+
+        /**
+         * Required by {@link Externalizable}.
+         */
+        public TestKey() {
+            // No-op.
+        }
+
+        /**
+         * @param field Test key 1.
+         */
+        public TestKey(String field) {
+            this.field = field;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object o) {
+            if (this == o)
+                return true;
+            if (o == null || getClass() != o.getClass())
+                return false;
+
+            TestKey key = (TestKey)o;
+
+            return !(field != null ? !field.equals(key.field) : key.field != null);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return field != null ? field.hashCode() : 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(ObjectOutput out) throws IOException {
+            out.writeObject(field);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            field = (String)in.readObject();
+
+            if (readCnt.decrementAndGet() <= 0)
+                throw new IOException("Class can not be unmarshalled.");
+        }
+    }
+
+    /**
+     * Test value.
+     */
+    protected static class TestValue implements Externalizable {
+        /**
+         * Required by {@link Externalizable}.
+         */
+        public TestValue() {
+            // No-op.
+        }
+
+        /** {@inheritDoc} */
+        @Override public void writeExternal(ObjectOutput out) throws IOException {
+            // No-op.
+        }
+
+        /** {@inheritDoc} */
+        @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+            if (valReadCnt.decrementAndGet() <= 0)
+                throw new IOException("Class can not be unmarshalled.");
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetFutureHangsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetFutureHangsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetFutureHangsSelfTest.java
index 53ac648..c005945 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetFutureHangsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/CacheGetFutureHangsSelfTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.cache.distributed;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicReferenceArray;
@@ -29,6 +30,7 @@ import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.marshaller.optimized.OptimizedMarshaller;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
@@ -135,12 +137,16 @@ public class CacheGetFutureHangsSelfTest extends GridCommonAbstractTest {
                     @Override public void run() {
                         T2<Ignite, Integer> ignite;
 
+                        Set<Integer> keys = F.asSet(1, 2, 3, 4, 5);
+
                         while ((ignite = randomNode()) != null) {
                             IgniteCache<Object, Object> cache = ignite.get1().cache(null);
 
                             for (int i = 0; i < 100; i++)
                                 cache.containsKey(ThreadLocalRandom.current().nextInt(100_000));
 
+                            cache.containsKeys(keys);
+
                             assertTrue(nodes.compareAndSet(ignite.get2(), null, ignite.get1()));
 
                             try {

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
index 6f0565b..dbd8758 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheAbstractNodeRestartSelfTest.java
@@ -661,6 +661,8 @@ public abstract class GridCacheAbstractNodeRestartSelfTest extends GridCommonAbs
                                     // It is ok if primary node leaves grid.
                                 }
 
+                                cache.get(key);
+
                                 int c = putCntr.incrementAndGet();
 
                                 if (c % logFreq == 0)

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheSingleGetMessageTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheSingleGetMessageTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheSingleGetMessageTest.java
new file mode 100644
index 0000000..42b5ee3
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/IgniteCacheSingleGetMessageTest.java
@@ -0,0 +1,357 @@
+/*
+ * 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.distributed;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.managers.communication.GridIoMessage;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetRequest;
+import org.apache.ignite.internal.processors.cache.distributed.near.GridNearSingleGetResponse;
+import org.apache.ignite.lang.IgniteInClosure;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.spi.IgniteSpiException;
+import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.transactions.Transaction;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+import static org.apache.ignite.transactions.TransactionConcurrency.OPTIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
+/**
+ *
+ */
+public class IgniteCacheSingleGetMessageTest extends GridCommonAbstractTest {
+    /** */
+    private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final int SRVS = 4;
+
+    /** */
+    private boolean client;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setClientMode(client);
+
+        TestCommunicationSpi commSpi = new TestCommunicationSpi();
+
+        cfg.setCommunicationSpi(commSpi);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
+        startGridsMultiThreaded(SRVS);
+
+        client = true;
+
+        startGridsMultiThreaded(SRVS, 1);
+
+        client = false;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        super.afterTestsStopped();
+
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testSingleGetMessage() throws Exception {
+        assertFalse(ignite(0).configuration().isClientMode());
+        assertTrue(ignite(SRVS).configuration().isClientMode());
+
+        List<CacheConfiguration<Integer, Integer>> ccfgs = cacheConfigurations();
+
+        for (int i = 0; i < ccfgs.size(); i++) {
+            CacheConfiguration<Integer, Integer> ccfg = ccfgs.get(i);
+
+            ccfg.setName("cache-" + i);
+
+            log.info("Test cache: " + i);
+
+            ignite(0).createCache(ccfg);
+
+            try {
+                IgniteCache<Integer, Integer> srvCache = ignite(0).cache(ccfg.getName());
+                IgniteCache<Integer, Integer> clientCache = ignite(SRVS).cache(ccfg.getName());
+
+                Integer key = nearKey(clientCache);
+
+                checkSingleGetMessage(clientCache, key, false);
+
+                if (ccfg.getBackups() > 0) {
+                    key = backupKeys(srvCache, 1, 100_000).get(0);
+
+                    checkSingleGetMessage(srvCache, key, true);
+                }
+
+                if (ccfg.getCacheMode() != REPLICATED) {
+                    key = nearKeys(srvCache, 1, 200_000).get(0);
+
+                    checkSingleGetMessage(srvCache, key, false);
+                }
+            }
+            finally {
+                ignite(0).destroyCache(ccfg.getName());
+            }
+        }
+    }
+
+    /**
+     * @param cache Cache.
+     * @param key Key.
+     * @param backup {@code True} if given key is backup key.
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("unchecked")
+    private void checkSingleGetMessage(IgniteCache<Integer, Integer> cache,
+        Integer key,
+        boolean backup) throws Exception {
+        CacheConfiguration<Integer, Integer> ccfg = cache.getConfiguration(CacheConfiguration.class);
+
+        Ignite node = cache.unwrap(Ignite.class);
+
+        TestCommunicationSpi spi = (TestCommunicationSpi)node.configuration().getCommunicationSpi();
+
+        spi.record(GridNearSingleGetRequest.class);
+
+        Ignite primary = primaryNode(key, cache.getName());
+
+        assertNotSame(node, primary);
+
+        TestCommunicationSpi primarySpi = (TestCommunicationSpi)primary.configuration().getCommunicationSpi();
+
+        primarySpi.record(GridNearSingleGetResponse.class);
+
+        assertNull(cache.get(key));
+
+        checkMessages(spi, primarySpi);
+
+        assertFalse(cache.containsKey(key));
+
+        checkMessages(spi, primarySpi);
+
+        cache.put(key, 1);
+
+        assertNotNull(cache.get(key));
+
+        if (backup)
+            checkNoMessages(spi, primarySpi);
+        else
+            checkMessages(spi, primarySpi);
+
+        assertTrue(cache.containsKey(key));
+
+        if (backup)
+            checkNoMessages(spi, primarySpi);
+        else
+            checkMessages(spi, primarySpi);
+
+        if (ccfg.getAtomicityMode() == TRANSACTIONAL) {
+            cache.remove(key);
+
+            try (Transaction tx = node.transactions().txStart(OPTIMISTIC, REPEATABLE_READ)) {
+                assertNull(cache.get(key));
+
+                tx.commit();
+            }
+
+            checkMessages(spi, primarySpi);
+
+            try (Transaction tx = node.transactions().txStart(OPTIMISTIC, REPEATABLE_READ)) {
+                assertFalse(cache.containsKey(key));
+
+                tx.commit();
+            }
+
+            checkMessages(spi, primarySpi);
+
+            cache.put(key, 1);
+
+            try (Transaction tx = node.transactions().txStart(OPTIMISTIC, REPEATABLE_READ)) {
+                assertNotNull(cache.get(key));
+
+                tx.commit();
+            }
+
+            if (backup)
+                checkNoMessages(spi, primarySpi);
+            else
+                checkMessages(spi, primarySpi);
+
+            try (Transaction tx = node.transactions().txStart(OPTIMISTIC, REPEATABLE_READ)) {
+                assertTrue(cache.containsKey(key));
+
+                tx.commit();
+            }
+
+            if (backup)
+                checkNoMessages(spi, primarySpi);
+            else
+                checkMessages(spi, primarySpi);
+        }
+    }
+
+    /**
+     * @param spi Near node SPI.
+     * @param primarySpi Primary node SPI.
+     */
+    private void checkMessages(TestCommunicationSpi spi, TestCommunicationSpi primarySpi) {
+        List<Object> msgs = spi.recordedMessages();
+
+        assertEquals(1, msgs.size());
+        assertTrue(msgs.get(0) instanceof GridNearSingleGetRequest);
+
+        msgs = primarySpi.recordedMessages();
+
+        assertEquals(1, msgs.size());
+        assertTrue(msgs.get(0) instanceof GridNearSingleGetResponse);
+    }
+
+    /**
+     * @param spi Near node SPI.
+     * @param primarySpi Primary node SPI.
+     */
+    private void checkNoMessages(TestCommunicationSpi spi, TestCommunicationSpi primarySpi) {
+        List<Object> msgs = spi.recordedMessages();
+        assertEquals(0, msgs.size());
+
+        msgs = primarySpi.recordedMessages();
+        assertEquals(0, msgs.size());
+    }
+
+    /**
+     * @return Cache configurations to test.
+     */
+    private List<CacheConfiguration<Integer, Integer>> cacheConfigurations() {
+        List<CacheConfiguration<Integer, Integer>> ccfgs = new ArrayList<>();
+
+        ccfgs.add(cacheConfiguration(PARTITIONED, TRANSACTIONAL, FULL_SYNC, 0));
+        ccfgs.add(cacheConfiguration(PARTITIONED, TRANSACTIONAL, FULL_SYNC, 1));
+        ccfgs.add(cacheConfiguration(REPLICATED, TRANSACTIONAL, FULL_SYNC, 0));
+
+        ccfgs.add(cacheConfiguration(PARTITIONED, ATOMIC, FULL_SYNC, 0));
+        ccfgs.add(cacheConfiguration(PARTITIONED, ATOMIC, FULL_SYNC, 1));
+        ccfgs.add(cacheConfiguration(REPLICATED, ATOMIC, FULL_SYNC, 0));
+
+        return ccfgs;
+    }
+
+    /**
+     * @param cacheMode Cache mode.
+     * @param atomicityMode Cache atomicity mode.
+     * @param syncMode Write synchronization mode.
+     * @param backups Number of backups.
+     * @return Cache configuration.
+     */
+    private CacheConfiguration<Integer, Integer> cacheConfiguration(
+        CacheMode cacheMode,
+        CacheAtomicityMode atomicityMode,
+        CacheWriteSynchronizationMode syncMode,
+        int backups) {
+        CacheConfiguration<Integer, Integer> ccfg = new CacheConfiguration<>();
+
+        ccfg.setCacheMode(cacheMode);
+        ccfg.setAtomicityMode(atomicityMode);
+        ccfg.setAtomicityMode(TRANSACTIONAL);
+        ccfg.setWriteSynchronizationMode(syncMode);
+
+        if (cacheMode == PARTITIONED)
+            ccfg.setBackups(backups);
+
+        return ccfg;
+    }
+
+    /**
+     *
+     */
+    private static class TestCommunicationSpi extends TcpCommunicationSpi {
+        /** */
+        private Class<?> recordCls;
+
+        /** */
+        private List<Object> recordedMsgs = new ArrayList<>();
+
+        /** {@inheritDoc} */
+        @Override public void sendMessage(ClusterNode node, Message msg, IgniteInClosure<IgniteException> ackC)
+            throws IgniteSpiException {
+            if (msg instanceof GridIoMessage) {
+                Object msg0 = ((GridIoMessage)msg).message();
+
+                synchronized (this) {
+                    if (recordCls != null && msg0.getClass().equals(recordCls))
+                        recordedMsgs.add(msg0);
+                }
+            }
+
+            super.sendMessage(node, msg, ackC);
+        }
+
+        /**
+         * @param recordCls Message class to record.
+         */
+        void record(@Nullable Class<?> recordCls) {
+            synchronized (this) {
+                this.recordCls = recordCls;
+            }
+        }
+
+        /**
+         * @return Recorded messages.
+         */
+        List<Object> recordedMessages() {
+            synchronized (this) {
+                List<Object> msgs = recordedMsgs;
+
+                recordedMsgs = new ArrayList<>();
+
+                return msgs;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedMetricsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedMetricsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedMetricsSelfTest.java
index 319aa56..2fa43be 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedMetricsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/GridCacheReplicatedMetricsSelfTest.java
@@ -18,7 +18,6 @@
 package org.apache.ignite.internal.processors.cache.distributed.replicated;
 
 import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.processors.cache.GridCacheTransactionalAbstractMetricsSelfTest;
 
 import static org.apache.ignite.cache.CacheMode.REPLICATED;
@@ -30,14 +29,6 @@ public class GridCacheReplicatedMetricsSelfTest extends GridCacheTransactionalAb
     /** */
     private static final int GRID_CNT = 2;
 
-    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
-        IgniteConfiguration c = super.getConfiguration(gridName);
-
-        c.getTransactionConfiguration().setTxSerializableEnabled(true);
-
-        return c;
-    }
-
     /** {@inheritDoc} */
     @Override protected CacheConfiguration cacheConfiguration(String gridName) throws Exception {
         CacheConfiguration cfg = super.cacheConfiguration(gridName);

http://git-wip-us.apache.org/repos/asf/ignite/blob/1f103067/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
index b89bffd..fcc8d37 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite4.java
@@ -81,6 +81,7 @@ import org.apache.ignite.internal.processors.cache.distributed.CacheGetFutureHan
 import org.apache.ignite.internal.processors.cache.distributed.CacheNoValueClassOnServerNodeTest;
 import org.apache.ignite.internal.processors.cache.distributed.IgniteCacheCreatePutMultiNodeSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.IgniteCacheCreatePutTest;
+import org.apache.ignite.internal.processors.cache.distributed.IgniteCacheSingleGetMessageTest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridCacheDhtTxPreloadSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.IgniteCacheLockFailoverSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.dht.IgniteCacheMultiTxLockSelfTest;
@@ -283,6 +284,8 @@ public class IgniteCacheTestSuite4 extends TestSuite {
 
         suite.addTestSuite(CacheGetFutureHangsSelfTest.class);
 
+        suite.addTestSuite(IgniteCacheSingleGetMessageTest.class);
+
         return suite;
     }
 }
\ No newline at end of file