You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/11/21 12:09:55 UTC

[01/47] ignite git commit: IGNITE-6752: JDBC thin: connection properties refactoring. This closes #2927.

Repository: ignite
Updated Branches:
  refs/heads/ignite-zk fcee8c846 -> 1f82a5311


IGNITE-6752: JDBC thin: connection properties refactoring. This closes #2927.


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

Branch: refs/heads/ignite-zk
Commit: 69acdaaaa3ef8bd5964f881707fc58d84bf8e5b4
Parents: 85027e7
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Mon Nov 13 15:37:02 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Nov 13 15:37:02 2017 +0300

----------------------------------------------------------------------
 .../thin/JdbcThinAutoCloseServerCursorTest.java |   4 +-
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   | 155 ++---
 .../org/apache/ignite/IgniteJdbcDriver.java     |  29 +-
 .../org/apache/ignite/IgniteJdbcThinDriver.java |  35 +-
 .../jdbc/thin/ConnectionProperties.java         | 148 +++++
 .../jdbc/thin/ConnectionPropertiesImpl.java     | 637 +++++++++++++++++++
 .../internal/jdbc/thin/JdbcThinConnection.java  | 163 +----
 .../internal/jdbc/thin/JdbcThinTcpIo.java       | 195 ++----
 .../internal/jdbc/thin/JdbcThinUtils.java       |  79 +--
 9 files changed, 945 insertions(+), 500 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAutoCloseServerCursorTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAutoCloseServerCursorTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAutoCloseServerCursorTest.java
index db4ed3f..943ca0e 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAutoCloseServerCursorTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinAutoCloseServerCursorTest.java
@@ -29,7 +29,6 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -51,8 +50,7 @@ public class JdbcThinAutoCloseServerCursorTest extends JdbcThinAbstractSelfTest
     private static final String CACHE_NAME = "cache";
 
     /** URL. */
-    private static final String URL = "jdbc:ignite:thin://127.0.0.1/?" +
-        JdbcThinUtils.PARAM_AUTO_CLOSE_SERVER_CURSOR + "=true";
+    private static final String URL = "jdbc:ignite:thin://127.0.0.1/?autoCloseServerCursor=true";
 
     /** {@inheritDoc} */
     @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
index 7f67136..0cf6ab6 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java
@@ -135,9 +135,10 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
         assertInvalid("jdbc:ignite:thin://:10000", "Host name is empty");
         assertInvalid("jdbc:ignite:thin://     :10000", "Host name is empty");
 
-        assertInvalid("jdbc:ignite:thin://127.0.0.1:-1", "Invalid port");
-        assertInvalid("jdbc:ignite:thin://127.0.0.1:0", "Invalid port");
-        assertInvalid("jdbc:ignite:thin://127.0.0.1:100000", "Invalid port");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1:-1", "Property cannot be lower than 1 [name=port, value=-1]");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1:0", "Property cannot be lower than 1 [name=port, value=0]");
+        assertInvalid("jdbc:ignite:thin://127.0.0.1:100000",
+            "Property cannot be upper than 65535 [name=port, value=100000]");
     }
 
     /**
@@ -147,31 +148,31 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      */
     public void testSocketBuffers() throws Exception {
         assertInvalid("jdbc:ignite:thin://127.0.0.1?socketSendBuffer=-1",
-            "Property cannot be negative [name=" + JdbcThinUtils.PARAM_SOCK_SND_BUF);
+            "Property cannot be lower than 0 [name=socketSendBuffer, value=-1]");
 
         assertInvalid("jdbc:ignite:thin://127.0.0.1?socketReceiveBuffer=-1",
-            "Property cannot be negative [name=" + JdbcThinUtils.PARAM_SOCK_RCV_BUF);
+            "Property cannot be lower than 0 [name=socketReceiveBuffer, value=-1]");
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
-            assertEquals(0, io(conn).socketSendBuffer());
-            assertEquals(0, io(conn).socketReceiveBuffer());
+            assertEquals(0, io(conn).connectionProperties().getSocketSendBuffer());
+            assertEquals(0, io(conn).connectionProperties().getSocketReceiveBuffer());
         }
 
         // Note that SO_* options are hints, so we check that value is equals to either what we set or to default.
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?socketSendBuffer=1024")) {
-            assertEquals(1024, io(conn).socketSendBuffer());
-            assertEquals(0, io(conn).socketReceiveBuffer());
+            assertEquals(1024, io(conn).connectionProperties().getSocketSendBuffer());
+            assertEquals(0, io(conn).connectionProperties().getSocketReceiveBuffer());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?socketReceiveBuffer=1024")) {
-            assertEquals(0, io(conn).socketSendBuffer());
-            assertEquals(1024, io(conn).socketReceiveBuffer());
+            assertEquals(0, io(conn).connectionProperties().getSocketSendBuffer());
+            assertEquals(1024, io(conn).connectionProperties().getSocketReceiveBuffer());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?" +
             "socketSendBuffer=1024&socketReceiveBuffer=2048")) {
-            assertEquals(1024, io(conn).socketSendBuffer());
-            assertEquals(2048, io(conn).socketReceiveBuffer());
+            assertEquals(1024, io(conn).connectionProperties().getSocketSendBuffer());
+            assertEquals(2048, io(conn).connectionProperties().getSocketReceiveBuffer());
         }
     }
 
@@ -182,76 +183,76 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      */
     public void testSqlHints() throws Exception {
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
-            assertFalse(io(conn).distributedJoins());
-            assertFalse(io(conn).enforceJoinOrder());
-            assertFalse(io(conn).collocated());
-            assertFalse(io(conn).replicatedOnly());
-            assertFalse(io(conn).lazy());
-            assertFalse(io(conn).skipReducerOnUpdate());
+            assertFalse(io(conn).connectionProperties().isDistributedJoins());
+            assertFalse(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertFalse(io(conn).connectionProperties().isCollocated());
+            assertFalse(io(conn).connectionProperties().isReplicatedOnly());
+            assertFalse(io(conn).connectionProperties().isLazy());
+            assertFalse(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?distributedJoins=true")) {
-            assertTrue(io(conn).distributedJoins());
-            assertFalse(io(conn).enforceJoinOrder());
-            assertFalse(io(conn).collocated());
-            assertFalse(io(conn).replicatedOnly());
-            assertFalse(io(conn).lazy());
-            assertFalse(io(conn).skipReducerOnUpdate());
+            assertTrue(io(conn).connectionProperties().isDistributedJoins());
+            assertFalse(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertFalse(io(conn).connectionProperties().isCollocated());
+            assertFalse(io(conn).connectionProperties().isReplicatedOnly());
+            assertFalse(io(conn).connectionProperties().isLazy());
+            assertFalse(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?enforceJoinOrder=true")) {
-            assertFalse(io(conn).distributedJoins());
-            assertTrue(io(conn).enforceJoinOrder());
-            assertFalse(io(conn).collocated());
-            assertFalse(io(conn).replicatedOnly());
-            assertFalse(io(conn).lazy());
-            assertFalse(io(conn).skipReducerOnUpdate());
+            assertFalse(io(conn).connectionProperties().isDistributedJoins());
+            assertTrue(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertFalse(io(conn).connectionProperties().isCollocated());
+            assertFalse(io(conn).connectionProperties().isReplicatedOnly());
+            assertFalse(io(conn).connectionProperties().isLazy());
+            assertFalse(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?collocated=true")) {
-            assertFalse(io(conn).distributedJoins());
-            assertFalse(io(conn).enforceJoinOrder());
-            assertTrue(io(conn).collocated());
-            assertFalse(io(conn).replicatedOnly());
-            assertFalse(io(conn).lazy());
-            assertFalse(io(conn).skipReducerOnUpdate());
+            assertFalse(io(conn).connectionProperties().isDistributedJoins());
+            assertFalse(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertTrue(io(conn).connectionProperties().isCollocated());
+            assertFalse(io(conn).connectionProperties().isReplicatedOnly());
+            assertFalse(io(conn).connectionProperties().isLazy());
+            assertFalse(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?replicatedOnly=true")) {
-            assertFalse(io(conn).distributedJoins());
-            assertFalse(io(conn).enforceJoinOrder());
-            assertFalse(io(conn).collocated());
-            assertTrue(io(conn).replicatedOnly());
-            assertFalse(io(conn).lazy());
-            assertFalse(io(conn).skipReducerOnUpdate());
+            assertFalse(io(conn).connectionProperties().isDistributedJoins());
+            assertFalse(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertFalse(io(conn).connectionProperties().isCollocated());
+            assertTrue(io(conn).connectionProperties().isReplicatedOnly());
+            assertFalse(io(conn).connectionProperties().isLazy());
+            assertFalse(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?lazy=true")) {
-            assertFalse(io(conn).distributedJoins());
-            assertFalse(io(conn).enforceJoinOrder());
-            assertFalse(io(conn).collocated());
-            assertFalse(io(conn).replicatedOnly());
-            assertTrue(io(conn).lazy());
-            assertFalse(io(conn).skipReducerOnUpdate());
+            assertFalse(io(conn).connectionProperties().isDistributedJoins());
+            assertFalse(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertFalse(io(conn).connectionProperties().isCollocated());
+            assertFalse(io(conn).connectionProperties().isReplicatedOnly());
+            assertTrue(io(conn).connectionProperties().isLazy());
+            assertFalse(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?skipReducerOnUpdate=true")) {
-            assertFalse(io(conn).distributedJoins());
-            assertFalse(io(conn).enforceJoinOrder());
-            assertFalse(io(conn).collocated());
-            assertFalse(io(conn).replicatedOnly());
-            assertFalse(io(conn).lazy());
-            assertTrue(io(conn).skipReducerOnUpdate());
+            assertFalse(io(conn).connectionProperties().isDistributedJoins());
+            assertFalse(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertFalse(io(conn).connectionProperties().isCollocated());
+            assertFalse(io(conn).connectionProperties().isReplicatedOnly());
+            assertFalse(io(conn).connectionProperties().isLazy());
+            assertTrue(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?distributedJoins=true&" +
             "enforceJoinOrder=true&collocated=true&replicatedOnly=true&lazy=true&skipReducerOnUpdate=true")) {
-            assertTrue(io(conn).distributedJoins());
-            assertTrue(io(conn).enforceJoinOrder());
-            assertTrue(io(conn).collocated());
-            assertTrue(io(conn).replicatedOnly());
-            assertTrue(io(conn).lazy());
-            assertTrue(io(conn).skipReducerOnUpdate());
+            assertTrue(io(conn).connectionProperties().isDistributedJoins());
+            assertTrue(io(conn).connectionProperties().isEnforceJoinOrder());
+            assertTrue(io(conn).connectionProperties().isCollocated());
+            assertTrue(io(conn).connectionProperties().isReplicatedOnly());
+            assertTrue(io(conn).connectionProperties().isLazy());
+            assertTrue(io(conn).connectionProperties().isSkipReducerOnUpdate());
         }
     }
 
@@ -262,35 +263,35 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      */
     public void testTcpNoDelay() throws Exception {
         assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=0",
-            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
+            "Failed to parse boolean property [name=tcpNoDelay, value=0]");
 
         assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=1",
-            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
+            "Failed to parse boolean property [name=tcpNoDelay, value=1]");
 
         assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=false1",
-            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
+            "Failed to parse boolean property [name=tcpNoDelay, value=false1]");
 
         assertInvalid("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=true1",
-            "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_TCP_NO_DELAY);
+            "Failed to parse boolean property [name=tcpNoDelay, value=true1]");
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
-            assertTrue(io(conn).tcpNoDelay());
+            assertTrue(io(conn).connectionProperties().isTcpNoDelay());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=true")) {
-            assertTrue(io(conn).tcpNoDelay());
+            assertTrue(io(conn).connectionProperties().isTcpNoDelay());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=True")) {
-            assertTrue(io(conn).tcpNoDelay());
+            assertTrue(io(conn).connectionProperties().isTcpNoDelay());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=false")) {
-            assertFalse(io(conn).tcpNoDelay());
+            assertFalse(io(conn).connectionProperties().isTcpNoDelay());
         }
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1?tcpNoDelay=False")) {
-            assertFalse(io(conn).tcpNoDelay());
+            assertFalse(io(conn).connectionProperties().isTcpNoDelay());
         }
     }
 
@@ -300,9 +301,9 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
      * @throws Exception If failed.
      */
     public void testAutoCloseServerCursorProperty() throws Exception {
-        String url = "jdbc:ignite:thin://127.0.0.1?" + JdbcThinUtils.PARAM_AUTO_CLOSE_SERVER_CURSOR;
+        String url = "jdbc:ignite:thin://127.0.0.1?autoCloseServerCursor";
 
-        String err = "Failed to parse boolean property [name=" + JdbcThinUtils.PARAM_AUTO_CLOSE_SERVER_CURSOR;
+        String err = "Failed to parse boolean property [name=autoCloseServerCursor";
 
         assertInvalid(url + "=0", err);
         assertInvalid(url + "=1", err);
@@ -310,23 +311,23 @@ public class JdbcThinConnectionSelfTest extends JdbcThinAbstractSelfTest {
         assertInvalid(url + "=true1", err);
 
         try (Connection conn = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1")) {
-            assertFalse(io(conn).autoCloseServerCursor());
+            assertFalse(io(conn).connectionProperties().isAutoCloseServerCursor());
         }
 
         try (Connection conn = DriverManager.getConnection(url + "=true")) {
-            assertTrue(io(conn).autoCloseServerCursor());
+            assertTrue(io(conn).connectionProperties().isAutoCloseServerCursor());
         }
 
         try (Connection conn = DriverManager.getConnection(url + "=True")) {
-            assertTrue(io(conn).autoCloseServerCursor());
+            assertTrue(io(conn).connectionProperties().isAutoCloseServerCursor());
         }
 
         try (Connection conn = DriverManager.getConnection(url + "=false")) {
-            assertFalse(io(conn).autoCloseServerCursor());
+            assertFalse(io(conn).connectionProperties().isAutoCloseServerCursor());
         }
 
         try (Connection conn = DriverManager.getConnection(url + "=False")) {
-            assertFalse(io(conn).autoCloseServerCursor());
+            assertFalse(io(conn).connectionProperties().isAutoCloseServerCursor());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
index ea9b7f8..8195bd4 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
@@ -30,7 +30,6 @@ import java.util.logging.Logger;
 import org.apache.ignite.cache.affinity.AffinityKey;
 import org.apache.ignite.internal.jdbc.JdbcConnection;
 import org.apache.ignite.internal.jdbc.JdbcDriverPropertyInfo;
-import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
 import org.apache.ignite.logger.java.JavaLogger;
 
 /**
@@ -304,12 +303,6 @@ public class IgniteJdbcDriver implements Driver {
     /** Collocated parameter name. */
     private static final String PARAM_COLLOCATED = "collocated";
 
-    /** Parameter: enforce join order flag. */
-    public static final String PARAM_ENFORCE_JOIN_ORDER = "enforceJoinOrder";
-
-    /** Parameter: lazy query execution flag. */
-    public static final String PARAM_LAZY = "lazy";
-
     /** Distributed joins parameter name. */
     private static final String PARAM_DISTRIBUTED_JOINS = "distributedJoins";
 
@@ -337,6 +330,12 @@ public class IgniteJdbcDriver implements Driver {
     /** Skip reducer on update property name. */
     private static final String PARAM_SKIP_REDUCER_ON_UPDATE = "skipReducerOnUpdate";
 
+    /** Parameter: enforce join order flag (SQL hint). */
+    public static final String PARAM_ENFORCE_JOIN_ORDER = "enforceJoinOrder";
+
+    /** Parameter: replicated only flag (SQL hint). */
+    public static final String PARAM_LAZY = "lazy";
+
     /** Hostname property name. */
     public static final String PROP_HOST = PROP_PREFIX + "host";
 
@@ -358,12 +357,6 @@ public class IgniteJdbcDriver implements Driver {
     /** Distributed joins property name. */
     public static final String PROP_DISTRIBUTED_JOINS = PROP_PREFIX + PARAM_DISTRIBUTED_JOINS;
 
-    /** Enforce join order property name. */
-    public static final String PROP_ENFORCE_JOIN_ORDER = PROP_PREFIX + PARAM_ENFORCE_JOIN_ORDER;
-
-    /** Lazy query execution property name. */
-    public static final String PROP_LAZY = PROP_PREFIX + PARAM_LAZY;
-
     /** Transactions allowed property name. */
     public static final String PROP_TX_ALLOWED = PROP_PREFIX + PARAM_TX_ALLOWED;
 
@@ -388,6 +381,12 @@ public class IgniteJdbcDriver implements Driver {
     /** Skip reducer on update update property name. */
     public static final String PROP_SKIP_REDUCER_ON_UPDATE = PROP_PREFIX + PARAM_SKIP_REDUCER_ON_UPDATE;
 
+    /** Transactions allowed property name. */
+    public static final String PROP_ENFORCE_JOIN_ORDER = PROP_PREFIX + PARAM_ENFORCE_JOIN_ORDER;
+
+    /** Lazy property name. */
+    public static final String PROP_LAZY = PROP_PREFIX + PARAM_LAZY;
+
     /** Cache name property name. */
     public static final String PROP_CFG = PROP_PREFIX + "cfg";
 
@@ -457,8 +456,8 @@ public class IgniteJdbcDriver implements Driver {
             new JdbcDriverPropertyInfo("Local", info.getProperty(PROP_LOCAL), ""),
             new JdbcDriverPropertyInfo("Collocated", info.getProperty(PROP_COLLOCATED), ""),
             new JdbcDriverPropertyInfo("Distributed Joins", info.getProperty(PROP_DISTRIBUTED_JOINS), ""),
-            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER), ""),
-            new JdbcDriverPropertyInfo("Lazy query execution", info.getProperty(JdbcThinUtils.PROP_LAZY), ""),
+            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(PROP_ENFORCE_JOIN_ORDER), ""),
+            new JdbcDriverPropertyInfo("Lazy query execution", info.getProperty(PROP_LAZY), ""),
             new JdbcDriverPropertyInfo("Transactions Allowed", info.getProperty(PROP_TX_ALLOWED), ""),
             new JdbcDriverPropertyInfo("Queries with multiple statements allowed", info.getProperty(PROP_MULTIPLE_STMTS), ""),
             new JdbcDriverPropertyInfo("Skip reducer on update", info.getProperty(PROP_SKIP_REDUCER_ON_UPDATE), "")

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
index a313f92..03f126f 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcThinDriver.java
@@ -23,17 +23,17 @@ import java.sql.DriverManager;
 import java.sql.DriverPropertyInfo;
 import java.sql.SQLException;
 import java.sql.SQLFeatureNotSupportedException;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Properties;
 import java.util.logging.Logger;
 import org.apache.ignite.cache.affinity.AffinityKey;
 import org.apache.ignite.internal.IgniteVersionUtils;
-import org.apache.ignite.internal.jdbc.JdbcDriverPropertyInfo;
+import org.apache.ignite.internal.jdbc.thin.ConnectionPropertiesImpl;
 import org.apache.ignite.internal.jdbc.thin.JdbcThinConnection;
 import org.apache.ignite.internal.jdbc.thin.JdbcThinUtils;
 import org.apache.ignite.internal.util.typedef.F;
 
+import static org.apache.ignite.internal.jdbc.thin.ConnectionPropertiesImpl.PROP_PREFIX;
+
 /**
  * JDBC driver thin implementation for In-Memory Data Grid.
  * <p>
@@ -130,18 +130,6 @@ import org.apache.ignite.internal.util.typedef.F;
  */
 @SuppressWarnings("JavadocReference")
 public class IgniteJdbcThinDriver implements Driver {
-    /*
-     * Static initializer.
-     */
-    static {
-        try {
-            DriverManager.registerDriver(new IgniteJdbcThinDriver());
-        }
-        catch (SQLException e) {
-            throw new RuntimeException("Failed to register " + IgniteJdbcThinDriver.class.getName(), e);
-        }
-    }
-
     /** Major version. */
     private static final int MAJOR_VER = IgniteVersionUtils.VER.major();
 
@@ -167,7 +155,7 @@ public class IgniteJdbcThinDriver implements Driver {
 
         String schema = parseUrl(url, props);
 
-        return new JdbcThinConnection(url, props, schema);
+        return new JdbcThinConnection(url, schema, props);
     }
 
     /** {@inheritDoc} */
@@ -179,18 +167,7 @@ public class IgniteJdbcThinDriver implements Driver {
     @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
         parseUrl(url, info);
 
-        List<DriverPropertyInfo> props = Arrays.<DriverPropertyInfo>asList(
-            new JdbcDriverPropertyInfo("Hostname", info.getProperty(JdbcThinUtils.PROP_HOST), ""),
-            new JdbcDriverPropertyInfo("Port number", info.getProperty(JdbcThinUtils.PROP_PORT), ""),
-            new JdbcDriverPropertyInfo("Distributed Joins", info.getProperty(JdbcThinUtils.PROP_DISTRIBUTED_JOINS), ""),
-            new JdbcDriverPropertyInfo("Enforce Join Order", info.getProperty(JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER), ""),
-            new JdbcDriverPropertyInfo("Collocated", info.getProperty(JdbcThinUtils.PROP_COLLOCATED), ""),
-            new JdbcDriverPropertyInfo("Replicated only", info.getProperty(JdbcThinUtils.PROP_REPLICATED_ONLY), ""),
-            new JdbcDriverPropertyInfo("Lazy query execution flag", info.getProperty(JdbcThinUtils.PROP_LAZY),""),
-            new JdbcDriverPropertyInfo("Skip reducer on update", info.getProperty(JdbcThinUtils.PROP_SKIP_REDUCER_ON_UPDATE),"")
-        );
-
-        return props.toArray(new DriverPropertyInfo[0]);
+        return ConnectionPropertiesImpl.getDriverPropertyInfo(info);
     }
 
     /** {@inheritDoc} */
@@ -285,7 +262,7 @@ public class IgniteJdbcThinDriver implements Driver {
             if (key.isEmpty() || val.isEmpty())
                 throw new SQLException("Invalid parameter format (key and value cannot be empty): " + param);
 
-            props.setProperty(JdbcThinUtils.PROP_PREFIX + key, val);
+            props.setProperty(PROP_PREFIX + key, val);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
new file mode 100644
index 0000000..d793484
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionProperties.java
@@ -0,0 +1,148 @@
+/*
+ * 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.jdbc.thin;
+
+import java.sql.SQLException;
+
+/**
+ * Provide access and manipulations with connection JDBC properties.
+ */
+public interface ConnectionProperties {
+    /**
+     * @return Host name or host's IP to connect.
+     */
+    public String getHost();
+
+    /**
+     * @param host Host name or host's IP to connect.
+     */
+    public void setHost(String host);
+
+    /**
+     * @return Port to connect.
+     */
+    public int getPort();
+
+    /**
+     * @param port Port to connect.
+     * @throws SQLException On error.
+     */
+    public void setPort(int port) throws SQLException;
+
+    /**
+     * @return Distributed joins flag.
+     */
+    public boolean isDistributedJoins();
+
+    /**
+     * @param distributedJoins Distributed joins flag.
+     */
+    public void setDistributedJoins(boolean distributedJoins);
+
+    /**
+     * @return Enforce join order flag.
+     */
+    public boolean isEnforceJoinOrder();
+
+    /**
+     * @param enforceJoinOrder Enforce join order flag.
+     */
+    public void setEnforceJoinOrder(boolean enforceJoinOrder);
+
+    /**
+     * @return Collocated flag.
+     */
+    public boolean isCollocated();
+
+    /**
+     * @param collocated Collocated flag.
+     */
+    public void setCollocated(boolean collocated);
+
+    /**
+     * @return Replicated only flag.
+     */
+    public boolean isReplicatedOnly();
+
+    /**
+     * @param replicatedOnly Replicated only flag.
+     */
+    public void setReplicatedOnly(boolean replicatedOnly);
+
+    /**
+     * @return Auto close server cursors flag.
+     */
+    public boolean isAutoCloseServerCursor();
+
+    /**
+     * @param autoCloseServerCursor Auto close server cursors flag.
+     */
+    public void setAutoCloseServerCursor(boolean autoCloseServerCursor);
+
+    /**
+     * @return Socket send buffer size.
+     */
+    public int getSocketSendBuffer();
+
+    /**
+     * @param size Socket send buffer size.
+     * @throws SQLException On error.
+     */
+    public void setSocketSendBuffer(int size) throws SQLException;
+
+    /**
+     * @return Socket receive buffer size.
+     */
+    public int getSocketReceiveBuffer();
+
+    /**
+     * @param size Socket receive buffer size.
+     * @throws SQLException On error.
+     */
+    public void setSocketReceiveBuffer(int size) throws SQLException;
+
+    /**
+     * @return TCP no delay flag.
+     */
+    public boolean isTcpNoDelay();
+
+    /**
+     * @param tcpNoDelay TCP no delay flag.
+     */
+    public void setTcpNoDelay(boolean tcpNoDelay);
+
+    /**
+     * @return Lazy query execution flag.
+     */
+    public boolean isLazy();
+
+    /**
+     * @param lazy Lazy query execution flag.
+     */
+    public void setLazy(boolean lazy);
+
+    /**
+     * @return Skip reducer on update flag.
+     */
+    public boolean isSkipReducerOnUpdate();
+
+    /**
+     * @param skipReducerOnUpdate Skip reducer on update flag.
+     */
+    public void setSkipReducerOnUpdate(boolean skipReducerOnUpdate);
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
new file mode 100644
index 0000000..86ba2fa
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/ConnectionPropertiesImpl.java
@@ -0,0 +1,637 @@
+/*
+ * 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.jdbc.thin;
+
+import java.io.Serializable;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Properties;
+import javax.naming.RefAddr;
+import javax.naming.Reference;
+import org.apache.ignite.configuration.ClientConnectorConfiguration;
+import org.apache.ignite.internal.processors.odbc.SqlStateCode;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * Holds JDBC connection properties.
+ */
+public class ConnectionPropertiesImpl implements ConnectionProperties, Serializable {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Prefix for property names. */
+    public static final String PROP_PREFIX = "ignite.jdbc.";
+
+    /** Host name property. */
+    private StringProperty host = new StringProperty(
+        "host", "Ignite node IP to connect", null, null, true, new PropertyValidator() {
+        private static final long serialVersionUID = 0L;
+
+        @Override public void validate(String host) throws SQLException {
+            if (F.isEmpty(host))
+                throw new SQLException("Host name is empty", SqlStateCode.CLIENT_CONNECTION_FAILED);
+        }
+    });
+
+    /** Connection port property. */
+    private IntegerProperty port = new IntegerProperty(
+        "port", "Ignite node IP to connect", ClientConnectorConfiguration.DFLT_PORT, false, 1, 0xFFFF);
+
+    /** Distributed joins property. */
+    private BooleanProperty distributedJoins = new BooleanProperty(
+        "distributedJoins", "Enable distributed joins", false, false);
+
+    /** Enforce join order property. */
+    private BooleanProperty enforceJoinOrder = new BooleanProperty(
+        "enforceJoinOrder", "Enable enforce join order", false, false);
+
+    /** Collocated property. */
+    private BooleanProperty collocated = new BooleanProperty(
+        "collocated", "Enable collocated query", false, false);
+
+    /** Replicated only property. */
+    private BooleanProperty replicatedOnly = new BooleanProperty(
+        "replicatedOnly", "Specify if the all queries contain only replicated tables", false, false);
+
+    /** Auto close server cursor property. */
+    private BooleanProperty autoCloseServerCursor = new BooleanProperty(
+        "autoCloseServerCursor", "Enable auto close server cursors when last piece of result set is retrieved. " +
+        "If the server-side cursor is already closed, you may get an exception when trying to call " +
+        "`ResultSet.getMetadata()` method.", false, false);
+
+    /** TCP no delay property. */
+    private BooleanProperty tcpNoDelay = new BooleanProperty(
+        "tcpNoDelay", "TCP no delay flag", true, false);
+
+    /** Lazy query execution property. */
+    private BooleanProperty lazy = new BooleanProperty(
+        "lazy", "Enable lazy query execution", false, false);
+
+    /** Socket send buffer size property. */
+    private IntegerProperty socketSendBuffer = new IntegerProperty(
+        "socketSendBuffer", "Socket send buffer size",
+        0, false, 0, Integer.MAX_VALUE);
+
+    /** Socket receive buffer size property. */
+    private IntegerProperty socketReceiveBuffer = new IntegerProperty(
+        "socketReceiveBuffer", "Socket send buffer size",
+        0, false, 0, Integer.MAX_VALUE);
+
+    /** Executes update queries on ignite server nodes flag. */
+    private BooleanProperty skipReducerOnUpdate = new BooleanProperty(
+        "skipReducerOnUpdate", "Enable execution update queries on ignite server nodes", false, false);
+
+    /** Properties array. */
+    private final ConnectionProperty [] propsArray = {
+        host, port,
+        distributedJoins, enforceJoinOrder, collocated, replicatedOnly, autoCloseServerCursor,
+        tcpNoDelay, lazy, socketSendBuffer, socketReceiveBuffer, skipReducerOnUpdate
+    };
+
+    /** {@inheritDoc} */
+    @Override public String getHost() {
+        return host.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setHost(String host) {
+        this.host.setValue(host);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getPort() {
+        return port.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setPort(int port) throws SQLException {
+        this.port.setValue(port);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributedJoins() {
+        return distributedJoins.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setDistributedJoins(boolean val) {
+        distributedJoins.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isEnforceJoinOrder() {
+        return enforceJoinOrder.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setEnforceJoinOrder(boolean val) {
+        enforceJoinOrder.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isCollocated() {
+        return collocated.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setCollocated(boolean val) {
+        collocated.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isReplicatedOnly() {
+        return replicatedOnly.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setReplicatedOnly(boolean val) {
+        replicatedOnly.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isAutoCloseServerCursor() {
+        return autoCloseServerCursor.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setAutoCloseServerCursor(boolean val) {
+        autoCloseServerCursor.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getSocketSendBuffer() {
+        return socketSendBuffer.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setSocketSendBuffer(int size) throws SQLException {
+        socketSendBuffer.setValue(size);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getSocketReceiveBuffer() {
+        return socketReceiveBuffer.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setSocketReceiveBuffer(int size) throws SQLException {
+        socketReceiveBuffer.setValue(size);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isTcpNoDelay() {
+        return tcpNoDelay.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTcpNoDelay(boolean val) {
+        tcpNoDelay.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isLazy() {
+        return lazy.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setLazy(boolean val) {
+        lazy.setValue(val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSkipReducerOnUpdate() {
+        return skipReducerOnUpdate.value();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setSkipReducerOnUpdate(boolean val) {
+        skipReducerOnUpdate.setValue(val);
+    }
+
+    /**
+     * @param props Environment properties.
+     * @throws SQLException On error.
+     */
+    void init(Properties props) throws SQLException {
+        Properties props0 = (Properties)props.clone();
+
+        for (ConnectionProperty aPropsArray : propsArray)
+            aPropsArray.init(props0);
+    }
+
+    /**
+     * @return Driver's properties info array.
+     */
+    private DriverPropertyInfo[] getDriverPropertyInfo() {
+        DriverPropertyInfo[] dpis = new DriverPropertyInfo[propsArray.length];
+
+        for (int i = 0; i < propsArray.length; ++i)
+            dpis[i] = propsArray[i].getDriverPropertyInfo();
+
+        return dpis;
+    }
+
+    /**
+     * @param props Environment properties.
+     * @return Driver's properties info array.
+     * @throws SQLException On error.
+     */
+    public static DriverPropertyInfo[] getDriverPropertyInfo(Properties props) throws SQLException {
+        ConnectionPropertiesImpl cpi = new ConnectionPropertiesImpl();
+
+        cpi.init(props);
+
+        return cpi.getDriverPropertyInfo();
+    }
+
+    /**
+     *
+     */
+    private interface PropertyValidator extends Serializable {
+        /**
+         * @param val String representation of the property value to validate.
+         * @throws SQLException On validation fails.
+         */
+        void validate(String val) throws SQLException;
+    }
+
+    /**
+     *
+     */
+    private abstract static class ConnectionProperty implements Serializable {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Name. */
+        protected String name;
+
+        /** Property description. */
+        protected String desc;
+
+        /** Default value. */
+        protected Object dfltVal;
+
+        /**
+         * An array of possible values if the value may be selected
+         * from a particular set of values; otherwise null.
+         */
+        protected String [] choices;
+
+        /** Required flag. */
+        protected boolean required;
+
+        /** Property validator. */
+        protected PropertyValidator validator;
+
+        /**
+         * @param name Name.
+         * @param desc Description.
+         * @param dfltVal Default value.
+         * @param choices Possible values.
+         * @param required {@code true} if the property is required.
+         */
+        ConnectionProperty(String name, String desc, Object dfltVal, String[] choices, boolean required) {
+            this.name = name;
+            this.desc= desc;
+            this.dfltVal = dfltVal;
+            this.choices = choices;
+            this.required = required;
+        }
+
+        /**
+         * @param name Name.
+         * @param desc Description.
+         * @param dfltVal Default value.
+         * @param choices Possible values.
+         * @param required {@code true} if the property is required.
+         * @param validator Property validator.
+         */
+        ConnectionProperty(String name, String desc, Object dfltVal, String[] choices, boolean required,
+            PropertyValidator validator) {
+            this.name = name;
+            this.desc= desc;
+            this.dfltVal = dfltVal;
+            this.choices = choices;
+            this.required = required;
+            this.validator = validator;
+        }
+
+        /**
+         * @return Default value.
+         */
+        Object getDfltVal() {
+            return dfltVal;
+        }
+
+        /**
+         * @return Property name.
+         */
+        String getName() {
+            return name;
+        }
+
+        /**
+         * @return Array of possible values if the value may be selected
+         * from a particular set of values; otherwise null
+         */
+        String[] choices() {
+            return choices;
+        }
+
+        /**
+         * @param props Properties.
+         * @throws SQLException On error.
+         */
+        void init(Properties props) throws SQLException {
+            String strVal = props.getProperty(PROP_PREFIX + name);
+
+            if (required && strVal == null) {
+                throw new SQLException("Property '" + name + "' is required but not defined",
+                    SqlStateCode.CLIENT_CONNECTION_FAILED);
+            }
+
+            if (validator != null)
+                validator.validate(strVal);
+
+            props.remove(name);
+
+            init(strVal);
+        }
+
+        /**
+         * @param ref Reference object.
+         * @throws SQLException On error.
+         */
+        void init(Reference ref) throws SQLException {
+            RefAddr refAddr = ref.get(name);
+
+            if (refAddr != null) {
+                String str = (String) refAddr.getContent();
+
+                if (validator != null)
+                    validator.validate(str);
+
+                init(str);
+            }
+        }
+
+        /**
+         * @param str String representation of the
+         * @throws SQLException on error.
+         */
+        abstract void init(String str) throws SQLException;
+
+        /**
+         * @return String representation of the property value.
+         */
+        abstract String valueObject();
+
+        /**
+         * @return JDBC property info object.
+         */
+        DriverPropertyInfo getDriverPropertyInfo() {
+            DriverPropertyInfo dpi = new DriverPropertyInfo(name, valueObject());
+
+            dpi.choices = choices();
+            dpi.required = required;
+            dpi.description = desc;
+
+            return dpi;
+        }
+    }
+
+    /**
+     *
+     */
+    private static class BooleanProperty extends ConnectionProperty {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Bool choices. */
+        private static final String [] boolChoices = new String[] {Boolean.TRUE.toString(), Boolean.FALSE.toString()};
+
+        /** Value. */
+        private boolean val;
+
+        /**
+         * @param name Name.
+         * @param desc Description.
+         * @param dfltVal Default value.
+         * @param required {@code true} if the property is required.
+         */
+        BooleanProperty(String name, String desc, boolean dfltVal, boolean required) {
+            super(name, desc, dfltVal, boolChoices, required);
+
+            val = dfltVal;
+        }
+
+        /**
+         * @return Property value.
+         */
+        boolean value() {
+            return val;
+        }
+
+        /** {@inheritDoc} */
+        @Override void init(String str) throws SQLException {
+            if (str == null)
+                val = (Boolean)dfltVal;
+            else {
+                if (Boolean.TRUE.toString().equalsIgnoreCase(str))
+                    val = true;
+                else if (Boolean.FALSE.toString().equalsIgnoreCase(str))
+                    val = false;
+                else
+                    throw new SQLException("Failed to parse boolean property [name=" + name +
+                        ", value=" + str + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override String valueObject() {
+            return Boolean.toString(val);
+        }
+
+        /**
+         * @param val Property value to set.
+         */
+        void setValue(boolean val) {
+            this.val = val;
+        }
+    }
+
+    /**
+     *
+     */
+    private abstract static class NumberProperty extends ConnectionProperty {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Value. */
+        protected Number val;
+
+        /** Allowed value range. */
+        private Number [] range;
+
+        /**
+         * @param name Name.
+         * @param desc Description.
+         * @param dfltVal Default value.
+         * @param required {@code true} if the property is required.
+         * @param min Lower bound of allowed range.
+         * @param max Upper bound of allowed range.
+         */
+        NumberProperty(String name, String desc, Number dfltVal, boolean required, Number min, Number max) {
+            super(name, desc, dfltVal, null, required);
+
+            assert dfltVal != null;
+
+            val = dfltVal;
+
+            range = new Number[] {min, max};
+        }
+
+        /** {@inheritDoc} */
+        @Override void init(String str) throws SQLException {
+            if (str == null)
+                val = (int)dfltVal;
+            else {
+                try {
+                    setValue(parse(str));
+                } catch (NumberFormatException e) {
+                    throw new SQLException("Failed to parse int property [name=" + name +
+                        ", value=" + str + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
+                }
+            }
+        }
+
+        /**
+         * @param str String value.
+         * @return Number value.
+         * @throws NumberFormatException On parse error.
+         */
+        protected abstract Number parse(String str) throws NumberFormatException;
+
+        /** {@inheritDoc} */
+        @Override String valueObject() {
+            return String.valueOf(val);
+        }
+
+        /**
+         * @param val Property value.
+         * @throws SQLException On error.
+         */
+        void setValue(Number val) throws SQLException {
+            if (range != null) {
+                if (val.doubleValue() < range[0].doubleValue()) {
+                    throw new SQLException("Property cannot be lower than " + range[0].toString() + " [name=" + name +
+                        ", value=" + val.toString() + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
+                }
+
+                if (val.doubleValue() > range[1].doubleValue()) {
+                    throw new SQLException("Property cannot be upper than " + range[1].toString() + " [name=" + name +
+                        ", value=" + val.toString() + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
+                }
+            }
+
+            this.val = val;
+        }
+    }
+
+    /**
+     *
+     */
+    private static class IntegerProperty extends NumberProperty {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /**
+         * @param name Name.
+         * @param desc Description.
+         * @param dfltVal Default value.
+         * @param required {@code true} if the property is required.
+         * @param min Lower bound of allowed range.
+         * @param max Upper bound of allowed range.
+         */
+        IntegerProperty(String name, String desc, Number dfltVal, boolean required, int min, int max) {
+            super(name, desc, dfltVal, required, min, max);
+        }
+
+        /** {@inheritDoc} */
+        @Override protected Number parse(String str) throws NumberFormatException {
+            return Integer.parseInt(str);
+        }
+
+        /**
+         * @return Property value.
+         */
+        int value() {
+            return val.intValue();
+        }
+    }
+
+    /**
+     *
+     */
+    private static class StringProperty extends ConnectionProperty {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Value */
+        private String val;
+
+        /**
+         * @param name Name.
+         * @param desc Description.
+         * @param dfltVal Default value.
+         * @param choices Possible values.
+         * @param required {@code true} if the property is required.
+         * @param validator Property value validator.
+         */
+        StringProperty(String name, String desc, String dfltVal, String [] choices, boolean required,
+            PropertyValidator validator) {
+            super(name, desc, dfltVal, choices, required, validator);
+
+            val = dfltVal;
+        }
+
+        /**
+         * @param val Property value.
+         */
+        void setValue(String val) {
+            this.val = val;
+        }
+
+        /**
+         * @return Property value.
+         */
+        String value() {
+            return val;
+        }
+
+        /** {@inheritDoc} */
+        @Override void init(String str) throws SQLException {
+            val = str;
+        }
+
+        /** {@inheritDoc} */
+        @Override String valueObject() {
+            return val;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
index 57b25e1..999c793 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java
@@ -51,18 +51,6 @@ import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT;
 import static java.sql.ResultSet.CONCUR_READ_ONLY;
 import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT;
 import static java.sql.ResultSet.TYPE_FORWARD_ONLY;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_AUTO_CLOSE_SERVER_CURSORS;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_COLLOCATED;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_DISTRIBUTED_JOINS;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_ENFORCE_JOIN_ORDER;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_HOST;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_LAZY;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_PORT;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_REPLICATED_ONLY;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_RCV_BUF;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_SND_BUF;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_TCP_NO_DELAY;
-import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SKIP_REDUCER_ON_UPDATE;
 
 /**
  * JDBC connection implementation.
@@ -103,53 +91,42 @@ public class JdbcThinConnection implements Connection {
     /** Jdbc metadata. Cache the JDBC object on the first access */
     private JdbcThinDatabaseMetadata metadata;
 
+    /** Connection properties. */
+    private ConnectionProperties connProps;
+
     /**
      * Creates new connection.
      *
      * @param url Connection URL.
-     * @param props Additional properties.
      * @param schema Schema name.
+     * @param props Connection properties.
      * @throws SQLException In case Ignite client failed to start.
      */
-    public JdbcThinConnection(String url, Properties props, String schema) throws SQLException {
+    public JdbcThinConnection(String url, String schema, Properties props) throws SQLException {
         assert url != null;
-        assert props != null;
 
         this.url = url;
 
+        connProps = new ConnectionPropertiesImpl();
+
+        ((ConnectionPropertiesImpl)connProps).init(props);
+
         holdability = HOLD_CURSORS_OVER_COMMIT;
         autoCommit = true;
         txIsolation = Connection.TRANSACTION_NONE;
 
         this.schema = normalizeSchema(schema);
 
-        String host = extractHost(props);
-        int port = extractPort(props);
-
-        boolean distributedJoins = extractBoolean(props, PROP_DISTRIBUTED_JOINS, false);
-        boolean enforceJoinOrder = extractBoolean(props, PROP_ENFORCE_JOIN_ORDER, false);
-        boolean collocated = extractBoolean(props, PROP_COLLOCATED, false);
-        boolean replicatedOnly = extractBoolean(props, PROP_REPLICATED_ONLY, false);
-        boolean autoCloseServerCursor = extractBoolean(props, PROP_AUTO_CLOSE_SERVER_CURSORS, false);
-        boolean lazyExec = extractBoolean(props, PROP_LAZY, false);
-
-        int sockSndBuf = extractIntNonNegative(props, PROP_SOCK_SND_BUF, 0);
-        int sockRcvBuf = extractIntNonNegative(props, PROP_SOCK_RCV_BUF, 0);
-
-        boolean tcpNoDelay  = extractBoolean(props, PROP_TCP_NO_DELAY, true);
-        boolean skipReducerOnUpdate  = extractBoolean(props, PROP_SKIP_REDUCER_ON_UPDATE, false);
-
         try {
-            cliIo = new JdbcThinTcpIo(host, port, distributedJoins, enforceJoinOrder, collocated, replicatedOnly,
-                autoCloseServerCursor, lazyExec, sockSndBuf, sockRcvBuf, tcpNoDelay, skipReducerOnUpdate);
+            cliIo = new JdbcThinTcpIo(connProps);
 
             cliIo.start();
         }
         catch (Exception e) {
             cliIo.close();
 
-            throw new SQLException("Failed to connect to Ignite cluster [host=" + host + ", port=" + port + ']',
-                SqlStateCode.CLIENT_CONNECTION_FAILED, e);
+            throw new SQLException("Failed to connect to Ignite cluster [host=" + connProps.getHost() +
+                ", port=" + connProps.getPort() + ']', SqlStateCode.CLIENT_CONNECTION_FAILED, e);
         }
     }
 
@@ -653,7 +630,7 @@ public class JdbcThinConnection implements Connection {
      * @return Auto close server cursors flag.
      */
     boolean autoCloseServerCursor() {
-        return cliIo.autoCloseServerCursor();
+        return connProps.isAutoCloseServerCursor();
     }
 
     /**
@@ -683,120 +660,6 @@ public class JdbcThinConnection implements Connection {
     }
 
     /**
-     * Extract host.
-     *
-     * @param props Properties.
-     * @return Host.
-     * @throws SQLException If failed.
-     */
-    private static String extractHost(Properties props) throws SQLException {
-        String host = props.getProperty(PROP_HOST);
-
-        if (host != null)
-            host = host.trim();
-
-        if (F.isEmpty(host))
-            throw new SQLException("Host name is empty.", SqlStateCode.CLIENT_CONNECTION_FAILED);
-
-        return host;
-    }
-
-    /**
-     * Extract port.
-     *
-     * @param props Properties.
-     * @return Port.
-     * @throws SQLException If failed.
-     */
-    private static int extractPort(Properties props) throws SQLException {
-        String portStr = props.getProperty(PROP_PORT);
-
-        if (portStr == null)
-            return JdbcThinUtils.DFLT_PORT;
-
-        int port;
-
-        try {
-            port = Integer.parseInt(portStr);
-
-            if (port <= 0 || port > 0xFFFF)
-                throw new SQLException("Invalid port: " + portStr, SqlStateCode.CLIENT_CONNECTION_FAILED);
-        }
-        catch (NumberFormatException e) {
-            throw new SQLException("Invalid port: " + portStr, SqlStateCode.CLIENT_CONNECTION_FAILED);
-        }
-
-        return port;
-    }
-
-    /**
-     * Extract boolean property.
-     *
-     * @param props Properties.
-     * @param propName Property name.
-     * @param dfltVal Default value.
-     * @return Value.
-     * @throws SQLException If failed.
-     */
-    private static boolean extractBoolean(Properties props, String propName, boolean dfltVal) throws SQLException {
-        String strVal = props.getProperty(propName);
-
-        if (strVal == null)
-            return dfltVal;
-
-        if (Boolean.TRUE.toString().equalsIgnoreCase(strVal))
-            return true;
-        else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal))
-            return false;
-        else
-            throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) +
-                ", value=" + strVal + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
-    }
-
-    /**
-     * Extract non-negative int property.
-     *
-     * @param props Properties.
-     * @param propName Property name.
-     * @param dfltVal Default value.
-     * @return Value.
-     * @throws SQLException If failed.
-     */
-    private static int extractIntNonNegative(Properties props, String propName, int dfltVal) throws SQLException {
-        int res = extractInt(props, propName, dfltVal);
-
-        if (res < 0)
-            throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) +
-                ", value=" + res + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
-
-        return res;
-    }
-
-    /**
-     * Extract int property.
-     *
-     * @param props Properties.
-     * @param propName Property name.
-     * @param dfltVal Default value.
-     * @return Value.
-     * @throws SQLException If failed.
-     */
-    private static int extractInt(Properties props, String propName, int dfltVal) throws SQLException {
-        String strVal = props.getProperty(propName);
-
-        if (strVal == null)
-            return dfltVal;
-
-        try {
-            return Integer.parseInt(strVal);
-        }
-        catch (NumberFormatException e) {
-            throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) +
-                ", value=" + strVal + ']', SqlStateCode.CLIENT_CONNECTION_FAILED);
-        }
-    }
-
-    /**
      * @return Connection URL.
      */
     public String url() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
index 0670fb1..4d23934 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java
@@ -20,9 +20,27 @@ package org.apache.ignite.internal.jdbc.thin;
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
 import java.net.Socket;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
 import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.binary.BinaryWriterExImpl;
@@ -39,6 +57,7 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest;
 import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse;
 import org.apache.ignite.internal.util.ipc.loopback.IpcClientTcpEndpoint;
+import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteProductVersion;
 
@@ -76,41 +95,8 @@ public class JdbcThinTcpIo {
     /** Initial output for query close message. */
     private static final int QUERY_CLOSE_MSG_SIZE = 9;
 
-    /** Host. */
-    private final String host;
-
-    /** Port. */
-    private final int port;
-
-    /** Distributed joins. */
-    private final boolean distributedJoins;
-
-    /** Enforce join order. */
-    private final boolean enforceJoinOrder;
-
-    /** Collocated flag. */
-    private final boolean collocated;
-
-    /** Replicated only flag. */
-    private final boolean replicatedOnly;
-
-    /** Lazy execution query flag. */
-    private final boolean lazy;
-
-    /** Flag to automatically close server cursor. */
-    private final boolean autoCloseServerCursor;
-
-    /** Executes update queries on server nodes. */
-    private final boolean skipReducerOnUpdate;
-
-    /** Socket send buffer. */
-    private final int sockSndBuf;
-
-    /** Socket receive buffer. */
-    private final int sockRcvBuf;
-
-    /** TCP no delay flag. */
-    private final boolean tcpNoDelay;
+    /** Connection properties. */
+    private final ConnectionProperties connProps;
 
     /** Endpoint. */
     private IpcClientTcpEndpoint endpoint;
@@ -130,34 +116,10 @@ public class JdbcThinTcpIo {
     /**
      * Constructor.
      *
-     * @param host Host.
-     * @param port Port.
-     * @param distributedJoins Distributed joins flag.
-     * @param enforceJoinOrder Enforce join order flag.
-     * @param collocated Collocated flag.
-     * @param replicatedOnly Replicated only flag.
-     * @param autoCloseServerCursor Flag to automatically close server cursors.
-     * @param lazy Lazy execution query flag.
-     * @param sockSndBuf Socket send buffer.
-     * @param sockRcvBuf Socket receive buffer.
-     * @param tcpNoDelay TCP no delay flag.
-     * @param skipReducerOnUpdate Executes update queries on ignite server nodes.
+     * @param connProps Connection properties.
      */
-    JdbcThinTcpIo(String host, int port, boolean distributedJoins, boolean enforceJoinOrder, boolean collocated,
-        boolean replicatedOnly, boolean autoCloseServerCursor, boolean lazy, int sockSndBuf, int sockRcvBuf,
-        boolean tcpNoDelay, boolean skipReducerOnUpdate) {
-        this.host = host;
-        this.port = port;
-        this.distributedJoins = distributedJoins;
-        this.enforceJoinOrder = enforceJoinOrder;
-        this.collocated = collocated;
-        this.replicatedOnly = replicatedOnly;
-        this.autoCloseServerCursor = autoCloseServerCursor;
-        this.lazy = lazy;
-        this.sockSndBuf = sockSndBuf;
-        this.sockRcvBuf = sockRcvBuf;
-        this.tcpNoDelay = tcpNoDelay;
-        this.skipReducerOnUpdate = skipReducerOnUpdate;
+    JdbcThinTcpIo(ConnectionProperties connProps) {
+        this.connProps = connProps;
     }
 
     /**
@@ -167,16 +129,16 @@ public class JdbcThinTcpIo {
     public void start() throws SQLException, IOException {
         Socket sock = new Socket();
 
-        if (sockSndBuf != 0)
-            sock.setSendBufferSize(sockSndBuf);
+        if (connProps.getSocketSendBuffer() != 0)
+            sock.setSendBufferSize(connProps.getSocketSendBuffer());
 
-        if (sockRcvBuf != 0)
-            sock.setReceiveBufferSize(sockRcvBuf);
+        if (connProps.getSocketReceiveBuffer() != 0)
+            sock.setReceiveBufferSize(connProps.getSocketReceiveBuffer());
 
-        sock.setTcpNoDelay(tcpNoDelay);
+        sock.setTcpNoDelay(connProps.isTcpNoDelay());
 
         try {
-            sock.connect(new InetSocketAddress(host, port));
+            sock.connect(new InetSocketAddress(connProps.getHost(), connProps.getPort()));
 
             endpoint = new IpcClientTcpEndpoint(sock);
 
@@ -184,8 +146,8 @@ public class JdbcThinTcpIo {
             in = new BufferedInputStream(endpoint.inputStream());
         }
         catch (IOException | IgniteCheckedException e) {
-            throw new SQLException("Failed to connect to server [host=" + host + ", port=" + port + ']',
-                SqlStateCode.CLIENT_CONNECTION_FAILED, e);
+            throw new SQLException("Failed to connect to server [host=" + connProps.getHost() +
+                ", port=" + connProps.getPort() + ']', SqlStateCode.CLIENT_CONNECTION_FAILED, e);
         }
 
         handshake(CURRENT_VER);
@@ -210,13 +172,13 @@ public class JdbcThinTcpIo {
 
         writer.writeByte(ClientListenerNioListener.JDBC_CLIENT);
 
-        writer.writeBoolean(distributedJoins);
-        writer.writeBoolean(enforceJoinOrder);
-        writer.writeBoolean(collocated);
-        writer.writeBoolean(replicatedOnly);
-        writer.writeBoolean(autoCloseServerCursor);
-        writer.writeBoolean(lazy);
-        writer.writeBoolean(skipReducerOnUpdate);
+        writer.writeBoolean(connProps.isDistributedJoins());
+        writer.writeBoolean(connProps.isEnforceJoinOrder());
+        writer.writeBoolean(connProps.isCollocated());
+        writer.writeBoolean(connProps.isReplicatedOnly());
+        writer.writeBoolean(connProps.isAutoCloseServerCursor());
+        writer.writeBoolean(connProps.isLazy());
+        writer.writeBoolean(connProps.isSkipReducerOnUpdate());
 
         send(writer.array());
 
@@ -280,11 +242,11 @@ public class JdbcThinTcpIo {
 
         writer.writeByte(ClientListenerNioListener.JDBC_CLIENT);
 
-        writer.writeBoolean(distributedJoins);
-        writer.writeBoolean(enforceJoinOrder);
-        writer.writeBoolean(collocated);
-        writer.writeBoolean(replicatedOnly);
-        writer.writeBoolean(autoCloseServerCursor);
+        writer.writeBoolean(connProps.isDistributedJoins());
+        writer.writeBoolean(connProps.isEnforceJoinOrder());
+        writer.writeBoolean(connProps.isCollocated());
+        writer.writeBoolean(connProps.isReplicatedOnly());
+        writer.writeBoolean(connProps.isAutoCloseServerCursor());
 
         send(writer.array());
 
@@ -429,59 +391,10 @@ public class JdbcThinTcpIo {
     }
 
     /**
-     * @return Distributed joins flag.
-     */
-    public boolean distributedJoins() {
-        return distributedJoins;
-    }
-
-    /**
-     * @return Enforce join order flag.
-     */
-    public boolean enforceJoinOrder() {
-        return enforceJoinOrder;
-    }
-
-    /**
-     * @return Collocated flag.
-     */
-    public boolean collocated() {
-        return collocated;
-    }
-
-    /**
-     * @return Replicated only flag.
+     * @return Connection properties.
      */
-    public boolean replicatedOnly() {
-        return replicatedOnly;
-    }
-
-    /**
-     * @return Auto close server cursors flag.
-     */
-    public boolean autoCloseServerCursor() {
-        return autoCloseServerCursor;
-    }
-
-    /**
-     * @return Socket send buffer size.
-     */
-    public int socketSendBuffer() {
-        return sockSndBuf;
-    }
-
-    /**
-     * @return Socket receive buffer size.
-     */
-    public int socketReceiveBuffer() {
-        return sockRcvBuf;
-    }
-
-    /**
-     * @return TCP no delay flag.
-     */
-    public boolean tcpNoDelay() {
-        return tcpNoDelay;
+    public ConnectionProperties connectionProperties() {
+        return connProps;
     }
 
     /**
@@ -490,18 +403,4 @@ public class JdbcThinTcpIo {
     IgniteProductVersion igniteVersion() {
         return igniteVer;
     }
-
-    /**
-     * @return Lazy query execution flag.
-     */
-    public boolean lazy() {
-        return lazy;
-    }
-
-    /**
-     * @return Server side update flag.
-     */
-    public boolean skipReducerOnUpdate() {
-        return skipReducerOnUpdate;
-    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/69acdaaa/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
index c9bf61c..5f895dd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinUtils.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.internal.jdbc.thin;
 
-import org.apache.ignite.configuration.ClientConnectorConfiguration;
-
 import java.sql.Time;
 import java.sql.Timestamp;
 import java.sql.Types;
@@ -37,6 +35,7 @@ import static java.sql.Types.TIME;
 import static java.sql.Types.TIMESTAMP;
 import static java.sql.Types.TINYINT;
 import static java.sql.Types.VARCHAR;
+import static org.apache.ignite.internal.jdbc.thin.ConnectionPropertiesImpl.PROP_PREFIX;
 
 /**
  * Utility methods for thin JDBC driver.
@@ -45,88 +44,12 @@ public class JdbcThinUtils {
     /** URL prefix. */
     public static final String URL_PREFIX = "jdbc:ignite:thin://";
 
-    /** Prefix for property names. */
-    public static final String PROP_PREFIX = "ignite.jdbc.";
-
     /** Port number property name. */
     public static final String PROP_PORT = PROP_PREFIX + "port";
 
     /** Hostname property name. */
     public static final String PROP_HOST = PROP_PREFIX + "host";
 
-    /** Parameter: distributed joins flag (SQL hint). */
-    public static final String PARAM_DISTRIBUTED_JOINS = "distributedJoins";
-
-    /** Parameter: enforce join order flag (SQL hint). */
-    public static final String PARAM_ENFORCE_JOIN_ORDER = "enforceJoinOrder";
-
-    /** Parameter: collocated flag (SQL hint). */
-    public static final String PARAM_COLLOCATED = "collocated";
-
-    /** Parameter: lazy query execution flag (SQL hint). */
-    public static final String PARAM_REPLICATED_ONLY = "replicatedOnly";
-
-    /** Parameter: replicated only flag (SQL hint). */
-    public static final String PARAM_LAZY = "lazy";
-
-    /** Parameter: socket send buffer. */
-    public static final String PARAM_SOCK_SND_BUF = "socketSendBuffer";
-
-    /** Parameter: socket receive buffer. */
-    public static final String PARAM_SOCK_RCV_BUF = "socketReceiveBuffer";
-
-    /** Parameter: TCP no-delay flag. */
-    public static final String PARAM_TCP_NO_DELAY = "tcpNoDelay";
-
-    /** Parameter: Automatically close server cursor. */
-    public static final String PARAM_AUTO_CLOSE_SERVER_CURSOR = "autoCloseServerCursor";
-
-    /** Parameter: execute update query in distributed mode on ignite server nodes. */
-    public static final String PARAM_SKIP_REDUCER_ON_UPDATE = "skipReducerOnUpdate";
-
-    /** Distributed joins property name. */
-    public static final String PROP_DISTRIBUTED_JOINS = PROP_PREFIX + PARAM_DISTRIBUTED_JOINS;
-
-    /** Transactions allowed property name. */
-    public static final String PROP_ENFORCE_JOIN_ORDER = PROP_PREFIX + PARAM_ENFORCE_JOIN_ORDER;
-
-    /** Collocated property name. */
-    public static final String PROP_COLLOCATED = PROP_PREFIX + PARAM_COLLOCATED;
-
-    /** Lazy property name. */
-    public static final String PROP_LAZY = PROP_PREFIX + PARAM_LAZY;
-
-    /** Replicated only property name. */
-    public static final String PROP_REPLICATED_ONLY = PROP_PREFIX + PARAM_REPLICATED_ONLY;
-
-    /** Socket send buffer property name. */
-    public static final String PROP_SOCK_SND_BUF = PROP_PREFIX + PARAM_SOCK_SND_BUF;
-
-    /** Socket receive buffer property name. */
-    public static final String PROP_SOCK_RCV_BUF = PROP_PREFIX + PARAM_SOCK_RCV_BUF;
-
-    /** TCP no delay property name. */
-    public static final String PROP_TCP_NO_DELAY = PROP_PREFIX + PARAM_TCP_NO_DELAY;
-
-    /** Automatically close server cursor. */
-    public static final String PROP_AUTO_CLOSE_SERVER_CURSORS = PROP_PREFIX + PARAM_AUTO_CLOSE_SERVER_CURSOR;
-
-    /** Executes update queries on ignite server nodes in distributed mode. */
-    public static final String PROP_SKIP_REDUCER_ON_UPDATE = PROP_PREFIX + PARAM_SKIP_REDUCER_ON_UPDATE;
-
-    /** Default port. */
-    public static final int DFLT_PORT = ClientConnectorConfiguration.DFLT_PORT;
-
-    /**
-     * Trim prefix from property.
-     *
-     * @param prop Property.
-     * @return Parameter name.
-     */
-    public static String trimPrefix(String prop) {
-        return prop.substring(PROP_PREFIX.length());
-    }
-
     /**
      * Converts Java class name to type from {@link Types}.
      *


[30/47] ignite git commit: IGNITE-5846 Add support of distributed matrices for OLS regression. This closes #3030.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockMatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockMatrixStorage.java
index cd76e5a..411b038 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockMatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockMatrixStorage.java
@@ -17,14 +17,6 @@
 
 package org.apache.ignite.ml.math.impls.storage.matrix;
 
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
@@ -38,16 +30,22 @@ import org.apache.ignite.ml.math.MatrixStorage;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.distributed.CacheUtils;
 import org.apache.ignite.ml.math.distributed.DistributedStorage;
-import org.apache.ignite.ml.math.distributed.keys.impl.BlockMatrixKey;
-import org.apache.ignite.ml.math.impls.matrix.BlockEntry;
+import org.apache.ignite.ml.math.distributed.keys.impl.MatrixBlockKey;
+import org.apache.ignite.ml.math.impls.matrix.MatrixBlockEntry;
 import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
 
-import static org.apache.ignite.ml.math.impls.matrix.BlockEntry.MAX_BLOCK_SIZE;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.*;
+
+import static org.apache.ignite.ml.math.impls.matrix.MatrixBlockEntry.MAX_BLOCK_SIZE;
 
 /**
  * Storage for {@link SparseBlockDistributedMatrix}.
  */
-public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, StorageConstants, DistributedStorage<BlockMatrixKey> {
+public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, StorageConstants, DistributedStorage<MatrixBlockKey> {
     /** Cache name used for all instances of {@link BlockMatrixStorage}. */
     private static final String CACHE_NAME = "ML_BLOCK_SPARSE_MATRICES_CONTAINER";
     /** */
@@ -65,8 +63,8 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
 
     /** Actual distributed storage. */
     private IgniteCache<
-        BlockMatrixKey /* Matrix block number with uuid. */,
-        BlockEntry /* Block of matrix, local sparse matrix. */
+            MatrixBlockKey /* Matrix block number with uuid. */,
+            MatrixBlockEntry /* Block of matrix, local sparse matrix. */
         > cache = null;
 
     /**
@@ -98,7 +96,7 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
     /**
      *
      */
-    public IgniteCache<BlockMatrixKey, BlockEntry> cache() {
+    public IgniteCache<MatrixBlockKey, MatrixBlockEntry> cache() {
         return cache;
     }
 
@@ -132,20 +130,6 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
         return RANDOM_ACCESS_MODE;
     }
 
-    /**
-     * @return Blocks in column.
-     */
-    public int blocksInCol() {
-        return blocksInCol;
-    }
-
-    /**
-     * @return Blocks in row.
-     */
-    public int blocksInRow() {
-        return blocksInRow;
-    }
-
     /** {@inheritDoc} */
     @Override public void writeExternal(ObjectOutput out) throws IOException {
         out.writeInt(rows);
@@ -210,8 +194,8 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      *
      * NB: NOT cell indices.
      */
-    public BlockMatrixKey getCacheKey(long blockIdRow, long blockIdCol) {
-        return new BlockMatrixKey(blockIdRow, blockIdCol, uuid, getAffinityKey(blockIdRow, blockIdCol));
+    public MatrixBlockKey getCacheKey(long blockIdRow, long blockIdCol) {
+        return new MatrixBlockKey(blockIdRow, blockIdCol, uuid, getAffinityKey(blockIdRow, blockIdCol));
     }
 
     /**
@@ -219,17 +203,17 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      *
      * NB: NOT cell indices.
      */
-    public BlockMatrixKey getCacheKey(IgnitePair<Long> blockId) {
-        return new BlockMatrixKey(blockId.get1(), blockId.get2(), uuid, getAffinityKey(blockId.get1(), blockId.get2()));
+    private MatrixBlockKey getCacheKey(IgnitePair<Long> blockId) {
+        return new MatrixBlockKey(blockId.get1(), blockId.get2(), uuid, getAffinityKey(blockId.get1(), blockId.get2()));
     }
 
     /** {@inheritDoc} */
-    @Override public Set<BlockMatrixKey> getAllKeys() {
+    @Override public Set<MatrixBlockKey> getAllKeys() {
         int maxRowIdx = rows - 1;
         int maxColIdx = cols - 1;
         IgnitePair<Long> maxBlockId = getBlockId(maxRowIdx, maxColIdx);
 
-        Set<BlockMatrixKey> keyset = new HashSet<>();
+        Set<MatrixBlockKey> keyset = new HashSet<>();
 
         for(int i = 0; i <= maxBlockId.get1(); i++)
             for(int j = 0; j <= maxBlockId.get2(); j++)
@@ -249,8 +233,8 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      * @param blockId block id.
      * @return The list of block entries.
      */
-    public List<BlockEntry> getRowForBlock(IgnitePair<Long> blockId) {
-        List<BlockEntry> res = new LinkedList<>();
+    public List<MatrixBlockEntry> getRowForBlock(IgnitePair<Long> blockId) {
+        List<MatrixBlockEntry> res = new LinkedList<>();
 
         for (int i = 0; i < blocksInCol; i++)
             res.add(getEntryById(new IgnitePair<>(blockId.get1(), (long) i)));
@@ -265,8 +249,8 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      * @param blockId block id.
      * @return The list of block entries.
      */
-    public List<BlockEntry> getColForBlock(IgnitePair<Long> blockId) {
-        List<BlockEntry> res = new LinkedList<>();
+    public List<MatrixBlockEntry> getColForBlock(IgnitePair<Long> blockId) {
+        List<MatrixBlockEntry> res = new LinkedList<>();
 
         for (int i = 0; i < blocksInRow; i++)
             res.add(getEntryById(new IgnitePair<>((long) i, blockId.get2())));
@@ -308,10 +292,10 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      * @param blockId blockId
      * @return BlockEntry
      */
-    private BlockEntry getEntryById(IgnitePair<Long> blockId) {
-        BlockMatrixKey key = getCacheKey(blockId.get1(), blockId.get2());
+    private MatrixBlockEntry getEntryById(IgnitePair<Long> blockId) {
+        MatrixBlockKey key = getCacheKey(blockId.get1(), blockId.get2());
 
-        BlockEntry entry = cache.localPeek(key, CachePeekMode.PRIMARY);
+        MatrixBlockEntry entry = cache.localPeek(key, CachePeekMode.PRIMARY);
         entry = entry != null ? entry : cache.get(key);
 
         if (entry == null)
@@ -325,8 +309,8 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      * @param blockId blockId
      * @return Empty BlockEntry
      */
-    private BlockEntry getEmptyBlockEntry(IgnitePair<Long> blockId) {
-        BlockEntry entry;
+    private MatrixBlockEntry getEmptyBlockEntry(IgnitePair<Long> blockId) {
+        MatrixBlockEntry entry;
         int rowMod = rows % maxBlockEdge;
         int colMod = cols % maxBlockEdge;
 
@@ -345,7 +329,7 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
         else
             colSize = blockId.get2() != (blocksInCol - 1) ? maxBlockEdge : colMod;
 
-        entry = new BlockEntry(rowSize, colSize);
+        entry = new MatrixBlockEntry(rowSize, colSize);
         return entry;
     }
 
@@ -354,7 +338,7 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      *
      * Get affinity key for the given id.
      */
-    private IgniteUuid getAffinityKey(long blockIdRow, long blockIdCol) {
+    private UUID getAffinityKey(long blockIdRow, long blockIdCol) {
         return null;
     }
 
@@ -368,13 +352,13 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
     private void matrixSet(int a, int b, double v) {
         IgnitePair<Long> blockId = getBlockId(a, b);
         // Remote set on the primary node (where given row or column is stored locally).
-        ignite().compute(groupForKey(CACHE_NAME, blockId)).run(() -> {
-            IgniteCache<BlockMatrixKey, BlockEntry> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
+        ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, blockId)).run(() -> {
+            IgniteCache<MatrixBlockKey, MatrixBlockEntry> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
 
-            BlockMatrixKey key = getCacheKey(blockId.get1(), blockId.get2());
+            MatrixBlockKey key = getCacheKey(blockId.get1(), blockId.get2());
 
             // Local get.
-            BlockEntry block = getEntryById(blockId);
+            MatrixBlockEntry block = getEntryById(blockId);
 
             block.set(a % block.rowSize(), b % block.columnSize(), v);
 
@@ -402,13 +386,13 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
      */
     private double matrixGet(int a, int b) {
         // Remote get from the primary node (where given row or column is stored locally).
-        return ignite().compute(groupForKey(CACHE_NAME, getBlockId(a, b))).call(() -> {
-            IgniteCache<BlockMatrixKey, BlockEntry> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
+        return ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, getBlockId(a, b))).call(() -> {
+            IgniteCache<MatrixBlockKey, MatrixBlockEntry> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
 
-            BlockMatrixKey key = getCacheKey(getBlockId(a, b));
+            MatrixBlockKey key = getCacheKey(getBlockId(a, b));
 
             // Local get.
-            BlockEntry block = cache.localPeek(key, CachePeekMode.PRIMARY);
+            MatrixBlockEntry block = cache.localPeek(key, CachePeekMode.PRIMARY);
 
             if (block == null)
                 block = cache.get(key);
@@ -420,8 +404,8 @@ public class BlockMatrixStorage extends CacheUtils implements MatrixStorage, Sto
     /**
      * Create new ML cache if needed.
      */
-    private IgniteCache<BlockMatrixKey, BlockEntry> newCache() {
-        CacheConfiguration<BlockMatrixKey, BlockEntry> cfg = new CacheConfiguration<>();
+    private IgniteCache<MatrixBlockKey, MatrixBlockEntry> newCache() {
+        CacheConfiguration<MatrixBlockKey, MatrixBlockEntry> cfg = new CacheConfiguration<>();
 
         // Write to primary.
         cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockVectorStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockVectorStorage.java
new file mode 100644
index 0000000..a44ed8e
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/BlockVectorStorage.java
@@ -0,0 +1,374 @@
+/*
+ * 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.ml.math.impls.storage.matrix;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.util.lang.IgnitePair;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.VectorStorage;
+import org.apache.ignite.ml.math.distributed.CacheUtils;
+import org.apache.ignite.ml.math.distributed.DistributedStorage;
+import org.apache.ignite.ml.math.distributed.keys.impl.VectorBlockKey;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.apache.ignite.ml.math.impls.vector.VectorBlockEntry;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.*;
+
+import static org.apache.ignite.ml.math.impls.matrix.MatrixBlockEntry.MAX_BLOCK_SIZE;
+
+/**
+ * Storage for {@link SparseBlockDistributedVector}.
+ */
+public class BlockVectorStorage extends CacheUtils implements VectorStorage, StorageConstants, DistributedStorage<VectorBlockKey> {
+    /** Cache name used for all instances of {@link BlockVectorStorage}. */
+    private static final String CACHE_NAME = "ML_BLOCK_SPARSE_MATRICES_CONTAINER";
+    /** */
+    private int blocks;
+    /** Amount of columns in the vector. */
+    private int size;
+    /** Matrix uuid. */
+    private UUID uuid;
+    /** Block size about 8 KB of data. */
+    private int maxBlockEdge = MAX_BLOCK_SIZE;
+
+    /** Actual distributed storage. */
+    private IgniteCache<
+            VectorBlockKey /* Matrix block number with uuid. */,
+            VectorBlockEntry /* Block of matrix, local sparse matrix. */
+            > cache = null;
+
+    /**
+     *
+     */
+    public BlockVectorStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param size Amount of columns in the vector.
+     */
+    public BlockVectorStorage(int size) {
+
+        assert size > 0;
+
+        this.size = size;
+
+        this.blocks = size % maxBlockEdge == 0 ? size / maxBlockEdge : size / maxBlockEdge + 1;
+
+        cache = newCache();
+
+        uuid = UUID.randomUUID();
+    }
+
+    /**
+     *
+     */
+    public IgniteCache<VectorBlockKey, VectorBlockEntry> cache() {
+        return cache;
+    }
+
+    /** {@inheritDoc} */
+    @Override public double get(int x) {
+        return matrixGet(x);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void set(int x, double v) {
+        matrixSet(x, v);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        return size;
+    }
+
+
+    /**
+     * @return Blocks in row.
+     */
+    public int blocksInRow() {
+        return blocks;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(size);
+        out.writeInt(blocks);
+        out.writeObject(uuid);
+        out.writeUTF(cache.getName());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        size = in.readInt();
+        blocks = in.readInt();
+        uuid = (UUID) in.readObject();
+
+        cache = ignite().getOrCreateCache(in.readUTF());
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** Delete all data from cache. */
+    @Override public void destroy() {
+        cache.clearAll(getAllKeys());
+    }
+
+    /**
+     * Get storage UUID.
+     *
+     * @return storage UUID.
+     */
+    public UUID getUUID() {
+        return uuid;
+    }
+
+    /**
+     * Build the cache key for the given blocks id.
+     *
+     * NB: NOT cell indices.
+     */
+    public VectorBlockKey getCacheKey(long blockId) {
+        return new VectorBlockKey(blockId, uuid, getAffinityKey(blockId));
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public Set<VectorBlockKey> getAllKeys() {
+        int maxIndex = size - 1;
+        long maxBlockId = getBlockId(maxIndex);
+
+        Set<VectorBlockKey> keyset = new HashSet<>();
+
+        for (int i = 0; i <= maxBlockId; i++)
+            keyset.add(getCacheKey(i));
+
+        return keyset;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String cacheName() {
+        return CACHE_NAME;
+    }
+
+
+    /**
+     * Get column for current block.
+     *
+     * @param blockId block id.
+     * @return The list of block entries.
+     */
+    public List<VectorBlockEntry> getColForBlock(long blockId) {
+        List<VectorBlockEntry> res = new LinkedList<>();
+
+        for (int i = 0; i < blocks; i++)
+            res.add(getEntryById(i));
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + size;
+        res = res * 37 + uuid.hashCode();
+        res = res * 37 + cache.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        BlockVectorStorage that = (BlockVectorStorage) obj;
+
+        return size == that.size && uuid.equals(that.uuid)
+                && (cache != null ? cache.equals(that.cache) : that.cache == null);
+    }
+
+    /**
+     *
+     */
+    private VectorBlockEntry getEntryById(long blockId) {
+        VectorBlockKey key = getCacheKey(blockId);
+
+        VectorBlockEntry entry = cache.localPeek(key, CachePeekMode.PRIMARY);
+        entry = entry != null ? entry : cache.get(key);
+
+        if (entry == null)
+            entry = getEmptyBlockEntry(blockId);
+
+        return entry;
+    }
+
+    @NotNull
+    private VectorBlockEntry getEmptyBlockEntry(long blockId) {
+        VectorBlockEntry entry;
+        int colMod = size % maxBlockEdge;
+
+        int colSize;
+
+        if (colMod == 0)
+            colSize = maxBlockEdge;
+        else
+            colSize = blockId != (blocks - 1) ? maxBlockEdge : colMod;
+
+        entry = new VectorBlockEntry(colSize);
+        return entry;
+    }
+
+    /**
+     * TODO: IGNITE-5646, WIP
+     *
+     * Get affinity key for the given id.
+     */
+    private UUID getAffinityKey(long blockId) {
+        return null;
+    }
+
+    /**
+     * Distributed matrix set.
+     *
+     * @param idx Row or column index.
+     * @param v   New value to set.
+     */
+    private void matrixSet(int idx, double v) {
+        long blockId = getBlockId(idx);
+        // Remote set on the primary node (where given row or column is stored locally).
+        ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, blockId)).run(() -> {
+            IgniteCache<VectorBlockKey, VectorBlockEntry> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
+
+            VectorBlockKey key = getCacheKey(blockId);
+
+            // Local get.
+            VectorBlockEntry block = getEntryById(blockId);
+
+            block.set(idx % block.size(), v);
+
+            // Local put.
+            cache.put(key, block);
+        });
+    }
+
+    /** */
+    private long getBlockId(int x) {
+        return (long) x / maxBlockEdge;
+    }
+
+    /**
+     * Distributed vector get.
+     *
+     * @param idx index.
+     * @return Vector value at (idx) index.
+     */
+    private double matrixGet(int idx) {
+        // Remote get from the primary node (where given row or column is stored locally).
+        return ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, getBlockId(idx))).call(() -> {
+            IgniteCache<VectorBlockKey, VectorBlockEntry> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
+
+            VectorBlockKey key = getCacheKey(getBlockId(idx));
+
+            // Local get.
+            VectorBlockEntry block = cache.localPeek(key, CachePeekMode.PRIMARY);
+
+            if (block == null)
+                block = cache.get(key);
+
+            return block == null ? 0.0 : block.get(idx % block.size());
+        });
+    }
+
+    /**
+     * Create new ML cache if needed.
+     */
+    private IgniteCache<VectorBlockKey, VectorBlockEntry> newCache() {
+        CacheConfiguration<VectorBlockKey, VectorBlockEntry> cfg = new CacheConfiguration<>();
+
+        // Write to primary.
+        cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
+
+        // Atomic transactions only.
+        cfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+
+        // No eviction.
+        cfg.setEvictionPolicy(null);
+
+        // No copying of values.
+        cfg.setCopyOnRead(false);
+
+        // Cache is partitioned.
+        cfg.setCacheMode(CacheMode.PARTITIONED);
+
+        // Random cache name.
+        cfg.setName(CACHE_NAME);
+
+        return Ignition.localIgnite().getOrCreateCache(cfg);
+    }
+
+    /**
+     * Avoid this method for large vectors
+     *
+     * @return data presented as array
+     */
+    @Override public double[] data() {
+        double[] res = new double[this.size];
+        for (int i = 0; i < this.size; i++) res[i] = this.get(i);
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
index 4648421..91db30e 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/MapWrapperStorage.java
@@ -17,13 +17,14 @@
 
 package org.apache.ignite.ml.math.impls.storage.matrix;
 
+import org.apache.ignite.internal.util.GridArgumentCheck;
+import org.apache.ignite.ml.math.VectorStorage;
+
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
 import java.util.Map;
 import java.util.Set;
-import org.apache.ignite.internal.util.GridArgumentCheck;
-import org.apache.ignite.ml.math.VectorStorage;
 
 /**
  * Storage for wrapping given map.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
index c40e73d..e976899 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/matrix/SparseDistributedMatrixStorage.java
@@ -19,14 +19,6 @@ package org.apache.ignite.ml.math.impls.storage.matrix;
 
 import it.unimi.dsi.fastutil.ints.Int2DoubleOpenHashMap;
 import it.unimi.dsi.fastutil.ints.Int2DoubleRBTreeMap;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-import java.util.stream.Collectors;
-import java.util.stream.IntStream;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
@@ -42,6 +34,15 @@ import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
 import org.apache.ignite.ml.math.distributed.keys.impl.SparseMatrixKey;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
 /**
  * {@link MatrixStorage} implementation for {@link SparseDistributedMatrix}.
  */
@@ -161,7 +162,7 @@ public class SparseDistributedMatrixStorage extends CacheUtils implements Matrix
      */
     private double matrixGet(int a, int b) {
         // Remote get from the primary node (where given row or column is stored locally).
-        return ignite().compute(groupForKey(CACHE_NAME, a)).call(() -> {
+        return ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, a)).call(() -> {
             IgniteCache<RowColMatrixKey, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
 
             // Local get.
@@ -183,7 +184,7 @@ public class SparseDistributedMatrixStorage extends CacheUtils implements Matrix
      */
     private void matrixSet(int a, int b, double v) {
         // Remote set on the primary node (where given row or column is stored locally).
-        ignite().compute(groupForKey(CACHE_NAME, a)).run(() -> {
+        ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, a)).run(() -> {
             IgniteCache<RowColMatrixKey, Map<Integer, Double>> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
 
             // Local get.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorage.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorage.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorage.java
new file mode 100644
index 0000000..8f79413
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorage.java
@@ -0,0 +1,280 @@
+/*
+ * 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.ml.math.impls.storage.vector;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.util.typedef.internal.A;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.VectorStorage;
+import org.apache.ignite.ml.math.distributed.CacheUtils;
+import org.apache.ignite.ml.math.distributed.DistributedStorage;
+import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
+import org.apache.ignite.ml.math.distributed.keys.impl.SparseMatrixKey;
+import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+/**
+ * {@link VectorStorage} implementation for {@link /*SparseDistributedVector}.
+ */
+public class SparseDistributedVectorStorage extends CacheUtils implements VectorStorage, StorageConstants, DistributedStorage<RowColMatrixKey> {
+    /** Cache name used for all instances of {@link SparseDistributedVectorStorage}. */
+    private static final String CACHE_NAME = "ML_SPARSE_VECTORS_CONTAINER";
+    /** Amount of elements in the vector. */
+    private int size;
+    /** Random or sequential access mode. */
+    private int acsMode;
+    /** Matrix uuid. */
+    private UUID uuid;
+
+    /** Actual distributed storage. */
+    private IgniteCache<RowColMatrixKey, Double> cache = null;
+
+    /**
+     *
+     */
+    public SparseDistributedVectorStorage() {
+        // No-op.
+    }
+
+    /**
+     * @param size    Amount of elements in the vector.
+     * @param acsMode Random or sequential access mode.
+     */
+    public SparseDistributedVectorStorage(int size, int acsMode) {
+
+        assert size > 0;
+        assertAccessMode(acsMode);
+
+        this.size = size;
+        this.acsMode = acsMode;
+
+        cache = newCache();
+
+        uuid = UUID.randomUUID();
+    }
+
+    /**
+     * Create new ML cache if needed.
+     */
+    private IgniteCache<RowColMatrixKey, Double> newCache() {
+        CacheConfiguration<RowColMatrixKey, Double> cfg = new CacheConfiguration<>();
+
+        // Write to primary.
+        cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.PRIMARY_SYNC);
+
+        // Atomic transactions only.
+        cfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+
+        // No eviction.
+        cfg.setEvictionPolicy(null);
+
+        // No copying of values.
+        cfg.setCopyOnRead(false);
+
+        // Cache is partitioned.
+        cfg.setCacheMode(CacheMode.PARTITIONED);
+
+        // Random cache name.
+        cfg.setName(CACHE_NAME);
+
+        return Ignition.localIgnite().getOrCreateCache(cfg);
+    }
+
+    /**
+     * Gets cache
+     *
+     * @return cache
+     */
+    public IgniteCache<RowColMatrixKey, Double> cache() {
+        return cache;
+    }
+
+    /**
+     * Gets access mode
+     *
+     * @return code of access mode
+     */
+    public int accessMode() {
+        return acsMode;
+    }
+
+    /**
+     * Gets vector element by element index
+     *
+     * @param i Vector element index.
+     * @return vector element
+     */
+    @Override public double get(int i) {
+        // Remote get from the primary node (where given row or column is stored locally).
+        return ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, getCacheKey(i))).call(() -> {
+            IgniteCache<RowColMatrixKey, Double> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
+            Double res = cache.get(getCacheKey(i));
+            if (res == null) return 0.0;
+            return res;
+        });
+    }
+
+    /**
+     * Sets vector element by index
+     *
+     * @param i Vector element index.
+     * @param v Value to set at given index.
+     */
+    @Override public void set(int i, double v) {
+        // Remote set on the primary node (where given row or column is stored locally).
+        ignite().compute(getClusterGroupForGivenKey(CACHE_NAME, getCacheKey(i))).run(() -> {
+            IgniteCache<RowColMatrixKey, Double> cache = Ignition.localIgnite().getOrCreateCache(CACHE_NAME);
+
+            RowColMatrixKey cacheKey = getCacheKey(i);
+
+            if (v != 0.0)
+                cache.put(cacheKey, v);
+            else if (cache.containsKey(cacheKey)) // remove zero elements
+                cache.remove(cacheKey);
+
+        });
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public int size() {
+        return size;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeInt(size);
+        out.writeInt(acsMode);
+        out.writeObject(uuid);
+        out.writeUTF(cache.getName());
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        size = in.readInt();
+        acsMode = in.readInt();
+        uuid = (UUID) in.readObject();
+        cache = ignite().getOrCreateCache(in.readUTF());
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isSequentialAccess() {
+        return acsMode == SEQUENTIAL_ACCESS_MODE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDense() {
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRandomAccess() {
+        return acsMode == RANDOM_ACCESS_MODE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isDistributed() {
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isArrayBased() {
+        return false;
+    }
+
+    /** Delete all data from cache. */
+    @Override public void destroy() {
+        Set<RowColMatrixKey> keyset = IntStream.range(0, size).mapToObj(this::getCacheKey).collect(Collectors.toSet());
+        cache.clearAll(keyset);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 1;
+
+        res = res * 37 + size;
+        res = res * 37 + acsMode;
+        res = res * 37 + uuid.hashCode();
+        res = res * 37 + cache.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+
+        if (obj == null || getClass() != obj.getClass())
+            return false;
+
+        SparseDistributedVectorStorage that = (SparseDistributedVectorStorage) obj;
+
+        return size == that.size && acsMode == that.acsMode
+                && uuid.equals(that.uuid) && (cache != null ? cache.equals(that.cache) : that.cache == null);
+    }
+
+    /**
+     * Builds cache key for vector element
+     *
+     * @param idx Index
+     * @return RowColMatrixKey
+     */
+    public RowColMatrixKey getCacheKey(int idx) {
+        return new SparseMatrixKey(idx, uuid, null);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Set<RowColMatrixKey> getAllKeys() {
+        int range = size;
+
+        return IntStream.range(0, range).mapToObj(i -> new SparseMatrixKey(i, getUUID(), null)).collect(Collectors.toSet());
+    }
+
+    /** {@inheritDoc} */
+    @Override public String cacheName() {
+        return CACHE_NAME;
+    }
+
+    /** */
+    public UUID getUUID() {
+        return uuid;
+    }
+
+    @Override
+    public double[] data() {
+        double[] result = new double[this.size];
+        for (int i = 0; i < this.size; i++) result[i] = this.get(i);
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVector.java
new file mode 100644
index 0000000..e460f9f
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVector.java
@@ -0,0 +1,139 @@
+/*
+ * 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.ml.math.impls.vector;
+
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distributed.CacheUtils;
+import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
+import org.apache.ignite.ml.math.impls.storage.matrix.BlockMatrixStorage;
+import org.apache.ignite.ml.math.impls.storage.matrix.BlockVectorStorage;
+import org.apache.ignite.ml.math.impls.storage.vector.SparseDistributedVectorStorage;
+
+import java.util.UUID;
+
+/**
+ * Sparse distributed vector implementation based on data grid.
+ * <p>
+ * Unlike {@link CacheVector} that is based on existing cache, this implementation creates distributed
+ * cache internally and doesn't rely on pre-existing cache.</p>
+ * <p>
+ * You also need to call {@link #destroy()} to remove the underlying cache when you no longer need this
+ * vector.</p>
+ * <p>
+ * <b>Currently fold supports only commutative operations.<b/></p>
+ */
+public class SparseBlockDistributedVector extends AbstractVector implements StorageConstants {
+    /**
+     *
+     */
+    public SparseBlockDistributedVector() {
+        // No-op.
+    }
+
+    /**
+     * @param size Vector size
+     */
+    public SparseBlockDistributedVector(int size) {
+
+        assert size > 0;
+        setStorage(new BlockVectorStorage(size));
+    }
+
+
+    /**
+     * @param data Data to fill storage
+     */
+    public SparseBlockDistributedVector(double[] data) {
+        setStorage(new BlockVectorStorage(data.length));
+        for (int i = 0; i < data.length; i++) {
+            double val = data[i];
+            if (val != 0.0) storage().set(i, val);
+        }
+    }
+
+
+    /** */
+    public BlockVectorStorage storage() {
+        return (BlockVectorStorage) getStorage();
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param d Value to divide to.
+     */
+    @Override public Vector divide(double d) {
+        return mapOverValues(v -> v / d);
+    }
+
+    @Override public Vector like(int size) {
+        return new SparseBlockDistributedVector(size);
+    }
+
+    @Override public Matrix likeMatrix(int rows, int cols) {
+        return new SparseBlockDistributedMatrix(rows, cols);
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param x Value to add.
+     */
+    @Override public Vector plus(double x) {
+        return mapOverValues(v -> v + x);
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param x Value to multiply.
+     */
+    @Override public Vector times(double x) {
+        return mapOverValues(v -> v * x);
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public Vector assign(double val) {
+        return mapOverValues(v -> val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector map(IgniteDoubleFunction<Double> fun) {
+        return mapOverValues(fun);
+    }
+
+    /**
+     * @param mapper Mapping function.
+     * @return Vector with mapped values.
+     */
+    private Vector mapOverValues(IgniteDoubleFunction<Double> mapper) {
+        CacheUtils.sparseMapForVector(getUUID(), mapper, storage().cacheName());
+
+        return this;
+    }
+
+    /** */
+    public UUID getUUID() {
+        return ((BlockVectorStorage) getStorage()).getUUID();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVector.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVector.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVector.java
new file mode 100644
index 0000000..b773bfa
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVector.java
@@ -0,0 +1,157 @@
+/*
+ * 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.ml.math.impls.vector;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.Ignition;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.lang.IgniteUuid;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.distributed.CacheUtils;
+import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
+import org.apache.ignite.ml.math.exceptions.CardinalityException;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
+import org.apache.ignite.ml.math.impls.matrix.*;
+import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorage;
+import org.apache.ignite.ml.math.impls.storage.vector.SparseDistributedVectorStorage;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Sparse distributed vector implementation based on data grid.
+ * <p>
+ * Unlike {@link CacheVector} that is based on existing cache, this implementation creates distributed
+ * cache internally and doesn't rely on pre-existing cache.</p>
+ * <p>
+ * You also need to call {@link #destroy()} to remove the underlying cache when you no longer need this
+ * vector.</p>
+ * <p>
+ * <b>Currently fold supports only commutative operations.<b/></p>
+ */
+public class SparseDistributedVector extends AbstractVector implements StorageConstants {
+    /**
+     *
+     */
+    public SparseDistributedVector() {
+        // No-op.
+    }
+
+    /**
+     * @param size    Vector size.
+     * @param acsMode Vector elements access mode..
+     */
+    public SparseDistributedVector(int size, int acsMode) {
+
+        assert size > 0;
+        assertAccessMode(acsMode);
+
+
+        setStorage(new SparseDistributedVectorStorage(size, acsMode));
+    }
+
+    public SparseDistributedVector(int size) {
+        this(size, StorageConstants.RANDOM_ACCESS_MODE);
+    }
+
+    /**
+     * @param data
+     */
+    public SparseDistributedVector(double[] data) {
+        setStorage(new SparseDistributedVectorStorage(data.length, StorageConstants.RANDOM_ACCESS_MODE));
+        for (int i = 0; i < data.length; i++) {
+            double value = data[i];
+            if (value != 0.0) storage().set(i, value);
+        }
+    }
+
+
+    /** */
+    public SparseDistributedVectorStorage storage() {
+        return (SparseDistributedVectorStorage) getStorage();
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param d Value to divide to.
+     */
+    @Override public Vector divide(double d) {
+        return mapOverValues(v -> v / d);
+    }
+
+    @Override
+    public Vector like(int size) {
+        return new SparseDistributedVector(size, storage().accessMode());
+    }
+
+    @Override
+    public Matrix likeMatrix(int rows, int cols) {
+        return new SparseDistributedMatrix(rows, cols);
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param x Value to add.
+     */
+    @Override public Vector plus(double x) {
+        return mapOverValues(v -> v + x);
+    }
+
+    /**
+     * Return the same matrix with updates values (broken contract).
+     *
+     * @param x Value to multiply.
+     */
+    @Override public Vector times(double x) {
+        return mapOverValues(v -> v * x);
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public Vector assign(double val) {
+        return mapOverValues(v -> val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector map(IgniteDoubleFunction<Double> fun) {
+        return mapOverValues(fun);
+    }
+
+    /**
+     * @param mapper Mapping function.
+     * @return Vector with mapped values.
+     */
+    private Vector mapOverValues(IgniteDoubleFunction<Double> mapper) {
+        CacheUtils.sparseMapForVector(getUUID(), mapper, storage().cacheName());
+
+        return this;
+    }
+
+    /** */
+    public UUID getUUID() {
+        return ((SparseDistributedVectorStorage) getStorage()).getUUID();
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/VectorBlockEntry.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/VectorBlockEntry.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/VectorBlockEntry.java
new file mode 100644
index 0000000..ad795c4
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/vector/VectorBlockEntry.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.ml.math.impls.vector;
+
+
+import org.apache.ignite.ml.math.Vector;
+
+
+/**
+ * Block for {@link SparseBlockDistributedVector}.
+ */
+public final class VectorBlockEntry extends SparseLocalVector {
+    /** Max block size. */
+    public static final int MAX_BLOCK_SIZE = 32;
+
+    /** */
+    public VectorBlockEntry() {
+        // No-op.
+    }
+
+    /** */
+    public VectorBlockEntry(int size) {
+        super(size, RANDOM_ACCESS_MODE);
+        assert size <= MAX_BLOCK_SIZE;
+    }
+
+    /** */
+    public VectorBlockEntry(Vector v) {
+        assert v.size() <= MAX_BLOCK_SIZE;
+
+        setStorage(v.getStorage());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
index c0a57d7..0ab568c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/util/MatrixUtil.java
@@ -71,7 +71,7 @@ public class MatrixUtil {
      * @return Like matrix.
      */
     public static Matrix like(Matrix matrix, int rows, int cols) {
-        if (isCopyLikeSupport(matrix) || isDistributed(matrix))
+        if (isCopyLikeSupport(matrix))
             return new DenseLocalOnHeapMatrix(rows, cols);
         else
             return matrix.like(rows, cols);
@@ -85,7 +85,7 @@ public class MatrixUtil {
      * @return Like vector.
      */
     public static Vector likeVector(Matrix matrix, int crd) {
-        if (isCopyLikeSupport(matrix) || isDistributed(matrix))
+        if (isCopyLikeSupport(matrix))
             return new DenseLocalOnHeapVector(crd);
         else
             return matrix.likeVector(crd);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java
index 5dc860c..784a455 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/MathImplDistributedTestSuite.java
@@ -21,7 +21,10 @@ import org.apache.ignite.ml.math.impls.matrix.CacheMatrixTest;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedBlockMatrixTest;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrixTest;
 import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorageTest;
+import org.apache.ignite.ml.math.impls.storage.vector.SparseDistributedVectorStorageTest;
 import org.apache.ignite.ml.math.impls.vector.CacheVectorTest;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVectorTest;
+import org.apache.ignite.ml.math.impls.vector.SparseDistributedVectorTest;
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
 
@@ -30,11 +33,14 @@ import org.junit.runners.Suite;
  */
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
-    CacheVectorTest.class,
-    CacheMatrixTest.class,
-    SparseDistributedMatrixStorageTest.class,
-    SparseDistributedMatrixTest.class,
-    SparseDistributedBlockMatrixTest.class
+        CacheVectorTest.class,
+        CacheMatrixTest.class,
+        SparseDistributedMatrixStorageTest.class,
+        SparseDistributedMatrixTest.class,
+        SparseDistributedBlockMatrixTest.class,
+        SparseDistributedVectorStorageTest.class,
+        SparseDistributedVectorTest.class,
+        SparseBlockDistributedVectorTest.class
 })
 public class MathImplDistributedTestSuite {
     // No-op.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedBlockMatrixTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedBlockMatrixTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedBlockMatrixTest.java
index fd6ed78..b4f5c2d 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedBlockMatrixTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedBlockMatrixTest.java
@@ -17,26 +17,23 @@
 
 package org.apache.ignite.ml.math.impls.matrix;
 
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.Collection;
-import java.util.Set;
-import java.util.UUID;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.distributed.DistributedStorage;
-import org.apache.ignite.ml.math.distributed.keys.impl.BlockMatrixKey;
-import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.distributed.keys.impl.MatrixBlockKey;
 import org.apache.ignite.ml.math.impls.MathTestConstants;
 import org.apache.ignite.ml.math.impls.storage.matrix.BlockMatrixStorage;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.testframework.junits.common.GridCommonTest;
 
+import java.io.*;
+import java.util.Collection;
+import java.util.Set;
+
 import static org.apache.ignite.ml.math.impls.MathTestConstants.UNEXPECTED_VAL;
 
 /**
@@ -207,14 +204,14 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
 
         cacheMatrix = new SparseBlockDistributedMatrix(rows, cols);
 
-        try {
-            cacheMatrix.copy();
-            fail("UnsupportedOperationException expected.");
-        }
-        catch (UnsupportedOperationException e) {
-            return;
-        }
-        fail("UnsupportedOperationException expected.");
+        cacheMatrix.set(rows-1, cols -1, 1);
+
+
+        Matrix newMatrix =  cacheMatrix.copy();
+        assert newMatrix.columnSize() == cols;
+        assert newMatrix.rowSize() == rows;
+        assert newMatrix.get(rows-1,cols-1) == 1;
+
     }
 
     /** Test cache behaviour for matrix with different blocks */
@@ -226,7 +223,7 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
     /** Test cache behaviour for matrix with homogeneous blocks */
     public void testCacheBehaviourWithHomogeneousBlocks(){
         IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
-        int size = BlockEntry.MAX_BLOCK_SIZE * 3;
+        int size = MatrixBlockEntry.MAX_BLOCK_SIZE * 3;
         cacheBehaviorLogic(size);
     }
 
@@ -242,10 +239,10 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
 
         assert cacheNames.contains(((DistributedStorage)cacheMatrix1.getStorage()).cacheName());
 
-        IgniteCache<BlockMatrixKey, Object> cache = ignite.getOrCreateCache(((DistributedStorage)cacheMatrix1.getStorage()).cacheName());
+        IgniteCache<MatrixBlockKey, Object> cache = ignite.getOrCreateCache(((DistributedStorage)cacheMatrix1.getStorage()).cacheName());
 
-        Set<BlockMatrixKey> keySet1 = buildKeySet(cacheMatrix1);
-        Set<BlockMatrixKey> keySet2 = buildKeySet(cacheMatrix2);
+        Set<MatrixBlockKey> keySet1 = buildKeySet(cacheMatrix1);
+        Set<MatrixBlockKey> keySet2 = buildKeySet(cacheMatrix2);
 
         assert cache.containsKeys(keySet1);
         assert cache.containsKeys(keySet2);
@@ -275,14 +272,10 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
 
         cacheMatrix = new SparseBlockDistributedMatrix(rows, cols);
 
-        try {
-            cacheMatrix.likeVector(1);
-            fail("UnsupportedOperationException expected.");
-        }
-        catch (UnsupportedOperationException e) {
-            return;
-        }
-        fail("UnsupportedOperationException expected.");
+        Vector v = cacheMatrix.likeVector(1);
+        assert v.size() == 1;
+        assert v instanceof SparseBlockDistributedVector;
+
     }
 
     /**
@@ -298,7 +291,7 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
      * Simple test for two square matrices with size which is proportional to MAX_BLOCK_SIZE constant
      */
     public void testSquareMatrixTimesWithHomogeneousBlocks(){
-        int size = BlockEntry.MAX_BLOCK_SIZE * 3;
+        int size = MatrixBlockEntry.MAX_BLOCK_SIZE * 3;
 
         squareMatrixTimesLogic(size);
     }
@@ -331,8 +324,8 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
     public void testNonSquareMatrixTimes(){
         IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
 
-        int size = BlockEntry.MAX_BLOCK_SIZE + 1;
-        int size2 = BlockEntry.MAX_BLOCK_SIZE * 2 + 1;
+        int size = MatrixBlockEntry.MAX_BLOCK_SIZE + 1;
+        int size2 = MatrixBlockEntry.MAX_BLOCK_SIZE * 2 + 1;
 
         Matrix cacheMatrix1 = new SparseBlockDistributedMatrix(size2, size);
         Matrix cacheMatrix2 = new SparseBlockDistributedMatrix(size, size2);
@@ -358,8 +351,8 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
     public void testNonSquareMatrixTimes2(){
         IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
 
-        int size = BlockEntry.MAX_BLOCK_SIZE + 1;
-        int size2 = BlockEntry.MAX_BLOCK_SIZE * 2 + 1;
+        int size = MatrixBlockEntry.MAX_BLOCK_SIZE + 1;
+        int size2 = MatrixBlockEntry.MAX_BLOCK_SIZE * 2 + 1;
 
         Matrix cacheMatrix1 = new SparseBlockDistributedMatrix(size, size2);
         Matrix cacheMatrix2 = new SparseBlockDistributedMatrix(size2, size);
@@ -379,6 +372,26 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
                     assertEquals(UNEXPECTED_VAL + " for "+ i +":"+ j, 0, res.get(i, j), PRECISION);
     }
 
+    public void testMatrixVectorTimes(){
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        SparseBlockDistributedMatrix a = new SparseBlockDistributedMatrix(new double[][] {{2.0, 4.0, 0.0}, {-2.0, 1.0, 3.0}, {-1.0, 0.0, 1.0}});
+        SparseBlockDistributedVector b = new SparseBlockDistributedVector(new double[] {1.0, 2.0, -1.0});
+        SparseBlockDistributedVector result = new SparseBlockDistributedVector(new double[] {10, -3.0, -2.0});
+
+
+        Vector calculatedResult = a.times(b);
+
+        for(int i = 0; i < calculatedResult.size(); i++)
+            assertEquals(UNEXPECTED_VAL + " for "+ i, result.get(i), calculatedResult.get(i), PRECISION);
+
+
+    }
+
+
+
+
+
     /** */
     private void initMtx(Matrix m) {
         for (int i = 0; i < m.rowSize(); i++)
@@ -387,7 +400,8 @@ public class SparseDistributedBlockMatrixTest extends GridCommonAbstractTest {
     }
 
     /** Build key set for SparseBlockDistributedMatrix. */
-    private Set<BlockMatrixKey> buildKeySet(SparseBlockDistributedMatrix m){
+    private Set<MatrixBlockKey> buildKeySet(SparseBlockDistributedMatrix m){
+
         BlockMatrixStorage storage = (BlockMatrixStorage)m.getStorage();
 
         return storage.getAllKeys();

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrixTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrixTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrixTest.java
index 1955588..a9343f4 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrixTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrixTest.java
@@ -30,11 +30,14 @@ import org.apache.ignite.IgniteCache;
 import org.apache.ignite.internal.util.IgniteUtils;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.distributed.DistributedStorage;
 import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
 import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
 import org.apache.ignite.ml.math.impls.MathTestConstants;
 import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorage;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.apache.ignite.ml.math.impls.vector.SparseDistributedVector;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.testframework.junits.common.GridCommonTest;
 
@@ -212,14 +215,13 @@ public class SparseDistributedMatrixTest extends GridCommonAbstractTest {
 
         cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
 
-        try {
-            cacheMatrix.copy();
-            fail("UnsupportedOperationException expected.");
-        }
-        catch (UnsupportedOperationException e) {
-            return;
+        Matrix copiedMtx = cacheMatrix.copy();
+
+        for (int i = 0; i < cacheMatrix.rowSize(); i++) {
+            for (int j = 0; j < cacheMatrix.columnSize(); j++) {
+                assert copiedMtx.get(i,j) == cacheMatrix.get(i,j);
+            }
         }
-        fail("UnsupportedOperationException expected.");
     }
 
     /** */
@@ -274,14 +276,9 @@ public class SparseDistributedMatrixTest extends GridCommonAbstractTest {
 
         cacheMatrix = new SparseDistributedMatrix(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
 
-        try {
-            cacheMatrix.likeVector(1);
-            fail("UnsupportedOperationException expected.");
-        }
-        catch (UnsupportedOperationException e) {
-            return;
-        }
-        fail("UnsupportedOperationException expected.");
+        Vector v = cacheMatrix.likeVector(1);
+        assert v.size() == 1;
+        assert v instanceof SparseDistributedVector;
     }
 
     /** */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorageTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorageTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorageTest.java
new file mode 100644
index 0000000..9b6aa32
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/storage/vector/SparseDistributedVectorStorageTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.ml.math.impls.storage.vector;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.impls.MathTestConstants;
+import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorage;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+
+/**
+ * Tests for {@link SparseDistributedVectorStorage}.
+ */
+@GridCommonTest(group = "Distributed Models")
+public class SparseDistributedVectorStorageTest extends GridCommonAbstractTest {
+    /** Number of nodes in grid */
+    private static final int NODE_COUNT = 3;
+    /** Cache name. */
+    private static final String CACHE_NAME = "test-cache";
+    /** */
+    private static final String UNEXPECTED_ATTRIBUTE_VALUE = "Unexpected attribute value.";
+    /** Grid instance. */
+    private Ignite ignite;
+
+    /**
+     * Default constructor.
+     */
+    public SparseDistributedVectorStorageTest() {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        for (int i = 1; i <= NODE_COUNT; i++)
+            startGrid(i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override protected void beforeTest() throws Exception {
+        ignite = grid(NODE_COUNT);
+
+        ignite.configuration().setPeerClassLoadingEnabled(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        ignite.destroyCache(CACHE_NAME);
+    }
+
+    /** */
+    public void testCacheCreation() throws Exception {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        final int size = MathTestConstants.STORAGE_SIZE;
+
+        SparseDistributedVectorStorage storage = new SparseDistributedVectorStorage(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        assertNotNull("SparseDistributedMatrixStorage cache is null.", storage.cache());
+    }
+
+    /** */
+    public void testSetGet() throws Exception {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        final int size = MathTestConstants.STORAGE_SIZE;
+
+        SparseDistributedVectorStorage storage = new SparseDistributedVectorStorage(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        for (int i = 0; i < size; i++) {
+                double v = Math.random();
+                storage.set(i, v);
+
+                assert Double.compare(v, storage.get(i)) == 0;
+                assert Double.compare(v, storage.get(i)) == 0;
+        }
+    }
+
+    /** */
+    public void testAttributes() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        final int size = MathTestConstants.STORAGE_SIZE;
+
+        SparseDistributedVectorStorage storage = new SparseDistributedVectorStorage(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        assertEquals(UNEXPECTED_ATTRIBUTE_VALUE, storage.size(), size);
+
+        assertFalse(UNEXPECTED_ATTRIBUTE_VALUE, storage.isArrayBased());
+        assertFalse(UNEXPECTED_ATTRIBUTE_VALUE, storage.isDense());
+        assertTrue(UNEXPECTED_ATTRIBUTE_VALUE, storage.isDistributed());
+
+        assertEquals(UNEXPECTED_ATTRIBUTE_VALUE, storage.isRandomAccess(), !storage.isSequentialAccess());
+        assertTrue(UNEXPECTED_ATTRIBUTE_VALUE, storage.isRandomAccess());
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVectorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVectorTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVectorTest.java
new file mode 100644
index 0000000..4ac2845
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseBlockDistributedVectorTest.java
@@ -0,0 +1,181 @@
+/*
+ * 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.ml.math.impls.vector;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.impls.MathTestConstants;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+
+import java.io.*;
+
+import static org.apache.ignite.ml.math.impls.MathTestConstants.UNEXPECTED_VAL;
+
+/**
+ * Tests for {@link SparseDistributedVector}.
+ */
+@GridCommonTest(group = "Distributed Models")
+public class SparseBlockDistributedVectorTest extends GridCommonAbstractTest {
+    /** Number of nodes in grid */
+    private static final int NODE_COUNT = 3;
+    /** Precision. */
+    private static final double PRECISION = 0.0;
+    /** Grid instance. */
+    private Ignite ignite;
+    /** Vector size */
+    private final int size = MathTestConstants.STORAGE_SIZE;
+    /** Vector for tests */
+    private SparseBlockDistributedVector sparseBlockDistributedVector;
+
+    /**
+     * Default constructor.
+     */
+    public SparseBlockDistributedVectorTest() {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        for (int i = 1; i <= NODE_COUNT; i++)
+            startGrid(i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override protected void beforeTest() throws Exception {
+        ignite = grid(NODE_COUNT);
+
+        ignite.configuration().setPeerClassLoadingEnabled(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (sparseBlockDistributedVector != null) {
+            sparseBlockDistributedVector.destroy();
+            sparseBlockDistributedVector = null;
+        }
+    }
+
+    /** */
+    public void testGetSet() throws Exception {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseBlockDistributedVector = new SparseBlockDistributedVector(size);
+
+        for (int i = 0; i < size; i++) {
+                double v = Math.random();
+                sparseBlockDistributedVector.set(i, v);
+                assertEquals("Unexpected value for vector element[" + i + "]", v, sparseBlockDistributedVector.get(i), PRECISION);
+        }
+    }
+
+    /** */
+    public void testExternalize() throws IOException, ClassNotFoundException {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseBlockDistributedVector = new SparseBlockDistributedVector(size);
+
+        sparseBlockDistributedVector.set(1, 1.0);
+
+        ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
+        ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream);
+
+        objOutputStream.writeObject(sparseBlockDistributedVector);
+
+        ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray());
+        ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream);
+
+        SparseBlockDistributedVector objRestored = (SparseBlockDistributedVector)objInputStream.readObject();
+
+        assertTrue(MathTestConstants.VAL_NOT_EQUALS, sparseBlockDistributedVector.equals(objRestored));
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, objRestored.get(1), 1.0, PRECISION);
+    }
+
+    /** Test simple math. */
+    public void testMath() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseBlockDistributedVector = new SparseBlockDistributedVector(size);
+        initVector(sparseBlockDistributedVector);
+
+        sparseBlockDistributedVector.assign(2.0);
+        for (int i = 0; i < sparseBlockDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 2.0, sparseBlockDistributedVector.get(i), PRECISION);
+
+        sparseBlockDistributedVector.plus(3.0);
+        for (int i = 0; i < sparseBlockDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 5.0, sparseBlockDistributedVector.get(i), PRECISION);
+
+        sparseBlockDistributedVector.times(2.0);
+        for (int i = 0; i < sparseBlockDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 10.0, sparseBlockDistributedVector.get(i), PRECISION);
+
+        sparseBlockDistributedVector.divide(10.0);
+        for (int i = 0; i < sparseBlockDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 1.0, sparseBlockDistributedVector.get(i), PRECISION);
+    }
+
+
+    /** */
+    public void testMap() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseBlockDistributedVector = new SparseBlockDistributedVector(size);
+        initVector(sparseBlockDistributedVector);
+
+        sparseBlockDistributedVector.map(i -> 100.0);
+        for (int i = 0; i < sparseBlockDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 100.0, sparseBlockDistributedVector.get(i), PRECISION);
+    }
+
+    /** */
+    public void testCopy() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseBlockDistributedVector = new SparseBlockDistributedVector(size);
+
+        Vector cp = sparseBlockDistributedVector.copy();
+        assertNotNull(cp);
+        for (int i = 0; i < size; i++)
+            assertEquals(UNEXPECTED_VAL, cp.get(i), sparseBlockDistributedVector.get(i), PRECISION);
+    }
+
+    /** */
+    public void testLike() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseBlockDistributedVector = new SparseBlockDistributedVector(size);
+
+        assertNotNull(sparseBlockDistributedVector.like(1));
+    }
+
+
+    /** */
+    private void initVector(Vector v) {
+        for (int i = 0; i < v.size(); i++)
+                v.set(i, 1.0);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVectorTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVectorTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVectorTest.java
new file mode 100644
index 0000000..416e254
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/math/impls/vector/SparseDistributedVectorTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.ml.math.impls.vector;
+
+import org.apache.ignite.Ignite;
+
+import org.apache.ignite.internal.util.IgniteUtils;
+
+import org.apache.ignite.ml.math.StorageConstants;
+import org.apache.ignite.ml.math.Vector;
+
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.impls.MathTestConstants;
+
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Ignore;
+
+import java.io.*;
+
+
+import static org.apache.ignite.ml.math.impls.MathTestConstants.UNEXPECTED_VAL;
+
+/**
+ * Tests for {@link SparseDistributedVector}.
+ */
+@GridCommonTest(group = "Distributed Models")
+public class SparseDistributedVectorTest extends GridCommonAbstractTest {
+    /** Number of nodes in grid */
+    private static final int NODE_COUNT = 3;
+    /** Precision. */
+    private static final double PRECISION = 0.0;
+    /** Grid instance. */
+    private Ignite ignite;
+    /** Vector size */
+    private final int size = MathTestConstants.STORAGE_SIZE;
+    /** Vector for tests */
+    private SparseDistributedVector sparseDistributedVector;
+
+    /**
+     * Default constructor.
+     */
+    public SparseDistributedVectorTest() {
+        super(false);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        for (int i = 1; i <= NODE_COUNT; i++)
+            startGrid(i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override protected void beforeTest() throws Exception {
+        ignite = grid(NODE_COUNT);
+
+        ignite.configuration().setPeerClassLoadingEnabled(true);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        if (sparseDistributedVector != null) {
+            sparseDistributedVector.destroy();
+            sparseDistributedVector = null;
+        }
+    }
+
+    /** */
+    public void testGetSet() throws Exception {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseDistributedVector = new SparseDistributedVector(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        for (int i = 0; i < size; i++) {
+                double v = Math.random();
+                sparseDistributedVector.set(i, v);
+                assertEquals("Unexpected value for vector element[" + i + "]", v, sparseDistributedVector.get(i), PRECISION);
+        }
+    }
+
+    /** */
+    public void testExternalize() throws IOException, ClassNotFoundException {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseDistributedVector = new SparseDistributedVector(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        sparseDistributedVector.set(1, 1.0);
+
+        ByteArrayOutputStream byteArrOutputStream = new ByteArrayOutputStream();
+        ObjectOutputStream objOutputStream = new ObjectOutputStream(byteArrOutputStream);
+
+        objOutputStream.writeObject(sparseDistributedVector);
+
+        ByteArrayInputStream byteArrInputStream = new ByteArrayInputStream(byteArrOutputStream.toByteArray());
+        ObjectInputStream objInputStream = new ObjectInputStream(byteArrInputStream);
+
+        SparseDistributedVector objRestored = (SparseDistributedVector)objInputStream.readObject();
+
+        assertTrue(MathTestConstants.VAL_NOT_EQUALS, sparseDistributedVector.equals(objRestored));
+        assertEquals(MathTestConstants.VAL_NOT_EQUALS, objRestored.get(1), 1.0, PRECISION);
+    }
+
+    /** Test simple math. */
+    public void testMath() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseDistributedVector = new SparseDistributedVector(size, StorageConstants.RANDOM_ACCESS_MODE);
+        initVector(sparseDistributedVector);
+
+        sparseDistributedVector.assign(2.0);
+        for (int i = 0; i < sparseDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 2.0, sparseDistributedVector.get(i), PRECISION);
+
+        sparseDistributedVector.plus(3.0);
+        for (int i = 0; i < sparseDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 5.0, sparseDistributedVector.get(i), PRECISION);
+
+        sparseDistributedVector.times(2.0);
+        for (int i = 0; i < sparseDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 10.0, sparseDistributedVector.get(i), PRECISION);
+
+        sparseDistributedVector.divide(10.0);
+        for (int i = 0; i < sparseDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 1.0, sparseDistributedVector.get(i), PRECISION);
+
+       // assertEquals(UNEXPECTED_VAL, sparseDistributedVector.rowSize() * sparseDistributedVector.columnSize(), sparseDistributedVector.sum(), PRECISION);
+    }
+
+
+    /** */
+    public void testMap() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseDistributedVector = new SparseDistributedVector(size, StorageConstants.RANDOM_ACCESS_MODE);
+        initVector(sparseDistributedVector);
+
+        sparseDistributedVector.map(i -> 100.0);
+        for (int i = 0; i < sparseDistributedVector.size(); i++)
+                assertEquals(UNEXPECTED_VAL, 100.0, sparseDistributedVector.get(i), PRECISION);
+    }
+
+    /** */
+    public void testCopy() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseDistributedVector = new SparseDistributedVector(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        Vector copy = sparseDistributedVector.copy();
+        assertNotNull(copy);
+        for (int i = 0; i < size; i++)
+            assertEquals(UNEXPECTED_VAL, copy.get(i), sparseDistributedVector.get(i), PRECISION);
+    }
+
+
+    /** */
+    public void testLike() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        sparseDistributedVector = new SparseDistributedVector(size, StorageConstants.RANDOM_ACCESS_MODE);
+
+        assertNotNull(sparseDistributedVector.like(1));
+    }
+
+
+    /** */
+    private void initVector(Vector v) {
+        for (int i = 0; i < v.size(); i++)
+                v.set(i, 1.0);
+    }
+}


[31/47] ignite git commit: IGNITE-5846 Add support of distributed matrices for OLS regression. This closes #3030.

Posted by sb...@apache.org.
IGNITE-5846 Add support of distributed matrices for OLS regression. This closes #3030.

Signed-off-by: nikolay_tikhonov <nt...@gridgain.com>


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

Branch: refs/heads/ignite-zk
Commit: b0a86018693581065f789635facb88b1e8dac834
Parents: cbd7e39
Author: YuriBabak <y....@gmail.com>
Authored: Fri Nov 17 16:06:34 2017 +0300
Committer: nikolay_tikhonov <nt...@gridgain.com>
Committed: Fri Nov 17 16:07:51 2017 +0300

----------------------------------------------------------------------
 .../clustering/KMeansDistributedClusterer.java  |  13 +-
 .../ignite/ml/math/distributed/CacheUtils.java  | 278 +++---
 .../math/distributed/keys/BlockMatrixKey.java   |  38 -
 .../distributed/keys/DataStructureCacheKey.java |  35 +
 .../math/distributed/keys/MatrixBlockKey.java   |  38 +
 .../math/distributed/keys/MatrixCacheKey.java   |  35 -
 .../math/distributed/keys/RowColMatrixKey.java  |   2 +-
 .../math/distributed/keys/VectorBlockKey.java   |  34 +
 .../distributed/keys/impl/BlockMatrixKey.java   | 164 ----
 .../distributed/keys/impl/MatrixBlockKey.java   | 162 ++++
 .../distributed/keys/impl/SparseMatrixKey.java  |  14 +-
 .../distributed/keys/impl/VectorBlockKey.java   | 151 +++
 .../ignite/ml/math/functions/Functions.java     |   3 +-
 .../ml/math/impls/matrix/AbstractMatrix.java    |  24 +-
 .../ignite/ml/math/impls/matrix/BlockEntry.java |  50 -
 .../ml/math/impls/matrix/MatrixBlockEntry.java  |  50 +
 .../matrix/SparseBlockDistributedMatrix.java    | 153 ++-
 .../impls/matrix/SparseDistributedMatrix.java   | 102 +-
 .../storage/matrix/BlockMatrixStorage.java      |  96 +-
 .../storage/matrix/BlockVectorStorage.java      | 374 ++++++++
 .../impls/storage/matrix/MapWrapperStorage.java |   5 +-
 .../matrix/SparseDistributedMatrixStorage.java  |  21 +-
 .../vector/SparseDistributedVectorStorage.java  | 280 ++++++
 .../vector/SparseBlockDistributedVector.java    | 139 +++
 .../impls/vector/SparseDistributedVector.java   | 157 ++++
 .../ml/math/impls/vector/VectorBlockEntry.java  |  49 +
 .../apache/ignite/ml/math/util/MatrixUtil.java  |   4 +-
 .../ml/math/MathImplDistributedTestSuite.java   |  16 +-
 .../SparseDistributedBlockMatrixTest.java       |  86 +-
 .../matrix/SparseDistributedMatrixTest.java     |  27 +-
 .../SparseDistributedVectorStorageTest.java     | 121 +++
 .../SparseBlockDistributedVectorTest.java       | 181 ++++
 .../vector/SparseDistributedVectorTest.java     | 192 ++++
 ...tedBlockOLSMultipleLinearRegressionTest.java | 926 ++++++++++++++++++
 ...tributedOLSMultipleLinearRegressionTest.java | 934 +++++++++++++++++++
 .../OLSMultipleLinearRegressionTest.java        |   1 +
 .../ml/regressions/RegressionsTestSuite.java    |   2 +-
 37 files changed, 4351 insertions(+), 606 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
index 6c25edc..4286f42 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/clustering/KMeansDistributedClusterer.java
@@ -196,12 +196,11 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
                 return list;
             },
-            key -> key.matrixId().equals(uid),
+            key -> key.dataStructureId().equals(uid),
             (list1, list2) -> {
                 list1.addAll(list2);
                 return list1;
-            },
-            ArrayList::new
+            }, ArrayList::new
         );
     }
 
@@ -216,7 +215,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
                 return map;
             },
-            key -> key.matrixId().equals(points.getUUID()),
+            key -> key.dataStructureId().equals(points.getUUID()),
             (map1, map2) -> {
                 map1.putAll(map2);
                 return map1;
@@ -247,10 +246,10 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
                 countMap.compute(resInd, (ind, v) -> v != null ? v + 1 : 1);
                 return countMap;
             },
-            key -> key.matrixId().equals(uid),
+            key -> key.dataStructureId().equals(uid),
             (map1, map2) -> MapUtil.mergeMaps(map1, map2, (integer, integer2) -> integer2 + integer,
                 ConcurrentHashMap::new),
-            ConcurrentHashMap::new);
+                ConcurrentHashMap::new);
     }
 
     /** */
@@ -278,7 +277,7 @@ public class KMeansDistributedClusterer extends BaseKMeansClusterer<SparseDistri
 
                 return counts;
             },
-            key -> key.matrixId().equals(uid),
+            key -> key.dataStructureId().equals(uid),
             SumsAndCounts::merge, SumsAndCounts::new
         );
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
index b9eb386..37384b8 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/CacheUtils.java
@@ -17,16 +17,6 @@
 
 package org.apache.ignite.ml.math.distributed;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.BinaryOperator;
-import java.util.stream.Stream;
-import javax.cache.Cache;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
@@ -40,18 +30,21 @@ import org.apache.ignite.lang.IgniteBiTuple;
 import org.apache.ignite.lang.IgniteCallable;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.lang.IgniteRunnable;
-import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.ml.math.KeyMapper;
-import org.apache.ignite.ml.math.distributed.keys.BlockMatrixKey;
-import org.apache.ignite.ml.math.distributed.keys.MatrixCacheKey;
-import org.apache.ignite.ml.math.functions.IgniteBiFunction;
-import org.apache.ignite.ml.math.functions.IgniteBinaryOperator;
-import org.apache.ignite.ml.math.functions.IgniteConsumer;
-import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
-import org.apache.ignite.ml.math.functions.IgniteFunction;
-import org.apache.ignite.ml.math.functions.IgniteSupplier;
-import org.apache.ignite.ml.math.functions.IgniteTriFunction;
-import org.apache.ignite.ml.math.impls.matrix.BlockEntry;
+import org.apache.ignite.ml.math.distributed.keys.DataStructureCacheKey;
+import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
+import org.apache.ignite.ml.math.distributed.keys.impl.MatrixBlockKey;
+import org.apache.ignite.ml.math.distributed.keys.impl.VectorBlockKey;
+import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
+import org.apache.ignite.ml.math.functions.*;
+import org.apache.ignite.ml.math.impls.matrix.MatrixBlockEntry;
+import org.apache.ignite.ml.math.impls.vector.VectorBlockEntry;
+
+import javax.cache.Cache;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.BinaryOperator;
+import java.util.stream.Stream;
 
 /**
  * Distribution-related misc. support.
@@ -104,11 +97,11 @@ public class CacheUtils {
 
     /**
      * @param cacheName Cache name.
-     * @param k Key into the cache.
-     * @param <K> Key type.
+     * @param k         Key into the cache.
+     * @param <K>       Key type.
      * @return Cluster group for given key.
      */
-    public static <K> ClusterGroup groupForKey(String cacheName, K k) {
+    protected static <K> ClusterGroup getClusterGroupForGivenKey(String cacheName, K k) {
         return ignite().cluster().forNode(ignite().affinity(cacheName).mapKeyToNode(k));
     }
 
@@ -116,8 +109,8 @@ public class CacheUtils {
      * @param cacheName Cache name.
      * @param keyMapper {@link KeyMapper} to validate cache key.
      * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      * @return Sum of the values obtained for valid keys.
      */
     public static <K, V> double sum(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) {
@@ -126,8 +119,7 @@ public class CacheUtils {
                 double v = valMapper.toDouble(ce.entry().getValue());
 
                 return acc == null ? v : acc + v;
-            }
-            else
+            } else
                 return acc;
         });
 
@@ -146,19 +138,17 @@ public class CacheUtils {
         Collection<Double> subSums = fold(cacheName, (CacheEntry<K, V> ce, Double acc) -> {
             V v = ce.entry().getValue();
 
-            double sum = 0.0;
+            double sum;
 
             if (v instanceof Map) {
-                Map<Integer, Double> map = (Map<Integer, Double>)v;
+                Map<Integer, Double> map = (Map<Integer, Double>) v;
 
                 sum = sum(map.values());
-            }
-            else if (v instanceof BlockEntry) {
-                BlockEntry be = (BlockEntry)v;
+            } else if (v instanceof MatrixBlockEntry) {
+                MatrixBlockEntry be = (MatrixBlockEntry) v;
 
                 sum = be.sum();
-            }
-            else
+            } else
                 throw new UnsupportedOperationException();
 
             return acc == null ? sum : acc + sum;
@@ -180,8 +170,8 @@ public class CacheUtils {
      * @param cacheName Cache name.
      * @param keyMapper {@link KeyMapper} to validate cache key.
      * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      * @return Minimum value for valid keys.
      */
     public static <K, V> double min(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) {
@@ -193,8 +183,7 @@ public class CacheUtils {
                     return v;
                 else
                     return Math.min(acc, v);
-            }
-            else
+            } else
                 return acc;
         });
 
@@ -216,16 +205,14 @@ public class CacheUtils {
             double min;
 
             if (v instanceof Map) {
-                Map<Integer, Double> map = (Map<Integer, Double>)v;
+                Map<Integer, Double> map = (Map<Integer, Double>) v;
 
                 min = Collections.min(map.values());
-            }
-            else if (v instanceof BlockEntry) {
-                BlockEntry be = (BlockEntry)v;
+            } else if (v instanceof MatrixBlockEntry) {
+                MatrixBlockEntry be = (MatrixBlockEntry) v;
 
                 min = be.minValue();
-            }
-            else
+            } else
                 throw new UnsupportedOperationException();
 
             if (acc == null)
@@ -253,16 +240,14 @@ public class CacheUtils {
             double max;
 
             if (v instanceof Map) {
-                Map<Integer, Double> map = (Map<Integer, Double>)v;
+                Map<Integer, Double> map = (Map<Integer, Double>) v;
 
                 max = Collections.max(map.values());
-            }
-            else if (v instanceof BlockEntry) {
-                BlockEntry be = (BlockEntry)v;
+            } else if (v instanceof MatrixBlockEntry) {
+                MatrixBlockEntry be = (MatrixBlockEntry) v;
 
                 max = be.maxValue();
-            }
-            else
+            } else
                 throw new UnsupportedOperationException();
 
             if (acc == null)
@@ -279,8 +264,8 @@ public class CacheUtils {
      * @param cacheName Cache name.
      * @param keyMapper {@link KeyMapper} to validate cache key.
      * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      * @return Maximum value for valid keys.
      */
     public static <K, V> double max(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper) {
@@ -292,8 +277,7 @@ public class CacheUtils {
                     return v;
                 else
                     return Math.max(acc, v);
-            }
-            else
+            } else
                 return acc;
         });
 
@@ -304,12 +288,12 @@ public class CacheUtils {
      * @param cacheName Cache name.
      * @param keyMapper {@link KeyMapper} to validate cache key.
      * @param valMapper {@link ValueMapper} to obtain double value for given cache key.
-     * @param mapper Mapping {@link IgniteFunction}.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param mapper    Mapping {@link IgniteFunction}.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      */
     public static <K, V> void map(String cacheName, KeyMapper<K> keyMapper, ValueMapper<V> valMapper,
-        IgniteFunction<Double, Double> mapper) {
+                                  IgniteFunction<Double, Double> mapper) {
         foreach(cacheName, (CacheEntry<K, V> ce) -> {
             K k = ce.entry().getKey();
 
@@ -321,7 +305,7 @@ public class CacheUtils {
 
     /**
      * @param matrixUuid Matrix UUID.
-     * @param mapper Mapping {@link IgniteFunction}.
+     * @param mapper     Mapping {@link IgniteFunction}.
      */
     @SuppressWarnings("unchecked")
     public static <K, V> void sparseMap(UUID matrixUuid, IgniteDoubleFunction<Double> mapper, String cacheName) {
@@ -335,18 +319,16 @@ public class CacheUtils {
             V v = ce.entry().getValue();
 
             if (v instanceof Map) {
-                Map<Integer, Double> map = (Map<Integer, Double>)v;
+                Map<Integer, Double> map = (Map<Integer, Double>) v;
 
                 for (Map.Entry<Integer, Double> e : (map.entrySet()))
                     e.setValue(mapper.apply(e.getValue()));
 
-            }
-            else if (v instanceof BlockEntry) {
-                BlockEntry be = (BlockEntry)v;
+            } else if (v instanceof MatrixBlockEntry) {
+                MatrixBlockEntry be = (MatrixBlockEntry) v;
 
                 be.map(mapper);
-            }
-            else
+            } else
                 throw new UnsupportedOperationException();
 
             ce.cache().put(k, v);
@@ -360,34 +342,40 @@ public class CacheUtils {
      */
     private static <K> IgnitePredicate<K> sparseKeyFilter(UUID matrixUuid) {
         return key -> {
-            if (key instanceof MatrixCacheKey)
-                return ((MatrixCacheKey)key).matrixId().equals(matrixUuid);
+            if (key instanceof DataStructureCacheKey)
+                return ((DataStructureCacheKey) key).dataStructureId().equals(matrixUuid);
             else if (key instanceof IgniteBiTuple)
-                return ((IgniteBiTuple<Integer, UUID>)key).get2().equals(matrixUuid);
+                return ((IgniteBiTuple<Integer, UUID>) key).get2().equals(matrixUuid);
+            else if (key instanceof MatrixBlockKey)
+                return ((MatrixBlockKey) key).dataStructureId().equals(matrixUuid);
+            else if (key instanceof RowColMatrixKey)
+                return ((RowColMatrixKey) key).dataStructureId().equals(matrixUuid);
+            else if (key instanceof VectorBlockKey)
+                return ((VectorBlockKey) key).dataStructureId().equals(matrixUuid);
             else
-                throw new UnsupportedOperationException();
+                throw new UnsupportedOperationException(); // TODO: handle my poor doubles
         };
     }
 
     /**
      * @param cacheName Cache name.
-     * @param fun An operation that accepts a cache entry and processes it.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param fun       An operation that accepts a cache entry and processes it.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      */
-    public static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun) {
+    private static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun) {
         foreach(cacheName, fun, null);
     }
 
     /**
      * @param cacheName Cache name.
-     * @param fun An operation that accepts a cache entry and processes it.
+     * @param fun       An operation that accepts a cache entry and processes it.
      * @param keyFilter Cache keys filter.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      */
-    public static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun,
-        IgnitePredicate<K> keyFilter) {
+    protected static <K, V> void foreach(String cacheName, IgniteConsumer<CacheEntry<K, V>> fun,
+                                         IgnitePredicate<K> keyFilter) {
         bcast(cacheName, () -> {
             Ignite ignite = Ignition.localIgnite();
             IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName);
@@ -405,7 +393,7 @@ public class CacheUtils {
                 // Iterate over given partition.
                 // Query returns an empty cursor if this partition is not stored on this node.
                 for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part,
-                    (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
+                        (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
                     fun.accept(new CacheEntry<>(entry, cache));
             }
         });
@@ -413,14 +401,14 @@ public class CacheUtils {
 
     /**
      * @param cacheName Cache name.
-     * @param fun An operation that accepts a cache entry and processes it.
-     * @param ignite Ignite.
-     * @param keysGen Keys generator.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param fun       An operation that accepts a cache entry and processes it.
+     * @param ignite    Ignite.
+     * @param keysGen   Keys generator.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      */
     public static <K, V> void update(String cacheName, Ignite ignite,
-        IgniteBiFunction<Ignite, Cache.Entry<K, V>, Stream<Cache.Entry<K, V>>> fun, IgniteSupplier<Set<K>> keysGen) {
+                                     IgniteBiFunction<Ignite, Cache.Entry<K, V>, Stream<Cache.Entry<K, V>>> fun, IgniteSupplier<Set<K>> keysGen) {
         bcast(cacheName, ignite, () -> {
             Ignite ig = Ignition.localIgnite();
             IgniteCache<K, V> cache = ig.getOrCreateCache(cacheName);
@@ -447,14 +435,14 @@ public class CacheUtils {
 
     /**
      * @param cacheName Cache name.
-     * @param fun An operation that accepts a cache entry and processes it.
-     * @param ignite Ignite.
-     * @param keysGen Keys generator.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
+     * @param fun       An operation that accepts a cache entry and processes it.
+     * @param ignite    Ignite.
+     * @param keysGen   Keys generator.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
      */
     public static <K, V> void update(String cacheName, Ignite ignite, IgniteConsumer<Cache.Entry<K, V>> fun,
-        IgniteSupplier<Set<K>> keysGen) {
+                                     IgniteSupplier<Set<K>> keysGen) {
         bcast(cacheName, ignite, () -> {
             Ignite ig = Ignition.localIgnite();
             IgniteCache<K, V> cache = ig.getOrCreateCache(cacheName);
@@ -485,10 +473,10 @@ public class CacheUtils {
      * <b>Currently fold supports only commutative operations.<b/>
      *
      * @param cacheName Cache name.
-     * @param folder Fold function operating over cache entries.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
-     * @param <A> Fold result type.
+     * @param folder    Fold function operating over cache entries.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
+     * @param <A>       Fold result type.
      * @return Fold operation result.
      */
     public static <K, V, A> Collection<A> fold(String cacheName, IgniteBiFunction<CacheEntry<K, V>, A, A> folder) {
@@ -499,14 +487,14 @@ public class CacheUtils {
      * <b>Currently fold supports only commutative operations.<b/>
      *
      * @param cacheName Cache name.
-     * @param folder Fold function operating over cache entries.
-     * @param <K> Cache key object type.
-     * @param <V> Cache value object type.
-     * @param <A> Fold result type.
+     * @param folder    Fold function operating over cache entries.
+     * @param <K>       Cache key object type.
+     * @param <V>       Cache value object type.
+     * @param <A>       Fold result type.
      * @return Fold operation result.
      */
     public static <K, V, A> Collection<A> fold(String cacheName, IgniteBiFunction<CacheEntry<K, V>, A, A> folder,
-        IgnitePredicate<K> keyFilter) {
+                                               IgnitePredicate<K> keyFilter) {
         return bcast(cacheName, () -> {
             Ignite ignite = Ignition.localIgnite();
             IgniteCache<K, V> cache = ignite.getOrCreateCache(cacheName);
@@ -526,7 +514,7 @@ public class CacheUtils {
                 // Iterate over given partition.
                 // Query returns an empty cursor if this partition is not stored on this node.
                 for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part,
-                    (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
+                        (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
                     a = folder.apply(new CacheEntry<>(entry, cache), a);
             }
 
@@ -537,34 +525,34 @@ public class CacheUtils {
     /**
      * Distributed version of fold operation.
      *
-     * @param cacheName Cache name.
-     * @param folder Folder.
-     * @param keyFilter Key filter.
+     * @param cacheName   Cache name.
+     * @param folder      Folder.
+     * @param keyFilter   Key filter.
      * @param accumulator Accumulator.
      * @param zeroValSupp Zero value supplier.
      */
     public static <K, V, A> A distributedFold(String cacheName, IgniteBiFunction<Cache.Entry<K, V>, A, A> folder,
-        IgnitePredicate<K> keyFilter, BinaryOperator<A> accumulator, IgniteSupplier<A> zeroValSupp) {
+                                              IgnitePredicate<K> keyFilter, BinaryOperator<A> accumulator, IgniteSupplier<A> zeroValSupp) {
         return sparseFold(cacheName, folder, keyFilter, accumulator, zeroValSupp, null, null, 0,
-            false);
+                false);
     }
 
     /**
      * Sparse version of fold. This method also applicable to sparse zeroes.
      *
-     * @param cacheName Cache name.
-     * @param folder Folder.
-     * @param keyFilter Key filter.
+     * @param cacheName   Cache name.
+     * @param folder      Folder.
+     * @param keyFilter   Key filter.
      * @param accumulator Accumulator.
      * @param zeroValSupp Zero value supplier.
-     * @param defVal Default value.
-     * @param defKey Default key.
-     * @param defValCnt Def value count.
+     * @param defVal      Default value.
+     * @param defKey      Default key.
+     * @param defValCnt   Def value count.
      * @param isNilpotent Is nilpotent.
      */
     private static <K, V, A> A sparseFold(String cacheName, IgniteBiFunction<Cache.Entry<K, V>, A, A> folder,
-        IgnitePredicate<K> keyFilter, BinaryOperator<A> accumulator, IgniteSupplier<A> zeroValSupp, V defVal, K defKey,
-        long defValCnt, boolean isNilpotent) {
+                                          IgnitePredicate<K> keyFilter, BinaryOperator<A> accumulator, IgniteSupplier<A> zeroValSupp, V defVal, K defKey,
+                                          long defValCnt, boolean isNilpotent) {
 
         A defRes = zeroValSupp.get();
 
@@ -591,7 +579,7 @@ public class CacheUtils {
                 // Iterate over given partition.
                 // Query returns an empty cursor if this partition is not stored on this node.
                 for (Cache.Entry<K, V> entry : cache.query(new ScanQuery<K, V>(part,
-                    (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
+                        (k, v) -> affinity.mapPartitionToNode(p) == locNode && (keyFilter == null || keyFilter.apply(k)))))
                     a = folder.apply(entry, a);
             }
 
@@ -601,10 +589,10 @@ public class CacheUtils {
     }
 
     public static <K, V, A, W> A reduce(String cacheName, Ignite ignite,
-        IgniteTriFunction<W, Cache.Entry<K, V>, A, A> acc,
-        IgniteSupplier<W> supp,
-        IgniteSupplier<Iterable<Cache.Entry<K, V>>> entriesGen, IgniteBinaryOperator<A> comb,
-        IgniteSupplier<A> zeroValSupp) {
+                                        IgniteTriFunction<W, Cache.Entry<K, V>, A, A> acc,
+                                        IgniteSupplier<W> supp,
+                                        IgniteSupplier<Iterable<Cache.Entry<K, V>>> entriesGen, IgniteBinaryOperator<A> comb,
+                                        IgniteSupplier<A> zeroValSupp) {
 
         A defRes = zeroValSupp.get();
 
@@ -624,15 +612,15 @@ public class CacheUtils {
     }
 
     public static <K, V, A, W> A reduce(String cacheName, IgniteTriFunction<W, Cache.Entry<K, V>, A, A> acc,
-        IgniteSupplier<W> supp,
-        IgniteSupplier<Iterable<Cache.Entry<K, V>>> entriesGen, IgniteBinaryOperator<A> comb,
-        IgniteSupplier<A> zeroValSupp) {
+                                        IgniteSupplier<W> supp,
+                                        IgniteSupplier<Iterable<Cache.Entry<K, V>>> entriesGen, IgniteBinaryOperator<A> comb,
+                                        IgniteSupplier<A> zeroValSupp) {
         return reduce(cacheName, Ignition.localIgnite(), acc, supp, entriesGen, comb, zeroValSupp);
     }
 
     /**
      * @param cacheName Cache name.
-     * @param run {@link Runnable} to broadcast to cache nodes for given cache name.
+     * @param run       {@link Runnable} to broadcast to cache nodes for given cache name.
      */
     public static void bcast(String cacheName, Ignite ignite, IgniteRunnable run) {
         ignite.compute(ignite.cluster().forDataNodes(cacheName)).broadcast(run);
@@ -640,8 +628,9 @@ public class CacheUtils {
 
     /**
      * Broadcast runnable to data nodes of given cache.
+     *
      * @param cacheName Cache name.
-     * @param run Runnable.
+     * @param run       Runnable.
      */
     public static void bcast(String cacheName, IgniteRunnable run) {
         bcast(cacheName, ignite(), run);
@@ -649,8 +638,8 @@ public class CacheUtils {
 
     /**
      * @param cacheName Cache name.
-     * @param call {@link IgniteCallable} to broadcast to cache nodes for given cache name.
-     * @param <A> Type returned by the callable.
+     * @param call      {@link IgniteCallable} to broadcast to cache nodes for given cache name.
+     * @param <A>       Type returned by the callable.
      */
     public static <A> Collection<A> bcast(String cacheName, IgniteCallable<A> call) {
         return bcast(cacheName, ignite(), call);
@@ -658,13 +647,42 @@ public class CacheUtils {
 
     /**
      * Broadcast callable to data nodes of given cache.
+     *
      * @param cacheName Cache name.
-     * @param ignite Ignite instance.
-     * @param call Callable to broadcast.
-     * @param <A> Type of callable result.
+     * @param ignite    Ignite instance.
+     * @param call      Callable to broadcast.
+     * @param <A>       Type of callable result.
      * @return Results of callable from each node.
      */
     public static <A> Collection<A> bcast(String cacheName, Ignite ignite, IgniteCallable<A> call) {
         return ignite.compute(ignite.cluster().forDataNodes(cacheName)).broadcast(call);
     }
+
+    /**
+     * @param vectorUuid Matrix UUID.
+     * @param mapper     Mapping {@link IgniteFunction}.
+     */
+    @SuppressWarnings("unchecked")
+    public static <K, V> void sparseMapForVector(UUID vectorUuid, IgniteDoubleFunction<V> mapper, String cacheName) {
+        A.notNull(vectorUuid, "vectorUuid");
+        A.notNull(cacheName, "cacheName");
+        A.notNull(mapper, "mapper");
+
+        foreach(cacheName, (CacheEntry<K, V> ce) -> {
+            K k = ce.entry().getKey();
+
+            V v = ce.entry().getValue();
+
+            if (v instanceof VectorBlockEntry) {
+                VectorBlockEntry entry = (VectorBlockEntry) v;
+
+                for (int i = 0; i < entry.size(); i++) entry.set(i, (Double) mapper.apply(entry.get(i)));
+
+                ce.cache().put(k, (V) entry);
+            } else {
+                V mappingRes = mapper.apply((Double) v);
+                ce.cache().put(k, mappingRes);
+            }
+        }, sparseKeyFilter(vectorUuid));
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java
deleted file mode 100644
index 091b325..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/BlockMatrixKey.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.ml.math.distributed.keys;
-
-import org.apache.ignite.internal.util.lang.IgnitePair;
-import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
-
-/**
- * Cache key for blocks in {@link SparseBlockDistributedMatrix}.
- *
- * TODO: check if using {@link IgnitePair} will be better for block id.
- */
-public interface BlockMatrixKey extends MatrixCacheKey {
-    /**
-     * @return block row id.
-     */
-    public long blockRowId();
-
-    /**
-     * @return block col id.
-     */
-    public long blockColId();
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/DataStructureCacheKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/DataStructureCacheKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/DataStructureCacheKey.java
new file mode 100644
index 0000000..d99ea48
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/DataStructureCacheKey.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.ml.math.distributed.keys;
+
+import java.util.UUID;
+
+/**
+ * Base matrix cache key.
+ */
+public interface DataStructureCacheKey {
+    /**
+     * @return matrix id.
+     */
+    public UUID dataStructureId();
+
+    /**
+     * @return affinity key.
+     */
+    public Object affinityKey();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixBlockKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixBlockKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixBlockKey.java
new file mode 100644
index 0000000..9c76568
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixBlockKey.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.ml.math.distributed.keys;
+
+import org.apache.ignite.internal.util.lang.IgnitePair;
+import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
+
+/**
+ * Cache key for blocks in {@link SparseBlockDistributedMatrix}.
+ *
+ * TODO: check if using {@link IgnitePair} will be better for block id.
+ */
+public interface MatrixBlockKey extends DataStructureCacheKey {
+    /**
+     * @return block row id.
+     */
+    public long blockRowId();
+
+    /**
+     * @return block col id.
+     */
+    public long blockColId();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java
deleted file mode 100644
index 0242560..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/MatrixCacheKey.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.ml.math.distributed.keys;
-
-import java.util.UUID;
-
-/**
- * Base matrix cache key.
- */
-public interface MatrixCacheKey {
-    /**
-     * @return matrix id.
-     */
-    public UUID matrixId();
-
-    /**
-     * @return affinity key.
-     */
-    public Object affinityKey();
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
index 168f49f..78af2e8 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/RowColMatrixKey.java
@@ -22,7 +22,7 @@ import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 /**
  * Cache key for {@link SparseDistributedMatrix}.
  */
-public interface RowColMatrixKey extends MatrixCacheKey {
+public interface RowColMatrixKey extends DataStructureCacheKey {
     /**
      *  Return index value(blockId, Row/Col index, etc.)
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/VectorBlockKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/VectorBlockKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/VectorBlockKey.java
new file mode 100644
index 0000000..32af965
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/VectorBlockKey.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.ml.math.distributed.keys;
+
+import org.apache.ignite.internal.util.lang.IgnitePair;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+
+/**
+ * Cache key for blocks in {@link SparseBlockDistributedVector}.
+ *
+ * TODO: check if using {@link IgnitePair} will be better for block id.
+ */
+public interface VectorBlockKey extends DataStructureCacheKey {
+    /**
+     * @return block id.
+     */
+    public long blockId();
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java
deleted file mode 100644
index cc8c488..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/BlockMatrixKey.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.ml.math.distributed.keys.impl;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.UUID;
-import org.apache.ignite.binary.BinaryObjectException;
-import org.apache.ignite.binary.BinaryRawReader;
-import org.apache.ignite.binary.BinaryRawWriter;
-import org.apache.ignite.binary.BinaryReader;
-import org.apache.ignite.binary.BinaryWriter;
-import org.apache.ignite.binary.Binarylizable;
-import org.apache.ignite.internal.binary.BinaryUtils;
-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.IgniteUuid;
-import org.apache.ignite.ml.math.impls.matrix.BlockEntry;
-import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Key implementation for {@link BlockEntry} using for {@link SparseBlockDistributedMatrix}.
- */
-public class BlockMatrixKey implements org.apache.ignite.ml.math.distributed.keys.BlockMatrixKey, Externalizable, Binarylizable {
-    /** */
-    private static final long serialVersionUID = 0L;
-    /** Block row ID */
-    private long blockIdRow;
-    /** Block col ID */
-    private long blockIdCol;
-    /** Matrix ID */
-    private UUID matrixUuid;
-    /** Block affinity key. */
-    private IgniteUuid affinityKey;
-
-    /**
-     * Empty constructor required for {@link Externalizable}.
-     */
-    public BlockMatrixKey() {
-        // No-op.
-    }
-
-    /**
-     * Construct matrix block key.
-     *
-     * @param matrixUuid Matrix uuid.
-     * @param affinityKey Affinity key.
-     */
-    public BlockMatrixKey(long rowId, long colId,  UUID matrixUuid, @Nullable IgniteUuid affinityKey) {
-        assert rowId >= 0;
-        assert colId >= 0;
-        assert matrixUuid != null;
-
-        this.blockIdRow = rowId;
-        this.blockIdCol = colId;
-        this.matrixUuid = matrixUuid;
-        this.affinityKey = affinityKey;
-    }
-
-    /** {@inheritDoc} */
-    @Override public long blockRowId() {
-        return blockIdRow;
-    }
-
-    /** {@inheritDoc} */
-    @Override public long blockColId() {
-        return blockIdCol;
-    }
-
-    /** {@inheritDoc} */
-    @Override public UUID matrixId() {
-        return matrixUuid;
-    }
-
-    /** {@inheritDoc} */
-    @Override public IgniteUuid affinityKey() {
-        return affinityKey;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeExternal(ObjectOutput out) throws IOException {
-        out.writeObject(matrixUuid);
-        U.writeGridUuid(out, affinityKey);
-        out.writeLong(blockIdRow);
-        out.writeLong(blockIdCol);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
-        matrixUuid = (UUID)in.readObject();
-        affinityKey = U.readGridUuid(in);
-        blockIdRow = in.readLong();
-        blockIdCol = in.readLong();
-    }
-
-    /** {@inheritDoc} */
-    @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
-        BinaryRawWriter out = writer.rawWriter();
-
-        out.writeUuid(matrixUuid);
-        BinaryUtils.writeIgniteUuid(out, affinityKey);
-        out.writeLong(blockIdRow);
-        out.writeLong(blockIdCol);
-    }
-
-    /** {@inheritDoc} */
-    @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
-        BinaryRawReader in = reader.rawReader();
-
-        matrixUuid = in.readUuid();
-        affinityKey = BinaryUtils.readIgniteUuid(in);
-        blockIdRow = in.readLong();
-        blockIdCol = in.readLong();
-    }
-
-    /** {@inheritDoc} */
-    @Override public int hashCode() {
-        int res = 37;
-
-        res += res * 37 + blockIdCol;
-        res += res * 37 + blockIdRow;
-        res += res * 37 + matrixUuid.hashCode();
-
-        return res;
-    }
-
-    /** {@inheritDoc} */
-    @Override public boolean equals(Object obj) {
-        if (obj == this)
-            return true;
-
-        if (obj == null || obj.getClass() != getClass())
-            return false;
-
-        BlockMatrixKey that = (BlockMatrixKey)obj;
-
-        return blockIdRow == that.blockIdRow && blockIdCol == that.blockIdCol && matrixUuid.equals(that.matrixUuid)
-            && F.eq(affinityKey, that.affinityKey);
-    }
-
-    /** {@inheritDoc} */
-    @Override public String toString() {
-        return S.toString(BlockMatrixKey.class, this);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/MatrixBlockKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/MatrixBlockKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/MatrixBlockKey.java
new file mode 100644
index 0000000..9e8d81e
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/MatrixBlockKey.java
@@ -0,0 +1,162 @@
+/*
+ * 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.ml.math.distributed.keys.impl;
+
+import org.apache.ignite.binary.*;
+import org.apache.ignite.internal.binary.BinaryUtils;
+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.IgniteUuid;
+import org.apache.ignite.ml.math.impls.matrix.MatrixBlockEntry;
+import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.UUID;
+
+/**
+ * Key implementation for {@link MatrixBlockEntry} using for {@link SparseBlockDistributedMatrix}.
+ */
+public class MatrixBlockKey implements org.apache.ignite.ml.math.distributed.keys.MatrixBlockKey, Externalizable, Binarylizable {
+    /** */
+    private static final long serialVersionUID = 0L;
+    /** Block row ID */
+    private long blockIdRow;
+    /** Block col ID */
+    private long blockIdCol;
+    /** Matrix ID */
+    private UUID matrixUuid;
+    /** Block affinity key. */
+    private UUID affinityKey;
+
+    /**
+     * Empty constructor required for {@link Externalizable}.
+     */
+    public MatrixBlockKey() {
+        // No-op.
+    }
+
+    /**
+     * Construct matrix block key.
+     *
+     * @param matrixUuid Matrix uuid.
+     * @param affinityKey Affinity key.
+     */
+    public MatrixBlockKey(long rowId, long colId, UUID matrixUuid, @Nullable UUID affinityKey) {
+        assert rowId >= 0;
+        assert colId >= 0;
+        assert matrixUuid != null;
+
+        this.blockIdRow = rowId;
+        this.blockIdCol = colId;
+        this.matrixUuid = matrixUuid;
+        this.affinityKey = affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long blockRowId() {
+        return blockIdRow;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long blockColId() {
+        return blockIdCol;
+    }
+
+    /** {@inheritDoc} */
+    @Override public UUID dataStructureId() {
+        return matrixUuid;
+    }
+
+    /** {@inheritDoc} */
+    @Override public UUID affinityKey() {
+        return affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(matrixUuid);
+        out.writeObject(affinityKey);
+        out.writeLong(blockIdRow);
+        out.writeLong(blockIdCol);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        matrixUuid = (UUID)in.readObject();
+        affinityKey = (UUID)in.readObject();
+        blockIdRow = in.readLong();
+        blockIdCol = in.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+        BinaryRawWriter out = writer.rawWriter();
+
+        out.writeUuid(matrixUuid);
+        out.writeUuid(affinityKey);
+        out.writeLong(blockIdRow);
+        out.writeLong(blockIdCol);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+        BinaryRawReader in = reader.rawReader();
+
+        matrixUuid = in.readUuid();
+        affinityKey = in.readUuid();
+        blockIdRow = in.readLong();
+        blockIdCol = in.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 37;
+
+        res += res * 37 + blockIdCol;
+        res += res * 37 + blockIdRow;
+        res += res * 37 + matrixUuid.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+
+        if (obj == null || obj.getClass() != getClass())
+            return false;
+
+        MatrixBlockKey that = (MatrixBlockKey)obj;
+
+        return blockIdRow == that.blockIdRow && blockIdCol == that.blockIdCol && matrixUuid.equals(that.matrixUuid)
+                && F.eq(affinityKey, that.affinityKey);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(MatrixBlockKey.class, this);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
index aa5e0ad..980d433 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/SparseMatrixKey.java
@@ -17,17 +17,18 @@
 
 package org.apache.ignite.ml.math.distributed.keys.impl;
 
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.UUID;
 import org.apache.ignite.cache.affinity.AffinityKeyMapped;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
 import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
 
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.UUID;
+
 /**
  * Key implementation for {@link SparseDistributedMatrix}.
  */
@@ -65,7 +66,7 @@ public class SparseMatrixKey implements RowColMatrixKey, Externalizable {
     }
 
     /** {@inheritDoc} */
-    @Override public UUID matrixId() {
+    @Override public UUID dataStructureId() {
         return matrixId;
     }
 
@@ -76,7 +77,6 @@ public class SparseMatrixKey implements RowColMatrixKey, Externalizable {
 
     /** {@inheritDoc} */
     @Override public void writeExternal(ObjectOutput out) throws IOException {
-//        U.writeGridUuid(out, matrixId);
         out.writeObject(matrixId);
         out.writeObject(affinityKey);
         out.writeInt(idx);

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/VectorBlockKey.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/VectorBlockKey.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/VectorBlockKey.java
new file mode 100644
index 0000000..6052010
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/distributed/keys/impl/VectorBlockKey.java
@@ -0,0 +1,151 @@
+/*
+ * 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.ml.math.distributed.keys.impl;
+
+import org.apache.ignite.binary.*;
+import org.apache.ignite.internal.binary.BinaryUtils;
+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.IgniteUuid;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.apache.ignite.ml.math.impls.vector.VectorBlockEntry;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.UUID;
+
+/**
+ * Key implementation for {@link VectorBlockEntry} using for {@link SparseBlockDistributedVector}.
+ */
+public class VectorBlockKey implements org.apache.ignite.ml.math.distributed.keys.VectorBlockKey, Externalizable, Binarylizable {
+    /** */
+    private static final long serialVersionUID = 0L;
+    /** Block row ID */
+    private long blockId;
+    /** Vector ID */
+    private UUID vectorUuid;
+    /** Block affinity key. */
+    private UUID affinityKey;
+
+    /**
+     * Empty constructor required for {@link Externalizable}.
+     */
+    public VectorBlockKey() {
+        // No-op.
+    }
+
+    /**
+     * Construct vector block key.
+     *
+     * @param vectorUuid Vector uuid.
+     * @param affinityKey Affinity key.
+     */
+    public VectorBlockKey(long blockId, UUID vectorUuid, @Nullable UUID affinityKey) {
+        assert blockId >= 0;
+        assert vectorUuid != null;
+
+        this.blockId = blockId;
+        this.vectorUuid = vectorUuid;
+        this.affinityKey = affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long blockId() {
+        return blockId;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public UUID dataStructureId() {
+        return vectorUuid;
+    }
+
+    /** {@inheritDoc} */
+    @Override public UUID affinityKey() {
+        return affinityKey;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(vectorUuid);
+        out.writeObject(affinityKey);
+        out.writeLong(blockId);
+
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        vectorUuid = (UUID)in.readObject();
+        affinityKey = (UUID)in.readObject();
+        blockId = in.readLong();
+
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeBinary(BinaryWriter writer) throws BinaryObjectException {
+        BinaryRawWriter out = writer.rawWriter();
+
+        out.writeUuid(vectorUuid);
+        out.writeUuid(affinityKey);
+        out.writeLong(blockId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readBinary(BinaryReader reader) throws BinaryObjectException {
+        BinaryRawReader in = reader.rawReader();
+
+        vectorUuid = in.readUuid();
+        affinityKey = in.readUuid();
+        blockId = in.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        int res = 37;
+
+        res += res * 37 + blockId;
+        res += res * 37 + vectorUuid.hashCode();
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        if (obj == this)
+            return true;
+
+        if (obj == null || obj.getClass() != getClass())
+            return false;
+
+        VectorBlockKey that = (VectorBlockKey)obj;
+
+        return blockId == that.blockId  && vectorUuid.equals(that.vectorUuid)
+            && F.eq(affinityKey, that.affinityKey);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(VectorBlockKey.class, this);
+    }
+
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java
index 0b4ad12..ce534bd 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/functions/Functions.java
@@ -17,10 +17,11 @@
 
 package org.apache.ignite.ml.math.functions;
 
+import org.apache.ignite.lang.IgniteBiTuple;
+
 import java.util.Comparator;
 import java.util.List;
 import java.util.function.BiFunction;
-import org.apache.ignite.lang.IgniteBiTuple;
 
 /**
  * Compatibility with Apache Mahout.

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
index 06fb34c..89f567e 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/AbstractMatrix.java
@@ -43,6 +43,7 @@ import org.apache.ignite.ml.math.functions.IgniteTriFunction;
 import org.apache.ignite.ml.math.functions.IntIntToDoubleFunction;
 import org.apache.ignite.ml.math.impls.vector.DenseLocalOnHeapVector;
 import org.apache.ignite.ml.math.impls.vector.MatrixVectorView;
+import org.apache.ignite.ml.math.util.MatrixUtil;
 
 /**
  * This class provides a helper implementation of the {@link Matrix}
@@ -282,7 +283,7 @@ public abstract class AbstractMatrix implements Matrix {
      *
      * @param row Row index.
      */
-    private void checkRowIndex(int row) {
+    void checkRowIndex(int row) {
         if (row < 0 || row >= rowSize())
             throw new RowIndexException(row);
     }
@@ -292,7 +293,7 @@ public abstract class AbstractMatrix implements Matrix {
      *
      * @param col Column index.
      */
-    private void checkColumnIndex(int col) {
+    void checkColumnIndex(int col) {
         if (col < 0 || col >= columnSize())
             throw new ColumnIndexException(col);
     }
@@ -303,7 +304,7 @@ public abstract class AbstractMatrix implements Matrix {
      * @param row Row index.
      * @param col Column index.
      */
-    protected void checkIndex(int row, int col) {
+    private void checkIndex(int row, int col) {
         checkRowIndex(row);
         checkColumnIndex(col);
     }
@@ -739,11 +740,12 @@ public abstract class AbstractMatrix implements Matrix {
     /** {@inheritDoc} */
     @Override public Vector getCol(int col) {
         checkColumnIndex(col);
-
-        Vector res = new DenseLocalOnHeapVector(rowSize());
+        Vector res;
+        if (isDistributed()) res = MatrixUtil.likeVector(this, rowSize());
+        else res = new DenseLocalOnHeapVector(rowSize());
 
         for (int i = 0; i < rowSize(); i++)
-            res.setX(i, getX(i,col));
+            res.setX(i, getX(i, col));
 
         return res;
     }
@@ -974,4 +976,14 @@ public abstract class AbstractMatrix implements Matrix {
     @Override public void compute(int row, int col, IgniteTriFunction<Integer, Integer, Double, Double> f) {
         setX(row, col, f.apply(row, col, getX(row, col)));
     }
+
+
+    protected int getMaxAmountOfColumns(double[][] data) {
+        int maxAmountOfColumns = 0;
+
+        for (int i = 0; i < data.length; i++)
+            maxAmountOfColumns = Math.max(maxAmountOfColumns, data[i].length);
+
+        return maxAmountOfColumns;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/BlockEntry.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/BlockEntry.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/BlockEntry.java
deleted file mode 100644
index 47f07ce..0000000
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/BlockEntry.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.ml.math.impls.matrix;
-
-import org.apache.ignite.ml.math.Matrix;
-
-/**
- * Block for {@link SparseBlockDistributedMatrix}.
- */
-public final class BlockEntry extends SparseLocalOnHeapMatrix {
-    /** Max block size. */
-    public static final int MAX_BLOCK_SIZE = 32;
-
-    /** */
-    public BlockEntry() {
-        // No-op.
-    }
-
-    /** */
-    public BlockEntry(int row, int col) {
-        super(row, col);
-
-        assert col <= MAX_BLOCK_SIZE;
-        assert row <= MAX_BLOCK_SIZE;
-    }
-
-    /** */
-    public BlockEntry(Matrix mtx) {
-        assert mtx.columnSize() <= MAX_BLOCK_SIZE;
-        assert mtx.rowSize() <= MAX_BLOCK_SIZE;
-
-        setStorage(mtx.getStorage());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixBlockEntry.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixBlockEntry.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixBlockEntry.java
new file mode 100644
index 0000000..a2d13a1
--- /dev/null
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/MatrixBlockEntry.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ml.math.impls.matrix;
+
+import org.apache.ignite.ml.math.Matrix;
+
+/**
+ * Block for {@link SparseBlockDistributedMatrix}.
+ */
+public final class MatrixBlockEntry extends SparseLocalOnHeapMatrix {
+    /** Max block size. */
+    public static final int MAX_BLOCK_SIZE = 32;
+
+    /** */
+    public MatrixBlockEntry() {
+        // No-op.
+    }
+
+    /** */
+    public MatrixBlockEntry(int row, int col) {
+        super(row, col);
+
+        assert col <= MAX_BLOCK_SIZE;
+        assert row <= MAX_BLOCK_SIZE;
+    }
+
+    /** */
+    public MatrixBlockEntry(Matrix mtx) {
+        assert mtx.columnSize() <= MAX_BLOCK_SIZE;
+        assert mtx.rowSize() <= MAX_BLOCK_SIZE;
+
+        setStorage(mtx.getStorage());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseBlockDistributedMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseBlockDistributedMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseBlockDistributedMatrix.java
index e829168..ea9fb8c 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseBlockDistributedMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseBlockDistributedMatrix.java
@@ -17,10 +17,6 @@
 
 package org.apache.ignite.ml.math.impls.matrix;
 
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
@@ -31,16 +27,25 @@ import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.distributed.CacheUtils;
-import org.apache.ignite.ml.math.distributed.keys.impl.BlockMatrixKey;
+import org.apache.ignite.ml.math.distributed.keys.impl.MatrixBlockKey;
+import org.apache.ignite.ml.math.distributed.keys.impl.VectorBlockKey;
 import org.apache.ignite.ml.math.exceptions.CardinalityException;
-import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
 import org.apache.ignite.ml.math.impls.storage.matrix.BlockMatrixStorage;
+import org.apache.ignite.ml.math.impls.storage.matrix.BlockVectorStorage;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.apache.ignite.ml.math.impls.vector.SparseDistributedVector;
+import org.apache.ignite.ml.math.impls.vector.VectorBlockEntry;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
 
 /**
- * Sparse block distributed matrix. This matrix represented by blocks 32x32 {@link BlockEntry}.
+ * Sparse block distributed matrix. This matrix represented by blocks 32x32 {@link MatrixBlockEntry}.
  *
- * Using separate cache with keys {@link BlockMatrixKey} and values {@link BlockEntry}.
+ * Using separate cache with keys {@link MatrixBlockKey} and values {@link MatrixBlockEntry}.
  */
 public class SparseBlockDistributedMatrix extends AbstractMatrix implements StorageConstants {
     /**
@@ -62,6 +67,18 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
     }
 
     /**
+     * @param data Data to fill the matrix
+     */
+    public SparseBlockDistributedMatrix(double[][] data) {
+        assert data.length > 0;
+        setStorage(new BlockMatrixStorage(data.length, getMaxAmountOfColumns(data)));
+
+        for (int i = 0; i < data.length; i++)
+            for (int j = 0; j < data[i].length; j++)
+                storage().set(i, j, data[i][j]);
+    }
+
+    /**
      * Return the same matrix with updates values (broken contract).
      *
      * @param d Value to divide to.
@@ -100,22 +117,22 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
             throw new CardinalityException(columnSize(), mtx.rowSize());
 
         SparseBlockDistributedMatrix matrixA = this;
-        SparseBlockDistributedMatrix matrixB = (SparseBlockDistributedMatrix)mtx;
+        SparseBlockDistributedMatrix matrixB = (SparseBlockDistributedMatrix) mtx;
 
         String cacheName = this.storage().cacheName();
         SparseBlockDistributedMatrix matrixC = new SparseBlockDistributedMatrix(matrixA.rowSize(), matrixB.columnSize());
 
         CacheUtils.bcast(cacheName, () -> {
             Ignite ignite = Ignition.localIgnite();
-            Affinity<BlockMatrixKey> affinity = ignite.affinity(cacheName);
+            Affinity<MatrixBlockKey> affinity = ignite.affinity(cacheName);
 
-            IgniteCache<BlockMatrixKey, BlockEntry> cache = ignite.getOrCreateCache(cacheName);
+            IgniteCache<MatrixBlockKey, MatrixBlockEntry> cache = ignite.getOrCreateCache(cacheName);
             ClusterNode locNode = ignite.cluster().localNode();
 
             BlockMatrixStorage storageC = matrixC.storage();
 
-            Map<ClusterNode, Collection<BlockMatrixKey>> keysCToNodes = affinity.mapKeysToNodes(storageC.getAllKeys());
-            Collection<BlockMatrixKey> locKeys = keysCToNodes.get(locNode);
+            Map<ClusterNode, Collection<MatrixBlockKey>> keysCToNodes = affinity.mapKeysToNodes(storageC.getAllKeys());
+            Collection<MatrixBlockKey> locKeys = keysCToNodes.get(locNode);
 
             if (locKeys == null)
                 return;
@@ -128,18 +145,18 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
 
                 IgnitePair<Long> newBlockId = new IgnitePair<>(newBlockIdRow, newBlockIdCol);
 
-                BlockEntry blockC = null;
+                MatrixBlockEntry blockC = null;
 
-                List<BlockEntry> aRow = matrixA.storage().getRowForBlock(newBlockId);
-                List<BlockEntry> bCol = matrixB.storage().getColForBlock(newBlockId);
+                List<MatrixBlockEntry> aRow = matrixA.storage().getRowForBlock(newBlockId);
+                List<MatrixBlockEntry> bCol = matrixB.storage().getColForBlock(newBlockId);
 
                 for (int i = 0; i < aRow.size(); i++) {
-                    BlockEntry blockA = aRow.get(i);
-                    BlockEntry blockB = bCol.get(i);
+                    MatrixBlockEntry blockA = aRow.get(i);
+                    MatrixBlockEntry blockB = bCol.get(i);
 
-                    BlockEntry tmpBlock = new BlockEntry(blockA.times(blockB));
+                    MatrixBlockEntry tmpBlock = new MatrixBlockEntry(blockA.times(blockB));
 
-                    blockC = blockC == null ? tmpBlock : new BlockEntry(blockC.plus(tmpBlock));
+                    blockC = blockC == null ? tmpBlock : new MatrixBlockEntry(blockC.plus(tmpBlock));
                 }
 
                 cache.put(storageC.getCacheKey(newBlockIdRow, newBlockIdCol), blockC);
@@ -149,6 +166,90 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
         return matrixC;
     }
 
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings({"unchecked"})
+    @Override public Vector times(final Vector vec) {
+        if (vec == null)
+            throw new IllegalArgumentException("The vector should be not null.");
+
+        if (columnSize() != vec.size())
+            throw new CardinalityException(columnSize(), vec.size());
+
+        SparseBlockDistributedMatrix matrixA = this;
+        SparseBlockDistributedVector vectorB = (SparseBlockDistributedVector) vec;
+
+
+        String cacheName = this.storage().cacheName();
+        SparseBlockDistributedVector vectorC = new SparseBlockDistributedVector(matrixA.rowSize());
+
+        CacheUtils.bcast(cacheName, () -> {
+            Ignite ignite = Ignition.localIgnite();
+            Affinity<VectorBlockKey> affinity = ignite.affinity(cacheName);
+
+            IgniteCache<VectorBlockKey, VectorBlockEntry> cache = ignite.getOrCreateCache(cacheName);
+            ClusterNode locNode = ignite.cluster().localNode();
+
+            BlockVectorStorage storageC = vectorC.storage();
+
+            Map<ClusterNode, Collection<VectorBlockKey>> keysCToNodes = affinity.mapKeysToNodes(storageC.getAllKeys());
+            Collection<VectorBlockKey> locKeys = keysCToNodes.get(locNode);
+
+            if (locKeys == null)
+                return;
+
+            // compute Cij locally on each node
+            // TODO: IGNITE:5114, exec in parallel
+            locKeys.forEach(key -> {
+                long newBlockId = key.blockId();
+
+
+                IgnitePair<Long> newBlockIdForMtx = new IgnitePair<>(newBlockId, 0L);
+
+                VectorBlockEntry blockC = null;
+
+                List<MatrixBlockEntry> aRow = matrixA.storage().getRowForBlock(newBlockIdForMtx);
+                List<VectorBlockEntry> bCol = vectorB.storage().getColForBlock(newBlockId);
+
+                for (int i = 0; i < aRow.size(); i++) {
+                    MatrixBlockEntry blockA = aRow.get(i);
+                    VectorBlockEntry blockB = bCol.get(i);
+
+                    VectorBlockEntry tmpBlock = new VectorBlockEntry(blockA.times(blockB));
+
+                    blockC = blockC == null ? tmpBlock : new VectorBlockEntry(blockC.plus(tmpBlock));
+                }
+
+                cache.put(storageC.getCacheKey(newBlockId), blockC);
+            });
+        });
+        return vectorC;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector getCol(int col) {
+        checkColumnIndex(col);
+
+        Vector res = new SparseDistributedVector(rowSize());
+
+        for (int i = 0; i < rowSize(); i++)
+            res.setX(i, getX(i, col));
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Vector getRow(int row) {
+        checkRowIndex(row);
+
+        Vector res = new SparseDistributedVector(columnSize());
+
+        for (int i = 0; i < columnSize(); i++)
+            res.setX(i, getX(row, i));
+        return res;
+    }
+
     /** {@inheritDoc} */
     @Override public Matrix assign(double val) {
         return mapOverValues(v -> val);
@@ -176,7 +277,11 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
 
     /** {@inheritDoc} */
     @Override public Matrix copy() {
-        throw new UnsupportedOperationException();
+        Matrix cp = like(rowSize(), columnSize());
+
+        cp.assign(this);
+
+        return cp;
     }
 
     /** {@inheritDoc} */
@@ -186,12 +291,12 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
 
     /** {@inheritDoc} */
     @Override public Vector likeVector(int crd) {
-        throw new UnsupportedOperationException();
+        return new SparseBlockDistributedVector(crd);
     }
 
     /** */
     private UUID getUUID() {
-        return ((BlockMatrixStorage)getStorage()).getUUID();
+        return ((BlockMatrixStorage) getStorage()).getUUID();
     }
 
     /**
@@ -208,6 +313,6 @@ public class SparseBlockDistributedMatrix extends AbstractMatrix implements Stor
      *
      */
     private BlockMatrixStorage storage() {
-        return (BlockMatrixStorage)getStorage();
+        return (BlockMatrixStorage) getStorage();
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
index 594aebc..497241d 100644
--- a/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
+++ b/modules/ml/src/main/java/org/apache/ignite/ml/math/impls/matrix/SparseDistributedMatrix.java
@@ -17,24 +17,24 @@
 
 package org.apache.ignite.ml.math.impls.matrix;
 
-import java.util.Collection;
-import java.util.Map;
-import java.util.UUID;
 import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.affinity.Affinity;
 import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.ml.math.Matrix;
 import org.apache.ignite.ml.math.StorageConstants;
 import org.apache.ignite.ml.math.Vector;
 import org.apache.ignite.ml.math.distributed.CacheUtils;
 import org.apache.ignite.ml.math.distributed.keys.RowColMatrixKey;
 import org.apache.ignite.ml.math.exceptions.CardinalityException;
-import org.apache.ignite.ml.math.exceptions.UnsupportedOperationException;
 import org.apache.ignite.ml.math.functions.IgniteDoubleFunction;
 import org.apache.ignite.ml.math.impls.storage.matrix.SparseDistributedMatrixStorage;
+import org.apache.ignite.ml.math.impls.storage.vector.SparseDistributedVectorStorage;
+import org.apache.ignite.ml.math.impls.vector.SparseDistributedVector;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.UUID;
 
 /**
  * Sparse distributed matrix implementation based on data grid.
@@ -68,6 +68,28 @@ public class SparseDistributedMatrix extends AbstractMatrix implements StorageCo
         assertStorageMode(stoMode);
 
         setStorage(new SparseDistributedMatrixStorage(rows, cols, stoMode, acsMode));
+
+    }
+
+    /**
+     * @param data Data to fill the matrix
+     */
+    public SparseDistributedMatrix(double[][] data) {
+        assert data.length > 0;
+        setStorage(new SparseDistributedMatrixStorage(data.length, getMaxAmountOfColumns(data),  StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE));
+
+        for (int i = 0; i < data.length; i++)
+            for (int j = 0; j < data[i].length; j++)
+                storage().set(i,j,data[i][j]);
+    }
+
+
+    /**
+     * @param rows Amount of rows in the matrix.
+     * @param cols Amount of columns in the matrix.
+     */
+    public SparseDistributedMatrix(int rows, int cols) {
+        this(rows, cols, StorageConstants.ROW_STORAGE_MODE, StorageConstants.RANDOM_ACCESS_MODE);
     }
 
     /** */
@@ -122,7 +144,6 @@ public class SparseDistributedMatrix extends AbstractMatrix implements StorageCo
             Ignite ignite = Ignition.localIgnite();
             Affinity<RowColMatrixKey> affinity = ignite.affinity(cacheName);
 
-            IgniteCache<RowColMatrixKey, BlockEntry> cache = ignite.getOrCreateCache(cacheName);
             ClusterNode locNode = ignite.cluster().localNode();
 
             SparseDistributedMatrixStorage storageC = matrixC.storage();
@@ -141,17 +162,17 @@ public class SparseDistributedMatrix extends AbstractMatrix implements StorageCo
                 int idx = key.index();
                 
                 if (isRowMode){
-                    Vector Aik = matrixA.getCol(idx);
+                    Vector Aik = matrixA.getRow(idx);
 
-                    for (int i = 0; i < columnSize(); i++) {
-                        Vector Bkj = matrixB.getRow(i);
+                    for (int i = 0; i < matrixB.columnSize(); i++) {
+                        Vector Bkj = matrixB.getCol(i);
                         matrixC.set(idx, i, Aik.times(Bkj).sum());
                     }
                 } else {
-                    Vector Bkj = matrixB.getRow(idx);
+                    Vector Bkj = matrixB.getCol(idx);
 
-                    for (int i = 0; i < rowSize(); i++) {
-                        Vector Aik = matrixA.getCol(i);
+                    for (int i = 0; i < matrixA.rowSize(); i++) {
+                        Vector Aik = matrixA.getRow(i);
                         matrixC.set(idx, i, Aik.times(Bkj).sum());
                     }
                 }
@@ -161,6 +182,49 @@ public class SparseDistributedMatrix extends AbstractMatrix implements StorageCo
         return matrixC;
     }
 
+
+    /** {@inheritDoc} */
+    @Override public Vector times(Vector vec) {
+        if (vec == null)
+            throw new IllegalArgumentException("The vector should be not null.");
+
+        if (columnSize() != vec.size())
+            throw new CardinalityException(columnSize(), vec.size());
+
+        SparseDistributedMatrix matrixA = this;
+        SparseDistributedVector vectorB = (SparseDistributedVector) vec;
+
+        String cacheName = storage().cacheName();
+        int rows = this.rowSize();
+
+        SparseDistributedVector vectorC = (SparseDistributedVector) likeVector(rows);
+
+        CacheUtils.bcast(cacheName, () -> {
+            Ignite ignite = Ignition.localIgnite();
+            Affinity<RowColMatrixKey> affinity = ignite.affinity(cacheName);
+
+            ClusterNode locNode = ignite.cluster().localNode();
+
+            SparseDistributedVectorStorage storageC = vectorC.storage();
+
+            Map<ClusterNode, Collection<RowColMatrixKey>> keysCToNodes = affinity.mapKeysToNodes(storageC.getAllKeys());
+            Collection<RowColMatrixKey> locKeys = keysCToNodes.get(locNode);
+
+            if (locKeys == null)
+                return;
+
+            // compute Cij locally on each node
+            // TODO: IGNITE:5114, exec in parallel
+            locKeys.forEach(key -> {
+                int idx = key.index();
+                Vector Aik = matrixA.getRow(idx);
+                vectorC.set(idx, Aik.times(vectorB).sum());
+            });
+        });
+
+        return vectorC;
+    }
+
     /** {@inheritDoc} */
     @Override public Matrix assign(double val) {
         return mapOverValues(v -> val);
@@ -198,17 +262,23 @@ public class SparseDistributedMatrix extends AbstractMatrix implements StorageCo
 
     /** {@inheritDoc} */
     @Override public Matrix copy() {
-        throw new UnsupportedOperationException();
+        Matrix cp = like(rowSize(), columnSize());
+
+        cp.assign(this);
+
+        return cp;
     }
 
     /** {@inheritDoc} */
     @Override public Matrix like(int rows, int cols) {
-        return new SparseDistributedMatrix(rows, cols, storage().storageMode(), storage().accessMode());
+        if(storage()==null) return new SparseDistributedMatrix(rows, cols);
+        else return new SparseDistributedMatrix(rows, cols, storage().storageMode(), storage().accessMode());
+
     }
 
     /** {@inheritDoc} */
     @Override public Vector likeVector(int crd) {
-        throw new UnsupportedOperationException();
+        return new SparseDistributedVector(crd, StorageConstants.RANDOM_ACCESS_MODE);
     }
 
     /** */


[20/47] ignite git commit: IGNITE-6336 .NET: Thin client: Create cache

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs
new file mode 100644
index 0000000..21ca247
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/CacheClientConfiguration.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Client.Cache
+{
+    using System;
+    using System.Collections.Generic;
+    using System.ComponentModel;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.IO;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Configuration;
+    using Apache.Ignite.Core.Impl;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Client.Cache;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Ignite client cache configuration.
+    /// Same thing as <see cref="CacheConfiguration"/>, but with a subset of properties that can be accessed from
+    /// Ignite thin client (see <see cref="IIgniteClient"/>).
+    /// <para />
+    /// Note that caches created from server nodes can be accessed from thin client, and vice versa.
+    /// The only difference is that thin client can not read or write certain <see cref="CacheConfiguration"/>
+    /// properties, so a separate class exists to make it clear which properties can be used.
+    /// </summary>
+    public class CacheClientConfiguration
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheConfiguration"/> class.
+        /// </summary>
+        public CacheClientConfiguration() : this((string) null)
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheConfiguration"/> class.
+        /// </summary>
+        /// <param name="name">Cache name.</param>
+        public CacheClientConfiguration(string name)
+        {
+            Name = name;
+
+            Backups = CacheConfiguration.DefaultBackups;
+            AtomicityMode = CacheConfiguration.DefaultAtomicityMode;
+            CacheMode = CacheConfiguration.DefaultCacheMode;
+            CopyOnRead = CacheConfiguration.DefaultCopyOnRead;
+            WriteSynchronizationMode = CacheConfiguration.DefaultWriteSynchronizationMode;
+            EagerTtl = CacheConfiguration.DefaultEagerTtl;
+            Invalidate = CacheConfiguration.DefaultInvalidate;
+            LockTimeout = CacheConfiguration.DefaultLockTimeout;
+            MaxConcurrentAsyncOperations = CacheConfiguration.DefaultMaxConcurrentAsyncOperations;
+            ReadFromBackup = CacheConfiguration.DefaultReadFromBackup;
+            RebalanceBatchSize = CacheConfiguration.DefaultRebalanceBatchSize;
+            RebalanceMode = CacheConfiguration.DefaultRebalanceMode;
+            RebalanceThrottle = CacheConfiguration.DefaultRebalanceThrottle;
+            RebalanceTimeout = CacheConfiguration.DefaultRebalanceTimeout;
+            PartitionLossPolicy = CacheConfiguration.DefaultPartitionLossPolicy;
+            SqlIndexMaxInlineSize = CacheConfiguration.DefaultSqlIndexMaxInlineSize;
+            RebalanceOrder = CacheConfiguration.DefaultRebalanceOrder;
+            RebalanceBatchesPrefetchCount = CacheConfiguration.DefaultRebalanceBatchesPrefetchCount;
+            MaxQueryIteratorsCount = CacheConfiguration.DefaultMaxQueryIteratorsCount;
+            QueryParallelism = CacheConfiguration.DefaultQueryParallelism;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheConfiguration"/> class 
+        /// and populates <see cref="QueryEntities"/> according to provided query types.
+        /// </summary>
+        /// <param name="name">Cache name.</param>
+        /// <param name="queryTypes">
+        /// Collection of types to be registered as query entities. These types should use 
+        /// <see cref="QuerySqlFieldAttribute"/> to configure query fields and properties.
+        /// </param>
+        public CacheClientConfiguration(string name, params Type[] queryTypes) : this(name)
+        {
+            QueryEntities = queryTypes.Select(type => new QueryEntity { ValueType = type }).ToArray();
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheConfiguration"/> class.
+        /// </summary>
+        /// <param name="name">Cache name.</param>
+        /// <param name="queryEntities">Query entities.</param>
+        public CacheClientConfiguration(string name, params QueryEntity[] queryEntities) : this(name)
+        {
+            QueryEntities = queryEntities;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheConfiguration"/> class,
+        /// performing a deep copy of specified cache configuration.
+        /// </summary>
+        /// <param name="other">The other configuration to perfrom deep copy from.</param>
+        public CacheClientConfiguration(CacheClientConfiguration other)
+        {
+            if (other != null)
+            {
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    ClientCacheConfigurationSerializer.Write(stream, other);
+
+                    stream.SynchronizeOutput();
+                    stream.Seek(0, SeekOrigin.Begin);
+
+                    ClientCacheConfigurationSerializer.Read(stream, this);
+                }
+
+                CopyLocalProperties(other);
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheClientConfiguration" /> class, copying properties from
+        /// provided server cache configuration. See also <see cref="ToCacheConfiguration"/>.
+        /// </summary>
+        /// <param name="cacheConfiguration">Server cache configuration.</param>
+        /// <param name="ignoreUnsupportedProperties">If set to <c>true</c>,
+        /// ignores unsupported properties instead of throwing an exception.</param>
+        public CacheClientConfiguration(CacheConfiguration cacheConfiguration, bool ignoreUnsupportedProperties)
+        {
+            IgniteArgumentCheck.NotNull(cacheConfiguration, "cacheConfiguration");
+
+            ClientCacheConfigurationSerializer.Copy(cacheConfiguration, this, ignoreUnsupportedProperties);
+        }
+
+        /// <summary>
+        /// Converts this instance to full <see cref="CacheConfiguration"/>.
+        /// </summary>
+        public CacheConfiguration ToCacheConfiguration()
+        {
+            var cfg = new CacheConfiguration();
+
+            ClientCacheConfigurationSerializer.Copy(this, cfg);
+
+            return cfg;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CacheClientConfiguration"/> class.
+        /// </summary>
+        internal CacheClientConfiguration(IBinaryStream stream)
+        {
+            Debug.Assert(stream != null);
+
+            ClientCacheConfigurationSerializer.Read(stream, this);
+        }
+
+        /// <summary>
+        /// Copies the local properties (properties that are not written in Write method).
+        /// </summary>
+        private void CopyLocalProperties(CacheClientConfiguration cfg)
+        {
+            Debug.Assert(cfg != null);
+
+            if (QueryEntities != null && cfg.QueryEntities != null)
+            {
+                var entities = cfg.QueryEntities.Where(x => x != null).ToDictionary(x => GetQueryEntityKey(x), x => x);
+
+                foreach (var entity in QueryEntities.Where(x => x != null))
+                {
+                    QueryEntity src;
+
+                    if (entities.TryGetValue(GetQueryEntityKey(entity), out src))
+                    {
+                        entity.CopyLocalProperties(src);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the query entity key.
+        /// </summary>
+        private static string GetQueryEntityKey(QueryEntity x)
+        {
+            return x.KeyTypeName + "^" + x.ValueTypeName;
+        }
+
+        /// <summary>
+        /// Gets or sets the cache name.
+        /// </summary>
+        public string Name { get; set; }
+
+        /// <summary>
+        /// Gets or sets write synchronization mode. This mode controls whether the main        
+        /// caller should wait for update on other nodes to complete or not.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultWriteSynchronizationMode)]
+        public CacheWriteSynchronizationMode WriteSynchronizationMode { get; set; }
+
+        /// <summary>
+        /// Gets or sets flag indicating whether expired cache entries will be eagerly removed from cache. 
+        /// When set to false, expired entries will be removed on next entry access.        
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultEagerTtl)]
+        public bool EagerTtl { get; set; }
+
+        /// <summary>
+        /// Gets or sets caching mode to use.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultCacheMode)]
+        public CacheMode CacheMode { get; set; }
+
+        /// <summary>
+        /// Gets or sets cache atomicity mode.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultAtomicityMode)]
+        public CacheAtomicityMode AtomicityMode { get; set; }
+
+        /// <summary>
+        /// Gets or sets number of nodes used to back up single partition for 
+        /// <see cref="Core.Cache.Configuration.CacheMode.Partitioned"/> cache.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultBackups)]
+        public int Backups { get; set; }
+
+        /// <summary>
+        /// Gets or sets default lock acquisition timeout.
+        /// </summary>
+        [DefaultValue(typeof(TimeSpan), "00:00:00")]
+        public TimeSpan LockTimeout { get; set; }
+
+        /// <summary>
+        /// Invalidation flag. If true, values will be invalidated (nullified) upon commit in near cache.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultInvalidate)]
+        public bool Invalidate { get; set; }
+
+        /// <summary>
+        /// Gets or sets cache rebalance mode.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultRebalanceMode)]
+        public CacheRebalanceMode RebalanceMode { get; set; }
+
+        /// <summary>
+        /// Gets or sets size (in number bytes) to be loaded within a single rebalance message.
+        /// Rebalancing algorithm will split total data set on every node into multiple batches prior to sending data.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultRebalanceBatchSize)]
+        public int RebalanceBatchSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets maximum number of allowed concurrent asynchronous operations, 0 for unlimited.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultMaxConcurrentAsyncOperations)]
+        public int MaxConcurrentAsyncOperations { get; set; }
+
+        /// <summary>
+        /// Gets or sets rebalance timeout.
+        /// </summary>
+        [DefaultValue(typeof(TimeSpan), "00:00:10")]
+        public TimeSpan RebalanceTimeout { get; set; }
+
+        /// <summary>
+        /// Gets or sets delay upon a node joining or leaving topology (or crash) 
+        /// after which rebalancing should be started automatically. 
+        /// Rebalancing should be delayed if you plan to restart nodes
+        /// after they leave topology, or if you plan to start multiple nodes at once or one after another
+        /// and don't want to repartition and rebalance until all nodes are started.
+        /// </summary>
+        public TimeSpan RebalanceDelay { get; set; }
+
+        /// <summary>
+        /// Time to wait between rebalance messages to avoid overloading of CPU or network.
+        /// When rebalancing large data sets, the CPU or network can get over-consumed with rebalancing messages,
+        /// which consecutively may slow down the application performance. This parameter helps tune 
+        /// the amount of time to wait between rebalance messages to make sure that rebalancing process
+        /// does not have any negative performance impact. Note that application will continue to work
+        /// properly while rebalancing is still in progress.
+        /// <para/>
+        /// Value of 0 means that throttling is disabled.
+        /// </summary>
+        public TimeSpan RebalanceThrottle { get; set; }
+
+        /// <summary>
+        /// Gets or sets flag indicating whether data can be read from backup.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultReadFromBackup)]
+        public bool ReadFromBackup { get; set; }
+
+        /// <summary>
+        /// Gets or sets flag indicating whether copy of the value stored in cache should be created
+        /// for cache operation implying return value. 
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultCopyOnRead)]
+        public bool CopyOnRead { get; set; }
+
+        /// <summary>
+        /// If true all the SQL table and field names will be escaped with double quotes like 
+        /// ({ "tableName"."fieldsName"}). This enforces case sensitivity for field names and
+        /// also allows having special characters in table and field names.
+        /// </summary>
+        public bool SqlEscapeAll { get; set; }
+
+        /// <summary>
+        /// Gets or sets the query entity configuration.
+        /// </summary>
+        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+        public ICollection<QueryEntity> QueryEntities { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether statistics gathering is enabled on a cache.
+        /// These statistics can be retrieved via <see cref="ICache{TK,TV}.GetMetrics()"/>.
+        /// </summary>
+        public bool EnableStatistics { get; set; }
+
+        /// <summary>
+        /// Gets or sets the name of the data region, see <see cref="DataRegionConfiguration"/>.
+        /// </summary>
+        public string DataRegionName { get; set; }
+
+        /// <summary>
+        /// Gets or sets the partition loss policy. This policy defines how Ignite will react to
+        /// a situation when all nodes for some partition leave the cluster.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultPartitionLossPolicy)]
+        public PartitionLossPolicy PartitionLossPolicy { get; set; }
+
+        /// <summary>
+        /// Gets or sets the cache group name. Caches with the same group name share single underlying 'physical'
+        /// cache (partition set), but are logically isolated. 
+        /// <para />
+        /// Since underlying cache is shared, the following configuration properties should be the same within group:
+        /// <see cref="CacheMode"/>, <see cref="PartitionLossPolicy"/>, <see cref="DataRegionName"/>.
+        /// <para />
+        /// Grouping caches reduces overall overhead, since internal data structures are shared.
+        /// </summary>
+        public string GroupName { get; set; }
+
+        /// <summary>
+        /// Gets or sets maximum inline size in bytes for sql indexes. See also <see cref="QueryIndex.InlineSize"/>.
+        /// -1 for automatic.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultSqlIndexMaxInlineSize)]
+        public int SqlIndexMaxInlineSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets the key configuration.
+        /// </summary>
+        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
+        public ICollection<CacheKeyConfiguration> KeyConfiguration { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether on-heap cache is enabled for the off-heap based page memory.
+        /// </summary>
+        public bool OnheapCacheEnabled { get; set; }
+
+        /// <summary>
+        /// Gets or sets the cache rebalance order. Caches with bigger RebalanceOrder are rebalanced later than caches
+        /// with smaller RebalanceOrder.
+        /// <para />
+        /// Default is 0, which means unordered rebalance. All caches with RebalanceOrder=0 are rebalanced without any
+        /// delay concurrently.
+        /// <para />
+        /// This parameter is applicable only for caches with <see cref="RebalanceMode"/> of
+        /// <see cref="CacheRebalanceMode.Sync"/> and <see cref="CacheRebalanceMode.Async"/>.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultRebalanceOrder)]
+        public int RebalanceOrder { get; set; }
+
+        /// <summary>
+        /// Gets or sets the rebalance batches prefetch count.
+        /// <para />
+        /// Source node can provide more than one batch at rebalance start to improve performance.
+        /// Default is <see cref="CacheConfiguration.DefaultRebalanceBatchesPrefetchCount"/>, minimum is 2.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultRebalanceBatchesPrefetchCount)]
+        public long RebalanceBatchesPrefetchCount { get; set; }
+
+        /// <summary>
+        /// Gets or sets the maximum number of active query iterators.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultMaxQueryIteratorsCount)]
+        public int MaxQueryIteratorsCount { get; set; }
+
+        /// <summary>
+        /// Gets or sets the size of the query detail metrics to be stored in memory.
+        /// <para />
+        /// 0 means disabled metrics.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultQueryDetailMetricsSize)]
+        public int QueryDetailMetricsSize { get; set; }
+
+        /// <summary>
+        /// Gets or sets the SQL schema.
+        /// Non-quoted identifiers are not case sensitive. Quoted identifiers are case sensitive.
+        /// <para />
+        /// Quoted <see cref="Name"/> is used by default.
+        /// </summary>
+        public string SqlSchema { get; set; }
+
+        /// <summary>
+        /// Gets or sets the desired query parallelism within a single node.
+        /// Query executor may or may not use this hint, depending on estimated query cost.
+        /// <para />
+        /// Default is <see cref="CacheConfiguration.DefaultQueryParallelism"/>.
+        /// </summary>
+        [DefaultValue(CacheConfiguration.DefaultQueryParallelism)]
+        public int QueryParallelism { get; set; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
index d772ba6..a3964c6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
@@ -220,5 +220,10 @@ namespace Apache.Ignite.Core.Client.Cache
         /// <param name="modes">Optional peek modes. If not provided, then total cache size is returned.</param>
         /// <returns>Cache size across all nodes.</returns>
         long GetSize(params CachePeekMode[] modes);
+
+        /// <summary>
+        /// Gets the cache configuration.
+        /// </summary>
+        CacheClientConfiguration GetConfiguration();
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs
index ceb8f26..d5ba835 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/IIgniteClient.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Core.Client
 {
     using System;
+    using System.Collections.Generic;
     using Apache.Ignite.Core.Client.Cache;
 
     /// <summary>
@@ -40,5 +41,54 @@ namespace Apache.Ignite.Core.Client
         /// <typeparam name="TK">Cache key type.</typeparam>
         /// <typeparam name="TV">Cache value type.</typeparam>
         ICacheClient<TK, TV> GetCache<TK, TV>(string name);
+
+        /// <summary>
+        /// Gets existing cache with the given name or creates new one using template configuration.
+        /// </summary>
+        /// <typeparam name="TK">Cache key type.</typeparam>
+        /// <typeparam name="TV">Cache value type.</typeparam>
+        /// <param name="name">Cache name.</param>
+        /// <returns>Existing or newly created cache.</returns>
+        ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(string name);
+
+        /// <summary>
+        /// Gets existing cache with the given name or creates new one using provided configuration.
+        /// </summary>
+        /// <typeparam name="TK">Cache key type.</typeparam>
+        /// <typeparam name="TV">Cache value type.</typeparam>
+        /// <param name="configuration">Cache configuration.</param>
+        /// <returns>Existing or newly created cache.</returns>
+        ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(CacheClientConfiguration configuration);
+
+        /// <summary>
+        /// Dynamically starts new cache using template configuration.
+        /// </summary>
+        /// <typeparam name="TK">Cache key type.</typeparam>
+        /// <typeparam name="TV">Cache value type.</typeparam>
+        /// <param name="name">Cache name.</param>
+        /// <returns>Existing or newly created cache.</returns>
+        ICacheClient<TK, TV> CreateCache<TK, TV>(string name);
+
+        /// <summary>
+        /// Dynamically starts new cache using provided configuration.
+        /// </summary>
+        /// <typeparam name="TK">Cache key type.</typeparam>
+        /// <typeparam name="TV">Cache value type.</typeparam>
+        /// <param name="configuration">Cache configuration.</param>
+        /// <returns>Existing or newly created cache.</returns>
+        ICacheClient<TK, TV> CreateCache<TK, TV>(CacheClientConfiguration configuration);
+
+        /// <summary>
+        /// Gets the collection of names of currently available caches, or empty collection if there are no caches.
+        /// </summary>
+        /// <returns>Collection of names of currently available caches.</returns>
+        ICollection<string> GetCacheNames();
+
+        /// <summary>
+        /// Destroys dynamically created (with <see cref="CreateCache{TK,TV}(string)"/> or 
+        /// <see cref="GetOrCreateCache{TK,TV}(string)"/>) cache.
+        /// </summary>
+        /// <param name="name">The name of the cache to stop.</param>
+        void DestroyCache(string name);
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
index f61da06..bf6a227 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IIgnite.cs
@@ -276,7 +276,6 @@ namespace Apache.Ignite.Core
 
         /// <summary>
         /// Gets the collection of names of currently available caches, or empty collection if there are no caches.
-        /// Note that null string is a valid cache name.
         /// </summary>
         /// <returns>Collection of names of currently available caches.</returns>
         ICollection<string> GetCacheNames();

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
index 9be06c5..de0277b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
@@ -124,5 +124,23 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             return res;
         }
+
+        /// <summary>
+        /// Reads the string collection.
+        /// </summary>
+        public static ICollection<string> ReadStringCollection(this IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            var cnt = reader.ReadInt();
+            var res = new List<string>(cnt);
+
+            for (var i = 0; i < cnt; i++)
+            {
+                res.Add(reader.ReadString());
+            }
+
+            return res;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
index be6e7da..a3b42b8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
@@ -327,6 +327,12 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
             return DoOutInOp(ClientOp.CacheGetSize, w => WritePeekModes(modes, w), s => s.ReadLong());
         }
 
+        /** <inheritDoc /> */
+        public CacheClientConfiguration GetConfiguration()
+        {
+            return DoOutInOp(ClientOp.CacheGetConfiguration, null, s => new CacheClientConfiguration(s));
+        }
+
         /// <summary>
         /// Does the out in op.
         /// </summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs
new file mode 100644
index 0000000..160d09f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/ClientCacheConfigurationSerializer.cs
@@ -0,0 +1,261 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Client.Cache
+{
+    using System;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Client.Cache;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+
+    /// <summary>
+    /// Writes and reads <see cref="CacheConfiguration"/> for thin client mode.
+    /// <para />
+    /// Thin client supports a subset of <see cref="CacheConfiguration"/> properties, so
+    /// <see cref="CacheConfiguration.Read"/> is not suitable.
+    /// </summary>
+    internal static class ClientCacheConfigurationSerializer
+    {
+        /// <summary>
+        /// Copies one cache configuration to another.
+        /// </summary>
+        public static void Copy(CacheConfiguration from, CacheClientConfiguration to, bool ignoreUnsupportedProperties)
+        {
+            Debug.Assert(from != null);
+            Debug.Assert(to != null);
+
+            to.AtomicityMode = from.AtomicityMode;
+            to.Backups = from.Backups;
+            to.CacheMode = from.CacheMode;
+            to.CopyOnRead = from.CopyOnRead;
+            to.DataRegionName = from.DataRegionName;
+            to.EagerTtl = from.EagerTtl;
+            to.EnableStatistics = from.EnableStatistics;
+            to.GroupName = from.GroupName;
+            to.Invalidate = from.Invalidate;
+            to.LockTimeout = from.LockTimeout;
+            to.MaxConcurrentAsyncOperations = from.MaxConcurrentAsyncOperations;
+            to.MaxQueryIteratorsCount = from.MaxQueryIteratorsCount;
+            to.Name = from.Name;
+            to.OnheapCacheEnabled = from.OnheapCacheEnabled;
+            to.PartitionLossPolicy = from.PartitionLossPolicy;
+            to.QueryDetailMetricsSize = from.QueryDetailMetricsSize;
+            to.QueryParallelism = from.QueryParallelism;
+            to.ReadFromBackup = from.ReadFromBackup;
+            to.RebalanceBatchSize = from.RebalanceBatchSize;
+            to.RebalanceBatchesPrefetchCount = from.RebalanceBatchesPrefetchCount;
+            to.RebalanceDelay = from.RebalanceDelay;
+            to.RebalanceMode = from.RebalanceMode;
+            to.RebalanceOrder = from.RebalanceOrder;
+            to.RebalanceThrottle = from.RebalanceThrottle;
+            to.RebalanceTimeout = from.RebalanceTimeout;
+            to.SqlEscapeAll = from.SqlEscapeAll;
+            to.SqlIndexMaxInlineSize = from.SqlIndexMaxInlineSize;
+            to.SqlSchema = from.SqlSchema;
+            to.WriteSynchronizationMode = from.WriteSynchronizationMode;
+
+            to.KeyConfiguration = from.KeyConfiguration;
+            to.QueryEntities = from.QueryEntities;
+
+            if (!ignoreUnsupportedProperties)
+            {
+                // Unsupported complex properties.
+                ThrowUnsupportedIfNotDefault(from.AffinityFunction, "AffinityFunction");
+                ThrowUnsupportedIfNotDefault(from.EvictionPolicy, "EvictionPolicy");
+                ThrowUnsupportedIfNotDefault(from.ExpiryPolicyFactory, "ExpiryPolicyFactory");
+                ThrowUnsupportedIfNotDefault(from.PluginConfigurations, "PluginConfigurations");
+                ThrowUnsupportedIfNotDefault(from.CacheStoreFactory, "CacheStoreFactory");
+                ThrowUnsupportedIfNotDefault(from.NearConfiguration, "NearConfiguration");
+
+                // Unsupported store-related properties.
+                ThrowUnsupportedIfNotDefault(from.KeepBinaryInStore, "KeepBinaryInStore");
+                ThrowUnsupportedIfNotDefault(from.LoadPreviousValue, "LoadPreviousValue");
+                ThrowUnsupportedIfNotDefault(from.ReadThrough, "ReadThrough");
+                ThrowUnsupportedIfNotDefault(from.WriteThrough, "WriteThrough");
+                ThrowUnsupportedIfNotDefault(from.StoreConcurrentLoadAllThreshold, "StoreConcurrentLoadAllThreshold",
+                    CacheConfiguration.DefaultStoreConcurrentLoadAllThreshold);
+                ThrowUnsupportedIfNotDefault(from.WriteBehindBatchSize, "WriteBehindBatchSize",
+                    CacheConfiguration.DefaultWriteBehindBatchSize);
+                ThrowUnsupportedIfNotDefault(from.WriteBehindCoalescing, "WriteBehindCoalescing",
+                    CacheConfiguration.DefaultWriteBehindCoalescing);
+                ThrowUnsupportedIfNotDefault(from.WriteBehindEnabled, "WriteBehindEnabled");
+                ThrowUnsupportedIfNotDefault(from.WriteBehindFlushFrequency, "WriteBehindFlushFrequency",
+                    CacheConfiguration.DefaultWriteBehindFlushFrequency);
+                ThrowUnsupportedIfNotDefault(from.WriteBehindFlushSize, "WriteBehindFlushSize",
+                    CacheConfiguration.DefaultWriteBehindFlushSize);
+                ThrowUnsupportedIfNotDefault(from.WriteBehindFlushThreadCount, "WriteBehindFlushThreadCount",
+                    CacheConfiguration.DefaultWriteBehindFlushThreadCount);
+            }
+        }
+        /// <summary>
+        /// Copies one cache configuration to another.
+        /// </summary>
+        public static void Copy(CacheClientConfiguration from, CacheConfiguration to)
+        {
+            Debug.Assert(from != null);
+            Debug.Assert(to != null);
+
+            to.AtomicityMode = from.AtomicityMode;
+            to.Backups = from.Backups;
+            to.CacheMode = from.CacheMode;
+            to.CopyOnRead = from.CopyOnRead;
+            to.DataRegionName = from.DataRegionName;
+            to.EagerTtl = from.EagerTtl;
+            to.EnableStatistics = from.EnableStatistics;
+            to.GroupName = from.GroupName;
+            to.Invalidate = from.Invalidate;
+            to.LockTimeout = from.LockTimeout;
+            to.MaxConcurrentAsyncOperations = from.MaxConcurrentAsyncOperations;
+            to.MaxQueryIteratorsCount = from.MaxQueryIteratorsCount;
+            to.Name = from.Name;
+            to.OnheapCacheEnabled = from.OnheapCacheEnabled;
+            to.PartitionLossPolicy = from.PartitionLossPolicy;
+            to.QueryDetailMetricsSize = from.QueryDetailMetricsSize;
+            to.QueryParallelism = from.QueryParallelism;
+            to.ReadFromBackup = from.ReadFromBackup;
+            to.RebalanceBatchSize = from.RebalanceBatchSize;
+            to.RebalanceBatchesPrefetchCount = from.RebalanceBatchesPrefetchCount;
+            to.RebalanceDelay = from.RebalanceDelay;
+            to.RebalanceMode = from.RebalanceMode;
+            to.RebalanceOrder = from.RebalanceOrder;
+            to.RebalanceThrottle = from.RebalanceThrottle;
+            to.RebalanceTimeout = from.RebalanceTimeout;
+            to.SqlEscapeAll = from.SqlEscapeAll;
+            to.SqlIndexMaxInlineSize = from.SqlIndexMaxInlineSize;
+            to.SqlSchema = from.SqlSchema;
+            to.WriteSynchronizationMode = from.WriteSynchronizationMode;
+
+            to.KeyConfiguration = from.KeyConfiguration;
+            to.QueryEntities = from.QueryEntities;
+        }
+
+        /// <summary>
+        /// Writes the specified config.
+        /// </summary>
+        public static void Write(IBinaryStream stream, CacheClientConfiguration cfg)
+        {
+            Debug.Assert(stream != null);
+            Debug.Assert(cfg != null);
+
+            // Configuration should be written with a system marshaller.
+            var writer = BinaryUtils.Marshaller.StartMarshal(stream);
+            var pos = writer.Stream.Position;
+            writer.WriteInt(0);  // Reserve for length.
+
+            writer.WriteInt((int)cfg.AtomicityMode);
+            writer.WriteInt(cfg.Backups);
+            writer.WriteInt((int)cfg.CacheMode);
+            writer.WriteBoolean(cfg.CopyOnRead);
+            writer.WriteString(cfg.DataRegionName);
+            writer.WriteBoolean(cfg.EagerTtl);
+            writer.WriteBoolean(cfg.EnableStatistics);
+            writer.WriteString(cfg.GroupName);
+            writer.WriteBoolean(cfg.Invalidate);
+            writer.WriteTimeSpanAsLong(cfg.LockTimeout);
+            writer.WriteInt(cfg.MaxConcurrentAsyncOperations);
+            writer.WriteInt(cfg.MaxQueryIteratorsCount);
+            writer.WriteString(cfg.Name);
+            writer.WriteBoolean(cfg.OnheapCacheEnabled);
+            writer.WriteInt((int)cfg.PartitionLossPolicy);
+            writer.WriteInt(cfg.QueryDetailMetricsSize);
+            writer.WriteInt(cfg.QueryParallelism);
+            writer.WriteBoolean(cfg.ReadFromBackup);
+            writer.WriteInt(cfg.RebalanceBatchSize);
+            writer.WriteLong(cfg.RebalanceBatchesPrefetchCount);
+            writer.WriteTimeSpanAsLong(cfg.RebalanceDelay);
+            writer.WriteInt((int)cfg.RebalanceMode);
+            writer.WriteInt(cfg.RebalanceOrder);
+            writer.WriteTimeSpanAsLong(cfg.RebalanceThrottle);
+            writer.WriteTimeSpanAsLong(cfg.RebalanceTimeout);
+            writer.WriteBoolean(cfg.SqlEscapeAll);
+            writer.WriteInt(cfg.SqlIndexMaxInlineSize);
+            writer.WriteString(cfg.SqlSchema);
+            writer.WriteInt((int)cfg.WriteSynchronizationMode);
+
+            writer.WriteCollectionRaw(cfg.KeyConfiguration);
+            writer.WriteCollectionRaw(cfg.QueryEntities);
+
+            // Write length (so that part of the config can be skipped).
+            var len = writer.Stream.Position - pos - 4;
+            writer.Stream.WriteInt(pos, len);
+        }
+        /// <summary>
+        /// Reads the config.
+        /// </summary>
+        public static void Read(IBinaryStream stream, CacheClientConfiguration cfg)
+        {
+            Debug.Assert(stream != null);
+
+            // Configuration should be read with system marshaller.
+            var reader = BinaryUtils.Marshaller.StartUnmarshal(stream);
+
+            var len = reader.ReadInt();
+            var pos = reader.Stream.Position;
+
+            cfg.AtomicityMode = (CacheAtomicityMode)reader.ReadInt();
+            cfg.Backups = reader.ReadInt();
+            cfg.CacheMode = (CacheMode)reader.ReadInt();
+            cfg.CopyOnRead = reader.ReadBoolean();
+            cfg.DataRegionName = reader.ReadString();
+            cfg.EagerTtl = reader.ReadBoolean();
+            cfg.EnableStatistics = reader.ReadBoolean();
+            cfg.GroupName = reader.ReadString();
+            cfg.Invalidate = reader.ReadBoolean();
+            cfg.LockTimeout = reader.ReadLongAsTimespan();
+            cfg.MaxConcurrentAsyncOperations = reader.ReadInt();
+            cfg.MaxQueryIteratorsCount = reader.ReadInt();
+            cfg.Name = reader.ReadString();
+            cfg.OnheapCacheEnabled = reader.ReadBoolean();
+            cfg.PartitionLossPolicy = (PartitionLossPolicy)reader.ReadInt();
+            cfg.QueryDetailMetricsSize = reader.ReadInt();
+            cfg.QueryParallelism = reader.ReadInt();
+            cfg.ReadFromBackup = reader.ReadBoolean();
+            cfg.RebalanceBatchSize = reader.ReadInt();
+            cfg.RebalanceBatchesPrefetchCount = reader.ReadLong();
+            cfg.RebalanceDelay = reader.ReadLongAsTimespan();
+            cfg.RebalanceMode = (CacheRebalanceMode)reader.ReadInt();
+            cfg.RebalanceOrder = reader.ReadInt();
+            cfg.RebalanceThrottle = reader.ReadLongAsTimespan();
+            cfg.RebalanceTimeout = reader.ReadLongAsTimespan();
+            cfg.SqlEscapeAll = reader.ReadBoolean();
+            cfg.SqlIndexMaxInlineSize = reader.ReadInt();
+            cfg.SqlSchema = reader.ReadString();
+            cfg.WriteSynchronizationMode = (CacheWriteSynchronizationMode)reader.ReadInt();
+            cfg.KeyConfiguration = reader.ReadCollectionRaw(r => new CacheKeyConfiguration(r));
+            cfg.QueryEntities = reader.ReadCollectionRaw(r => new QueryEntity(r));
+
+            Debug.Assert(len == reader.Stream.Position - pos);
+        }
+
+        /// <summary>
+        /// Throws the unsupported exception if property is not default.
+        /// </summary>
+        // ReSharper disable ParameterOnlyUsedForPreconditionCheck.Local
+        // ReSharper disable UnusedParameter.Local
+        private static void ThrowUnsupportedIfNotDefault<T>(T obj, string propertyName, T defaultValue = default(T))
+        {
+            if (!Equals(obj, defaultValue))
+            {
+                throw new NotSupportedException(
+                    string.Format("{0}.{1} property is not supported in thin client mode.",
+                        typeof(CacheConfiguration).Name, propertyName));
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
index 3511a79..779b73e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
@@ -49,6 +49,13 @@ namespace Apache.Ignite.Core.Impl.Client
         CacheRemoveIfEquals = 25,
         CacheGetSize = 26,
         CacheRemoveKeys = 27,
-        CacheRemoveAll = 28
+        CacheRemoveAll = 28,
+        CacheCreateWithName = 29,
+        CacheGetOrCreateWithName = 30,
+        CacheDestroy = 31,
+        CacheGetNames = 32,
+        CacheGetConfiguration = 33,
+        CacheCreateWithConfiguration = 34,
+        CacheGetOrCreateWithConfiguration = 35
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs
index a2e66e8..294a202 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientStatus.cs
@@ -26,6 +26,7 @@ namespace Apache.Ignite.Core.Impl.Client
         Fail = 1,
         InvalidOpCode = 2,
         CacheDoesNotExist = 1000,
+        CacheExists = 1001,
         TooManyCursors = 1010
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
index d05355a..13a3a83 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/IgniteClient.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Core.Impl.Client
 {
     using System;
+    using System.Collections.Generic;
     using System.Diagnostics;
     using System.Diagnostics.CodeAnalysis;
     using Apache.Ignite.Core.Binary;
@@ -25,6 +26,7 @@ namespace Apache.Ignite.Core.Impl.Client
     using Apache.Ignite.Core.Client.Cache;
     using Apache.Ignite.Core.Datastream;
     using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Binary.IO;
     using Apache.Ignite.Core.Impl.Client.Cache;
     using Apache.Ignite.Core.Impl.Cluster;
     using Apache.Ignite.Core.Impl.Common;
@@ -88,6 +90,62 @@ namespace Apache.Ignite.Core.Impl.Client
         }
 
         /** <inheritDoc /> */
+        public ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(string name)
+        {
+            IgniteArgumentCheck.NotNull(name, "name");
+
+            DoOutOp(ClientOp.CacheGetOrCreateWithName, w => w.WriteString(name));
+
+            return GetCache<TK, TV>(name);
+        }
+
+        /** <inheritDoc /> */
+        public ICacheClient<TK, TV> GetOrCreateCache<TK, TV>(CacheClientConfiguration configuration)
+        {
+            IgniteArgumentCheck.NotNull(configuration, "configuration");
+
+            DoOutOp(ClientOp.CacheGetOrCreateWithConfiguration,
+                w => ClientCacheConfigurationSerializer.Write(w.Stream, configuration));
+
+            return GetCache<TK, TV>(configuration.Name);
+        }
+
+        /** <inheritDoc /> */
+        public ICacheClient<TK, TV> CreateCache<TK, TV>(string name)
+        {
+            IgniteArgumentCheck.NotNull(name, "name");
+
+            DoOutOp(ClientOp.CacheCreateWithName, w => w.WriteString(name));
+
+            return GetCache<TK, TV>(name);
+        }
+
+        /** <inheritDoc /> */
+        public ICacheClient<TK, TV> CreateCache<TK, TV>(CacheClientConfiguration configuration)
+        {
+            IgniteArgumentCheck.NotNull(configuration, "configuration");
+
+            DoOutOp(ClientOp.CacheCreateWithConfiguration,
+                w => ClientCacheConfigurationSerializer.Write(w.Stream, configuration));
+
+            return GetCache<TK, TV>(configuration.Name);
+        }
+
+        /** <inheritDoc /> */
+        public ICollection<string> GetCacheNames()
+        {
+            return DoOutInOp(ClientOp.CacheGetNames, null, s => Marshaller.StartUnmarshal(s).ReadStringCollection());
+        }
+
+        /** <inheritDoc /> */
+        public void DestroyCache(string name)
+        {
+            IgniteArgumentCheck.NotNull(name, "name");
+
+            DoOutOp(ClientOp.CacheDestroy, w => w.WriteString(name));
+        }
+
+        /** <inheritDoc /> */
         public IIgnite GetIgnite()
         {
             throw GetClientNotSupportedException();
@@ -155,5 +213,32 @@ namespace Apache.Ignite.Core.Impl.Client
 
             return new NotSupportedException(msg);
         }
+
+        /// <summary>
+        /// Does the out in op.
+        /// </summary>
+        private T DoOutInOp<T>(ClientOp opId, Action<BinaryWriter> writeAction,
+            Func<IBinaryStream, T> readFunc)
+        {
+            return _socket.DoOutInOp(opId, stream =>
+            {
+                if (writeAction != null)
+                {
+                    var writer = _marsh.StartMarshal(stream);
+
+                    writeAction(writer);
+
+                    _marsh.FinishMarshal(writer);
+                }
+            }, readFunc);
+        }
+
+        /// <summary>
+        /// Does the out op.
+        /// </summary>
+        private void DoOutOp(ClientOp opId, Action<BinaryWriter> writeAction = null)
+        {
+            DoOutInOp<object>(opId, writeAction, null);
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
index 1249ed8..8f78382 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/App.config
@@ -30,10 +30,6 @@
                          localhost="127.0.0.1" peerAssemblyLoadingMode="CurrentAppDomain">
         <atomicConfiguration atomicSequenceReserveSize="10" />
 
-        <cacheConfiguration>
-            <cacheConfiguration name="default-cache" />
-        </cacheConfiguration>
-
         <discoverySpi type="TcpDiscoverySpi">
             <ipFinder type="TcpDiscoveryMulticastIpFinder">
                 <endpoints>

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs
index 9158b09..cc35840 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientPutGetExample.cs
@@ -36,12 +36,11 @@ namespace Apache.Ignite.Examples.ThinClient
     /// 2) Start example.
     /// <para />
     /// This example can also work via pure Java node started with ignite.bat/ignite.sh.
-    /// The only requirement is that the nodes have to create the cache named "default-cache" in advance.
     /// </summary>
     public static class ThinClientPutGetExample
     {
         /// <summary> Cache name. </summary>
-        private const string CacheName = "default-cache";
+        private const string CacheName = "thinClientCache";
 
         [STAThread]
         public static void Main()
@@ -56,7 +55,7 @@ namespace Apache.Ignite.Examples.ThinClient
                 Console.WriteLine();
                 Console.WriteLine(">>> Cache put-get client example started.");
 
-                ICacheClient<int, Organization> cache = igniteClient.GetCache<int, Organization>(CacheName);
+                ICacheClient<int, Organization> cache = igniteClient.GetOrCreateCache<int, Organization>(CacheName);
 
                 PutGet(cache);
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs
index 49c87b7..61b3a8b 100644
--- a/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs
+++ b/modules/platforms/dotnet/examples/Apache.Ignite.Examples/ThinClient/ThinClientQueryExample.cs
@@ -40,7 +40,7 @@ namespace Apache.Ignite.Examples.ThinClient
     public class ThinClientQueryExample
     {
         /// <summary> Cache name. </summary>
-        private const string CacheName = "default-cache";
+        private const string CacheName = "thinClientCache";
 
         [STAThread]
         public static void Main()
@@ -55,7 +55,7 @@ namespace Apache.Ignite.Examples.ThinClient
                 Console.WriteLine();
                 Console.WriteLine(">>> Cache query client example started.");
 
-                ICacheClient<int, Employee> cache = igniteClient.GetCache<int, Employee>(CacheName);
+                ICacheClient<int, Employee> cache = igniteClient.GetOrCreateCache<int, Employee>(CacheName);
 
                 // Populate cache with sample data entries.
                 PopulateCache(cache);


[18/47] ignite git commit: IGNITE-6926) Web console: Fixed SimpleWorkerPool next worker selection logic.

Posted by sb...@apache.org.
IGNITE-6926) Web console: Fixed SimpleWorkerPool next worker selection logic.


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

Branch: refs/heads/ignite-zk
Commit: 50b384bfa2a68289326fbee093f52c9b5193b7ff
Parents: 63b628d
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Thu Nov 16 10:12:24 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Thu Nov 16 10:12:24 2017 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/utils/SimpleWorkerPool.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/50b384bf/modules/web-console/frontend/app/utils/SimpleWorkerPool.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/utils/SimpleWorkerPool.js b/modules/web-console/frontend/app/utils/SimpleWorkerPool.js
index b76dc52..495a4d2 100644
--- a/modules/web-console/frontend/app/utils/SimpleWorkerPool.js
+++ b/modules/web-console/frontend/app/utils/SimpleWorkerPool.js
@@ -65,7 +65,7 @@ export default class SimpleWorkerPool {
     }
 
     _getNextWorker() {
-        return this._workers.find((w) => !w.tid);
+        return this._workers.find((w) => _.isNil(w.tid));
     }
 
     _getNextTask() {
@@ -106,7 +106,7 @@ export default class SimpleWorkerPool {
         this._tasks.push({tid, data});
 
         if (this.__dbg)
-            console.log(`Pool: [name=${this._name}, queue=${this._tasks.length}]`);
+            console.log(`Pool: [name=${this._name}, tid=${tid}, queue=${this._tasks.length}]`);
 
         this._run();
 


[09/47] ignite git commit: IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer

Posted by sb...@apache.org.
IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer

This closes #2985


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

Branch: refs/heads/ignite-zk
Commit: ec38564a83ecddd520f5227d904468c04720389a
Parents: 46c480b
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Nov 14 17:17:56 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Nov 14 17:17:56 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.AspNet.csproj                 |   3 +-
 .../Apache.Ignite.Core.Tests.csproj             |   2 +
 .../Cache/CacheConfigurationTest.cs             |   7 +
 .../Cache/MemoryMetricsTest.cs                  |   1 +
 .../Cache/PersistentStoreTestObsolete.cs        |   6 +-
 .../Compute/ComputeApiTestFullFooter.cs         |   2 +
 .../ConsoleRedirectTest.cs                      |  45 +-
 .../Apache.Ignite.Core.Tests/DeploymentTest.cs  | 137 +++--
 .../Apache.Ignite.Core.Tests/ExecutableTest.cs  |  18 +-
 .../IgniteConfigurationTest.cs                  |   1 +
 .../IgniteStartStopTest.cs                      |  12 +-
 .../MultiAppDomainTest.cs                       | 171 +++++++
 .../Process/ListDataReader.cs                   |  52 ++
 .../Apache.Ignite.Core.Tests/TestUtils.cs       |  18 +-
 .../Apache.Ignite.Core.csproj                   |  57 +--
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |  26 +-
 .../Apache.Ignite.Core/Impl/ExceptionUtils.cs   |  20 +-
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |   4 +-
 .../Apache.Ignite.Core/Impl/IgniteManager.cs    |  79 +--
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |  82 +--
 .../Impl/PlatformJniTarget.cs                   | 248 ++++++---
 .../Impl/Unmanaged/IUnmanagedTarget.cs          |  42 --
 .../Impl/Unmanaged/IgniteJniNativeMethods.cs    |  96 ----
 .../Impl/Unmanaged/Jni/AppDomains.cs            | 135 +++++
 .../Impl/Unmanaged/Jni/CallbackDelegates.cs     |  52 ++
 .../Impl/Unmanaged/Jni/Callbacks.cs             | 292 +++++++++++
 .../Impl/Unmanaged/Jni/ConsoleWriter.cs         |  40 ++
 .../Impl/Unmanaged/Jni/Env.cs                   | 500 +++++++++++++++++++
 .../Impl/Unmanaged/Jni/EnvDelegates.cs          | 109 ++++
 .../Impl/Unmanaged/Jni/EnvInterface.cs          | 263 ++++++++++
 .../Impl/Unmanaged/Jni/GlobalRef.cs             |  87 ++++
 .../Impl/Unmanaged/Jni/JniResult.cs             |  35 ++
 .../Impl/Unmanaged/Jni/Jvm.cs                   | 335 +++++++++++++
 .../Impl/Unmanaged/Jni/JvmDelegates.cs          |  31 ++
 .../Impl/Unmanaged/Jni/JvmInterface.cs          |  40 ++
 .../Impl/Unmanaged/Jni/MethodId.cs              | 157 ++++++
 .../Impl/Unmanaged/Jni/NativeMethod.cs          |  48 ++
 .../Impl/Unmanaged/UnmanagedCallbackHandlers.cs |  38 --
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        | 236 ++-------
 .../Impl/Unmanaged/UnmanagedContext.cs          |  53 --
 .../Unmanaged/UnmanagedNonReleaseableTarget.cs  |  70 ---
 .../Impl/Unmanaged/UnmanagedTarget.cs           |  77 ---
 .../Impl/Unmanaged/UnmanagedUtils.cs            | 257 ++++------
 .../dotnet/Apache.Ignite.Core/build-common.ps1  |  77 ---
 .../Apache.Ignite.EntityFramework.csproj        |   3 +-
 .../Apache.Ignite.Log4Net.csproj                |   4 +-
 modules/platforms/dotnet/Apache.Ignite.ndproj   |   8 +-
 modules/platforms/dotnet/Apache.Ignite.sln      | 143 ------
 .../dotnet/Apache.Ignite/IgniteRunner.cs        |   8 +-
 modules/platforms/dotnet/DEVNOTES.txt           |  15 +-
 50 files changed, 2939 insertions(+), 1303 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj b/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
index 4508776..ade81cc 100644
--- a/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
@@ -25,7 +25,7 @@
     <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
     <DebugType>full</DebugType>
     <PlatformTarget>AnyCPU</PlatformTarget>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <ErrorReport>prompt</ErrorReport>
     <CodeAnalysisRuleSet>Apache.Ignite.AspNet.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
@@ -39,6 +39,7 @@
     <CodeAnalysisRuleSet>Apache.Ignite.AspNet.ruleset</CodeAnalysisRuleSet>
     <DocumentationFile>bin\Release\Apache.Ignite.AspNet.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <PropertyGroup>
     <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 6c7e2b8..2ef6db1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -161,10 +161,12 @@
     <Compile Include="Common\IgniteGuidTest.cs" />
     <Compile Include="Deployment\RuntimeDependencyFunc.cs" />
     <Compile Include="EventsTestLocalListeners.cs" />
+    <Compile Include="Process\ListDataReader.cs" />
     <Compile Include="Log\ConcurrentMemoryTarget.cs" />
     <Compile Include="Log\DefaultLoggerTest.cs" />
     <Compile Include="Log\Log4NetLoggerTest.cs" />
     <Compile Include="Log\NLogLoggerTest.cs" />
+    <Compile Include="MultiAppDomainTest.cs" />
     <Compile Include="Plugin\Cache\CacheJavaPluginConfiguration.cs" />
     <Compile Include="Plugin\Cache\CacheJavaPluginTest.cs" />
     <Compile Include="Plugin\PluginTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
index b5d8367..9593777 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
@@ -81,10 +81,17 @@ namespace Apache.Ignite.Core.Tests.Cache
                             Name = "myMemPolicy",
                             InitialSize = 77 * 1024 * 1024,
                             MaxSize = 99 * 1024 * 1024
+                        },
+                        new MemoryPolicyConfiguration
+                        {
+                            Name = MemoryConfiguration.DefaultDefaultMemoryPolicyName,
+                            InitialSize = 55 * 1024 * 1024,
+                            MaxSize = 88 * 1024 * 1024
                         }
                     }
                 },
 #pragma warning restore 618
+                DataStorageConfiguration = null,
                 SpringConfigUrl = "Config\\cache-default.xml"
             };
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
index 7ccee94..67319f4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/MemoryMetricsTest.cs
@@ -102,6 +102,7 @@ namespace Apache.Ignite.Core.Tests.Cache
         {
             var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
             {
+                DataStorageConfiguration = null,
                 MemoryConfiguration = new MemoryConfiguration
                 {
                     DefaultMemoryPolicyName = MemoryPolicyWithMetrics,

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
index a6b9b3b..63a9f47 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
@@ -60,7 +60,8 @@ namespace Apache.Ignite.Core.Tests.Cache
                     WalStorePath = Path.Combine(_tempDir, "WalStore"),
                     WalArchivePath = Path.Combine(_tempDir, "WalArchive"),
                     MetricsEnabled = true
-                }
+                },
+                DataStorageConfiguration = null
             };
 
             const string cacheName = "persistentCache";
@@ -116,7 +117,8 @@ namespace Apache.Ignite.Core.Tests.Cache
         {
             var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
             {
-                PersistentStoreConfiguration = new PersistentStoreConfiguration()
+                PersistentStoreConfiguration = new PersistentStoreConfiguration(),
+                DataStorageConfiguration = null
             };
 
             // Default config, inactive by default (IsActiveOnStart is ignored when persistence is enabled).

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTestFullFooter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTestFullFooter.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTestFullFooter.cs
index a0d54e4..cc86db7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTestFullFooter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Compute/ComputeApiTestFullFooter.cs
@@ -61,6 +61,8 @@ namespace Apache.Ignite.Core.Tests.Compute
 
             File.WriteAllText(path, text);
 
+            Assert.IsTrue(File.Exists(path));
+
             return path;
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
index 3ab5ed3..ed556b4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
@@ -52,10 +52,10 @@ namespace Apache.Ignite.Core.Tests
             _stdErr = Console.Error;
 
             _outSb = new StringBuilder();
-            Console.SetOut(new StringWriter(_outSb));
+            Console.SetOut(new MyStringWriter(_outSb));
 
             _errSb = new StringBuilder();
-            Console.SetError(new StringWriter(_errSb));
+            Console.SetError(new MyStringWriter(_errSb));
         }
 
         /// <summary>
@@ -64,8 +64,12 @@ namespace Apache.Ignite.Core.Tests
         [TearDown]
         public void TearDown()
         {
+            MyStringWriter.Throw = false;
+
             Console.SetOut(_stdOut);
             Console.SetError(_stdErr);
+
+            Ignition.StopAll(true);
         }
 
         /// <summary>
@@ -81,6 +85,18 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
+        /// Tests the exception in console writer.
+        /// </summary>
+        [Test]
+        public void TestExceptionInWriterPropagatesToJavaAndBack()
+        {
+            MyStringWriter.Throw = true;
+
+            var ex = Assert.Throws<IgniteException>(() => Ignition.Start(TestUtils.GetTestConfiguration()));
+            Assert.AreEqual("foo", ex.Message);
+        }
+
+        /// <summary>
         /// Tests startup error in Java.
         /// </summary>
         [Test]
@@ -145,8 +161,11 @@ namespace Apache.Ignite.Core.Tests
                     LoaderOptimization = LoaderOptimization.MultiDomainHost
                 });
 
+                var type = typeof(IgniteRunner);
+                Assert.IsNotNull(type.FullName);
+
                 var runner = (IIgniteRunner)childDomain.CreateInstanceAndUnwrap(
-                    typeof(IgniteRunner).Assembly.FullName, typeof(IgniteRunner).FullName);
+                    type.Assembly.FullName, type.FullName);
 
                 runner.Run();
             }
@@ -174,5 +193,25 @@ namespace Apache.Ignite.Core.Tests
                 // Will be stopped automatically on domain unload.
             }
         }
+
+        private class MyStringWriter : StringWriter
+        {
+            public static bool Throw { get; set; }
+
+            public MyStringWriter(StringBuilder sb) : base(sb)
+            {
+                // No-op.
+            }
+
+            public override void Write(string value)
+            {
+                if (Throw)
+                {
+                    throw new Exception("foo");
+                }
+
+                base.Write(value);
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
index 1d80c60..eb329af 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
@@ -32,6 +32,9 @@ namespace Apache.Ignite.Core.Tests
     /// </summary>
     public class DeploymentTest
     {
+        /** */
+        private string _tempFolder;
+
         /// <summary>
         /// Tests the custom deployment where IGNITE_HOME can't be resolved, and there is a user-defined classpath.
         /// </summary>
@@ -39,35 +42,12 @@ namespace Apache.Ignite.Core.Tests
         public void TestCustomDeployment()
         {
             // Create temp folder
-            var folder = IgniteUtils.GetTempDirectoryName();
-
-            // Copy jars
-            var home = IgniteHome.Resolve(null);
-
-            var jarNames = new[] {@"\ignite-core-", @"\cache-api-1.0.0.jar", @"\modules\spring\" };
-
-            var jars = Directory.GetFiles(home, "*.jar", SearchOption.AllDirectories)
-                .Where(jarPath => jarNames.Any(jarPath.Contains)).ToArray();
-
-            Assert.Greater(jars.Length, 3);
-
-            foreach (var jar in jars)
-            {
-                var fileName = Path.GetFileName(jar);
-                Assert.IsNotNull(fileName);
-                File.Copy(jar, Path.Combine(folder, fileName), true);
-            }
+            var folder = _tempFolder;
+            DeployTo(folder);
 
             // Build classpath
             var classpath = string.Join(";", Directory.GetFiles(folder).Select(Path.GetFileName));
 
-            // Copy .NET binaries
-            foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly, GetType().Assembly})
-            {
-                Assert.IsNotNull(asm.Location);
-                File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
-            }
-
             // Copy config
             var springPath = Path.GetFullPath("config\\compute\\compute-grid2.xml");
             var springFile = Path.GetFileName(springPath);
@@ -88,38 +68,97 @@ namespace Apache.Ignite.Core.Tests
 
             Assert.IsNotNull(proc);
 
-            try
-            {
-                VerifyNodeStarted(exePath);
-            }
-            finally
+            VerifyNodeStarted(exePath);
+        }
+
+        /// <summary>
+        /// Tests missing JARs.
+        /// </summary>
+        [Test]
+        public void TestMissingJarsCauseProperException()
+        {
+            // Create temp folder
+            var folder = _tempFolder;
+            DeployTo(folder);
+
+            // Build classpath
+            var classpath = string.Join(";",
+                Directory.GetFiles(folder).Where(x => !x.Contains("ignite-core-")).Select(Path.GetFileName));
+
+            // Start a node and check the exception.
+            var exePath = Path.Combine(folder, "Apache.Ignite.exe");
+            var reader = new ListDataReader();
+
+            var proc = IgniteProcess.Start(exePath, string.Empty, args: new[]
             {
-                proc.Kill();
-
-                Assert.IsTrue(
-                    TestUtils.WaitForCondition(() =>
-                    {
-                        try
-                        {
-                            Directory.Delete(folder, true);
-                            return true;
-                        }
-                        catch (Exception)
-                        {
-                            return false;
-                        }
-                    }, 1000), "Failed to remove temp directory: " + folder);
-            }
+                "-jvmClasspath=" + classpath,
+                "-J-ea",
+                "-J-Xms512m",
+                "-J-Xmx512m"
+            }, outReader: reader);
+
+            // Wait for process to fail.
+            Assert.IsNotNull(proc);
+            Assert.IsTrue(proc.WaitForExit(10000));
+            Assert.IsTrue(proc.HasExited);
+            Assert.AreEqual(-1, proc.ExitCode);
+
+            // Check error message.
+            Assert.AreEqual("ERROR: Apache.Ignite.Core.Common.IgniteException: Java class is not found " +
+                            "(did you set IGNITE_HOME environment variable?): " +
+                            "org/apache/ignite/internal/processors/platform/PlatformIgnition",
+                reader.GetOutput().First());
         }
 
         /// <summary>
-        /// Fixture tear down.
+        /// Sets up the test.
         /// </summary>
-        [TestFixtureTearDown]
-        public void TestFixtureTearDown()
+        [SetUp]
+        public void SetUp()
+        {
+            _tempFolder = IgniteUtils.GetTempDirectoryName();
+        }
+
+        /// <summary>
+        /// Tears down the test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
         {
             Ignition.StopAll(true);
             IgniteProcess.KillAll();
+
+            Directory.Delete(_tempFolder, true);
+        }
+
+        /// <summary>
+        /// Deploys binaries to specified folder
+        /// </summary>
+        private void DeployTo(string folder)
+        {
+            // Copy jars.
+            var home = IgniteHome.Resolve(null);
+
+            var jarNames = new[] {@"\ignite-core-", @"\cache-api-1.0.0.jar", @"\modules\spring\"};
+
+            var jars = Directory.GetFiles(home, "*.jar", SearchOption.AllDirectories)
+                .Where(jarPath => jarNames.Any(jarPath.Contains)).ToArray();
+
+            Assert.Greater(jars.Length, 3);
+
+            foreach (var jar in jars)
+            {
+                var fileName = Path.GetFileName(jar);
+                Assert.IsNotNull(fileName);
+                File.Copy(jar, Path.Combine(folder, fileName), true);
+            }
+
+            // Copy .NET binaries
+            foreach (var asm in new[] {typeof(IgniteRunner).Assembly, typeof(Ignition).Assembly, GetType().Assembly})
+            {
+                Assert.IsNotNull(asm.Location);
+                File.Copy(asm.Location, Path.Combine(folder, Path.GetFileName(asm.Location)));
+            }
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
index 8f422f4..b885d28 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ExecutableTest.cs
@@ -320,10 +320,7 @@ namespace Apache.Ignite.Core.Tests
                 Assert.IsTrue(proc.Join(30000, out exitCode));
                 Assert.AreEqual(-1, exitCode);
 
-                lock (reader.List)
-                {
-                    Assert.AreEqual(err, reader.List.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x)));
-                }
+                Assert.AreEqual(err, reader.GetOutput().FirstOrDefault(x => !string.IsNullOrWhiteSpace(x)));
             };
 
             checkError("blabla", "ERROR: Apache.Ignite.Core.Common.IgniteException: Missing argument value: " +
@@ -477,18 +474,5 @@ namespace Apache.Ignite.Core.Tests
             /// </summary>
             public int JvmMaxMemoryMb { get; set; }
         }
-
-        private class ListDataReader : IIgniteProcessOutputReader
-        {
-            public readonly List<string> List = new List<string>();
-
-            public void OnOutput(System.Diagnostics.Process proc, string data, bool err)
-            {
-                lock (List)
-                {
-                    List.Add(data);
-                }
-            }
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index f68371a..6e09704 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -249,6 +249,7 @@ namespace Apache.Ignite.Core.Tests
             // When Spring XML is used, .NET overrides Spring.
             var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration())
             {
+                DataStorageConfiguration = null,
                 SpringConfigUrl = @"config\spring-test.xml",
                 NetworkSendRetryDelay = TimeSpan.FromSeconds(45),
                 MetricsHistorySize = 57

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
index 529128a..aa292ab 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
@@ -229,7 +229,7 @@ namespace Apache.Ignite.Core.Tests
                 JvmClasspath = TestUtils.CreateTestClasspath()
             };
 
-            for (var i = 0; i < 20; i++)
+            for (var i = 0; i < 50; i++)
             {
                 Console.WriteLine("Iteration: " + i);
 
@@ -239,16 +239,12 @@ namespace Apache.Ignite.Core.Tests
 
                 if (i % 2 == 0) // Try to stop ignite from another thread.
                 {
-                    var t = new Thread(() => {
-                        grid.Dispose();
-                    });
-
-                    t.Start();
-
-                    t.Join();
+                    Task.Factory.StartNew(() => grid.Dispose()).Wait();
                 }
                 else
+                {
                     grid.Dispose();
+                }
 
                 GC.Collect(); // At the time of writing java references are cleaned from finalizer, so GC is needed.
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs
new file mode 100644
index 0000000..0157255
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/MultiAppDomainTest.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Tests
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests Ignite behavior in multi-AppDomain scenario.
+    /// Such a scenario occurs within IIS, for example, or within application plugins.
+    /// </summary>
+    [Category(TestUtils.CategoryIntensive)]
+    public class MultiAppDomainTest
+    {
+        /** */
+        public const string CacheName = "cache";
+
+        /** */
+        private readonly List<AppDomain> _domains = new List<AppDomain>();
+
+        /// <summary>
+        /// Tears down the test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
+        {
+            Ignition.StopAll(true);
+
+            UnloadDomains();
+        }
+
+        /// <summary>
+        /// Tests the IIS behavior:
+        /// when application is restarted, new AppDomain is started while old one is still running.
+        /// </summary>
+        [Test]
+        public void TestIisBehavior()
+        {
+            var ignite = Ignition.Start(GetConfig());
+            
+            var cache = ignite.CreateCache<int, int>(new CacheConfiguration
+            {
+                Name =  CacheName,
+                CacheMode = CacheMode.Replicated  // Use Replicated to avoid data loss due to node stop.
+            });
+
+            cache[1] = 1;
+
+            // Check same domain.
+            new DomainRunner().RunTest();
+
+            var type = typeof(DomainRunner);
+            Assert.IsNotNull(type.FullName);
+
+            // Start and stop domains.
+            for (var i = 0; i < 10; i++)
+            {
+                var domain = CreateDomain(i);
+
+                var runner = (DomainRunner) domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
+                runner.RunTest();
+
+                // Verify node start.
+                var expectedNodeCount = Math.Min(i + 3, 7);
+                Assert.AreEqual(expectedNodeCount, ignite.GetCluster().GetNodes().Count);
+
+                // Current AppDomain does not see other instances.
+                Assert.AreEqual(2, Ignition.GetAll().Count);
+
+                if (i > 3)
+                {
+                    var oldDomain = _domains[i - 3];
+                    _domains[i - 3] = null;
+
+                    AppDomain.Unload(oldDomain);
+
+                    // Verify node exit.
+                    TestUtils.WaitForCondition(
+                        () => ignite.GetCluster().GetNodes().Count == expectedNodeCount - 1, 5000);
+                }
+            }
+
+            UnloadDomains();
+
+            // Verify node exit: only two nodes from current domain should be there.
+            TestUtils.WaitForCondition(() => ignite.GetCluster().GetNodes().Count == 2, 5000);
+        }
+
+        /// <summary>
+        /// Creates the domain.
+        /// </summary>
+        private AppDomain CreateDomain(int i)
+        {
+            var domain = AppDomain.CreateDomain("TestIisBehavior-" + i, null, new AppDomainSetup
+            {
+                ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
+                ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
+                ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
+                LoaderOptimization = LoaderOptimization.MultiDomainHost
+            });
+
+            _domains.Add(domain);
+
+            return domain;
+        }
+
+        /// <summary>
+        /// Unloads the domains.
+        /// </summary>
+        private void UnloadDomains()
+        {
+            foreach (var appDomain in _domains)
+            {
+                if (appDomain != null)
+                {
+                    AppDomain.Unload(appDomain);
+                }
+            }
+
+            _domains.Clear();
+        }
+
+        /// <summary>
+        /// Gets the configuration.
+        /// </summary>
+        private static IgniteConfiguration GetConfig()
+        {
+            return new IgniteConfiguration(TestUtils.GetTestConfiguration())
+            {
+                AutoGenerateIgniteInstanceName = true
+            };
+        }
+
+        /// <summary>
+        /// Class to instantiate in another domain.
+        /// </summary>
+        private class DomainRunner : MarshalByRefObject
+        {
+            /// <summary>
+            /// Runs the test.
+            /// </summary>
+            public void RunTest()
+            {
+                var cfg = GetConfig();
+
+                // No need to stop: this will happen on domain unload.
+                var ignite = Ignition.Start(cfg);
+                
+                var cache = ignite.GetCache<int, int>(CacheName);
+                Assert.AreEqual(1, cache[1]);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs
new file mode 100644
index 0000000..e201c96
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Process/ListDataReader.cs
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Tests.Process
+{
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Linq;
+
+    /// <summary>
+    /// Reads process output into a list.
+    /// </summary>
+    public class ListDataReader : IIgniteProcessOutputReader
+    {
+        /** Target list. */
+        private readonly List<string> _list = new List<string>();
+
+        /** <inheritdoc /> */
+        public void OnOutput(Process proc, string data, bool err)
+        {
+            lock (_list)
+            {
+                _list.Add(data);
+            }
+        }
+
+        /// <summary>
+        /// Gets the output.
+        /// </summary>
+        public IList<string> GetOutput()
+        {
+            lock (_list)
+            {
+                return _list.ToList();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
index 28e7ae8..03e8bf7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
@@ -26,6 +26,7 @@ namespace Apache.Ignite.Core.Tests
     using System.Linq;
     using System.Threading;
     using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Configuration;
     using Apache.Ignite.Core.Discovery.Tcp;
     using Apache.Ignite.Core.Discovery.Tcp.Static;
     using Apache.Ignite.Core.Impl;
@@ -63,8 +64,8 @@ namespace Apache.Ignite.Core.Tests
             : new List<string>
             {
                 "-XX:+HeapDumpOnOutOfMemoryError",
-                "-Xms512m",
-                "-Xmx512m",
+                "-Xms64m",
+                "-Xmx99m",
                 "-ea",
                 "-DIGNITE_ATOMIC_CACHE_DELETE_HISTORY_SIZE=1000",
                 "-DIGNITE_QUIET=true"
@@ -345,7 +346,18 @@ namespace Apache.Ignite.Core.Tests
                 Localhost = "127.0.0.1",
                 JvmOptions = TestJavaOptions(jvmDebug),
                 JvmClasspath = CreateTestClasspath(),
-                IgniteInstanceName = name
+                IgniteInstanceName = name,
+                DataStorageConfiguration = new DataStorageConfiguration
+                {
+                    DefaultDataRegionConfiguration = new DataRegionConfiguration
+                    {
+                        Name = DataStorageConfiguration.DefaultDataRegionName,
+                        InitialSize = 128 * 1024 * 1024,
+                        MaxSize = Environment.Is64BitProcess
+                            ? DataRegionConfiguration.DefaultMaxSize
+                            : 256 * 1024 * 1024
+                    }
+                }
             };
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 852c071..165a57e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -69,7 +69,7 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <DocumentationFile>bin\Debug\Apache.Ignite.Core.XML</DocumentationFile>
     <PlatformTarget>AnyCPU</PlatformTarget>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <CodeAnalysisRuleSet>Apache.Ignite.Core.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
@@ -82,6 +82,7 @@
     <CodeAnalysisRuleSet>Apache.Ignite.Core.ruleset</CodeAnalysisRuleSet>
     <DebugType>none</DebugType>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
@@ -132,8 +133,22 @@
     <Compile Include="Impl\IPlatformTargetInternal.cs" />
     <Compile Include="Impl\DataRegionMetrics.cs" />
     <Compile Include="Impl\PersistentStore\PersistentStoreMetrics.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\AppDomains.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\CallbackDelegates.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\Callbacks.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\ConsoleWriter.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\EnvDelegates.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\Env.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\EnvInterface.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\JvmInterface.cs" />
     <Compile Include="Impl\PlatformDisposableTargetAdapter.cs" />
     <Compile Include="Impl\PlatformJniTarget.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\GlobalRef.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\MethodId.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\NativeMethod.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\JniResult.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\Jvm.cs" />
+    <Compile Include="Impl\Unmanaged\Jni\JvmDelegates.cs" />
     <Compile Include="PersistentStore\CheckpointWriteOrder.cs" />
     <Compile Include="PersistentStore\IPersistentStoreMetrics.cs" />
     <Compile Include="PersistentStore\Package-Info.cs" />
@@ -497,14 +512,8 @@
     <Compile Include="Impl\Transactions\TransactionImpl.cs" />
     <Compile Include="Impl\Transactions\TransactionMetricsImpl.cs" />
     <Compile Include="Impl\Transactions\TransactionsImpl.cs" />
-    <Compile Include="Impl\Unmanaged\IgniteJniNativeMethods.cs" />
-    <Compile Include="Impl\Unmanaged\IUnmanagedTarget.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedCallbackHandlers.cs" />
     <Compile Include="Impl\Unmanaged\UnmanagedCallbackOp.cs" />
     <Compile Include="Impl\Unmanaged\UnmanagedCallbacks.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedContext.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedNonReleaseableTarget.cs" />
-    <Compile Include="Impl\Unmanaged\UnmanagedTarget.cs" />
     <Compile Include="Impl\Unmanaged\UnmanagedUtils.cs" />
     <Compile Include="Interop\IPlatformTarget.cs" />
     <Compile Include="Interop\JavaObject.cs" />
@@ -571,39 +580,10 @@
     <Compile Include="Transactions\TransactionState.cs" />
     <Compile Include="Transactions\TransactionTimeoutException.cs" />
   </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
-    <EmbeddedResource Include="$(SolutionDir)\x64\Debug\ignite.jni.dll">
-      <Link>resources\debug\x64\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
-    <EmbeddedResource Include="$(SolutionDir)\x64\Release\ignite.jni.dll">
-      <Link>resources\release\x64\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
-    <EmbeddedResource Include="$(SolutionDir)\Win32\Debug\ignite.jni.dll">
-      <Link>resources\debug\x86\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
-    <EmbeddedResource Include="$(SolutionDir)\Win32\Release\ignite.jni.dll">
-      <Link>resources\release\x86\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
-  <ItemGroup Condition="'$(Platform)' == 'AnyCPU'">
-    <EmbeddedResource Include="$(ProjectDir)..\..\cpp\jni\project\vs\x64\$(Configuration)\ignite.jni.dll">
-      <Link>resources\x64\ignite.jni.dll</Link>
-    </EmbeddedResource>
-    <EmbeddedResource Include="$(ProjectDir)..\..\cpp\jni\project\vs\Win32\$(Configuration)\ignite.jni.dll" Condition="'$(Configuration)' == 'Release' Or Exists('$(ProjectDir)..\..\cpp\jni\project\vs\Win32\$(Configuration)\ignite.jni.dll')">
-      <Link>resources\x86\ignite.jni.dll</Link>
-    </EmbeddedResource>
-  </ItemGroup>
   <ItemGroup>
     <None Include="Apache.Ignite.Core.ruleset" />
     <None Include="Apache.Ignite.Core.nuspec" />
     <None Include="Apache.Ignite.Core.Schema.nuspec" />
-    <None Include="build-common.ps1" />
     <None Include="NuGet\Uninstall.ps1" />
     <None Include="NuGet\PostBuild.ps1" />
     <None Include="NuGet\Install.ps1" />
@@ -614,11 +594,6 @@
     </None>
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
-  <PropertyGroup Condition="'$(Platform)' == 'AnyCPU'">
-    <PreBuildEvent>cd "$(ProjectDir)"
-	set COMPLUS_ApplicationMigrationRuntimeActivationConfigPath=$(ProjectDir)
-	PowerShell.exe -executionpolicy remotesigned -File build-common.ps1 -Configuration $(ConfigurationName) -msbuildexe "$(MSBuildBinPath)\msbuild.exe"</PreBuildEvent>
-  </PropertyGroup>
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
        Other similar extension points exist, see Microsoft.Common.targets.
   <Target Name="BeforeBuild">

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index 4e5eae5..bc14fdd 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -40,6 +40,7 @@ namespace Apache.Ignite.Core
     using Apache.Ignite.Core.Impl.Log;
     using Apache.Ignite.Core.Impl.Memory;
     using Apache.Ignite.Core.Impl.Unmanaged;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Lifecycle;
     using Apache.Ignite.Core.Log;
     using Apache.Ignite.Core.Resource;
@@ -209,7 +210,7 @@ namespace Apache.Ignite.Core
         /// Starts Ignite with given configuration.
         /// </summary>
         /// <returns>Started Ignite.</returns>
-        public static unsafe IIgnite Start(IgniteConfiguration cfg)
+        public static IIgnite Start(IgniteConfiguration cfg)
         {
             IgniteArgumentCheck.NotNull(cfg, "cfg");
 
@@ -228,9 +229,8 @@ namespace Apache.Ignite.Core
                 // 2. Create context.
                 IgniteUtils.LoadDlls(cfg.JvmDllPath, log);
 
-                var cbs = new UnmanagedCallbacks(log);
-
-                IgniteManager.CreateJvmContext(cfg, cbs, log);
+                var cbs = IgniteManager.CreateJvmContext(cfg, log);
+                var env = cbs.Jvm.AttachCurrentThread();
                 log.Debug("JVM started.");
 
                 var gridName = cfg.IgniteInstanceName;
@@ -248,8 +248,7 @@ namespace Apache.Ignite.Core
                 try
                 {
                     // 4. Initiate Ignite start.
-                    UU.IgnitionStart(cbs.Context, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null);
-
+                    UU.IgnitionStart(env, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null, cbs.IgniteId);
 
                     // 5. At this point start routine is finished. We expect STARTUP object to have all necessary data.
                     var node = _startup.Ignite;
@@ -268,7 +267,7 @@ namespace Apache.Ignite.Core
 
                     return node;
                 }
-                catch (Exception)
+                catch (Exception ex)
                 {
                     // 1. Perform keys cleanup.
                     string name = _startup.Name;
@@ -283,7 +282,7 @@ namespace Apache.Ignite.Core
 
                     // 2. Stop Ignite node if it was started.
                     if (interopProc != null)
-                        UU.IgnitionStop(interopProc.Target.Context, gridName, true);
+                        UU.IgnitionStop(gridName, true);
 
                     // 3. Throw error further (use startup error if exists because it is more precise).
                     if (_startup.Error != null)
@@ -293,7 +292,14 @@ namespace Apache.Ignite.Core
                             _startup.Error);
                     }
 
-                    throw;
+                    var jex = ex as JavaException;
+
+                    if (jex == null)
+                    {
+                        throw;
+                    }
+
+                    throw ExceptionUtils.GetException(null, jex);
                 }
                 finally
                 {
@@ -456,7 +462,7 @@ namespace Apache.Ignite.Core
         /// <param name="stream">Stream.</param>
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
             Justification = "PlatformJniTarget is passed further")]
-        internal static void OnStart(IUnmanagedTarget interopProc, IBinaryStream stream)
+        internal static void OnStart(GlobalRef interopProc, IBinaryStream stream)
         {
             try
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
index b81d04b..0dab997 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/ExceptionUtils.cs
@@ -126,10 +126,26 @@ namespace Apache.Ignite.Core.Impl
             BinaryReader reader = null, Exception innerException = null)
         {
             // Set JavaException as immediate inner.
-            innerException = new JavaException(clsName, msg, stackTrace, innerException);
+            var jex = new JavaException(clsName, msg, stackTrace, innerException);
 
+            return GetException(igniteInt, jex, reader);
+        }
+
+        /// <summary>
+        /// Creates exception according to native code class and message.
+        /// </summary>
+        /// <param name="igniteInt">The ignite.</param>
+        /// <param name="innerException">Java exception.</param>
+        /// <param name="reader">Error data reader.</param>
+        /// <returns>Exception.</returns>
+        public static Exception GetException(IIgniteInternal igniteInt, JavaException innerException,
+            BinaryReader reader = null)
+        {
             var ignite = igniteInt == null ? null : igniteInt.GetIgnite();
 
+            var msg = innerException.JavaMessage;
+            var clsName = innerException.JavaClassName;
+
             ExceptionFactory ctor;
 
             if (Exs.TryGetValue(clsName, out ctor))
@@ -157,7 +173,7 @@ namespace Apache.Ignite.Core.Impl
                     "variable?): " + msg, innerException);
 
             if (ClsCachePartialUpdateErr.Equals(clsName, StringComparison.OrdinalIgnoreCase))
-                return ProcessCachePartialUpdateException(igniteInt, msg, stackTrace, reader);
+                return ProcessCachePartialUpdateException(igniteInt, msg, innerException.Message, reader);
 
             // Predefined mapping not found - check plugins.
             if (igniteInt != null && igniteInt.PluginProcessor != null)

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
index 78b7c74..ae751a4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Ignite.cs
@@ -378,7 +378,7 @@ namespace Apache.Ignite.Core.Impl
         /// Internal stop routine.
         /// </summary>
         /// <param name="cancel">Cancel flag.</param>
-        internal unsafe void Stop(bool cancel)
+        internal void Stop(bool cancel)
         {
             var jniTarget = _proc as PlatformJniTarget;
 
@@ -387,7 +387,7 @@ namespace Apache.Ignite.Core.Impl
                 throw new IgniteException("Ignition.Stop is not supported in thin client.");
             }
 
-            UU.IgnitionStop(jniTarget.Target.Context, Name, cancel);
+            UU.IgnitionStop(Name, cancel);
 
             _cbs.Cleanup();
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
index ee54218..fd067b9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
@@ -22,18 +22,17 @@ namespace Apache.Ignite.Core.Impl
     using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.Linq;
-    using System.Runtime.InteropServices;
     using System.Text;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Impl.Memory;
     using Apache.Ignite.Core.Impl.Unmanaged;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Log;
-    using UU = Apache.Ignite.Core.Impl.Unmanaged.UnmanagedUtils;
 
     /// <summary>
     /// Native interface manager.
     /// </summary>
-    public static unsafe class IgniteManager
+    internal static class IgniteManager
     {
         /** Java Command line argument: Xms. Case sensitive. */
         private const string CmdJvmMinMemJava = "-Xms";
@@ -44,9 +43,6 @@ namespace Apache.Ignite.Core.Impl
         /** Monitor for DLL load synchronization. */
         private static readonly object SyncRoot = new object();
 
-        /** First created context. */
-        private static void* _ctx;
-
         /** Configuration used on JVM start. */
         private static JvmConfiguration _jvmCfg;
 
@@ -57,10 +53,9 @@ namespace Apache.Ignite.Core.Impl
         /// Create JVM.
         /// </summary>
         /// <param name="cfg">Configuration.</param>
-        /// <param name="cbs">Callbacks.</param>
-        /// <param name="log"></param>
-        /// <returns>Context.</returns>
-        internal static void CreateJvmContext(IgniteConfiguration cfg, UnmanagedCallbacks cbs, ILogger log)
+        /// <param name="log">Logger</param>
+        /// <returns>Callback context.</returns>
+        internal static UnmanagedCallbacks CreateJvmContext(IgniteConfiguration cfg, ILogger log)
         {
             lock (SyncRoot)
             {
@@ -79,16 +74,19 @@ namespace Apache.Ignite.Core.Impl
                 }
 
                 // 2. Create unmanaged pointer.
-                void* ctx = CreateJvm(cfg, cbs);
+                var jvm = CreateJvm(cfg);
+                jvm.EnableJavaConsoleWriter();
 
-                cbs.SetContext(ctx);
+                var cbs = new UnmanagedCallbacks(log, jvm);
+                jvm.RegisterCallbacks(cbs);
 
-                // 3. If this is the first JVM created, preserve it.
-                if (_ctx == null)
+                // 3. If this is the first JVM created, preserve configuration.
+                if (_jvmCfg == null)
                 {
-                    _ctx = ctx;
                     _jvmCfg = jvmCfg;
                 }
+
+                return cbs;
             }
         }
         
@@ -101,63 +99,18 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /// <summary>
-        /// Blocks until JVM stops.
-        /// </summary>
-        public static void DestroyJvm()
-        {
-            lock (SyncRoot)
-            {
-                if (_ctx != null)
-                {
-                    UU.DestroyJvm(_ctx);
-
-                    _ctx = null;
-                }
-            }
-        }
-
-        /// <summary>
         /// Create JVM.
         /// </summary>
         /// <returns>JVM.</returns>
-        private static void* CreateJvm(IgniteConfiguration cfg, UnmanagedCallbacks cbs)
+        private static Jvm CreateJvm(IgniteConfiguration cfg)
         {
             var cp = Classpath.CreateClasspath(cfg);
 
             var jvmOpts = GetMergedJvmOptions(cfg);
-            
-            var opts = new sbyte*[1 + jvmOpts.Count];
 
-            int idx = 0;
-                
-            opts[idx++] = IgniteUtils.StringToUtf8Unmanaged(cp);
+            jvmOpts.Add(cp);
 
-            foreach (string cfgOpt in jvmOpts)
-                opts[idx++] = IgniteUtils.StringToUtf8Unmanaged(cfgOpt);
-
-            try
-            {
-                IntPtr mem = Marshal.AllocHGlobal(opts.Length * 8);
-
-                fixed (sbyte** opts0 = opts)
-                {
-                    PlatformMemoryUtils.CopyMemory(opts0, mem.ToPointer(), opts.Length * 8);
-                }
-
-                try
-                {
-                    return UU.CreateContext(mem.ToPointer(), opts.Length, cbs.CallbacksPointer);
-                }
-                finally
-                {
-                    Marshal.FreeHGlobal(mem);
-                }
-            }
-            finally
-            {
-                foreach (sbyte* opt in opts)
-                    Marshal.FreeHGlobal((IntPtr)opt);
-            }
+            return Jvm.GetOrCreate(jvmOpts);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
index e439208..38eda1b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
@@ -33,7 +33,6 @@ namespace Apache.Ignite.Core.Impl
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Cluster;
     using Apache.Ignite.Core.Impl.Common;
-    using Apache.Ignite.Core.Impl.Unmanaged;
     using Apache.Ignite.Core.Log;
     using Microsoft.Win32;
     using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
@@ -69,9 +68,6 @@ namespace Apache.Ignite.Core.Impl
         /** File: jvm.dll. */
         internal const string FileJvmDll = "jvm.dll";
 
-        /** File: Ignite.Jni.dll. */
-        internal const string FileIgniteJniDll = "ignite.jni.dll";
-        
         /** Prefix for temp directory names. */
         private const string DirIgniteTmp = "Ignite_";
         
@@ -136,9 +132,6 @@ namespace Apache.Ignite.Core.Impl
             // 1. Load JNI dll.
             LoadJvmDll(configJvmDllPath, log);
 
-            // 2. Load GG JNI dll.
-            UnmanagedUtils.Initialize();
-
             _loaded = true;
         }
 
@@ -238,7 +231,7 @@ namespace Apache.Ignite.Core.Impl
         /// Formats the Win32 error.
         /// </summary>
         [ExcludeFromCodeCoverage]
-        public static string FormatWin32Error(int errorCode)
+        private static string FormatWin32Error(int errorCode)
         {
             if (errorCode == NativeMethods.ERROR_BAD_EXE_FORMAT)
             {
@@ -252,9 +245,7 @@ namespace Apache.Ignite.Core.Impl
             if (errorCode == NativeMethods.ERROR_MOD_NOT_FOUND)
             {
                 return "DLL could not be loaded (126: ERROR_MOD_NOT_FOUND). " +
-                       "This can be caused by missing dependencies. " +
-                       "Make sure that Microsoft Visual C++ 2010 Redistributable Package is installed " +
-                       "(https://www.microsoft.com/en-us/download/details.aspx?id=14632).";
+                       "This can be caused by missing dependencies. ";
             }
 
             return string.Format("{0}: {1}", errorCode, new Win32Exception(errorCode).Message);
@@ -340,75 +331,6 @@ namespace Apache.Ignite.Core.Impl
         }
 
         /// <summary>
-        /// Unpacks an embedded resource into a temporary folder and returns the full path of resulting file.
-        /// </summary>
-        /// <param name="resourceName">Resource name.</param>
-        /// <param name="fileName">Name of the resulting file.</param>
-        /// <returns>
-        /// Path to a temp file with an unpacked resource.
-        /// </returns>
-        public static string UnpackEmbeddedResource(string resourceName, string fileName)
-        {
-            var dllRes = Assembly.GetExecutingAssembly().GetManifestResourceNames()
-                .Single(x => x.EndsWith(resourceName, StringComparison.OrdinalIgnoreCase));
-
-            return WriteResourceToTempFile(dllRes, fileName);
-        }
-
-        /// <summary>
-        /// Writes the resource to temporary file.
-        /// </summary>
-        /// <param name="resource">The resource.</param>
-        /// <param name="name">File name prefix</param>
-        /// <returns>Path to the resulting temp file.</returns>
-        private static string WriteResourceToTempFile(string resource, string name)
-        {
-            // Dll file name should not be changed, so we create a temp folder with random name instead.
-            var file = Path.Combine(GetTempDirectoryName(), name);
-
-            using (var src = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource))
-            using (var dest = File.OpenWrite(file))
-            {
-                // ReSharper disable once PossibleNullReferenceException
-                src.CopyTo(dest);
-
-                return file;
-            }
-        }
-
-        /// <summary>
-        /// Tries to clean temporary directories created with <see cref="GetTempDirectoryName"/>.
-        /// </summary>
-        internal static void TryCleanTempDirectories()
-        {
-            var dt = DateTime.Now;
-
-            foreach (var dir in Directory.EnumerateDirectories(Path.GetTempPath(), DirIgniteTmp + "*"))
-            {
-                if ((dt - Directory.GetCreationTime(dir)).TotalMinutes < 1)
-                {
-                    // Do not clean up recently created temp directories:
-                    // they may be used by currently starting up nodes.
-                    // This is a workaround for multiple node startup problem, see IGNITE-5730.
-                    continue;
-                }
-
-                try
-                {
-                    Directory.Delete(dir, true);
-                }
-                catch (IOException)
-                {
-                    // Expected
-                }
-                catch (UnauthorizedAccessException)
-                {
-                    // Expected
-                }
-            }
-        }
-
-        /// <summary>
         /// Creates a uniquely named, empty temporary directory on disk and returns the full path of that directory.
         /// </summary>
         /// <returns>The full path of the temporary directory.</returns>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/PlatformJniTarget.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/PlatformJniTarget.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/PlatformJniTarget.cs
index c7d9ab4..c0fcea4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/PlatformJniTarget.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/PlatformJniTarget.cs
@@ -25,11 +25,12 @@ namespace Apache.Ignite.Core.Impl
     using System.Threading;
     using System.Threading.Tasks;
     using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Binary.IO;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Impl.Memory;
-    using Apache.Ignite.Core.Impl.Unmanaged;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Interop;
     using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
     using BinaryWriter = Apache.Ignite.Core.Impl.Binary.BinaryWriter;
@@ -55,7 +56,7 @@ namespace Apache.Ignite.Core.Impl
             };
         
         /** Unmanaged target. */
-        private readonly IUnmanagedTarget _target;
+        private readonly GlobalRef _target;
 
         /** Marshaller. */
         private readonly Marshaller _marsh;
@@ -65,7 +66,7 @@ namespace Apache.Ignite.Core.Impl
         /// </summary>
         /// <param name="target">Target.</param>
         /// <param name="marsh">Marshaller.</param>
-        public PlatformJniTarget(IUnmanagedTarget target, Marshaller marsh)
+        public PlatformJniTarget(GlobalRef target, Marshaller marsh)
         {
             Debug.Assert(target != null);
             Debug.Assert(marsh != null);
@@ -77,7 +78,7 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Gets the target.
         /// </summary>
-        public IUnmanagedTarget Target
+        public GlobalRef Target
         {
             get { return _target; }
         }
@@ -88,43 +89,71 @@ namespace Apache.Ignite.Core.Impl
         /** <inheritdoc /> */
         public long InStreamOutLong(int type, Action<IBinaryStream> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                writeAction(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    writeAction(stream);
 
-                return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                    return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
         public IPlatformTargetInternal InStreamOutObject(int type, Action<IBinaryStream> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                writeAction(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    writeAction(stream);
 
-                var target = UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput());
+                    var target = UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput());
 
-                return target == null ? null : new PlatformJniTarget(target, _marsh);
+                    return target == null ? null : new PlatformJniTarget(target, _marsh);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
         public IPlatformTargetInternal OutObjectInternal(int type)
         {
-            return GetPlatformTarget(UU.TargetOutObject(_target, type));
+            try
+            {
+                return GetPlatformTarget(UU.TargetOutObject(_target, type));
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
         }
 
         /** <inheritdoc /> */
         public T OutStream<T>(int type, Func<IBinaryStream, T> readAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                UU.TargetOutStream(_target, type, stream.MemoryPointer);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    UU.TargetOutStream(_target, type, stream.MemoryPointer);
 
-                stream.SynchronizeInput();
+                    stream.SynchronizeInput();
 
-                return readAction(stream);
+                    return readAction(stream);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -132,16 +161,23 @@ namespace Apache.Ignite.Core.Impl
         public TR InStreamOutStream<TR>(int type, Action<IBinaryStream> writeAction, 
             Func<IBinaryStream, TR> readAction)
         {
-            using (var outStream = IgniteManager.Memory.Allocate().GetStream())
-            using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                writeAction(outStream);
+                using (var outStream = IgniteManager.Memory.Allocate().GetStream())
+                using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    writeAction(outStream);
 
-                UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+                    UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
 
-                inStream.SynchronizeInput();
+                    inStream.SynchronizeInput();
 
-                return readAction(inStream);
+                    return readAction(inStream);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -149,33 +185,40 @@ namespace Apache.Ignite.Core.Impl
         public TR InStreamOutLong<TR>(int type, Action<IBinaryStream> outAction, Func<IBinaryStream, long, TR> inAction, 
             Func<IBinaryStream, Exception> readErrorAction)
         {
-            Debug.Assert(readErrorAction != null);
-
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                outAction(stream);
+                Debug.Assert(readErrorAction != null);
 
-                var res = UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    outAction(stream);
 
-                if (res != PlatformTargetAdapter.Error && inAction == null)
-                    return default(TR);  // quick path for void operations
+                    var res = UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
 
-                stream.SynchronizeInput();
+                    if (res != PlatformTargetAdapter.Error && inAction == null)
+                        return default(TR);  // quick path for void operations
 
-                stream.Seek(0, SeekOrigin.Begin);
+                    stream.SynchronizeInput();
 
-                if (res != PlatformTargetAdapter.Error)
-                {
-                    return inAction != null ? inAction(stream, res) : default(TR);
-                }
+                    stream.Seek(0, SeekOrigin.Begin);
 
-                throw readErrorAction(stream);
+                    if (res != PlatformTargetAdapter.Error)
+                    {
+                        return inAction != null ? inAction(stream, res) : default(TR);
+                    }
+
+                    throw readErrorAction(stream);
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
-        public unsafe TR InObjectStreamOutObjectStream<TR>(int type, Action<IBinaryStream> writeAction, 
+        public TR InObjectStreamOutObjectStream<TR>(int type, Action<IBinaryStream> writeAction, 
             Func<IBinaryStream, IPlatformTargetInternal, TR> readAction, IPlatformTargetInternal arg)
         {
             PlatformMemoryStream outStream = null;
@@ -199,8 +242,8 @@ namespace Apache.Ignite.Core.Impl
                     inPtr = inStream.MemoryPointer;
                 }
 
-                var res = UU.TargetInObjectStreamOutObjectStream(_target, type, 
-                    ((PlatformJniTarget)arg).Target.Target, outPtr, inPtr);
+                var res = UU.TargetInObjectStreamOutObjectStream(_target, type,
+                    ((PlatformJniTarget) arg).Target, outPtr, inPtr);
 
                 if (readAction == null)
                     return default(TR);
@@ -212,6 +255,10 @@ namespace Apache.Ignite.Core.Impl
                 return readAction(inStream, target);
 
             }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
             finally
             {
                 try
@@ -246,7 +293,7 @@ namespace Apache.Ignite.Core.Impl
         /// <param name="convertFunc">The function to read future result from stream.</param>
         /// <returns>Created future.</returns>
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
-        private Future<T> GetFuture<T>(Func<long, int, IUnmanagedTarget> listenAction, bool keepBinary = false,
+        private Future<T> GetFuture<T>(Func<long, int, GlobalRef> listenAction, bool keepBinary = false,
             Func<BinaryReader, T> convertFunc = null)
         {
             var futType = FutureType.Object;
@@ -262,7 +309,7 @@ namespace Apache.Ignite.Core.Impl
 
             var futHnd = _marsh.Ignite.HandleRegistry.Allocate(fut);
 
-            IUnmanagedTarget futTarget;
+            GlobalRef futTarget;
 
             try
             {
@@ -323,22 +370,36 @@ namespace Apache.Ignite.Core.Impl
         /** <inheritdoc /> */
         public long InLongOutLong(int type, long val)
         {
-            return UU.TargetInLongOutLong(_target, type, val);
+            try
+            {
+                return UU.TargetInLongOutLong(_target, type, val);
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
         }
 
         /** <inheritdoc /> */
         [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
         public long InStreamOutLong(int type, Action<IBinaryRawWriter> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                var writer = _marsh.StartMarshal(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    var writer = _marsh.StartMarshal(stream);
 
-                writeAction(writer);
+                    writeAction(writer);
 
-                FinishMarshal(writer);
+                    FinishMarshal(writer);
 
-                return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                    return UU.TargetInStreamOutLong(_target, type, stream.SynchronizeOutput());
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -347,20 +408,27 @@ namespace Apache.Ignite.Core.Impl
         public T InStreamOutStream<T>(int type, Action<IBinaryRawWriter> writeAction, 
             Func<IBinaryRawReader, T> readAction)
         {
-            using (var outStream = IgniteManager.Memory.Allocate().GetStream())
-            using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                var writer = _marsh.StartMarshal(outStream);
+                using (var outStream = IgniteManager.Memory.Allocate().GetStream())
+                using (var inStream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    var writer = _marsh.StartMarshal(outStream);
 
-                writeAction(writer);
+                    writeAction(writer);
 
-                FinishMarshal(writer);
+                    FinishMarshal(writer);
 
-                UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
+                    UU.TargetInStreamOutStream(_target, type, outStream.SynchronizeOutput(), inStream.MemoryPointer);
 
-                inStream.SynchronizeInput();
+                    inStream.SynchronizeInput();
 
-                return readAction(_marsh.StartUnmarshal(inStream));
+                    return readAction(_marsh.StartUnmarshal(inStream));
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -368,20 +436,27 @@ namespace Apache.Ignite.Core.Impl
         [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
         public IPlatformTarget InStreamOutObject(int type, Action<IBinaryRawWriter> writeAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                var writer = _marsh.StartMarshal(stream);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    var writer = _marsh.StartMarshal(stream);
 
-                writeAction(writer);
+                    writeAction(writer);
 
-                FinishMarshal(writer);
+                    FinishMarshal(writer);
 
-                return GetPlatformTarget(UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput()));
+                    return GetPlatformTarget(UU.TargetInStreamOutObject(_target, type, stream.SynchronizeOutput()));
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
         /** <inheritdoc /> */
-        public unsafe T InObjectStreamOutObjectStream<T>(int type, IPlatformTarget arg, 
+        public T InObjectStreamOutObjectStream<T>(int type, IPlatformTarget arg, 
             Action<IBinaryRawWriter> writeAction, Func<IBinaryRawReader, IPlatformTarget, T> readAction)
         {
             PlatformMemoryStream outStream = null;
@@ -417,6 +492,10 @@ namespace Apache.Ignite.Core.Impl
                 return readAction(_marsh.StartUnmarshal(inStream), GetPlatformTarget(res));
 
             }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
+            }
             finally
             {
                 try
@@ -437,13 +516,20 @@ namespace Apache.Ignite.Core.Impl
         [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
         public T OutStream<T>(int type, Func<IBinaryRawReader, T> readAction)
         {
-            using (var stream = IgniteManager.Memory.Allocate().GetStream())
+            try
             {
-                UU.TargetOutStream(_target, type, stream.MemoryPointer);
+                using (var stream = IgniteManager.Memory.Allocate().GetStream())
+                {
+                    UU.TargetOutStream(_target, type, stream.MemoryPointer);
 
-                stream.SynchronizeInput();
+                    stream.SynchronizeInput();
 
-                return readAction(_marsh.StartUnmarshal(stream));
+                    return readAction(_marsh.StartUnmarshal(stream));
+                }
+            }
+            catch (JavaException jex)
+            {
+                throw ConvertException(jex);
             }
         }
 
@@ -476,7 +562,14 @@ namespace Apache.Ignite.Core.Impl
                         FinishMarshal(writer);
                     }
 
-                    UU.TargetInStreamAsync(_target, type, stream.SynchronizeOutput());
+                    try
+                    {
+                        UU.TargetInStreamAsync(_target, type, stream.SynchronizeOutput());
+                    }
+                    catch (JavaException jex)
+                    {
+                        throw ConvertException(jex);
+                    }
                 }
             }, false, convertFunc).Task;
         }
@@ -505,7 +598,14 @@ namespace Apache.Ignite.Core.Impl
                         FinishMarshal(writer);
                     }
 
-                    return UU.TargetInStreamOutObjectAsync(_target, type, stream.SynchronizeOutput());
+                    try
+                    {
+                        return UU.TargetInStreamOutObjectAsync(_target, type, stream.SynchronizeOutput());
+                    }
+                    catch (JavaException jex)
+                    {
+                        throw ConvertException(jex);
+                    }
                 }
             }, false, convertFunc).GetTask(cancellationToken);
         }
@@ -513,7 +613,7 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Gets the platform target.
         /// </summary>
-        private IPlatformTargetInternal GetPlatformTarget(IUnmanagedTarget target)
+        private IPlatformTargetInternal GetPlatformTarget(GlobalRef target)
         {
             return target == null ? null : new PlatformJniTarget(target, _marsh);
         }
@@ -521,9 +621,17 @@ namespace Apache.Ignite.Core.Impl
         /// <summary>
         /// Gets the target pointer.
         /// </summary>
-        private static unsafe void* GetTargetPtr(IPlatformTarget target)
+        private static GlobalRef GetTargetPtr(IPlatformTarget target)
+        {
+            return target == null ? null : ((PlatformJniTarget) target)._target;
+        }
+
+        /// <summary>
+        /// Converts the exception.
+        /// </summary>
+        private Exception ConvertException(JavaException jex)
         {
-            return target == null ? null : ((PlatformJniTarget) target)._target.Target;
+            return ExceptionUtils.GetException(_marsh.Ignite, jex);
         }
 
         #endregion

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IUnmanagedTarget.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IUnmanagedTarget.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IUnmanagedTarget.cs
deleted file mode 100644
index 235f20d..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IUnmanagedTarget.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System;
-
-    /// <summary>
-    /// Unmanaged target.
-    /// </summary>
-    internal unsafe interface IUnmanagedTarget : IDisposable
-    {
-        /// <summary>
-        /// Context.
-        /// </summary>
-        void* Context { get; }
-
-        /// <summary>
-        /// Target.
-        /// </summary>
-        void* Target { get; }
-
-        /// <summary>
-        /// Creates new instance with same context and different target.
-        /// </summary>
-        IUnmanagedTarget ChangeTarget(void* target);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs
deleted file mode 100644
index f96157c..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/IgniteJniNativeMethods.cs
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System.Runtime.InteropServices;
-    using System.Security;
-
-    /// <summary>
-    /// Ignite JNI native methods.
-    /// </summary>
-    [SuppressUnmanagedCodeSecurity]
-    internal static unsafe class IgniteJniNativeMethods
-    {
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteReallocate")]
-        public static extern int Reallocate(long memPtr, int cap);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteIgnitionStart")]
-        public static extern void IgnitionStart(void* ctx, sbyte* cfgPath, sbyte* gridName, int factoryId, 
-            long dataPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteIgnitionStop")]
-        [return: MarshalAs(UnmanagedType.U1)]
-        public static extern bool IgnitionStop(void* ctx, sbyte* gridName, [MarshalAs(UnmanagedType.U1)] bool cancel);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInLongOutLong")]
-        public static extern long TargetInLongOutLong(void* ctx, void* target, int opType, long val);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutLong")]
-        public static extern long TargetInStreamOutLong(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutStream")]
-        public static extern void TargetInStreamOutStream(void* ctx, void* target, int opType, long inMemPtr,
-            long outMemPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutObject")]
-        public static extern void* TargetInStreamOutObject(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInObjectStreamOutObjectStream")]
-        public static extern void* TargetInObjectStreamOutObjectStream(void* ctx, void* target, int opType,
-            void* arg, long inMemPtr, long outMemPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetOutStream")]
-        public static extern void TargetOutStream(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetOutObject")]
-        public static extern void* TargetOutObject(void* ctx, void* target, int opType);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamAsync")]
-        public static extern void TargetInStreamAsync(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteTargetInStreamOutObjectAsync")]
-        public static extern void* TargetInStreamOutObjectAsync(void* ctx, void* target, int opType, long memPtr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteAcquire")]
-        public static extern void* Acquire(void* ctx, void* target);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteRelease")]
-        public static extern void Release(void* target);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteThrowToJava")]
-        public static extern void ThrowToJava(void* ctx, char* msg);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteHandlersSize")]
-        public static extern int HandlersSize();
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteCreateContext")]
-        public static extern void* CreateContext(void* opts, int optsLen, void* cbs);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteDeleteContext")]
-        public static extern void DeleteContext(void* ptr);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteDestroyJvm")]
-        public static extern void DestroyJvm(void* ctx);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteSetConsoleHandler")]
-        public static extern void SetConsoleHandler(void* consoleHandler);
-
-        [DllImport(IgniteUtils.FileIgniteJniDll, EntryPoint = "IgniteRemoveConsoleHandler")]
-        public static extern int RemoveConsoleHandler(void* consoleHandler);
-    }
-}
\ No newline at end of file


[34/47] ignite git commit: IGNITE-6850: SQL: Added INLINE_SIZE option support to CREATE INDEX statement. This closes #3013.

Posted by sb...@apache.org.
IGNITE-6850: SQL: Added INLINE_SIZE option support to CREATE INDEX statement. This closes #3013.


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

Branch: refs/heads/ignite-zk
Commit: 8ee6cb5cf6832f53dcfb7e0f1ca915d39a532017
Parents: 19bddc6
Author: gg-shq <ks...@gmail.com>
Authored: Fri Nov 17 16:17:28 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Nov 17 16:17:28 2017 +0300

----------------------------------------------------------------------
 .../apache/ignite/IgniteSystemProperties.java   |   3 +
 .../apache/ignite/internal/sql/SqlKeyword.java  |   3 +
 .../ignite/internal/sql/SqlParserUtils.java     |  25 +++-
 .../sql/command/SqlCreateIndexCommand.java      |  41 +++++-
 .../sql/SqlParserCreateIndexSelfTest.java       |  23 +++
 .../processors/query/h2/IgniteH2Indexing.java   |  12 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |   1 +
 .../cache/index/AbstractSchemaSelfTest.java     |  22 ++-
 .../DynamicIndexAbstractBasicSelfTest.java      | 147 ++++++++++++++++++-
 .../DynamicIndexAbstractConcurrentSelfTest.java |  29 ++--
 .../cache/index/SchemaExchangeSelfTest.java     |   2 +-
 .../query/h2/sql/GridQueryParsingTest.java      |  21 ++-
 12 files changed, 283 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
index 4294c71..e0ace11 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteSystemProperties.java
@@ -452,6 +452,9 @@ public final class IgniteSystemProperties {
      */
     public static final String IGNITE_SQL_MERGE_TABLE_PREFETCH_SIZE = "IGNITE_SQL_MERGE_TABLE_PREFETCH_SIZE";
 
+    /** Disable fallback to H2 SQL parser if the internal SQL parser fails to parse the statement. */
+    public static final String IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK = "IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK";
+
     /** Maximum size for affinity assignment history. */
     public static final String IGNITE_AFFINITY_HISTORY_SIZE = "IGNITE_AFFINITY_HISTORY_SIZE";
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlKeyword.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlKeyword.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlKeyword.java
index ac826cc..08fa94b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlKeyword.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlKeyword.java
@@ -99,6 +99,9 @@ public class SqlKeyword {
     /** Keyword: INDEX. */
     public static final String INDEX = "INDEX";
 
+    /** Keyword: INLINE_SIZE. */
+    public static final String INLINE_SIZE = "INLINE_SIZE";
+
     /** Keyword: INT. */
     public static final String INT = "INT";
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlParserUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlParserUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlParserUtils.java
index 2f3b3da..d812b3d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlParserUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/SqlParserUtils.java
@@ -91,22 +91,35 @@ public class SqlParserUtils {
     }
 
     /**
-     * Parse integer value.
+     * Parse integer value (positive or negative).
      *
      * @param lex Lexer.
      * @return Integer value.
      */
     public static int parseInt(SqlLexer lex) {
+        int sign = 1;
+
+        if (lex.lookAhead().tokenType() == SqlLexerTokenType.MINUS) {
+            sign = -1;
+
+            lex.shift();
+        }
+
         if (lex.shift() && lex.tokenType() == SqlLexerTokenType.DEFAULT) {
             try {
-                return Integer.parseInt(lex.token());
+                long val = sign * Long.parseLong(lex.token());
+
+                if (val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE)
+                    return (int)val;
+
+                // Fall through.
             }
             catch (NumberFormatException e) {
-                // No-op.
+                // Fall through.
             }
         }
 
-        throw errorUnexpectedToken(lex, "[number]");
+        throw errorUnexpectedToken(lex, "[integer]");
     }
 
     /**
@@ -136,9 +149,9 @@ public class SqlParserUtils {
 
             String first = lex.token();
 
-            SqlLexerToken nextToken = lex.lookAhead();
+            SqlLexerToken nextTok = lex.lookAhead();
 
-            if (nextToken.tokenType() == SqlLexerTokenType.DOT) {
+            if (nextTok.tokenType() == SqlLexerTokenType.DOT) {
                 lex.shift();
 
                 String second = parseIdentifier(lex);

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlCreateIndexCommand.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlCreateIndexCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlCreateIndexCommand.java
index ef89a5a..05eeb44 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlCreateIndexCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/command/SqlCreateIndexCommand.java
@@ -17,9 +17,11 @@
 
 package org.apache.ignite.internal.sql.command;
 
+import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.internal.sql.SqlLexer;
 import org.apache.ignite.internal.sql.SqlLexerTokenType;
 import org.apache.ignite.internal.sql.SqlLexerToken;
+import org.apache.ignite.internal.sql.SqlParserUtils;
 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;
@@ -34,6 +36,7 @@ import java.util.Set;
 import static org.apache.ignite.internal.sql.SqlKeyword.ASC;
 import static org.apache.ignite.internal.sql.SqlKeyword.DESC;
 import static org.apache.ignite.internal.sql.SqlKeyword.IF;
+import static org.apache.ignite.internal.sql.SqlKeyword.INLINE_SIZE;
 import static org.apache.ignite.internal.sql.SqlKeyword.ON;
 import static org.apache.ignite.internal.sql.SqlParserUtils.error;
 import static org.apache.ignite.internal.sql.SqlParserUtils.errorUnexpectedToken;
@@ -71,6 +74,9 @@ public class SqlCreateIndexCommand implements SqlCommand {
     @GridToStringExclude
     private Set<String> colNames;
 
+    /** Inline size. Zero effectively disables inlining. */
+    private int inlineSize = QueryIndex.DFLT_INLINE_SIZE;
+
     /** {@inheritDoc} */
     @Override public String schemaName() {
         return schemaName;
@@ -110,6 +116,13 @@ public class SqlCreateIndexCommand implements SqlCommand {
     }
 
     /**
+     * @return Inline size.
+     */
+    public int inlineSize() {
+        return inlineSize;
+    }
+
+    /**
      * @param spatial Spatial index flag.
      * @return This instance.
      */
@@ -141,6 +154,8 @@ public class SqlCreateIndexCommand implements SqlCommand {
 
         parseColumnList(lex);
 
+        parseInlineSize(lex);
+
         return this;
     }
 
@@ -157,7 +172,27 @@ public class SqlCreateIndexCommand implements SqlCommand {
         return parseIdentifier(lex, IF);
     }
 
-    /*
+    /**
+     * Parses inline size option if exists.
+     *
+     * @param lex Lexer.
+     */
+    private void parseInlineSize(SqlLexer lex) {
+        SqlLexerToken nextTok = lex.lookAhead();
+
+        if (matchesKeyword(nextTok, INLINE_SIZE)) {
+            lex.shift();
+
+            int stmtInlineSize = SqlParserUtils.parseInt(lex);
+
+            if (stmtInlineSize < 0)
+                throw error(lex, "Inline size should be positive: " + stmtInlineSize);
+
+            inlineSize = stmtInlineSize;
+        }
+    }
+
+    /**
      * @param lex Lexer.
      */
     private void parseColumnList(SqlLexer lex) {
@@ -165,7 +200,7 @@ public class SqlCreateIndexCommand implements SqlCommand {
             throw errorUnexpectedToken(lex, "(");
 
         while (true) {
-            perseIndexColumn(lex);
+            parseIndexColumn(lex);
 
             if (skipCommaOrRightParenthesis(lex))
                 break;
@@ -175,7 +210,7 @@ public class SqlCreateIndexCommand implements SqlCommand {
     /**
      * @param lex Lexer.
      */
-    private void perseIndexColumn(SqlLexer lex) {
+    private void parseIndexColumn(SqlLexer lex) {
         String name = parseIdentifier(lex);
         boolean desc = false;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/core/src/test/java/org/apache/ignite/internal/sql/SqlParserCreateIndexSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/sql/SqlParserCreateIndexSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/sql/SqlParserCreateIndexSelfTest.java
index e7bc3e9..8cfeb2c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/sql/SqlParserCreateIndexSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/sql/SqlParserCreateIndexSelfTest.java
@@ -123,6 +123,29 @@ public class SqlParserCreateIndexSelfTest extends SqlParserAbstractSelfTest {
 
         // PRIMARY KEY
         assertParseError(null, "CREATE PRIMARY KEY INDEX idx ON tbl(a)", "Unsupported keyword: \"PRIMARY\"");
+
+        // INLINE_SIZE option
+        assertParseError(null, "CREATE INDEX ON tbl(a) INLINE_SIZE",
+            "Unexpected end of command (expected: \"[integer]\")");
+
+        assertParseError(null, "CREATE INDEX ON tbl(a) INLINE_SIZE HASH",
+            "Unexpected token: \"HASH\" (expected: \"[integer]\")");
+
+        assertParseError(null, "CREATE INDEX ON tbl(a) INLINE_SIZE elegua",
+            "Unexpected token: \"ELEGUA\" (expected: \"[integer]\")");
+
+        assertParseError(null, "CREATE INDEX ON tbl(a) INLINE_SIZE -9223372036854775808",
+            "Unexpected token: \"9223372036854775808\" (expected: \"[integer]\")");
+
+        assertParseError(null, "CREATE INDEX ON tbl(a) INLINE_SIZE " + Integer.MIN_VALUE,
+            "Inline size should be positive: " + Integer.MIN_VALUE);
+
+        assertParseError(null, "CREATE INDEX ON tbl(a) INLINE_SIZE -1", "Inline size should be positive: -1");
+
+        parseValidate(null, "CREATE INDEX idx ON schema.tbl(a) INLINE_SIZE 0", "SCHEMA", "TBL", "IDX", "A", false);
+        parseValidate(null, "CREATE INDEX idx ON schema.tbl(a) INLINE_SIZE 1", "SCHEMA", "TBL", "IDX", "A", false);
+        parseValidate(null, "CREATE INDEX idx ON schema.tbl(a) INLINE_SIZE " + Integer.MAX_VALUE,
+            "SCHEMA", "TBL", "IDX", "A", false);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 333a958..c37e5f0 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -49,6 +49,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.cache.query.FieldsQueryCursor;
 import org.apache.ignite.cache.query.QueryCancelledException;
 import org.apache.ignite.cache.query.QueryCursor;
@@ -116,6 +117,7 @@ import org.apache.ignite.internal.processors.query.h2.twostep.MapQueryLazyWorker
 import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitor;
 import org.apache.ignite.internal.processors.query.schema.SchemaIndexCacheVisitorClosure;
 import org.apache.ignite.internal.processors.timeout.GridTimeoutProcessor;
+import org.apache.ignite.internal.sql.SqlParseException;
 import org.apache.ignite.internal.sql.SqlParser;
 import org.apache.ignite.internal.sql.command.SqlCommand;
 import org.apache.ignite.internal.sql.command.SqlCreateIndexCommand;
@@ -1359,7 +1361,15 @@ public class IgniteH2Indexing implements GridQueryIndexing {
             if (log.isDebugEnabled())
                 log.debug("Failed to parse SQL with native parser [qry=" + qry.getSql() + ", err=" + e + ']');
 
-            return null;
+            if (!IgniteSystemProperties.getBoolean(IgniteSystemProperties.IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK))
+                return null;
+
+            int code = IgniteQueryErrorCode.PARSING;
+
+            if (e instanceof SqlParseException)
+                code = ((SqlParseException)e).code();
+
+            throw new IgniteSQLException("Failed to parse DDL statement: " + qry.getSql(), code, e);
         }
 
         // Execute.

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index 3c8d9fe..ea721f7 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -135,6 +135,7 @@ public class DdlStatementsProcessor {
                 }
 
                 newIdx.setFields(flds);
+                newIdx.setInlineSize(cmd0.inlineSize());
 
                 fut = ctx.query().dynamicIndexCreate(tbl.cacheName(), cmd0.schemaName(), typeDesc.tableName(),
                     newIdx, cmd0.ifNotExists());

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
index eb3b8e1..0074020 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
@@ -152,11 +152,12 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
      * @param cacheName Cache name.
      * @param tblName Table name.
      * @param idxName Index name.
+     * @param inlineSize Inline size.
      * @param fields Fields.
      */
     protected static void assertIndex(String cacheName, String tblName, String idxName,
-        IgniteBiTuple<String, Boolean>... fields) {
-        assertIndex(cacheName, false, tblName, idxName, fields);
+        int inlineSize, IgniteBiTuple<String, Boolean>... fields) {
+        assertIndex(cacheName, false, tblName, idxName, inlineSize, fields);
     }
 
     /**
@@ -167,12 +168,13 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
      *     affinity nodes as well.
      * @param tblName Table name.
      * @param idxName Index name.
+     * @param inlineSize Inline size.
      * @param fields Fields.
      */
     protected static void assertIndex(String cacheName, boolean checkNonAffinityNodes, String tblName, String idxName,
-        IgniteBiTuple<String, Boolean>... fields) {
+        int inlineSize, IgniteBiTuple<String, Boolean>... fields) {
         for (Ignite node : Ignition.allGrids())
-            assertIndex(node, checkNonAffinityNodes, cacheName, tblName, idxName, fields);
+            assertIndex(node, checkNonAffinityNodes, cacheName, tblName, idxName, inlineSize, fields);
     }
 
     /**
@@ -184,10 +186,11 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
      * @param cacheName Cache name.
      * @param tblName Table name.
      * @param idxName Index name.
+     * @param inlineSize Inline size.
      * @param fields Fields.
      */
     protected static void assertIndex(Ignite node, boolean checkNonAffinityNode, String cacheName, String tblName,
-        String idxName, IgniteBiTuple<String, Boolean>... fields) {
+        String idxName, int inlineSize, IgniteBiTuple<String, Boolean>... fields) {
         IgniteEx node0 = (IgniteEx)node;
 
         assertIndexDescriptor(node0, cacheName, tblName, idxName, fields);
@@ -195,7 +198,7 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
         if (checkNonAffinityNode || affinityNode(node0, cacheName)) {
             QueryTypeDescriptorImpl typeDesc = typeExisting(node0, cacheName, tblName);
 
-            assertIndex(typeDesc, idxName, fields);
+            assertIndex(typeDesc, idxName, inlineSize, fields);
         }
     }
 
@@ -248,10 +251,11 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
      *
      * @param typeDesc Type descriptor.
      * @param idxName Index name.
+     * @param inlineSize Inline size.
      * @param fields Fields (order is important).
      */
     protected static void assertIndex(QueryTypeDescriptorImpl typeDesc, String idxName,
-        IgniteBiTuple<String, Boolean>... fields) {
+        int inlineSize, IgniteBiTuple<String, Boolean>... fields) {
         QueryIndexDescriptorImpl idxDesc = typeDesc.index(idxName);
 
         assertNotNull(idxDesc);
@@ -259,6 +263,7 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
         assertEquals(idxName, idxDesc.name());
         assertEquals(typeDesc, idxDesc.typeDescriptor());
         assertEquals(QueryIndexType.SORTED, idxDesc.type());
+        assertEquals(inlineSize, idxDesc.inlineSize());
 
         List<String> fieldNames = new ArrayList<>(idxDesc.fields());
 
@@ -489,6 +494,9 @@ public class AbstractSchemaSelfTest extends GridCommonAbstractTest {
 
         sql.a(')');
 
+        if (idx.getInlineSize() != QueryIndex.DFLT_INLINE_SIZE)
+            sql.a(" INLINE_SIZE ").a(idx.getInlineSize());
+
         executeSql(node, cacheName, sql.toString());
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
index 56f28d4..f7d99b4 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
@@ -24,6 +24,7 @@ import java.util.concurrent.Callable;
 import javax.cache.CacheException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
@@ -197,7 +198,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
 
         dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false);
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
 
         assertSchemaException(new RunnableX() {
             @Override public void run() throws Exception {
@@ -206,7 +207,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         }, IgniteQueryErrorCode.INDEX_ALREADY_EXISTS);
 
         dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, true);
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
 
         assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1);
 
@@ -281,7 +282,8 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED), field(alias(FIELD_NAME_2_ESCAPED)));
 
         dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false);
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1_ESCAPED), field(alias(FIELD_NAME_2_ESCAPED)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE,
+            field(FIELD_NAME_1_ESCAPED), field(alias(FIELD_NAME_2_ESCAPED)));
 
         assertCompositeIndexOperations(SQL_COMPOSITE);
 
@@ -605,7 +607,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         QueryIndex idx = index(IDX_NAME_1, field(alias(FIELD_NAME_2_ESCAPED)));
 
         dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false);
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(alias(FIELD_NAME_2_ESCAPED)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(alias(FIELD_NAME_2_ESCAPED)));
 
         assertSimpleIndexOperations(SQL_SIMPLE_FIELD_2);
 
@@ -613,6 +615,135 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
     }
 
     /**
+     * Tests creating index with inline size for PARTITIONED ATOMIC cache.
+     *
+     * @throws Exception If failed.
+     */
+    public void testCreateIndexWithInlineSizePartitionedAtomic() throws Exception {
+        checkCreateIndexWithInlineSize(PARTITIONED, ATOMIC, false);
+    }
+
+    /**
+     * Tests creating index with inline size for PARTITIONED ATOMIC cache with near cache.
+     *
+     * @throws Exception If failed.
+     */
+    public void testCreateIndexWithInlineSizePartitionedAtomicNear() throws Exception {
+        checkCreateIndexWithInlineSize(PARTITIONED, ATOMIC, true);
+    }
+
+    /**
+     * Tests creating index with inline size for PARTITIONED TRANSACTIONAL cache.
+     *
+     * @throws Exception If failed.
+     */
+    public void testCreateIndexWithInlineSizePartitionedTransactional() throws Exception {
+        checkCreateIndexWithInlineSize(PARTITIONED, TRANSACTIONAL, false);
+    }
+
+    /**
+     * Tests creating index with inline size for PARTITIONED TRANSACTIONAL cache with near cache.
+     *
+     * @throws Exception If failed.
+     */
+    public void testCreateIndexWithInlineSizePartitionedTransactionalNear() throws Exception {
+        checkCreateIndexWithInlineSize(PARTITIONED, TRANSACTIONAL, true);
+    }
+
+    /**
+     * Tests creating index with inline size for REPLICATED ATOMIC cache.
+     *
+     * @throws Exception If failed.
+     */
+    public void testCreateIndexWithInlineSizeReplicatedAtomic() throws Exception {
+        checkCreateIndexWithInlineSize(REPLICATED, ATOMIC, false);
+    }
+
+    /**
+     * Tests creating index with inline size option for REPLICATED TRANSACTIONAL cache.
+     *
+     * @throws Exception If failed.
+     */
+    public void testCreateIndexWithInlineSizeReplicatedTransactional() throws Exception {
+        checkCreateIndexWithInlineSize(REPLICATED, TRANSACTIONAL, false);
+    }
+
+    /**
+     * Checks that inline size parameter is correctly handled during index creation.
+     *
+     * @param mode Mode.
+     * @param atomicityMode Atomicity mode.
+     * @param near Near flag.
+     * @throws Exception If failed.
+     */
+    private void checkCreateIndexWithInlineSize(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near)
+        throws Exception {
+
+        initialize(mode, atomicityMode, near);
+
+        String prevFallbackPropVal = System.getProperty(IgniteSystemProperties.IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK);
+
+        try {
+            System.setProperty(IgniteSystemProperties.IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, "true");
+
+            checkNoIndexIsCreatedForInlineSize(-2, IgniteQueryErrorCode.PARSING);
+            checkNoIndexIsCreatedForInlineSize(Integer.MIN_VALUE, IgniteQueryErrorCode.PARSING);
+
+            checkIndexCreatedForInlineSize(0);
+            loadInitialData();
+            checkIndexCreatedForInlineSize(1);
+            loadInitialData();
+            checkIndexCreatedForInlineSize(Integer.MAX_VALUE);
+        }
+        finally {
+            if (prevFallbackPropVal != null)
+                System.setProperty(IgniteSystemProperties.IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK, prevFallbackPropVal);
+            else
+                System.clearProperty(IgniteSystemProperties.IGNITE_SQL_PARSER_DISABLE_H2_FALLBACK);
+        }
+    }
+
+    /**
+     * Verifies that index is created with the specified inline size.
+     *
+     * @param inlineSize Inline size to put into CREATE INDEX
+     * @throws Exception If failed.
+     */
+    private void checkIndexCreatedForInlineSize(int inlineSize) throws Exception {
+        QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
+        idx.setInlineSize(inlineSize);
+
+        dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false);
+
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, inlineSize, field(FIELD_NAME_1_ESCAPED));
+        assertSimpleIndexOperations(SQL_SIMPLE_FIELD_1);
+        assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
+
+        dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false);
+
+        assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
+    }
+
+    /**
+     * Verifies that no index is created and an exception is thrown.
+     *
+     * @param inlineSize Inline size value in the CREATE INDEX statement.
+     * @param igniteQryErrorCode Expected error code in the thrown exception.
+     * @throws Exception If failed for any other reason than the expected exception.
+     */
+    private void checkNoIndexIsCreatedForInlineSize(final int inlineSize, int igniteQryErrorCode) throws Exception {
+        assertSchemaException(new RunnableX() {
+            @Override public void run() throws Exception {
+                QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
+                idx.setInlineSize(inlineSize);
+                dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false);
+            }
+        }, igniteQryErrorCode);
+
+        assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
+    }
+
+    /**
      * Test simple index drop for PARTITIONED ATOMIC cache.
      *
      * @throws Exception If failed.
@@ -681,7 +812,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         QueryIndex idx1 = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
 
         dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx1, false);
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
 
         assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
 
@@ -691,7 +822,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         QueryIndex idx2 = index(IDX_NAME_2, field(alias(FIELD_NAME_2_ESCAPED)));
 
         dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx2, false);
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(alias(FIELD_NAME_2_ESCAPED)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE, field(alias(FIELD_NAME_2_ESCAPED)));
 
         // Load some data.
         loadInitialData();
@@ -705,7 +836,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         assertIndexNotUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
 
         // Make sure the second index is still there.
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(alias(FIELD_NAME_2_ESCAPED)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE, field(alias(FIELD_NAME_2_ESCAPED)));
     }
 
     /**
@@ -906,7 +1037,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
         final QueryIndex idx = index(IDX_NAME_2, field(FIELD_NAME_1));
 
         dynamicIndexCreate(STATIC_CACHE_NAME, TBL_NAME, idx, true);
-        assertIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
+        assertIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
 
         dynamicIndexDrop(STATIC_CACHE_NAME, IDX_NAME_1, true);
         assertNoIndex(STATIC_CACHE_NAME, TBL_NAME, IDX_NAME_1);

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java
index 3190b5e..610688a 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractConcurrentSelfTest.java
@@ -170,7 +170,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
 
         idxFut1.get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
         assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
         assertSqlSimpleData(SQL_SIMPLE_FIELD_1, KEY_AFTER - SQL_ARG_1);
 
@@ -191,7 +191,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
 
         idxFut2.get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(aliasUnescaped(FIELD_NAME_2)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE, field(aliasUnescaped(FIELD_NAME_2)));
         assertIndexUsed(IDX_NAME_2, SQL_SIMPLE_FIELD_2, SQL_ARG_1);
         assertSqlSimpleData(SQL_SIMPLE_FIELD_2, KEY_AFTER - SQL_ARG_1);
     }
@@ -234,8 +234,8 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         idxFut1.get();
         idxFut2.get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(aliasUnescaped(FIELD_NAME_2)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE, field(aliasUnescaped(FIELD_NAME_2)));
 
         idxLatch.countDown();
 
@@ -277,7 +277,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
 
         idxLatch.countDown();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
 
         put(srv1, 0, KEY_AFTER);
 
@@ -341,7 +341,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         updateFut.get();
 
         // Make sure index is there.
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
         assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
 
         // Get expected values.
@@ -423,7 +423,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         // Validate index state.
         idxFut.get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
 
         assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
         assertSqlSimpleData(SQL_SIMPLE_FIELD_1, LARGE_CACHE_SIZE - SQL_ARG_1);
@@ -539,7 +539,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         queryProcessor(cli).dynamicIndexDrop(CACHE_NAME, CACHE_NAME, IDX_NAME_1, true).get();
         queryProcessor(cli).dynamicIndexCreate(CACHE_NAME, CACHE_NAME, TBL_NAME, idx, true).get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
 
         put(cli, 0, KEY_AFTER);
 
@@ -670,7 +670,8 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
             }
         });
 
-        assertIndex(cli, true, CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(cli, true, CACHE_NAME, TBL_NAME, IDX_NAME_1,
+            QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
         assertIndexUsed(IDX_NAME_1, SQL_SIMPLE_FIELD_1, SQL_ARG_1);
 
         // Check index drop.
@@ -689,7 +690,8 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
 
         queryProcessor(srv).dynamicIndexCreate(CACHE_NAME, CACHE_NAME, TBL_NAME, idx, false).get();
 
-        assertIndex(cli, true, CACHE_NAME, TBL_NAME, IDX_NAME_2, field(aliasUnescaped(FIELD_NAME_2)));
+        assertIndex(cli, true, CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE,
+            field(aliasUnescaped(FIELD_NAME_2)));
         assertIndexUsed(IDX_NAME_2, SQL_SIMPLE_FIELD_2, SQL_ARG_2);
 
         reconnectClientNode(srv, cli, restartCache, new RunnableX() {
@@ -703,7 +705,8 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
             }
         });
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, field(FIELD_NAME_1), field(aliasUnescaped(FIELD_NAME_2)));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_2, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1),
+            field(aliasUnescaped(FIELD_NAME_2)));
         assertIndexUsed(IDX_NAME_2, SQL_COMPOSITE, SQL_ARG_1, SQL_ARG_2);
     }
 
@@ -861,7 +864,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         queryProcessor(cli).dynamicIndexDrop(CACHE_NAME, CACHE_NAME, IDX_NAME_1, true).get();
         queryProcessor(cli).dynamicIndexCreate(CACHE_NAME, CACHE_NAME, TBL_NAME, idx, true).get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
 
         put(cli, 0, KEY_AFTER);
 
@@ -962,7 +965,7 @@ public abstract class DynamicIndexAbstractConcurrentSelfTest extends DynamicInde
         queryProcessor(cli).dynamicIndexDrop(CACHE_NAME, CACHE_NAME, IDX_NAME_1, true).get();
         queryProcessor(cli).dynamicIndexCreate(CACHE_NAME, CACHE_NAME, TBL_NAME, idx, true).get();
 
-        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, field(FIELD_NAME_1));
+        assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1));
 
         put(cli, 0, KEY_AFTER);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SchemaExchangeSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SchemaExchangeSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SchemaExchangeSelfTest.java
index 0524c75..1d0e973 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SchemaExchangeSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/SchemaExchangeSelfTest.java
@@ -480,7 +480,7 @@ public class SchemaExchangeSelfTest extends AbstractSchemaSelfTest {
 
         assertIndex(CACHE_NAME,
             QueryUtils.normalizeObjectName(TBL_NAME, true),
-            QueryUtils.normalizeObjectName(IDX_NAME_1, false),
+            QueryUtils.normalizeObjectName(IDX_NAME_1, false), QueryIndex.DFLT_INLINE_SIZE,
             field(QueryUtils.normalizeObjectName(FIELD_NAME_1_ESCAPED, false)));
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8ee6cb5c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
index a1fe04b..dc72c31 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
@@ -508,28 +508,34 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
      */
     public void testParseCreateIndex() throws Exception {
         assertCreateIndexEquals(
-            buildCreateIndex(null, "Person", "sch1", false, QueryIndexType.SORTED, "name", true),
+            buildCreateIndex(null, "Person", "sch1", false, QueryIndexType.SORTED,
+            QueryIndex.DFLT_INLINE_SIZE,"name", true),
             "create index on Person (name)");
 
         assertCreateIndexEquals(
-            buildCreateIndex("idx", "Person", "sch1", false, QueryIndexType.SORTED, "name", true),
+            buildCreateIndex("idx", "Person", "sch1", false, QueryIndexType.SORTED,
+            QueryIndex.DFLT_INLINE_SIZE, "name", true),
             "create index idx on Person (name ASC)");
 
         assertCreateIndexEquals(
-            buildCreateIndex("idx", "Person", "sch1", false, QueryIndexType.GEOSPATIAL, "name", true),
+            buildCreateIndex("idx", "Person", "sch1", false, QueryIndexType.GEOSPATIAL,
+            QueryIndex.DFLT_INLINE_SIZE, "name", true),
             "create spatial index sch1.idx on sch1.Person (name ASC)");
 
         assertCreateIndexEquals(
-            buildCreateIndex("idx", "Person", "sch1", true, QueryIndexType.SORTED, "name", true),
+            buildCreateIndex("idx", "Person", "sch1", true, QueryIndexType.SORTED,
+            QueryIndex.DFLT_INLINE_SIZE, "name", true),
             "create index if not exists sch1.idx on sch1.Person (name)");
 
         // When we specify schema for the table and don't specify it for the index, resulting schema is table's
         assertCreateIndexEquals(
-            buildCreateIndex("idx", "Person", "sch1", true, QueryIndexType.SORTED, "name", false),
+            buildCreateIndex("idx", "Person", "sch1", true, QueryIndexType.SORTED,
+            QueryIndex.DFLT_INLINE_SIZE,"name", false),
             "create index if not exists idx on sch1.Person (name dEsC)");
 
         assertCreateIndexEquals(
-            buildCreateIndex("idx", "Person", "sch1", true, QueryIndexType.GEOSPATIAL, "old", true, "name", false),
+            buildCreateIndex("idx", "Person", "sch1", true, QueryIndexType.GEOSPATIAL,
+            QueryIndex.DFLT_INLINE_SIZE, "old", true, "name", false),
             "create spatial index if not exists idx on Person (old, name desc)");
 
         // Schemas for index and table must match
@@ -955,7 +961,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
      *
      */
     private static GridSqlCreateIndex buildCreateIndex(String name, String tblName, String schemaName,
-        boolean ifNotExists, QueryIndexType type, Object... flds) {
+        boolean ifNotExists, QueryIndexType type, int inlineSize, Object... flds) {
         QueryIndex idx = new QueryIndex();
 
         idx.setName(name);
@@ -969,6 +975,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
 
         idx.setFields(trueFlds);
         idx.setIndexType(type);
+        idx.setInlineSize(inlineSize);
 
         GridSqlCreateIndex res = new GridSqlCreateIndex();
 


[36/47] ignite git commit: IGNITE-6270: SQL: added "AFFINITY_KEY" and "CACHE_GROUP" parameters to "CREATE TABLE" command as more convenient synonyms to existing "AFFINITYKEY" and "CACHEGROUP". This closes #2831.

Posted by sb...@apache.org.
IGNITE-6270: SQL: added "AFFINITY_KEY" and "CACHE_GROUP" parameters to "CREATE TABLE" command as more convenient synonyms to existing "AFFINITYKEY" and "CACHEGROUP". This closes #2831.


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

Branch: refs/heads/ignite-zk
Commit: 4f77ef29ecb8a47e512f921115f37844cc27d4d4
Parents: 8ee6cb5
Author: Alexander Paschenko <al...@gmail.com>
Authored: Fri Nov 17 17:09:01 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Nov 17 17:09:01 2017 +0300

----------------------------------------------------------------------
 .../examples/datagrid/CacheQueryDdlExample.java |  2 +-
 .../ignite/examples/datagrid/JdbcExample.java   |  2 +-
 .../thin/JdbcThinComplexDmlDdlSelfTest.java     |  5 +-
 .../query/h2/sql/GridSqlQueryParser.java        | 12 ++++-
 .../index/H2DynamicIndexingComplexTest.java     |  4 +-
 .../cache/index/H2DynamicTableSelfTest.java     | 49 +++++++++++++++-----
 6 files changed, 53 insertions(+), 21 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4f77ef29/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryDdlExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryDdlExample.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryDdlExample.java
index e27907d..7ac2751 100644
--- a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryDdlExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryDdlExample.java
@@ -62,7 +62,7 @@ public class CacheQueryDdlExample {
                 // Create table based on PARTITIONED template with one backup.
                 cache.query(new SqlFieldsQuery(
                     "CREATE TABLE person (id LONG, name VARCHAR, city_id LONG, PRIMARY KEY (id, city_id)) " +
-                    "WITH \"backups=1, affinityKey=city_id\"")).getAll();
+                    "WITH \"backups=1, affinity_key=city_id\"")).getAll();
 
                 // Create an index.
                 cache.query(new SqlFieldsQuery("CREATE INDEX on Person (city_id)")).getAll();

http://git-wip-us.apache.org/repos/asf/ignite/blob/4f77ef29/examples/src/main/java/org/apache/ignite/examples/datagrid/JdbcExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/JdbcExample.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/JdbcExample.java
index bc96e42..7a02a7e 100644
--- a/examples/src/main/java/org/apache/ignite/examples/datagrid/JdbcExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/datagrid/JdbcExample.java
@@ -51,7 +51,7 @@ public class JdbcExample {
 
                 // Create table based on PARTITIONED template with one backup.
                 stmt.executeUpdate("CREATE TABLE person (id LONG, name VARCHAR, city_id LONG, " +
-                    "PRIMARY KEY (id, city_id)) WITH \"backups=1, affinityKey=city_id\"");
+                    "PRIMARY KEY (id, city_id)) WITH \"backups=1, affinity_key=city_id\"");
 
                 // Create an index.
                 stmt.executeUpdate("CREATE INDEX on Person (city_id)");

http://git-wip-us.apache.org/repos/asf/ignite/blob/4f77ef29/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java
index d4e03bc..cdc9130 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinComplexDmlDdlSelfTest.java
@@ -32,7 +32,6 @@ import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
 import org.apache.ignite.lang.IgniteCallable;
 import org.apache.ignite.lang.IgnitePredicate;
@@ -151,12 +150,12 @@ public class JdbcThinComplexDmlDdlSelfTest extends GridCommonAbstractTest {
         sql(new UpdateChecker(0),
             "CREATE TABLE person (id int, name varchar, age int, company varchar, city varchar, " +
                 "primary key (id, name, city)) WITH \"template=" + cacheMode.name() + ",atomicity=" + atomicityMode.name()
-                + ",affinitykey=city\"");
+                + ",affinity_key=city\"");
 
         sql(new UpdateChecker(0), "CREATE INDEX idx on person (city asc, name asc)");
 
         sql(new UpdateChecker(0), "CREATE TABLE city (name varchar, population int, primary key (name)) WITH " +
-            "\"template=" + cacheMode.name() + ",atomicity=" + atomicityMode.name() + ",affinitykey=name\"");
+            "\"template=" + cacheMode.name() + ",atomicity=" + atomicityMode.name() + ",affinity_key=name\"");
 
         sql(new UpdateChecker(3),
             "INSERT INTO city (name, population) values(?, ?), (?, ?), (?, ?)",

http://git-wip-us.apache.org/repos/asf/ignite/blob/4f77ef29/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index 46b2aee..8ffc5fa 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -457,10 +457,16 @@ public class GridSqlQueryParser {
     private static final String PARAM_ATOMICITY = "ATOMICITY";
 
     /** */
-    private static final String PARAM_CACHE_GROUP = "CACHEGROUP";
+    private static final String PARAM_CACHE_GROUP_OLD = "CACHEGROUP";
 
     /** */
-    private static final String PARAM_AFFINITY_KEY = "AFFINITYKEY";
+    private static final String PARAM_AFFINITY_KEY_OLD = "AFFINITYKEY";
+
+    /** */
+    private static final String PARAM_CACHE_GROUP = "CACHE_GROUP";
+
+    /** */
+    private static final String PARAM_AFFINITY_KEY = "AFFINITY_KEY";
 
     /** */
     private static final String PARAM_WRITE_SYNC = "WRITE_SYNCHRONIZATION_MODE";
@@ -1317,6 +1323,7 @@ public class GridSqlQueryParser {
 
                 break;
 
+            case PARAM_CACHE_GROUP_OLD:
             case PARAM_CACHE_GROUP:
                 ensureNotEmpty(name, val);
 
@@ -1324,6 +1331,7 @@ public class GridSqlQueryParser {
 
                 break;
 
+            case PARAM_AFFINITY_KEY_OLD:
             case PARAM_AFFINITY_KEY:
                 ensureNotEmpty(name, val);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/4f77ef29/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
index 0be691e..f9d3408 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
@@ -94,12 +94,12 @@ public abstract class H2DynamicIndexingComplexTest extends DynamicIndexAbstractS
     public void testOperations() {
         executeSql("CREATE TABLE person (id int, name varchar, age int, company varchar, city varchar, " +
             "primary key (id, name, city)) WITH \"template=" + cacheMode.name() + ",atomicity=" + atomicityMode.name() +
-            ",affinitykey=city\"");
+            ",affinity_key=city\"");
 
         executeSql("CREATE INDEX idx on person (city asc, name asc)");
 
         executeSql("CREATE TABLE city (name varchar, population int, primary key (name)) WITH " +
-            "\"template=" + cacheMode.name() + ",atomicity=" + atomicityMode.name() + ",affinitykey=name\"");
+            "\"template=" + cacheMode.name() + ",atomicity=" + atomicityMode.name() + ",affinity_key=name\"");
 
         executeSql("INSERT INTO city (name, population) values(?, ?), (?, ?), (?, ?)",
             "St. Petersburg", 6000000,

http://git-wip-us.apache.org/repos/asf/ignite/blob/4f77ef29/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index ef59a62..71b0b5f 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -141,6 +141,14 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     }
 
     /**
+     * Test that {@code CREATE TABLE} actually creates new cache, H2 table and type descriptor on all nodes.
+     * @throws Exception if failed.
+     */
+    public void testCreateTableWithCacheGroupAndLegacyParamName() throws Exception {
+        doTestCreateTable(CACHE_NAME, "MyGroup", null, null, true);
+    }
+
+    /**
      * Test that {@code CREATE TABLE} actually creates new cache from template,
      * H2 table and type descriptor on all nodes.
      * @throws Exception if failed.
@@ -484,10 +492,27 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      */
     private void doTestCreateTable(String tplCacheName, String cacheGrp, CacheMode cacheMode,
         CacheWriteSynchronizationMode writeSyncMode, String... additionalParams) {
+        doTestCreateTable(tplCacheName, cacheGrp, cacheMode, writeSyncMode, false, additionalParams);
+    }
+
+    /**
+     * Test that {@code CREATE TABLE} with given template cache name actually creates new cache,
+     * H2 table and type descriptor on all nodes, optionally with cache type check.
+     * @param tplCacheName Template cache name.
+     * @param cacheGrp Cache group name, or {@code null} if no group is set.
+     * @param cacheMode Expected cache mode, or {@code null} if no check is needed.
+     * @param writeSyncMode Expected write sync mode, or {@code null} if no check is needed.
+     * @param useLegacyCacheGrpParamName Whether legacy (harder-to-read) cache group param name should be used.
+     * @param additionalParams Supplemental parameters to append to {@code CREATE TABLE} SQL.
+     */
+    private void doTestCreateTable(String tplCacheName, String cacheGrp, CacheMode cacheMode,
+        CacheWriteSynchronizationMode writeSyncMode, boolean useLegacyCacheGrpParamName, String... additionalParams) {
+        String cacheGrpParamName = useLegacyCacheGrpParamName ? "cacheGroup" : "cache_group";
+
         String sql = "CREATE TABLE \"Person\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
             (F.isEmpty(tplCacheName) ? "" : "\"template=" + tplCacheName + "\",") + "\"backups=10,atomicity=atomic\"" +
-            (F.isEmpty(cacheGrp) ? "" : ",\"cacheGroup=" + cacheGrp + '"');
+            (F.isEmpty(cacheGrp) ? "" : ",\"" + cacheGrpParamName + '=' + cacheGrp + '"');
 
         for (String p : additionalParams)
             sql += ",\"" + p + "\"";
@@ -582,7 +607,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      * Test that attempting to omit mandatory value of CACHEGROUP parameter yields an error.
      */
     public void testEmptyCacheGroup() {
-        assertCreateTableWithParamsThrows("cachegroup=", "Parameter value cannot be empty: CACHEGROUP");
+        assertCreateTableWithParamsThrows("cache_group=", "Parameter value cannot be empty: CACHE_GROUP");
     }
 
     /**
@@ -817,7 +842,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
      */
     public void testAffinityKey() throws Exception {
         execute("CREATE TABLE \"City\" (\"name\" varchar primary key, \"code\" int) WITH wrap_key,wrap_value," +
-            "\"affinityKey='name'\"");
+            "\"affinity_key='name'\"");
 
         assertAffinityCacheConfiguration("City", "name");
 
@@ -830,7 +855,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         // We need unique name for this table to avoid conflicts with existing binary metadata.
         execute("CREATE TABLE \"Person2\" (\"id\" int, \"city\" varchar," +
             " \"name\" varchar, \"surname\" varchar, \"age\" int, PRIMARY KEY (\"id\", \"city\")) WITH " +
-            "wrap_key,wrap_value,\"template=cache,affinityKey='city'\"");
+            "wrap_key,wrap_value,\"template=cache,affinity_key='city'\"");
 
         assertAffinityCacheConfiguration("Person2", "city");
 
@@ -903,22 +928,22 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
     @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
     public void testAffinityKeyCaseSensitivity() {
         execute("CREATE TABLE \"A\" (\"name\" varchar primary key, \"code\" int) WITH wrap_key,wrap_value," +
-            "\"affinityKey='name'\"");
+            "\"affinity_key='name'\"");
 
         assertAffinityCacheConfiguration("A", "name");
 
         execute("CREATE TABLE \"B\" (name varchar primary key, \"code\" int) WITH wrap_key,wrap_value," +
-            "\"affinityKey=name\"");
+            "\"affinity_key=name\"");
 
         assertAffinityCacheConfiguration("B", "NAME");
 
         execute("CREATE TABLE \"C\" (name varchar primary key, \"code\" int) WITH wrap_key,wrap_value," +
-            "\"affinityKey=NamE\"");
+            "\"affinity_key=NamE\"");
 
         assertAffinityCacheConfiguration("C", "NAME");
 
         execute("CREATE TABLE \"D\" (\"name\" varchar primary key, \"code\" int) WITH wrap_key,wrap_value," +
-            "\"affinityKey=NAME\"");
+            "\"affinity_key=NAME\"");
 
         assertAffinityCacheConfiguration("D", "name");
 
@@ -926,7 +951,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 execute("CREATE TABLE \"E\" (name varchar primary key, \"code\" int) WITH wrap_key,wrap_value," +
-                    "\"affinityKey='Name'\"");
+                    "\"affinity_key='Name'\"");
 
                 return null;
             }
@@ -937,7 +962,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
                 execute("CREATE TABLE \"E\" (\"name\" varchar, \"Name\" int, val int, primary key(\"name\", " +
-                    "\"Name\")) WITH \"affinityKey=name\"");
+                    "\"Name\")) WITH \"affinity_key=name\"");
 
                 return null;
             }
@@ -967,7 +992,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         // Error arises because user has specified case sensitive affinity column name
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
-                execute("CREATE TABLE \"E\" (name varchar primary key, \"code\" int) WITH \"affinityKey=code\"");
+                execute("CREATE TABLE \"E\" (name varchar primary key, \"code\" int) WITH \"affinity_key=code\"");
 
                 return null;
             }
@@ -982,7 +1007,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
         // Error arises because user has specified case sensitive affinity column name
         GridTestUtils.assertThrows(null, new Callable<Object>() {
             @Override public Object call() throws Exception {
-                execute("CREATE TABLE \"E\" (name varchar primary key, \"code\" int) WITH \"affinityKey=missing\"");
+                execute("CREATE TABLE \"E\" (name varchar primary key, \"code\" int) WITH \"affinity_key=missing\"");
 
                 return null;
             }


[33/47] ignite git commit: Merge remote-tracking branch 'origin/master'

Posted by sb...@apache.org.
Merge remote-tracking branch 'origin/master'


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

Branch: refs/heads/ignite-zk
Commit: 19bddc6933d4ec94b1efe41733de91ec2396a5ca
Parents: 64ffa3d b0a8601
Author: devozerov <vo...@gridgain.com>
Authored: Fri Nov 17 16:09:29 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Nov 17 16:09:29 2017 +0300

----------------------------------------------------------------------
 .../clustering/KMeansDistributedClusterer.java  |  13 +-
 .../ignite/ml/math/distributed/CacheUtils.java  | 278 +++---
 .../math/distributed/keys/BlockMatrixKey.java   |  38 -
 .../distributed/keys/DataStructureCacheKey.java |  35 +
 .../math/distributed/keys/MatrixBlockKey.java   |  38 +
 .../math/distributed/keys/MatrixCacheKey.java   |  35 -
 .../math/distributed/keys/RowColMatrixKey.java  |   2 +-
 .../math/distributed/keys/VectorBlockKey.java   |  34 +
 .../distributed/keys/impl/BlockMatrixKey.java   | 164 ----
 .../distributed/keys/impl/MatrixBlockKey.java   | 162 ++++
 .../distributed/keys/impl/SparseMatrixKey.java  |  14 +-
 .../distributed/keys/impl/VectorBlockKey.java   | 151 +++
 .../ignite/ml/math/functions/Functions.java     |   3 +-
 .../ml/math/impls/matrix/AbstractMatrix.java    |  24 +-
 .../ignite/ml/math/impls/matrix/BlockEntry.java |  50 -
 .../ml/math/impls/matrix/MatrixBlockEntry.java  |  50 +
 .../matrix/SparseBlockDistributedMatrix.java    | 153 ++-
 .../impls/matrix/SparseDistributedMatrix.java   | 102 +-
 .../storage/matrix/BlockMatrixStorage.java      |  96 +-
 .../storage/matrix/BlockVectorStorage.java      | 374 ++++++++
 .../impls/storage/matrix/MapWrapperStorage.java |   5 +-
 .../matrix/SparseDistributedMatrixStorage.java  |  21 +-
 .../vector/SparseDistributedVectorStorage.java  | 280 ++++++
 .../vector/SparseBlockDistributedVector.java    | 139 +++
 .../impls/vector/SparseDistributedVector.java   | 157 ++++
 .../ml/math/impls/vector/VectorBlockEntry.java  |  49 +
 .../apache/ignite/ml/math/util/MatrixUtil.java  |   4 +-
 .../ml/math/MathImplDistributedTestSuite.java   |  16 +-
 .../SparseDistributedBlockMatrixTest.java       |  86 +-
 .../matrix/SparseDistributedMatrixTest.java     |  27 +-
 .../SparseDistributedVectorStorageTest.java     | 121 +++
 .../SparseBlockDistributedVectorTest.java       | 181 ++++
 .../vector/SparseDistributedVectorTest.java     | 192 ++++
 ...tedBlockOLSMultipleLinearRegressionTest.java | 926 ++++++++++++++++++
 ...tributedOLSMultipleLinearRegressionTest.java | 934 +++++++++++++++++++
 .../OLSMultipleLinearRegressionTest.java        |   1 +
 .../ml/regressions/RegressionsTestSuite.java    |   2 +-
 37 files changed, 4351 insertions(+), 606 deletions(-)
----------------------------------------------------------------------



[21/47] ignite git commit: IGNITE-6336 .NET: Thin client: Create cache

Posted by sb...@apache.org.
IGNITE-6336 .NET: Thin client: Create cache

This closes #2935


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

Branch: refs/heads/ignite-zk
Commit: 52b46c35fb4bf4f2b96bdc10673563843502fcbe
Parents: af6b933
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Thu Nov 16 11:22:46 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Thu Nov 16 11:22:46 2017 +0300

----------------------------------------------------------------------
 .../configuration/CacheConfiguration.java       |   5 +-
 .../platform/client/ClientMessageParser.java    |  49 +++
 .../platform/client/ClientStatus.java           |   3 +
 .../ClientCacheConfigurationSerializer.java     | 180 ++++++++
 ...ientCacheCreateWithConfigurationRequest.java |  58 +++
 .../cache/ClientCacheCreateWithNameRequest.java |  56 +++
 .../client/cache/ClientCacheDestroyRequest.java |  49 +++
 .../ClientCacheGetConfigurationRequest.java     |  47 +++
 .../ClientCacheGetConfigurationResponse.java    |  51 +++
 .../cache/ClientCacheGetNamesRequest.java       |  46 ++
 .../cache/ClientCacheGetNamesResponse.java      |  56 +++
 ...acheGetOrCreateWithConfigurationRequest.java |  58 +++
 .../ClientCacheGetOrCreateWithNameRequest.java  |  49 +++
 .../utils/PlatformConfigurationUtils.java       |  24 +-
 .../Apache.Ignite.Core.Tests.csproj             |   2 +
 .../Cache/CacheConfigurationTest.cs             |   2 +-
 .../Cache/ClientCacheConfigurationTest.cs       | 211 ++++++++++
 .../Client/Cache/CreateCacheTest.cs             | 209 +++++++++
 .../Client/ClientTestBase.cs                    |   7 +
 .../IgniteConfigurationTest.cs                  |   2 +
 .../Apache.Ignite.Core.csproj                   |   2 +
 .../Cache/Configuration/QueryEntity.cs          |  10 +-
 .../Client/Cache/CacheClientConfiguration.cs    | 420 +++++++++++++++++++
 .../Client/Cache/ICacheClient.cs                |   5 +
 .../Apache.Ignite.Core/Client/IIgniteClient.cs  |  50 +++
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |   1 -
 .../Impl/Binary/BinaryReaderExtensions.cs       |  18 +
 .../Impl/Client/Cache/CacheClient.cs            |   6 +
 .../Cache/ClientCacheConfigurationSerializer.cs | 261 ++++++++++++
 .../Apache.Ignite.Core/Impl/Client/ClientOp.cs  |   9 +-
 .../Impl/Client/ClientStatus.cs                 |   1 +
 .../Impl/Client/IgniteClient.cs                 |  85 ++++
 .../examples/Apache.Ignite.Examples/App.config  |   4 -
 .../ThinClient/ThinClientPutGetExample.cs       |   5 +-
 .../ThinClient/ThinClientQueryExample.cs        |   4 +-
 35 files changed, 2010 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index aeb1b2f..7d2730c 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -1711,8 +1711,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
      * @return {@code this} for chaining.
      */
     public CacheConfiguration<K, V> setSqlSchema(String sqlSchema) {
-        A.ensure((sqlSchema != null), "Schema could not be null.");
-        A.ensure(!sqlSchema.isEmpty(), "Schema could not be empty.");
+        if (sqlSchema != null) {
+            A.ensure(!sqlSchema.isEmpty(), "Schema could not be empty.");
+        }
 
         this.sqlSchema = sqlSchema;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
index f0f0f4c..4ad6a90 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
@@ -37,11 +37,18 @@ import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheCl
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheClearRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheContainsKeyRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheContainsKeysRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheCreateWithConfigurationRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheCreateWithNameRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheDestroyRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAllRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndPutIfAbsentRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndPutRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndRemoveRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetAndReplaceRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetConfigurationRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetNamesRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetOrCreateWithConfigurationRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetOrCreateWithNameRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGetSizeRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCachePutAllRequest;
@@ -144,6 +151,27 @@ public class ClientMessageParser implements ClientListenerMessageParser {
     /** */
     private static final short OP_CACHE_REMOVE_ALL = 28;
 
+    /** */
+    private static final short OP_CACHE_CREATE_WITH_NAME = 29;
+
+    /** */
+    private static final short OP_CACHE_GET_OR_CREATE_WITH_NAME = 30;
+
+    /** */
+    private static final short OP_CACHE_DESTROY = 31;
+
+    /** */
+    private static final short OP_CACHE_GET_NAMES = 32;
+
+    /** */
+    private static final short OP_CACHE_GET_CONFIGURATION = 33;
+
+    /** */
+    private static final short OP_CACHE_CREATE_WITH_CONFIGURATION = 34;
+
+    /** */
+    private static final short OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION = 35;
+
     /** Marshaller. */
     private final GridBinaryMarshaller marsh;
 
@@ -262,6 +290,27 @@ public class ClientMessageParser implements ClientListenerMessageParser {
 
             case OP_CACHE_REMOVE_ALL:
                 return new ClientCacheRemoveAllRequest(reader);
+
+            case OP_CACHE_CREATE_WITH_NAME:
+                return new ClientCacheCreateWithNameRequest(reader);
+
+            case OP_CACHE_GET_OR_CREATE_WITH_NAME:
+                return new ClientCacheGetOrCreateWithNameRequest(reader);
+
+            case OP_CACHE_DESTROY:
+                return new ClientCacheDestroyRequest(reader);
+
+            case OP_CACHE_GET_NAMES:
+                return new ClientCacheGetNamesRequest(reader);
+
+            case OP_CACHE_GET_CONFIGURATION:
+                return new ClientCacheGetConfigurationRequest(reader);
+
+            case OP_CACHE_CREATE_WITH_CONFIGURATION:
+                return new ClientCacheCreateWithConfigurationRequest(reader);
+
+            case OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION:
+                return new ClientCacheGetOrCreateWithConfigurationRequest(reader);
         }
 
         return new ClientRawRequest(reader.readLong(), ClientStatus.INVALID_OP_CODE,

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
index 0f374ff..4f55072 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientStatus.java
@@ -40,6 +40,9 @@ public final class ClientStatus {
     /** Cache does not exist. */
     public static final int CACHE_DOES_NOT_EXIST = 1000;
 
+    /** Cache already exists. */
+    public static final int CACHE_EXISTS = 1001;
+
     /** Too many cursors. */
     public static final int TOO_MANY_CURSORS = 1010;
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
new file mode 100644
index 0000000..0f28b81
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheConfigurationSerializer.java
@@ -0,0 +1,180 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.binary.BinaryRawWriter;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheKeyConfiguration;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CacheRebalanceMode;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.cache.PartitionLossPolicy;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import static org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.readQueryEntity;
+import static org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.writeEnumInt;
+import static org.apache.ignite.internal.processors.platform.utils.PlatformConfigurationUtils.writeQueryEntity;
+
+/**
+ * Cache configuration serializer.
+ */
+public class ClientCacheConfigurationSerializer {
+    /**
+     * Writes the cache configuration.
+     * @param writer Writer.
+     * @param cfg Configuration.
+     */
+    static void write(BinaryRawWriterEx writer, CacheConfiguration cfg) {
+        assert writer != null;
+        assert cfg != null;
+
+        // Reserve for length.
+        int pos = writer.reserveInt();
+
+        writeEnumInt(writer, cfg.getAtomicityMode(), CacheConfiguration.DFLT_CACHE_ATOMICITY_MODE);
+        writer.writeInt(cfg.getBackups());
+        writeEnumInt(writer, cfg.getCacheMode(), CacheConfiguration.DFLT_CACHE_MODE);
+        writer.writeBoolean(cfg.isCopyOnRead());
+        writer.writeString(cfg.getDataRegionName());
+        writer.writeBoolean(cfg.isEagerTtl());
+        writer.writeBoolean(cfg.isStatisticsEnabled());
+        writer.writeString(cfg.getGroupName());
+        writer.writeBoolean(cfg.isInvalidate());
+        writer.writeLong(cfg.getDefaultLockTimeout());
+        writer.writeInt(cfg.getMaxConcurrentAsyncOperations());
+        writer.writeInt(cfg.getMaxQueryIteratorsCount());
+        writer.writeString(cfg.getName());
+        writer.writeBoolean(cfg.isOnheapCacheEnabled());
+        writer.writeInt(cfg.getPartitionLossPolicy().ordinal());
+        writer.writeInt(cfg.getQueryDetailMetricsSize());
+        writer.writeInt(cfg.getQueryParallelism());
+        writer.writeBoolean(cfg.isReadFromBackup());
+        writer.writeInt(cfg.getRebalanceBatchSize());
+        writer.writeLong(cfg.getRebalanceBatchesPrefetchCount());
+        writer.writeLong(cfg.getRebalanceDelay());
+        writeEnumInt(writer, cfg.getRebalanceMode(), CacheConfiguration.DFLT_REBALANCE_MODE);
+        writer.writeInt(cfg.getRebalanceOrder());
+        writer.writeLong(cfg.getRebalanceThrottle());
+        writer.writeLong(cfg.getRebalanceTimeout());
+        writer.writeBoolean(cfg.isSqlEscapeAll());
+        writer.writeInt(cfg.getSqlIndexMaxInlineSize());
+        writer.writeString(cfg.getSqlSchema());
+        writeEnumInt(writer, cfg.getWriteSynchronizationMode());
+
+        CacheKeyConfiguration[] keys = cfg.getKeyConfiguration();
+
+        if (keys != null) {
+            writer.writeInt(keys.length);
+
+            for (CacheKeyConfiguration key : keys) {
+                writer.writeString(key.getTypeName());
+                writer.writeString(key.getAffinityKeyFieldName());
+            }
+        } else {
+            writer.writeInt(0);
+        }
+
+        //noinspection unchecked
+        Collection<QueryEntity> qryEntities = cfg.getQueryEntities();
+
+        if (qryEntities != null) {
+            writer.writeInt(qryEntities.size());
+
+            for (QueryEntity e : qryEntities)
+                writeQueryEntity(writer, e);
+        } else
+            writer.writeInt(0);
+
+        // Write length (so that part of the config can be skipped).
+        writer.writeInt(pos, writer.out().position() - pos - 4);
+    }
+
+    /**
+     * Reads the cache configuration.
+     *
+     * @param reader Reader.
+     * @return Configuration.
+     */
+    static CacheConfiguration read(BinaryRawReader reader) {
+        reader.readInt();  // Skip length.
+
+        CacheConfiguration cfg = new CacheConfiguration()
+                .setAtomicityMode(CacheAtomicityMode.fromOrdinal(reader.readInt()))
+                .setBackups(reader.readInt())
+                .setCacheMode(CacheMode.fromOrdinal(reader.readInt()))
+                .setCopyOnRead(reader.readBoolean())
+                .setDataRegionName(reader.readString())
+                .setEagerTtl(reader.readBoolean())
+                .setStatisticsEnabled(reader.readBoolean())
+                .setGroupName(reader.readString())
+                .setInvalidate(reader.readBoolean())
+                .setDefaultLockTimeout(reader.readLong())
+                .setMaxConcurrentAsyncOperations(reader.readInt())
+                .setMaxQueryIteratorsCount(reader.readInt())
+                .setName(reader.readString())
+                .setOnheapCacheEnabled(reader.readBoolean())
+                .setPartitionLossPolicy(PartitionLossPolicy.fromOrdinal((byte)reader.readInt()))
+                .setQueryDetailMetricsSize(reader.readInt())
+                .setQueryParallelism(reader.readInt())
+                .setReadFromBackup(reader.readBoolean())
+                .setRebalanceBatchSize(reader.readInt())
+                .setRebalanceBatchesPrefetchCount(reader.readLong())
+                .setRebalanceDelay(reader.readLong())
+                .setRebalanceMode(CacheRebalanceMode.fromOrdinal(reader.readInt()))
+                .setRebalanceOrder(reader.readInt())
+                .setRebalanceThrottle(reader.readLong())
+                .setRebalanceTimeout(reader.readLong())
+                .setSqlEscapeAll(reader.readBoolean())
+                .setSqlIndexMaxInlineSize(reader.readInt())
+                .setSqlSchema(reader.readString())
+                .setWriteSynchronizationMode(CacheWriteSynchronizationMode.fromOrdinal(reader.readInt()));
+
+        // Key configuration.
+        int keyCnt = reader.readInt();
+
+        if (keyCnt > 0) {
+            CacheKeyConfiguration[] keys = new CacheKeyConfiguration[keyCnt];
+
+            for (int i = 0; i < keyCnt; i++) {
+                keys[i] = new CacheKeyConfiguration(reader.readString(), reader.readString());
+            }
+
+            cfg.setKeyConfiguration(keys);
+        }
+
+        // Query entities.
+        int qryEntCnt = reader.readInt();
+
+        if (qryEntCnt > 0) {
+            Collection<QueryEntity> entities = new ArrayList<>(qryEntCnt);
+
+            for (int i = 0; i < qryEntCnt; i++)
+                entities.add(readQueryEntity(reader));
+
+            cfg.setQueryEntities(entities);
+        }
+
+        return cfg;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
new file mode 100644
index 0000000..4b4dcec
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithConfigurationRequest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheExistsException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.platform.client.ClientStatus;
+import org.apache.ignite.internal.processors.platform.client.IgniteClientException;
+
+/**
+ * Cache create with configuration request.
+ */
+@SuppressWarnings("unchecked")
+public class ClientCacheCreateWithConfigurationRequest extends ClientRequest {
+    /** Cache configuration. */
+    private final CacheConfiguration cacheCfg;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheCreateWithConfigurationRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheCfg = ClientCacheConfigurationSerializer.read(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        try {
+            ctx.kernalContext().grid().createCache(cacheCfg);
+        } catch (CacheExistsException e) {
+            throw new IgniteClientException(ClientStatus.CACHE_EXISTS, e.getMessage());
+        }
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
new file mode 100644
index 0000000..9155d76
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheCreateWithNameRequest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheExistsException;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.platform.client.ClientStatus;
+import org.apache.ignite.internal.processors.platform.client.IgniteClientException;
+
+/**
+ * Cache create with name request.
+ */
+public class ClientCacheCreateWithNameRequest extends ClientRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheCreateWithNameRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheName = reader.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        try {
+            ctx.kernalContext().grid().createCache(cacheName);
+        } catch (CacheExistsException e) {
+            throw new IgniteClientException(ClientStatus.CACHE_EXISTS, e.getMessage());
+        }
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.java
new file mode 100644
index 0000000..032116d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheDestroyRequest.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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache destroy request.
+ */
+public class ClientCacheDestroyRequest extends ClientRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheDestroyRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheName = reader.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        ctx.kernalContext().grid().destroyCache(cacheName);
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
new file mode 100644
index 0000000..3632095
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationRequest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache configuration request.
+ */
+public class ClientCacheGetConfigurationRequest extends ClientCacheRequest {
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetConfigurationRequest(BinaryRawReader reader) {
+        super(reader);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        CacheConfiguration cfg = ((IgniteCache<Object, Object>) rawCache(ctx))
+                .getConfiguration(CacheConfiguration.class);
+
+        return new ClientCacheGetConfigurationResponse(requestId(), cfg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
new file mode 100644
index 0000000..2033dfe
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetConfigurationResponse.java
@@ -0,0 +1,51 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache configuration response.
+ */
+public class ClientCacheGetConfigurationResponse extends ClientResponse {
+    /** Cache configuration. */
+    private final CacheConfiguration cfg;
+
+    /**
+     * Constructor.
+     *
+     * @param reqId Request id.
+     * @param cfg Cache configuration.
+     */
+    ClientCacheGetConfigurationResponse(long reqId, CacheConfiguration cfg) {
+        super(reqId);
+
+        assert cfg != null;
+
+        this.cfg = cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        ClientCacheConfigurationSerializer.write(writer, cfg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.java
new file mode 100644
index 0000000..376fcc1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesRequest.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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+import java.util.Collection;
+
+/**
+ * Cache names request.
+ */
+public class ClientCacheGetNamesRequest extends ClientRequest {
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetNamesRequest(BinaryRawReader reader) {
+        super(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        Collection<String> names = ctx.kernalContext().grid().cacheNames();
+
+        return new ClientCacheGetNamesResponse(requestId(), names);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
new file mode 100644
index 0000000..6266515
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetNamesResponse.java
@@ -0,0 +1,56 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+import java.util.Collection;
+
+/**
+ * Cache names response.
+ */
+public class ClientCacheGetNamesResponse extends ClientResponse {
+    /** Cache names. */
+    private final Collection<String> cacheNames;
+
+    /**
+     * Constructor.
+     *
+     * @param reqId Request id.
+     * @param cacheNames Cache names.
+     */
+    ClientCacheGetNamesResponse(long reqId, Collection<String> cacheNames) {
+        super(reqId);
+
+        assert cacheNames != null;
+
+        this.cacheNames = cacheNames;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        writer.writeInt(cacheNames.size());
+
+        for (String name : cacheNames) {
+            writer.writeString(name);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
new file mode 100644
index 0000000..267318a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithConfigurationRequest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.CacheExistsException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.platform.client.ClientStatus;
+import org.apache.ignite.internal.processors.platform.client.IgniteClientException;
+
+/**
+ * Cache get or create with configuration request.
+ */
+@SuppressWarnings("unchecked")
+public class ClientCacheGetOrCreateWithConfigurationRequest extends ClientRequest {
+    /** Cache configuration. */
+    private final CacheConfiguration cacheCfg;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetOrCreateWithConfigurationRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheCfg = ClientCacheConfigurationSerializer.read(reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        try {
+            ctx.kernalContext().grid().getOrCreateCache(cacheCfg);
+        } catch (CacheExistsException e) {
+            throw new IgniteClientException(ClientStatus.CACHE_EXISTS, e.getMessage());
+        }
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.java
new file mode 100644
index 0000000..94dd115
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheGetOrCreateWithNameRequest.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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Cache create with name request.
+ */
+public class ClientCacheGetOrCreateWithNameRequest extends ClientRequest {
+    /** Cache name. */
+    private final String cacheName;
+
+    /**
+     * Constructor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheGetOrCreateWithNameRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cacheName = reader.readString();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        ctx.kernalContext().grid().getOrCreateCache(cacheName);
+
+        return super.process(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
index c1a807c..a8df0c6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/utils/PlatformConfigurationUtils.java
@@ -209,11 +209,7 @@ public class PlatformConfigurationUtils {
         ccfg.setMaxQueryIteratorsCount(in.readInt());
         ccfg.setQueryDetailMetricsSize(in.readInt());
         ccfg.setQueryParallelism(in.readInt());
-
-        String sqlSchema = in.readString();
-        if (sqlSchema != null) {
-            ccfg.setSqlSchema(sqlSchema);
-        }
+        ccfg.setSqlSchema(in.readString());
 
         int qryEntCnt = in.readInt();
 
@@ -480,12 +476,14 @@ public class PlatformConfigurationUtils {
      * @param in Stream.
      * @return QueryEntity.
      */
-    private static QueryEntity readQueryEntity(BinaryRawReader in) {
+    public static QueryEntity readQueryEntity(BinaryRawReader in) {
         QueryEntity res = new QueryEntity();
 
         res.setKeyType(in.readString());
         res.setValueType(in.readString());
         res.setTableName(in.readString());
+        res.setKeyFieldName(in.readString());
+        res.setValueFieldName(in.readString());
 
         // Fields
         int cnt = in.readInt();
@@ -541,9 +539,6 @@ public class PlatformConfigurationUtils {
             res.setIndexes(indexes);
         }
 
-        res.setKeyFieldName(in.readString());
-        res.setValueFieldName(in.readString());
-
         return res;
     }
 
@@ -988,12 +983,14 @@ public class PlatformConfigurationUtils {
      * @param writer Writer.
      * @param queryEntity Query entity.
      */
-    private static void writeQueryEntity(BinaryRawWriter writer, QueryEntity queryEntity) {
+    public static void writeQueryEntity(BinaryRawWriter writer, QueryEntity queryEntity) {
         assert queryEntity != null;
 
         writer.writeString(queryEntity.getKeyType());
         writer.writeString(queryEntity.getValueType());
         writer.writeString(queryEntity.getTableName());
+        writer.writeString(queryEntity.getKeyFieldName());
+        writer.writeString(queryEntity.getValueFieldName());
 
         // Fields
         LinkedHashMap<String, String> fields = queryEntity.getFields();
@@ -1039,9 +1036,6 @@ public class PlatformConfigurationUtils {
         }
         else
             writer.writeInt(0);
-
-        writer.writeString(queryEntity.getKeyFieldName());
-        writer.writeString(queryEntity.getValueFieldName());
     }
 
     /**
@@ -1343,7 +1337,7 @@ public class PlatformConfigurationUtils {
      * @param w Writer.
      * @param e Enum.
      */
-    private static void writeEnumInt(BinaryRawWriter w, Enum e) {
+    public static void writeEnumInt(BinaryRawWriter w, Enum e) {
         w.writeInt(e == null ? 0 : e.ordinal());
     }
 
@@ -1353,7 +1347,7 @@ public class PlatformConfigurationUtils {
      * @param w Writer.
      * @param e Enum.
      */
-    private static void writeEnumInt(BinaryRawWriter w, Enum e, Enum def) {
+    public static void writeEnumInt(BinaryRawWriter w, Enum e, Enum def) {
         assert def != null;
 
         w.writeInt(e == null ? def.ordinal() : e.ordinal());

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 2ef6db1..2e34ba2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -107,7 +107,9 @@
     <Compile Include="Cache\Store\CacheStoreSessionTestSharedFactory.cs" />
     <Compile Include="Client\Cache\CacheTest.cs" />
     <Compile Include="Client\Cache\CacheTestNoMeta.cs" />
+    <Compile Include="Client\Cache\ClientCacheConfigurationTest.cs" />
     <Compile Include="Client\Cache\EmptyObject.cs" />
+    <Compile Include="Client\Cache\CreateCacheTest.cs" />
     <Compile Include="Client\Cache\ScanQueryTest.cs" />
     <Compile Include="Client\Cache\Person.cs" />
     <Compile Include="Client\ClientTestBase.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
index 9593777..63f5cd8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
@@ -578,7 +578,7 @@ namespace Apache.Ignite.Core.Tests.Cache
         /// <summary>
         /// Gets the custom cache configuration.
         /// </summary>
-        private static CacheConfiguration GetCustomCacheConfiguration(string name = null)
+        public static CacheConfiguration GetCustomCacheConfiguration(string name = null)
         {
             return new CacheConfiguration
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs
new file mode 100644
index 0000000..381f924
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/ClientCacheConfigurationTest.cs
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Tests.Client.Cache
+{
+    using System;
+    using System.IO;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Client.Cache;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Client.Cache;
+    using Apache.Ignite.Core.Tests.Cache;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests client cache configuration handling.
+    /// </summary>
+    public class ClientCacheConfigurationTest
+    {
+        /// <summary>
+        /// Tests the serialization/deserialization of <see cref="CacheConfiguration"/>.
+        /// </summary>
+        [Test]
+        public void TestSerializeDeserialize()
+        {
+            // Empty.
+            TestSerializeDeserialize(new CacheConfiguration("foo"));
+
+            // Full config: has unsupported properties.
+            var cfg = CacheConfigurationTest.GetCustomCacheConfiguration("bar");
+            cfg.ReadThrough = true;
+            cfg.WriteBehindEnabled = true;
+            
+            TestSerializeDeserializeUnspported(cfg, "AffinityFunction");
+            cfg.AffinityFunction = null;
+
+            TestSerializeDeserializeUnspported(cfg, "EvictionPolicy");
+            cfg.EvictionPolicy = null;
+
+            TestSerializeDeserializeUnspported(cfg, "ExpiryPolicyFactory");
+            cfg.ExpiryPolicyFactory = null;
+
+            TestSerializeDeserializeUnspported(cfg, "PluginConfigurations");
+            cfg.PluginConfigurations = null;
+
+            TestSerializeDeserializeUnspported(cfg, "CacheStoreFactory");
+            cfg.CacheStoreFactory = null;
+
+            TestSerializeDeserializeUnspported(cfg, "NearConfiguration");
+            cfg.NearConfiguration = null;
+
+            // Store-specific properties.
+            TestSerializeDeserializeUnspported(cfg, "KeepBinaryInStore");
+            cfg.KeepBinaryInStore = false;
+
+            TestSerializeDeserializeUnspported(cfg, "LoadPreviousValue");
+            cfg.LoadPreviousValue = false;
+
+            TestSerializeDeserializeUnspported(cfg, "ReadThrough");
+            cfg.ReadThrough = false;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteThrough");
+            cfg.WriteThrough = false;
+
+            TestSerializeDeserializeUnspported(cfg, "StoreConcurrentLoadAllThreshold");
+            cfg.StoreConcurrentLoadAllThreshold = CacheConfiguration.DefaultStoreConcurrentLoadAllThreshold;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindBatchSize");
+            cfg.WriteBehindBatchSize = CacheConfiguration.DefaultWriteBehindBatchSize;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindCoalescing");
+            cfg.WriteBehindCoalescing = CacheConfiguration.DefaultWriteBehindCoalescing;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindEnabled");
+            cfg.WriteBehindEnabled = CacheConfiguration.DefaultWriteBehindEnabled;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindFlushFrequency");
+            cfg.WriteBehindFlushFrequency = CacheConfiguration.DefaultWriteBehindFlushFrequency;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindFlushSize");
+            cfg.WriteBehindFlushSize = CacheConfiguration.DefaultWriteBehindFlushSize;
+
+            TestSerializeDeserializeUnspported(cfg, "WriteBehindFlushThreadCount");
+            cfg.WriteBehindFlushThreadCount = CacheConfiguration.DefaultWriteBehindFlushThreadCount;
+
+            // Full config without unsupported properties.
+            TestSerializeDeserialize(cfg);
+        }
+
+        /// <summary>
+        /// Tests <see cref="CacheConfiguration"/> to <see cref="CacheClientConfiguration"/> and reverse conversion.
+        /// </summary>
+        [Test]
+        public void TestConfigConversion()
+        {
+            // Copy ctor.
+            var clientCfg = new CacheClientConfiguration(
+                CacheConfigurationTest.GetCustomCacheConfiguration("z"), true);
+
+            AssertClientConfigsAreEqual(clientCfg, new CacheClientConfiguration(clientCfg));
+
+            // Convert to server cfg.
+            var serverCfg = clientCfg.ToCacheConfiguration();
+            AssertClientConfigsAreEqual(clientCfg, new CacheClientConfiguration(serverCfg, false));
+        }
+
+        /// <summary>
+        /// Tests the constructors.
+        /// </summary>
+        [Test]
+        public void TestConstructors()
+        {
+            // Default property values.
+            var clientCfg = new CacheClientConfiguration();
+            var defCfg = new CacheClientConfiguration(new CacheConfiguration(), false);
+
+            AssertClientConfigsAreEqual(defCfg, clientCfg);
+
+            // Name.
+            clientCfg = new CacheClientConfiguration("foo");
+            Assert.AreEqual("foo", clientCfg.Name);
+
+            clientCfg.Name = null;
+            AssertClientConfigsAreEqual(defCfg, clientCfg);
+
+            // Query entities.
+            clientCfg = new CacheClientConfiguration("bar", typeof(QueryPerson));
+            Assert.AreEqual("bar", clientCfg.Name);
+            var qe = clientCfg.QueryEntities.Single();
+            Assert.AreEqual(typeof(QueryPerson), qe.ValueType);
+            Assert.AreEqual("Name", qe.Fields.Single().Name);
+
+            clientCfg = new CacheClientConfiguration("baz", new QueryEntity(typeof(QueryPerson)));
+            qe = clientCfg.QueryEntities.Single();
+            Assert.AreEqual(typeof(QueryPerson), qe.ValueType);
+            Assert.AreEqual("Name", qe.Fields.Single().Name);
+        }
+
+        /// <summary>
+        /// Tests the serialization/deserialization of <see cref="CacheConfiguration"/>.
+        /// </summary>
+        private static void TestSerializeDeserializeUnspported(CacheConfiguration cfg, string propName)
+        {
+            var ex = Assert.Throws<NotSupportedException>(() => TestSerializeDeserialize(cfg));
+            Assert.AreEqual(string.Format("{0}.{1} property is not supported in thin client mode.",
+                typeof(CacheConfiguration).Name, propName), ex.Message);
+        }
+
+        /// <summary>
+        /// Tests the serialization/deserialization of <see cref="CacheConfiguration"/>.
+        /// </summary>
+        private static void TestSerializeDeserialize(CacheConfiguration cfg)
+        {
+            var clientCfg = new CacheClientConfiguration(cfg, false);
+
+            AssertClientConfigsAreEqual(clientCfg, SerializeDeserialize(clientCfg));
+        }
+
+        /// <summary>
+        /// Asserts the client configs are equal.
+        /// </summary>
+        public static void AssertClientConfigsAreEqual(CacheClientConfiguration cfg, CacheClientConfiguration cfg2)
+        {
+            if (cfg2.QueryEntities != null)
+            {
+                // Remove identical aliases which are added during config roundtrip.
+                foreach (var e in cfg2.QueryEntities)
+                {
+                    e.Aliases = e.Aliases.Where(x => x.Alias != x.FullName).ToArray();
+                }
+            }
+
+            TestUtils.AssertReflectionEqual(cfg, cfg2);
+        }
+
+        /// <summary>
+        /// Serializes and deserializes the config.
+        /// </summary>
+        private static CacheClientConfiguration SerializeDeserialize(CacheClientConfiguration cfg)
+        {
+            using (var stream = new BinaryHeapStream(128))
+            {
+                ClientCacheConfigurationSerializer.Write(stream, cfg);
+                stream.Seek(0, SeekOrigin.Begin);
+                return new CacheClientConfiguration(stream);
+            }
+        }
+
+        private class QueryPerson
+        {
+            [QuerySqlField]
+            // ReSharper disable once UnusedMember.Local
+            public string Name { get; set; }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
new file mode 100644
index 0000000..c92fbac
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CreateCacheTest.cs
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Tests.Client.Cache
+{
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Client;
+    using Apache.Ignite.Core.Client.Cache;
+    using Apache.Ignite.Core.Configuration;
+    using Apache.Ignite.Core.Impl.Client;
+    using Apache.Ignite.Core.Tests.Cache;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests dynamic cache start from client nodes.
+    /// </summary>
+    public class CreateCacheTest : ClientTestBase
+    {
+        /** Template cache name. */
+        private const string TemplateCacheName = "template-cache-*";
+
+        /// <summary>
+        /// Tears down the test.
+        /// </summary>
+        [TearDown]
+        public void TearDown()
+        {
+            DestroyCaches();
+        }
+
+        /// <summary>
+        /// Destroys caches.
+        /// </summary>
+        private void DestroyCaches()
+        {
+            foreach (var cacheName in Client.GetCacheNames())
+            {
+                Client.DestroyCache(cacheName);
+            }
+        }
+
+        /// <summary>
+        /// Tests the GetCacheNames.
+        /// </summary>
+        [Test]
+        public void TestGetCacheNames()
+        {
+            DestroyCaches();
+            Assert.AreEqual(0, Client.GetCacheNames().Count);
+
+            Client.CreateCache<int, int>("a");
+            Assert.AreEqual("a", Client.GetCacheNames().Single());
+
+            Client.CreateCache<int, int>("b");
+            Assert.AreEqual(new[] {"a", "b"}, Client.GetCacheNames().OrderBy(x => x).ToArray());
+
+            Client.DestroyCache("a");
+            Assert.AreEqual("b", Client.GetCacheNames().Single());
+        }
+
+        /// <summary>
+        /// Tests create from template.
+        /// </summary>
+        [Test]
+        public void TestCreateFromTemplate()
+        {
+            // No template: default configuration.
+            var cache = Client.CreateCache<int, int>("foobar");
+            TestUtils.AssertReflectionEqual(new CacheClientConfiguration("foobar"), cache.GetConfiguration());
+
+            // Create when exists.
+            var ex = Assert.Throws<IgniteClientException>(() => Client.CreateCache<int, int>(cache.Name));
+            Assert.AreEqual(
+                "Failed to start cache (a cache with the same name is already started): foobar", ex.Message);
+            Assert.AreEqual((int) ClientStatus.CacheExists, ex.ErrorCode);
+
+            // Template: custom configuration.
+            cache = Client.CreateCache<int, int>(TemplateCacheName.Replace("*", "1"));
+            var cfg = cache.GetConfiguration();
+            Assert.AreEqual(CacheAtomicityMode.Transactional, cfg.AtomicityMode);
+            Assert.AreEqual(3, cfg.Backups);
+            Assert.AreEqual(CacheMode.Partitioned, cfg.CacheMode);
+        }
+
+        /// <summary>
+        /// Tests getOrCreate from template.
+        /// </summary>
+        [Test]
+        public void TestGetOrCreateFromTemplate()
+        {
+            // No template: default configuration.
+            var cache = Client.GetOrCreateCache<int, int>("foobar");
+            TestUtils.AssertReflectionEqual(new CacheClientConfiguration { Name = "foobar"}, cache.GetConfiguration());
+            cache[1] = 1;
+
+            // Create when exists.
+            cache = Client.GetOrCreateCache<int, int>("foobar");
+            Assert.AreEqual(1, cache[1]);
+
+            // Template: custom configuration.
+            cache = Client.GetOrCreateCache<int, int>(TemplateCacheName.Replace("*", "1"));
+            var cfg = cache.GetConfiguration();
+            Assert.AreEqual(CacheAtomicityMode.Transactional, cfg.AtomicityMode);
+            Assert.AreEqual(3, cfg.Backups);
+            Assert.AreEqual(CacheMode.Partitioned, cfg.CacheMode);
+
+            // Create when exists.
+            cache[1] = 1;
+            cache = Client.GetOrCreateCache<int, int>(cache.Name);
+            Assert.AreEqual(1, cache[1]);
+        }
+
+        /// <summary>
+        /// Tests cache creation from configuration.
+        /// </summary>
+        [Test]
+        public void TestCreateFromConfiguration()
+        {
+            // Default config.
+            var cfg = new CacheClientConfiguration("a");
+            var cache = Client.CreateCache<int, int>(cfg);
+            TestUtils.AssertReflectionEqual(cfg, cache.GetConfiguration());
+
+            // Create when exists.
+            var ex = Assert.Throws<IgniteClientException>(() => Client.CreateCache<int, int>(cfg));
+            Assert.AreEqual(
+                "Failed to start cache (a cache with the same name is already started): a", ex.Message);
+            Assert.AreEqual((int) ClientStatus.CacheExists, ex.ErrorCode);
+
+            // Custom config.
+            cfg = GetFullCacheConfiguration("b");
+
+            cache = Client.CreateCache<int, int>(cfg);
+            ClientCacheConfigurationTest.AssertClientConfigsAreEqual(cfg, cache.GetConfiguration());
+        }
+
+        /// <summary>
+        /// Tests cache creation from configuration.
+        /// </summary>
+        [Test]
+        public void TestGetOrCreateFromConfiguration()
+        {
+            // Default configur.
+            var cfg = new CacheClientConfiguration("a");
+            var cache = Client.GetOrCreateCache<int, int>(cfg);
+            TestUtils.AssertReflectionEqual(cfg, cache.GetConfiguration());
+            cache[1] = 1;
+
+            // Create when exists.
+            cache = Client.GetOrCreateCache<int, int>("a");
+            Assert.AreEqual(1, cache[1]);
+
+            // Custom config.
+            cfg = GetFullCacheConfiguration("b");
+
+            cache = Client.GetOrCreateCache<int, int>(cfg);
+            ClientCacheConfigurationTest.AssertClientConfigsAreEqual(cfg, cache.GetConfiguration());
+        }
+
+        /// <summary>
+        /// Gets the full cache configuration.
+        /// </summary>
+        private static CacheClientConfiguration GetFullCacheConfiguration(string name)
+        {
+            return new CacheClientConfiguration(CacheConfigurationTest.GetCustomCacheConfiguration(name), true);
+        }
+
+        /** <inheritdoc /> */
+        protected override IgniteConfiguration GetIgniteConfiguration()
+        {
+            return new IgniteConfiguration(base.GetIgniteConfiguration())
+            {
+                CacheConfiguration = new[]
+                {
+                    new CacheConfiguration(TemplateCacheName)
+                    {
+                        AtomicityMode = CacheAtomicityMode.Transactional,
+                        Backups = 3
+                    }
+                },
+                DataStorageConfiguration = new DataStorageConfiguration
+                {
+                    DataRegionConfigurations = new[]
+                    {
+                        new DataRegionConfiguration
+                        {
+                            Name = "myMemPolicy"
+                        } 
+                    }
+                }
+            };
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
index 408eb73..9b7a566 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
@@ -64,6 +64,8 @@ namespace Apache.Ignite.Core.Tests.Client
             {
                 Ignition.Start(cfg);
             }
+
+            Client = GetClient();
         }
 
         /// <summary>
@@ -85,6 +87,11 @@ namespace Apache.Ignite.Core.Tests.Client
         }
 
         /// <summary>
+        /// Gets the client.
+        /// </summary>
+        public IIgniteClient Client { get; set; }
+
+        /// <summary>
         /// Gets the cache.
         /// </summary>
         protected static ICache<int, T> GetCache<T>()

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
index 6e09704..98c3f11 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationTest.cs
@@ -27,6 +27,7 @@ namespace Apache.Ignite.Core.Tests
     using Apache.Ignite.Core.Cache.Configuration;
     using Apache.Ignite.Core.Cache.Eviction;
     using Apache.Ignite.Core.Client;
+    using Apache.Ignite.Core.Client.Cache;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Communication.Tcp;
     using Apache.Ignite.Core.Configuration;
@@ -99,6 +100,7 @@ namespace Apache.Ignite.Core.Tests
             CheckDefaultValueAttributes(new QueryIndex());
             CheckDefaultValueAttributes(new DataStorageConfiguration());
             CheckDefaultValueAttributes(new DataRegionConfiguration());
+            CheckDefaultValueAttributes(new CacheClientConfiguration());
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 8a32583..0076d47 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -96,6 +96,7 @@
     <Compile Include="Binary\TimestampAttribute.cs" />
     <Compile Include="Cache\Configuration\CacheKeyConfiguration.cs" />
     <Compile Include="Cache\Configuration\DataPageEvictionMode.cs" />
+    <Compile Include="Client\Cache\CacheClientConfiguration.cs" />
     <Compile Include="Configuration\CheckpointWriteOrder.cs" />
     <Compile Include="Configuration\DataPageEvictionMode.cs" />
     <Compile Include="Configuration\DataRegionConfiguration.cs" />
@@ -119,6 +120,7 @@
     <Compile Include="Impl\Binary\MultidimensionalArrayHolder.cs" />
     <Compile Include="Impl\Binary\MultidimensionalArraySerializer.cs" />
     <Compile Include="Impl\Client\Cache\CacheFlags.cs" />
+    <Compile Include="Impl\Client\Cache\ClientCacheConfigurationSerializer.cs" />
     <Compile Include="Impl\Client\Cache\Query\ClientQueryCursor.cs" />
     <Compile Include="Impl\Cache\Query\PlatformQueryQursorBase.cs" />
     <Compile Include="Impl\Binary\BinaryProcessorClient.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/52b46c35/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
index eb509a0..4db15eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/QueryEntity.cs
@@ -237,6 +237,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
             KeyTypeName = reader.ReadString();
             ValueTypeName = reader.ReadString();
             TableName = reader.ReadString();
+            KeyFieldName = reader.ReadString();
+            ValueFieldName = reader.ReadString();
 
             var count = reader.ReadInt();
             Fields = count == 0
@@ -249,9 +251,6 @@ namespace Apache.Ignite.Core.Cache.Configuration
 
             count = reader.ReadInt();
             Indexes = count == 0 ? null : Enumerable.Range(0, count).Select(x => new QueryIndex(reader)).ToList();
-
-            KeyFieldName = reader.ReadString();
-            ValueFieldName = reader.ReadString();
         }
 
         /// <summary>
@@ -262,6 +261,8 @@ namespace Apache.Ignite.Core.Cache.Configuration
             writer.WriteString(KeyTypeName);
             writer.WriteString(ValueTypeName);
             writer.WriteString(TableName);
+            writer.WriteString(KeyFieldName);
+            writer.WriteString(ValueFieldName);
 
             if (Fields != null)
             {
@@ -303,9 +304,6 @@ namespace Apache.Ignite.Core.Cache.Configuration
             }
             else
                 writer.WriteInt(0);
-
-            writer.WriteString(KeyFieldName);
-            writer.WriteString(ValueFieldName);
         }
 
         /// <summary>


[15/47] ignite git commit: IGNITE-5635 Web Console: Added spinning wheel for execute, scan and export actions on Queries screen.

Posted by sb...@apache.org.
IGNITE-5635 Web Console: Added spinning wheel for execute, scan and export actions on Queries screen.


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

Branch: refs/heads/ignite-zk
Commit: f992386e25e643f329b219ec2d0f877e50920b40
Parents: 8c278ca
Author: alexdel <ve...@yandex.ru>
Authored: Wed Nov 15 19:35:30 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Wed Nov 15 19:35:30 2017 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/sql/sql.controller.js  | 28 ++++++-
 .../frontend/public/stylesheets/style.scss      | 10 +++
 .../web-console/frontend/views/sql/sql.tpl.pug  | 84 ++++++++++++++++++--
 3 files changed, 112 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/f992386e/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 8d27d30..b4c8a6f 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -59,6 +59,9 @@ class Paragraph {
         self.maxPages = 0;
         self.filter = '';
         self.useAsDefaultSchema = false;
+        self.localQueryMode = false;
+        self.csvIsPreparing = false;
+        self.scanningInProgress = false;
 
         _.assign(this, paragraph);
 
@@ -200,6 +203,14 @@ class Paragraph {
     chartTimeLineEnabled() {
         return _.nonEmpty(this.chartKeyCols) && _.eq(this.chartKeyCols[0], TIME_LINE);
     }
+
+    executionInProgress(showLocal = false) {
+        return this.loading && (this.localQueryMode === showLocal);
+    }
+
+    checkScanInProgress(showLocal = false) {
+        return this.scanningInProgress && (this.localQueryMode === showLocal);
+    }
 }
 
 // Controller for SQL notebook screen.
@@ -1409,6 +1420,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             const enforceJoinOrder = !!paragraph.enforceJoinOrder;
             const lazy = !!paragraph.lazy;
 
+            paragraph.localQueryMode = local;
+
             $scope.queryAvailable(paragraph) && _chooseNode(paragraph.cacheName, local)
                 .then((nid) => {
                     Notebook.save($scope.notebook)
@@ -1506,8 +1519,12 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             const filter = paragraph.filter;
             const pageSize = paragraph.pageSize;
 
+            paragraph.localQueryMode = local;
+
             $scope.scanAvailable(paragraph) && _chooseNode(cacheName, local)
                 .then((nid) => {
+                    paragraph.scanningInProgress = true;
+
                     Notebook.save($scope.notebook)
                         .catch(Messages.showError);
 
@@ -1537,7 +1554,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                             paragraph.setError(err);
 
                             _showLoading(paragraph, false);
-                        });
+                        })
+                        .then(() => paragraph.scanningInProgress = false);
                 });
         };
 
@@ -1664,6 +1682,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         };
 
         $scope.exportCsvAll = (paragraph) => {
+            paragraph.csvIsPreparing = true;
+
             const args = paragraph.queryArgs;
 
             return Promise.resolve(args.localNid || _chooseNode(args.cacheName, false))
@@ -1672,7 +1692,11 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                     : agentMgr.querySqlGetAll(nid, args.cacheName, args.query, !!args.nonCollocatedJoins, !!args.enforceJoinOrder, false, !!args.localNid, !!args.lazy))
                 .then((res) => _export(exportFileName(paragraph, true), paragraph.gridOptions.columnDefs, res.columns, res.rows))
                 .catch(Messages.showError)
-                .then(() => paragraph.ace && paragraph.ace.focus());
+                .then(() => {
+                    paragraph.csvIsPreparing = false;
+
+                    return paragraph.ace && paragraph.ace.focus();
+                });
         };
 
         // $scope.exportPdfAll = function(paragraph) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/f992386e/modules/web-console/frontend/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/public/stylesheets/style.scss b/modules/web-console/frontend/public/stylesheets/style.scss
index b259f1d..8433747 100644
--- a/modules/web-console/frontend/public/stylesheets/style.scss
+++ b/modules/web-console/frontend/public/stylesheets/style.scss
@@ -2201,3 +2201,13 @@ html,body,.splash-screen {
 .demo-mode {
     padding-top: 30px;
 }
+
+// Fix for injecting svg icon into BS btn
+.btn--with-icon {
+    display: flex;
+    align-items: center;
+
+    span {
+        margin-left: 5px;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/f992386e/modules/web-console/frontend/views/sql/sql.tpl.pug
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/views/sql/sql.tpl.pug b/modules/web-console/frontend/views/sql/sql.tpl.pug
index 7ee966d..b324622 100644
--- a/modules/web-console/frontend/views/sql/sql.tpl.pug
+++ b/modules/web-console/frontend/views/sql/sql.tpl.pug
@@ -123,8 +123,17 @@ mixin query-settings
                     span Lazy result set
 
 mixin query-actions
-    button.btn.btn-primary(ng-disabled='!queryAvailable(paragraph)' ng-click='execute(paragraph)') Execute
-    button.btn.btn-primary(ng-disabled='!queryAvailable(paragraph)' ng-click='execute(paragraph, true)') Execute on selected node
+    button.btn.btn-primary(ng-disabled='!queryAvailable(paragraph)' ng-click='execute(paragraph)')
+        div
+            i.fa.fa-fw.fa-play(ng-hide='paragraph.executionInProgress(false)')
+            i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.executionInProgress(false)')
+            span.tipLabelExecute Execute
+    button.btn.btn-primary(ng-disabled='!queryAvailable(paragraph)' ng-click='execute(paragraph, true)')
+        div
+            i.fa.fa-fw.fa-play(ng-hide='paragraph.executionInProgress(true)')
+            i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.executionInProgress(true)')
+            span.tipLabelExecute Execute on selected node
+
 
     a.btn.btn-default(ng-disabled='!queryAvailable(paragraph)' ng-click='explain(paragraph)' data-placement='bottom' bs-tooltip='' data-title='{{queryTooltip(paragraph, "explain query")}}') Explain
 
@@ -141,8 +150,35 @@ mixin table-result-heading-query
                 +result-toolbar
         .col-xs-4
             .pull-right
-                -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
-                +btn-group('paragraph.loading', options, '{{ queryTooltip(paragraph, "export query results") }}')
+                .btn-group.panel-tip-container
+                    button.btn.btn-primary.btn--with-icon(
+                        ng-click='exportCsv(paragraph)'
+
+                        ng-disabled='paragraph.loading'
+
+                        bs-tooltip=''
+                        ng-attr-title='{{ queryTooltip(paragraph, "export query results") }}'
+
+                        data-trigger='hover'
+                        data-placement='bottom'
+                    )
+                        svg(ignite-icon='csv' ng-if='!paragraph.csvIsPreparing')
+                        i.fa.fa-fw.fa-refresh.fa-spin(ng-if='paragraph.csvIsPreparing')
+                        span Export
+
+                    -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
+                    button.btn.dropdown-toggle.btn-primary(
+                        ng-disabled='paragraph.loading'
+
+                        bs-dropdown=`${JSON.stringify(options)}`
+
+                        data-toggle='dropdown'
+                        data-container='body'
+                        data-placement='bottom-right'
+                    )
+                        span.caret
+
+
 
 mixin table-result-heading-scan
     .total.row
@@ -157,8 +193,34 @@ mixin table-result-heading-scan
                 +result-toolbar
         .col-xs-4
             .pull-right
-                -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
-                +btn-group('paragraph.loading', options, '{{ scanTooltip(paragraph) }}')
+                .btn-group.panel-tip-container
+                    // TODO: replace this logic for exporting under one component
+                    button.btn.btn-primary.btn--with-icon(
+                        ng-click='exportCsv(paragraph)'
+
+                        ng-disabled='paragraph.loading'
+
+                        bs-tooltip=''
+                        ng-attr-title='{{ scanTooltip(paragraph) }}'
+
+                        data-trigger='hover'
+                        data-placement='bottom'
+                    )
+                        svg(ignite-icon='csv' ng-if='!paragraph.csvIsPreparing')
+                        i.fa.fa-fw.fa-refresh.fa-spin(ng-if='paragraph.csvIsPreparing')
+                        span Export
+
+                    -var options = [{ text: "Export", click: 'exportCsv(paragraph)' }, { text: 'Export all', click: 'exportCsvAll(paragraph)' }]
+                    button.btn.dropdown-toggle.btn-primary(
+                        ng-disabled='paragraph.loading'
+
+                        bs-dropdown=`${JSON.stringify(options)}`
+
+                        data-toggle='dropdown'
+                        data-container='body'
+                        data-placement='bottom-right'
+                    )
+                        span.caret
 
 mixin table-result-body
     .grid(ui-grid='paragraph.gridOptions' ui-grid-resize-columns ui-grid-exporter)
@@ -197,9 +259,15 @@ mixin paragraph-scan
 
         .col-sm-12.sql-controls
             button.btn.btn-primary(ng-disabled='!scanAvailable(paragraph)' ng-click='scan(paragraph)')
-                | Scan
+                div
+                    i.fa.fa-fw.fa-play(ng-hide='paragraph.checkScanInProgress(false)')
+                    i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.checkScanInProgress(false)')
+                    span.tipLabelExecute Scan
+
             button.btn.btn-primary(ng-disabled='!scanAvailable(paragraph)' ng-click='scan(paragraph, true)')
-                | Scan on selected node
+                    i.fa.fa-fw.fa-play(ng-hide='paragraph.checkScanInProgress(true)')
+                    i.fa.fa-fw.fa-refresh.fa-spin(ng-show='paragraph.checkScanInProgress(true)')
+                    span.tipLabelExecute Scan on selected node
 
         .col-sm-12.sql-result(ng-if='paragraph.queryExecuted()' ng-switch='paragraph.resultType()')
             .error(ng-switch-when='error') Error: {{paragraph.error.message}}


[46/47] ignite git commit: zk

Posted by sb...@apache.org.
zk


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

Branch: refs/heads/ignite-zk
Commit: fb6bd0ac39f97db0d7e347aff6fa26edda10f940
Parents: fcee8c8
Author: sboikov <sb...@gridgain.com>
Authored: Tue Nov 21 13:43:15 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Nov 21 15:09:20 2017 +0300

----------------------------------------------------------------------
 .../discovery/zk/internal/ZkEventAckFuture.java | 139 +++++++++++++++++++
 .../discovery/zk/internal/ZookeeperClient.java  | 121 ++++++++++++++--
 .../zk/internal/ZookeeperDiscoveryImpl.java     |  55 +++++++-
 3 files changed, 296 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/fb6bd0ac/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkEventAckFuture.java
----------------------------------------------------------------------
diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkEventAckFuture.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkEventAckFuture.java
new file mode 100644
index 0000000..fa0da99
--- /dev/null
+++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZkEventAckFuture.java
@@ -0,0 +1,139 @@
+/*
+ * 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.spi.discovery.zk.internal;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.zookeeper.AsyncCallback;
+import org.apache.zookeeper.WatchedEvent;
+import org.apache.zookeeper.Watcher;
+import org.apache.zookeeper.data.Stat;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ *
+ */
+public class ZkEventAckFuture extends GridFutureAdapter<Void> implements Watcher, AsyncCallback.Children2Callback {
+    /** */
+    private final IgniteLogger log;
+
+    /** */
+    private final ZookeeperDiscoveryImpl impl;
+
+    /** */
+    private final Long evtId;
+
+    /** */
+    private final String evtPath;
+
+    /** */
+    private final int expAcks;
+
+    /** */
+    private final Set<Integer> remaininAcks;
+
+    ZkEventAckFuture(ZookeeperDiscoveryImpl impl, String evtPath, Long evtId) {
+        this.impl = impl;
+        this.log = impl.log();
+        this.evtPath = evtPath;
+        this.evtId = evtId;
+
+        ZkClusterNodes top = impl.nodes();
+
+        remaininAcks = U.newHashSet(top.nodesById.size());
+
+        for (ZookeeperClusterNode node : top.nodesByInternalId.values()) {
+            if (!node.isLocal())
+                remaininAcks.add(node.internalId());
+        }
+
+        expAcks = remaininAcks.size();
+
+        if (expAcks == 0)
+            onDone();
+        else
+            impl.zkClient().getChildrenAsync(evtPath, this, this);
+    }
+
+    /**
+     * @return Event ID.
+     */
+    Long eventId() {
+        return evtId;
+    }
+
+    /**
+     * @param node Failed node.
+     */
+    void onNodeFail(ZookeeperClusterNode node) {
+        assert !remaininAcks.isEmpty();
+
+        if (remaininAcks.remove(node.internalId()) && remaininAcks.isEmpty())
+            onDone();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean onDone(@Nullable Void res, @Nullable Throwable err) {
+        if (super.onDone(res, err)) {
+            impl.removeAckFuture(this);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void process(WatchedEvent evt) {
+        if (isDone())
+            return;
+
+        if (evt.getType() == Event.EventType.NodeChildrenChanged) {
+            if (evtPath.equals(evt.getPath()))
+                impl.zkClient().getChildrenAsync(evtPath, this, this);
+            else
+                U.warn(log, "Received event for unknown path: " + evt.getPath());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void processResult(int rc, String path, Object ctx, List<String> children, Stat stat) {
+        assert rc == 0 : rc;
+
+        if (isDone())
+            return;
+
+        if (expAcks == stat.getCversion()) {
+            log.info("Received expected number of acks [expCnt=" + expAcks + ", cVer=" + stat.getCversion() + ']');
+
+            onDone();
+        }
+        else {
+            for (int i = 0; i < children.size(); i++) {
+                Integer nodeInternalId = Integer.parseInt(children.get(i));
+
+                if (remaininAcks.remove(nodeInternalId) && remaininAcks.size() == 0)
+                    onDone();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/fb6bd0ac/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
----------------------------------------------------------------------
diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
index 6393b90..4fdc9fc 100644
--- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
+++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperClient.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.spi.discovery.zk.internal;
 
 import java.util.ArrayDeque;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Timer;
 import java.util.TimerTask;
@@ -27,6 +28,7 @@ import org.apache.ignite.lang.IgniteRunnable;
 import org.apache.zookeeper.AsyncCallback;
 import org.apache.zookeeper.CreateMode;
 import org.apache.zookeeper.KeeperException;
+import org.apache.zookeeper.Op;
 import org.apache.zookeeper.WatchedEvent;
 import org.apache.zookeeper.Watcher;
 import org.apache.zookeeper.ZooDefs;
@@ -264,6 +266,29 @@ public class ZookeeperClient implements Watcher {
     }
 
 
+    void deleteAllIfExists(String parent, List<String> paths, int ver)
+        throws ZookeeperClientFailedException, InterruptedException
+    {
+        // TODO ZK: need check for max size?
+        List<Op> ops = new ArrayList<>(paths.size());
+
+        for (String path : paths)
+            ops.add(Op.delete(parent + "/" + path, ver));
+
+        for (;;) {
+            long connStartTime = this.connStartTime;
+
+            try {
+                zk.multi(ops);
+
+                return;
+            }
+            catch (Exception e) {
+                onZookeeperError(connStartTime, e);
+            }
+        }
+    }
+
     void delete(String path, int ver)
         throws KeeperException.NoNodeException, ZookeeperClientFailedException, InterruptedException
     {
@@ -331,7 +356,7 @@ public class ZookeeperClient implements Watcher {
     void getChildrenAsync(String path, Watcher watcher, AsyncCallback.Children2Callback cb) {
         GetChildrenOperation op = new GetChildrenOperation(path, watcher, cb);
 
-        zk.getChildren(path, watcher, new ChildreCallbackWrapper(op), null);
+        zk.getChildren(path, watcher, new ChildrenCallbackWrapper(op), null);
     }
 
     void getDataAsync(String path, Watcher watcher, AsyncCallback.DataCallback cb) {
@@ -340,6 +365,15 @@ public class ZookeeperClient implements Watcher {
         zk.getData(path, watcher, new DataCallbackWrapper(op), null);
     }
 
+    void createAsync(String path, byte[] data, CreateMode createMode, AsyncCallback.StringCallback cb) {
+        if (data == null)
+            data = EMPTY_BYTES;
+
+        CreateOperation op = new CreateOperation(path, data, createMode, cb);
+
+        zk.create(path, data, ZK_ACL, createMode, new CreateCallbackWrapper(op), null);
+    }
+
     /**
      *
      */
@@ -437,6 +471,29 @@ public class ZookeeperClient implements Watcher {
     /**
      *
      */
+    private void closeClient() {
+        try {
+            zk.close();
+        }
+        catch (Exception closeErr) {
+            U.warn(log, "Failed to close zookeeper client: " + closeErr, closeErr);
+        }
+
+        connTimer.cancel();
+    }
+
+    /**
+     *
+     */
+    private void scheduleConnectionCheck() {
+        assert state == ConnectionState.Disconnected : state;
+
+        connTimer.schedule(new ConnectionTimeoutTask(connStartTime), connLossTimeout);
+    }
+
+    /**
+     *
+     */
     interface ZkAsyncOperation {
         /**
          *
@@ -532,37 +589,75 @@ public class ZookeeperClient implements Watcher {
     /**
      *
      */
-    private void closeClient() {
-        try {
-            zk.close();
-        }
-        catch (Exception closeErr) {
-            U.warn(log, "Failed to close zookeeper client: " + closeErr, closeErr);
+    class CreateOperation implements ZkAsyncOperation {
+        /** */
+        private final String path;
+
+        /** */
+        private final byte[] data;
+
+        /** */
+        private final CreateMode createMode;
+
+        /** */
+        private final AsyncCallback.StringCallback cb;
+
+        CreateOperation(String path, byte[] data, CreateMode createMode, AsyncCallback.StringCallback cb) {
+            this.path = path;
+            this.data = data;
+            this.createMode = createMode;
+            this.cb = cb;
         }
 
-        connTimer.cancel();
+        /** {@inheritDoc} */
+        @Override public void execute() {
+            createAsync(path, data, createMode, cb);
+        }
     }
 
     /**
      *
      */
-    private void scheduleConnectionCheck() {
-        assert state == ConnectionState.Disconnected : state;
+    class CreateCallbackWrapper implements AsyncCallback.StringCallback {
+        /** */
+        final CreateOperation op;
 
-        connTimer.schedule(new ConnectionTimeoutTask(connStartTime), connLossTimeout);
+        /**
+         * @param op Operation.
+         */
+        CreateCallbackWrapper(CreateOperation op) {
+            this.op = op;
+        }
+
+        @Override public void processResult(int rc, String path, Object ctx, String name) {
+            if (rc == KeeperException.Code.NODEEXISTS.intValue())
+                return;
+
+            if (needRetry(rc)) {
+                U.warn(log, "Failed to execute async operation, connection lost. Will retry after connection restore [path=" + path + ']');
+
+                retryQ.add(op);
+            }
+            else if (rc == KeeperException.Code.SESSIONEXPIRED.intValue())
+                U.warn(log, "Failed to execute async operation, connection lost [path=" + path + ']');
+            else {
+                if (op.cb != null)
+                    op.cb.processResult(rc, path, ctx, name);
+            }
+        }
     }
 
     /**
      *
      */
-    class ChildreCallbackWrapper implements AsyncCallback.Children2Callback {
+    class ChildrenCallbackWrapper implements AsyncCallback.Children2Callback {
         /** */
         private final GetChildrenOperation op;
 
         /**
          * @param op Operation.
          */
-        private ChildreCallbackWrapper(GetChildrenOperation op) {
+        private ChildrenCallbackWrapper(GetChildrenOperation op) {
             this.op = op;
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/fb6bd0ac/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java
----------------------------------------------------------------------
diff --git a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java
index ece71f9..6f8c07f 100644
--- a/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java
+++ b/modules/zookeeper/src/main/java/org/apache/ignite/spi/discovery/zk/internal/ZookeeperDiscoveryImpl.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CountDownLatch;
 import org.apache.curator.utils.PathUtils;
 import org.apache.ignite.IgniteCheckedException;
@@ -112,6 +113,9 @@ public class ZookeeperDiscoveryImpl {
     /** */
     private boolean crd;
 
+    /** */
+    private Map<Long, ZkEventAckFuture> ackFuts = new ConcurrentHashMap<>();
+
     /**
      * @param log
      * @param basePath
@@ -145,6 +149,10 @@ public class ZookeeperDiscoveryImpl {
         dataCallback = new ZkDataCallback();
     }
 
+    IgniteLogger log() {
+        return log;
+    }
+
     public ClusterNode localNode() {
         return locNode;
     }
@@ -664,21 +672,38 @@ public class ZookeeperDiscoveryImpl {
         // TODO ZK: use multi.
         zkClient.setData(zkPaths.evtsPath, null, -1);
 
-        for (String evtPath : zkClient.getChildren(zkPaths.evtsPath)) {
+        List<String> evtChildren = zkClient.getChildren(zkPaths.evtsPath);
+
+        for (String evtPath : evtChildren) {
             String evtDir = zkPaths.evtsPath + "/" + evtPath;
 
             removeChildren(evtDir);
-
-            zkClient.delete(evtDir, -1);
         }
 
+        zkClient.deleteAllIfExists(zkPaths.evtsPath, evtChildren, -1);
+
         for (String evtPath : zkClient.getChildren(zkPaths.customEvtsDir))
             zkClient.delete(zkPaths.customEvtsDir + "/" + evtPath, -1);
     }
 
+    /**
+     * @param path Path.
+     * @throws Exception If failed.
+     */
     private void removeChildren(String path) throws Exception {
-        for (String childPath : zkClient.getChildren(path))
-            zkClient.delete(path + "/" + childPath, -1);
+        zkClient.deleteAllIfExists(path, zkClient.getChildren(path), -1);
+    }
+
+    void removeAckFuture(ZkEventAckFuture fut) {
+        ackFuts.remove(fut.eventId());
+    }
+
+    ZkClusterNodes nodes() {
+        return top;
+    }
+
+    ZookeeperClient zkClient() {
+        return zkClient;
     }
 
     /**
@@ -914,7 +939,7 @@ public class ZookeeperDiscoveryImpl {
     @SuppressWarnings("unchecked")
     private void notifyCustomEvent(ZkDiscoveryCustomEventData evtData, DiscoverySpiCustomMessage msg) {
         if (log.isInfoEnabled())
-            log.info(" [topVer=" + evtData.topologyVersion() + ", msg=" + msg.getClass().getSimpleName() + ']');
+            log.info(" [topVer=" + evtData.topologyVersion() + ", msg=" + msg + ']');
 
         ZookeeperClusterNode sndNode = top.nodesById.get(evtData.sndNodeId);
 
@@ -928,6 +953,19 @@ public class ZookeeperDiscoveryImpl {
             topSnapshot,
             Collections.<Long, Collection<ClusterNode>>emptyMap(),
             msg);
+
+        if (crd) {
+            ZkEventAckFuture fut = new ZkEventAckFuture(this,
+                zkPaths.customEvtsDir + "/" + evtData.evtPath,
+                evtData.eventId());
+
+            ackFuts.put(evtData.eventId(), fut);
+        }
+        else {
+            String ackPath = zkPaths.customEvtsDir + "/" + evtData.evtPath + "/" + locNode.internalId();
+
+            zkClient.createAsync(ackPath, null, CreateMode.PERSISTENT, null);
+        }
     }
 
     /**
@@ -970,6 +1008,11 @@ public class ZookeeperDiscoveryImpl {
             topSnapshot,
             Collections.<Long, Collection<ClusterNode>>emptyMap(),
             null);
+
+        if (crd) {
+            for (ZkEventAckFuture ackFut : ackFuts.values())
+                ackFut.onNodeFail(failedNode);
+        }
     }
 
     /**


[47/47] ignite git commit: Merge remote-tracking branch 'remotes/origin/master' into ignite-zk

Posted by sb...@apache.org.
Merge remote-tracking branch 'remotes/origin/master' into ignite-zk


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

Branch: refs/heads/ignite-zk
Commit: 1f82a5311d099ad31c22deec391ad91d568f9705
Parents: fb6bd0a db343b6
Author: sboikov <sb...@gridgain.com>
Authored: Tue Nov 21 15:09:27 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Nov 21 15:09:27 2017 +0300

----------------------------------------------------------------------
 .../examples/datagrid/CacheQueryDdlExample.java |   2 +-
 .../ignite/examples/datagrid/JdbcExample.java   |   2 +-
 .../thin/JdbcThinAutoCloseServerCursorTest.java |   4 +-
 .../thin/JdbcThinComplexDmlDdlSelfTest.java     |   5 +-
 .../jdbc/thin/JdbcThinConnectionSelfTest.java   | 155 +--
 .../org/apache/ignite/IgniteJdbcDriver.java     |  29 +-
 .../org/apache/ignite/IgniteJdbcThinDriver.java |  35 +-
 .../apache/ignite/IgniteSystemProperties.java   |   3 +
 .../configuration/CacheConfiguration.java       |   5 +-
 .../jdbc/thin/ConnectionProperties.java         | 148 +++
 .../jdbc/thin/ConnectionPropertiesImpl.java     | 637 +++++++++++++
 .../internal/jdbc/thin/JdbcThinConnection.java  | 163 +---
 .../internal/jdbc/thin/JdbcThinTcpIo.java       | 195 +---
 .../internal/jdbc/thin/JdbcThinUtils.java       |  79 +-
 .../cache/GridCacheAffinityManager.java         |   7 +-
 .../cache/IgniteCacheOffheapManagerImpl.java    |   4 +-
 .../CacheDataStructuresManager.java             |  12 +
 .../near/GridNearOptimisticTxPrepareFuture.java |  14 +-
 .../cache/distributed/near/GridNearTxLocal.java |   7 +-
 .../cache/query/GridCacheQueryManager.java      |   5 +-
 .../cache/store/CacheStoreManager.java          |  12 +-
 .../store/GridCacheStoreManagerAdapter.java     |   7 +
 .../cache/store/GridCacheWriteBehindStore.java  |  10 +-
 .../datastreamer/DataStreamerImpl.java          |  20 +-
 .../datastructures/GridCacheQueueAdapter.java   |   5 +
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      |   2 +-
 .../processors/odbc/jdbc/JdbcStatementType.java |  13 +
 .../processors/odbc/odbc/OdbcMessageParser.java |  14 +-
 .../odbc/odbc/OdbcQueryExecuteBatchRequest.java |  16 +-
 .../odbc/odbc/OdbcQueryExecuteRequest.java      |  16 +-
 .../odbc/odbc/OdbcRequestHandler.java           |   9 +-
 .../platform/PlatformAbstractBootstrap.java     |  18 +-
 .../processors/platform/PlatformBootstrap.java  |   7 +-
 .../processors/platform/PlatformIgnition.java   |   4 +-
 .../platform/cache/PlatformCache.java           |   2 +-
 .../platform/client/ClientMessageParser.java    |  83 +-
 .../platform/client/ClientStatus.java           |   3 +
 .../ClientCacheConfigurationSerializer.java     | 180 ++++
 ...ientCacheCreateWithConfigurationRequest.java |  58 ++
 .../cache/ClientCacheCreateWithNameRequest.java |  56 ++
 .../client/cache/ClientCacheDestroyRequest.java |  49 +
 .../cache/ClientCacheEntryQueryCursor.java      |  46 +
 .../cache/ClientCacheFieldsQueryCursor.java     |  53 ++
 .../ClientCacheGetConfigurationRequest.java     |  47 +
 .../ClientCacheGetConfigurationResponse.java    |  51 +
 .../cache/ClientCacheGetNamesRequest.java       |  46 +
 .../cache/ClientCacheGetNamesResponse.java      |  56 ++
 ...acheGetOrCreateWithConfigurationRequest.java |  58 ++
 .../ClientCacheGetOrCreateWithNameRequest.java  |  49 +
 .../client/cache/ClientCacheQueryCursor.java    | 141 +++
 .../cache/ClientCacheQueryNextPageRequest.java  |  49 +
 .../cache/ClientCacheQueryNextPageResponse.java |  50 +
 .../client/cache/ClientCacheQueryResponse.java  |  52 ++
 .../client/cache/ClientCacheRequest.java        |  30 +-
 .../cache/ClientCacheScanQueryCursor.java       | 135 ---
 .../ClientCacheScanQueryNextPageRequest.java    |  49 -
 .../ClientCacheScanQueryNextPageResponse.java   |  50 -
 .../cache/ClientCacheScanQueryRequest.java      |   5 +-
 .../cache/ClientCacheScanQueryResponse.java     |  52 --
 .../cache/ClientCacheSqlFieldsQueryRequest.java | 126 +++
 .../ClientCacheSqlFieldsQueryResponse.java      |  75 ++
 .../cache/ClientCacheSqlQueryRequest.java       |  79 ++
 .../dotnet/PlatformDotNetBootstrap.java         |  26 +-
 .../PlatformDotNetConfigurationClosure.java     |  22 +-
 .../utils/PlatformConfigurationUtils.java       |  24 +-
 .../processors/query/GridQueryIndexing.java     |   5 +-
 .../processors/query/GridQueryProcessor.java    |  19 +-
 .../apache/ignite/internal/sql/SqlKeyword.java  |   3 +
 .../ignite/internal/sql/SqlParserUtils.java     |  25 +-
 .../sql/command/SqlCreateIndexCommand.java      |  41 +-
 .../cache/VisorCacheMetricsCollectorTask.java   |   5 +-
 .../visor/node/VisorGridConfiguration.java      |   6 +-
 ...reSessionListenerWriteBehindEnabledTest.java | 117 ++-
 .../cache/IgniteCacheDynamicStopSelfTest.java   |   2 +-
 ...IgniteClientCacheInitializationFailTest.java |   2 +-
 .../GridCacheQueueClientDisconnectTest.java     | 117 +++
 .../datastreamer/DataStreamerImplSelfTest.java  |  60 ++
 .../sql/SqlParserCreateIndexSelfTest.java       |  23 +
 .../IgniteCacheDataStructuresSelfTestSuite.java |   2 +
 .../hadoop/impl/v1/HadoopV1MapTask.java         |   6 +-
 .../hadoop/impl/v1/HadoopV1Reporter.java        |   8 +-
 .../processors/query/h2/IgniteH2Indexing.java   |  33 +-
 .../query/h2/ddl/DdlStatementsProcessor.java    |   1 +
 .../processors/query/h2/opt/GridH2Table.java    |  15 +-
 .../query/h2/sql/GridSqlQueryParser.java        |  12 +-
 .../h2/twostep/GridReduceQueryExecutor.java     |  11 +-
 ...CheckClusterStateBeforeExecuteQueryTest.java |  89 ++
 .../IgniteCacheQueryNodeRestartSelfTest2.java   |  75 +-
 .../IgniteCacheQueryNodeRestartTxSelfTest.java  |  36 +
 .../cache/index/AbstractSchemaSelfTest.java     |  22 +-
 ...ynamicColumnsAbstractConcurrentSelfTest.java |  25 +-
 .../cache/index/DynamicColumnsAbstractTest.java | 180 +---
 .../DynamicIndexAbstractBasicSelfTest.java      | 147 ++-
 .../DynamicIndexAbstractConcurrentSelfTest.java |  29 +-
 .../H2DynamicColumnsAbstractBasicSelfTest.java  |  35 +-
 .../index/H2DynamicIndexingComplexTest.java     |   4 +-
 .../cache/index/H2DynamicTableSelfTest.java     |  49 +-
 .../cache/index/SchemaExchangeSelfTest.java     |   2 +-
 .../query/h2/sql/GridQueryParsingTest.java      |  21 +-
 .../IgniteCacheQuerySelfTestSuite.java          |   3 +
 .../IgniteCacheQuerySelfTestSuite2.java         |   2 +
 .../clustering/KMeansDistributedClusterer.java  |  13 +-
 .../ignite/ml/math/distributed/CacheUtils.java  | 278 +++---
 .../math/distributed/keys/BlockMatrixKey.java   |  38 -
 .../distributed/keys/DataStructureCacheKey.java |  35 +
 .../math/distributed/keys/MatrixBlockKey.java   |  38 +
 .../math/distributed/keys/MatrixCacheKey.java   |  35 -
 .../math/distributed/keys/RowColMatrixKey.java  |   2 +-
 .../math/distributed/keys/VectorBlockKey.java   |  34 +
 .../distributed/keys/impl/BlockMatrixKey.java   | 164 ----
 .../distributed/keys/impl/MatrixBlockKey.java   | 162 ++++
 .../distributed/keys/impl/SparseMatrixKey.java  |  14 +-
 .../distributed/keys/impl/VectorBlockKey.java   | 151 +++
 .../ignite/ml/math/functions/Functions.java     |   3 +-
 .../ml/math/impls/matrix/AbstractMatrix.java    |  24 +-
 .../ignite/ml/math/impls/matrix/BlockEntry.java |  50 -
 .../ml/math/impls/matrix/MatrixBlockEntry.java  |  50 +
 .../matrix/SparseBlockDistributedMatrix.java    | 153 ++-
 .../impls/matrix/SparseDistributedMatrix.java   | 102 +-
 .../storage/matrix/BlockMatrixStorage.java      |  96 +-
 .../storage/matrix/BlockVectorStorage.java      | 374 ++++++++
 .../impls/storage/matrix/MapWrapperStorage.java |   5 +-
 .../matrix/SparseDistributedMatrixStorage.java  |  21 +-
 .../vector/SparseDistributedVectorStorage.java  | 280 ++++++
 .../vector/SparseBlockDistributedVector.java    | 139 +++
 .../impls/vector/SparseDistributedVector.java   | 157 ++++
 .../ml/math/impls/vector/VectorBlockEntry.java  |  49 +
 .../apache/ignite/ml/math/util/MatrixUtil.java  |   4 +-
 .../ml/math/MathImplDistributedTestSuite.java   |  16 +-
 .../SparseDistributedBlockMatrixTest.java       |  86 +-
 .../matrix/SparseDistributedMatrixTest.java     |  27 +-
 .../SparseDistributedVectorStorageTest.java     | 121 +++
 .../SparseBlockDistributedVectorTest.java       | 181 ++++
 .../vector/SparseDistributedVectorTest.java     | 192 ++++
 ...tedBlockOLSMultipleLinearRegressionTest.java | 926 ++++++++++++++++++
 ...tributedOLSMultipleLinearRegressionTest.java | 934 +++++++++++++++++++
 .../OLSMultipleLinearRegressionTest.java        |   1 +
 .../ml/regressions/RegressionsTestSuite.java    |   2 +-
 .../cpp/odbc-test/src/attributes_test.cpp       |  44 +
 .../platforms/cpp/odbc-test/src/parser_test.cpp |   2 +-
 .../cpp/odbc-test/src/queries_test.cpp          | 113 +++
 .../cpp/odbc/include/ignite/odbc/common_types.h |   3 +
 .../cpp/odbc/include/ignite/odbc/connection.h   |  81 +-
 .../cpp/odbc/include/ignite/odbc/message.h      |  33 +-
 .../cpp/odbc/include/ignite/odbc/parser.h       |   2 +-
 .../include/ignite/odbc/query/batch_query.h     |   8 +-
 .../odbc/include/ignite/odbc/query/data_query.h |   8 +-
 .../cpp/odbc/include/ignite/odbc/statement.h    |   4 +
 .../include/ignite/odbc/system/socket_client.h  |  75 +-
 .../odbc/os/linux/src/system/socket_client.cpp  | 265 +++++-
 .../odbc/os/win/src/system/socket_client.cpp    | 312 ++++++-
 modules/platforms/cpp/odbc/src/connection.cpp   | 143 ++-
 .../odbc/src/diagnostic/diagnostic_record.cpp   |   6 +
 modules/platforms/cpp/odbc/src/message.cpp      |  34 +-
 .../cpp/odbc/src/query/batch_query.cpp          |  21 +-
 .../platforms/cpp/odbc/src/query/data_query.cpp |  21 +-
 modules/platforms/cpp/odbc/src/statement.cpp    |  43 +-
 .../Apache.Ignite.AspNet.csproj                 |   3 +-
 .../Apache.Ignite.Core.Tests.csproj             |   6 +
 .../Binary/BinarySelfTest.cs                    |  88 ++
 .../Cache/CacheConfigurationTest.cs             |   9 +-
 .../Cache/MemoryMetricsTest.cs                  |   1 +
 .../Cache/PersistentStoreTestObsolete.cs        |   7 +-
 .../Cache/Query/CacheQueriesTest.cs             |   2 +
 .../Cache/Query/Linq/CacheLinqTest.Base.cs      |   3 +-
 .../Cache/Query/Linq/CacheLinqTest.Join.cs      | 110 ++-
 .../Cache/Query/Linq/CacheLinqTest.Misc.cs      |  11 +-
 .../Client/Cache/CacheTestNoMeta.cs             |  11 +-
 .../Cache/ClientCacheConfigurationTest.cs       | 211 +++++
 .../Client/Cache/CreateCacheTest.cs             | 209 +++++
 .../Client/Cache/Person.cs                      |  29 +
 .../Client/Cache/SqlQueryTest.cs                | 268 ++++++
 .../Client/ClientTestBase.cs                    |  18 +-
 .../Compute/ComputeApiTestFullFooter.cs         |   2 +
 .../Config/full-config.xml                      |   2 +-
 .../ConsoleRedirectTest.cs                      |  74 +-
 .../Apache.Ignite.Core.Tests/DeploymentTest.cs  | 137 ++-
 .../Apache.Ignite.Core.Tests/ExecutableTest.cs  |  18 +-
 .../IgniteConfigurationSerializerTest.cs        |   1 +
 .../IgniteConfigurationTest.cs                  |   3 +
 .../IgniteStartStopTest.cs                      |  12 +-
 .../MultiAppDomainTest.cs                       | 171 ++++
 .../Process/ListDataReader.cs                   |  52 ++
 .../Apache.Ignite.Core.Tests/TestUtils.cs       |  34 +-
 .../Apache.Ignite.Core.csproj                   |  65 +-
 .../Cache/Configuration/QueryEntity.cs          |  10 +-
 .../Cache/Query/IFieldsQueryCursor.cs           |  34 +
 .../Client/Cache/CacheClientConfiguration.cs    | 420 +++++++++
 .../Client/Cache/ICacheClient.cs                |  19 +
 .../Apache.Ignite.Core/Client/IIgniteClient.cs  |  50 +
 .../dotnet/Apache.Ignite.Core/IIgnite.cs        |   1 -
 .../Apache.Ignite.Core/IgniteConfiguration.cs   |  23 +
 .../IgniteConfigurationSection.xsd              |   5 +
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |  28 +-
 .../Impl/Binary/BinaryReaderExtensions.cs       |  18 +
 .../Impl/Binary/BinaryReflectiveActions.cs      |  16 +
 .../Impl/Binary/BinarySystemHandlers.cs         |  13 +-
 .../Impl/Binary/BinaryUtils.cs                  |  41 +-
 .../Impl/Binary/Marshaller.cs                   |   1 +
 .../Impl/Binary/MultidimensionalArrayHolder.cs  | 132 +++
 .../Binary/MultidimensionalArraySerializer.cs   |  48 +
 .../Impl/Cache/Query/FieldsQueryCursor.cs       |  29 +-
 .../Impl/Cache/Query/PlatformQueryQursorBase.cs |   8 +-
 .../Impl/Cache/Query/QueryCursor.cs             |  16 +-
 .../Impl/Cache/Query/QueryCursorBase.cs         |  22 +-
 .../Impl/Client/Cache/CacheClient.cs            |  86 +-
 .../Cache/ClientCacheConfigurationSerializer.cs | 261 ++++++
 .../Cache/Query/ClientFieldsQueryCursor.cs      |  79 ++
 .../Client/Cache/Query/ClientQueryCursor.cs     |  62 +-
 .../Client/Cache/Query/ClientQueryCursorBase.cs |  89 ++
 .../Impl/Client/Cache/Query/StatementType.cs    |  42 +
 .../Apache.Ignite.Core/Impl/Client/ClientOp.cs  |  13 +-
 .../Impl/Client/ClientStatus.cs                 |   1 +
 .../Impl/Client/IgniteClient.cs                 |  85 ++
 .../Apache.Ignite.Core/Impl/ExceptionUtils.cs   |  20 +-
 .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs    |   4 +-
 .../Apache.Ignite.Core/Impl/IgniteManager.cs    |  83 +-
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |  82 +-
 .../Impl/PlatformJniTarget.cs                   | 248 +++--
 .../Impl/Unmanaged/IUnmanagedTarget.cs          |  42 -
 .../Impl/Unmanaged/IgniteJniNativeMethods.cs    |  96 --
 .../Impl/Unmanaged/Jni/AppDomains.cs            | 135 +++
 .../Impl/Unmanaged/Jni/CallbackDelegates.cs     |  52 ++
 .../Impl/Unmanaged/Jni/Callbacks.cs             | 292 ++++++
 .../Impl/Unmanaged/Jni/ConsoleWriter.cs         |  47 +
 .../Impl/Unmanaged/Jni/Env.cs                   | 500 ++++++++++
 .../Impl/Unmanaged/Jni/EnvDelegates.cs          | 109 +++
 .../Impl/Unmanaged/Jni/EnvInterface.cs          | 263 ++++++
 .../Impl/Unmanaged/Jni/GlobalRef.cs             |  87 ++
 .../Impl/Unmanaged/Jni/JniResult.cs             |  35 +
 .../Impl/Unmanaged/Jni/Jvm.cs                   | 335 +++++++
 .../Impl/Unmanaged/Jni/JvmDelegates.cs          |  31 +
 .../Impl/Unmanaged/Jni/JvmInterface.cs          |  40 +
 .../Impl/Unmanaged/Jni/MethodId.cs              | 157 ++++
 .../Impl/Unmanaged/Jni/NativeMethod.cs          |  48 +
 .../Impl/Unmanaged/UnmanagedCallbackHandlers.cs |  38 -
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        | 243 ++---
 .../Impl/Unmanaged/UnmanagedContext.cs          |  53 --
 .../Unmanaged/UnmanagedNonReleaseableTarget.cs  |  70 --
 .../Impl/Unmanaged/UnmanagedTarget.cs           |  77 --
 .../Impl/Unmanaged/UnmanagedUtils.cs            | 256 ++---
 .../dotnet/Apache.Ignite.Core/build-common.ps1  |  77 --
 .../Apache.Ignite.EntityFramework.csproj        |   3 +-
 .../Impl/CacheQueryModelVisitor.cs              |  28 +-
 .../Apache.Ignite.Log4Net.csproj                |   4 +-
 modules/platforms/dotnet/Apache.Ignite.ndproj   |   8 +-
 modules/platforms/dotnet/Apache.Ignite.sln      | 143 ---
 .../dotnet/Apache.Ignite/IgniteRunner.cs        |   8 +-
 modules/platforms/dotnet/DEVNOTES.txt           |  15 +-
 modules/platforms/dotnet/build.ps1              |  10 +-
 .../examples/Apache.Ignite.Examples/App.config  |   4 -
 .../ThinClient/ThinClientPutGetExample.cs       |   5 +-
 .../ThinClient/ThinClientQueryExample.cs        |   4 +-
 .../commands/cache/VisorCacheCommandSpec.scala  |  44 +-
 modules/web-console/.gitignore                  |  11 +-
 modules/web-console/DEVNOTES.txt                |  33 +-
 modules/web-console/assembly/README.txt         |  60 ++
 modules/web-console/assembly/direct-install.xml |  91 ++
 modules/web-console/backend/.gitignore          |   6 -
 modules/web-console/backend/app/apiServer.js    |  76 +-
 .../web-console/backend/app/browsersHandler.js  | 442 +++++----
 modules/web-console/backend/app/mongo.js        |  73 +-
 modules/web-console/backend/app/nconf.js        |  44 +-
 modules/web-console/backend/app/routes.js       |  26 +-
 modules/web-console/backend/app/settings.js     |  84 +-
 modules/web-console/backend/index.js            |  25 +-
 modules/web-console/backend/injector.js         |   4 +-
 modules/web-console/backend/package.json        |  22 +-
 .../compose/frontend/nginx/web-console.conf     |   1 -
 .../docker/standalone/nginx/web-console.conf    |   1 -
 modules/web-console/frontend/.gitignore         |   8 +-
 .../generator/JavaTransformer.service.js        |   2 +
 .../frontend/app/modules/sql/sql.controller.js  |  72 +-
 .../frontend/app/utils/SimpleWorkerPool.js      |   4 +-
 .../frontend/public/stylesheets/style.scss      |  10 +
 .../web-console/frontend/views/sql/sql.tpl.pug  |  84 +-
 .../frontend/webpack/webpack.dev.babel.js       |   5 +-
 modules/web-console/pom.xml                     | 103 +-
 .../agent/handlers/AbstractListener.java        |   2 +-
 279 files changed, 15375 insertions(+), 3792 deletions(-)
----------------------------------------------------------------------



[24/47] ignite git commit: IGNITE-6907 .NET: Fix LINQ multitable conditional joins

Posted by sb...@apache.org.
IGNITE-6907 .NET: Fix LINQ multitable conditional joins

This closes #3049


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

Branch: refs/heads/ignite-zk
Commit: 1ebeee00e96f18fab851930e672525a62c29fdd0
Parents: 69eced6
Author: Alexey Popov <ta...@gmail.com>
Authored: Fri Nov 17 12:52:38 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Nov 17 12:52:38 2017 +0300

----------------------------------------------------------------------
 .../Cache/Query/Linq/CacheLinqTest.Base.cs      |   3 +-
 .../Cache/Query/Linq/CacheLinqTest.Join.cs      | 110 +++++++++++++++++--
 .../Cache/Query/Linq/CacheLinqTest.Misc.cs      |  11 +-
 .../Impl/CacheQueryModelVisitor.cs              |  28 ++++-
 4 files changed, 133 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1ebeee00/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
index ae9fd5f..9132de7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Base.cs
@@ -295,7 +295,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
             var persons = GetPersonCache().AsCacheQueryable();
 
             var res = persons
-                .Select(x => new {Foo = x.Key % 2 == 0 ? even : odd, x.Value})
+                .Select(x => new { x.Key, Foo = x.Key % 2 == 0 ? even : odd, x.Value })
+                .OrderBy(x => x.Key)
                 .ToArray();
 
             if (comparer != null)

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ebeee00/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
index f589329..4192fb0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Join.cs
@@ -85,6 +85,23 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
         }
 
         /// <summary>
+        /// Tests the multi key join inline
+        /// </summary>
+        [Test]
+        public void TestMultiKeyJoinInline()
+        {
+            var organizations = GetOrgCache().AsCacheQueryable();
+            var persons = GetPersonCache().AsCacheQueryable();
+
+            var multiKey = persons.Where(p => p.Key == 1).Join(organizations,
+                p => new { OrgId = p.Value.OrganizationId, p.Key },
+                o => new { OrgId = o.Value.Id, Key = o.Key - 1000 },
+                (p, o) => new { PersonName = p.Value.Name, OrgName = o.Value.Name });
+
+            Assert.AreEqual(" Person_1  ", multiKey.Single().PersonName);
+        }
+
+        /// <summary>
         /// Tests the cross cache join.
         /// </summary>
         [Test]
@@ -243,17 +260,23 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
         [Test]
         public void TestMultipleFrom()
         {
-            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < PersonCount);
-            var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Value.Name != "1");
-
-            var all = persons.SelectMany(person => roles.Select(role => new { role, person }));
-            Assert.AreEqual(RoleCount * PersonCount, all.Count());
+            var persons = GetPersonCache().AsCacheQueryable();
+            var roles = GetRoleCache().AsCacheQueryable();
+            var organizations = GetOrgCache().AsCacheQueryable();
 
             var filtered =
                 from person in persons
                 from role in roles
-                where person.Key == role.Key.Foo
-                select new { Person = person.Value.Name, Role = role.Value.Name };
+                from org in organizations
+                where person.Key == role.Key.Foo && person.Value.OrganizationId == org.Value.Id
+                select new
+                {
+                    PersonKey = person.Key,
+                    Person = person.Value.Name,
+                    RoleFoo = role.Key.Foo,
+                    Role = role.Value.Name,
+                    Org = org.Value.Name
+                };
 
             var res = filtered.ToArray();
 
@@ -261,22 +284,85 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
         }
 
         /// <summary>
-        /// Tests query with multiple from clause with inline query sources.
+        /// Tests query with two from clause.
         /// </summary>
         [Test]
-        public void TestMultipleFromInline()
+        public void TestTwoFromSubquery()
         {
+            var persons = GetPersonCache().AsCacheQueryable();
+            var roles = GetRoleCache().AsCacheQueryable();
+            var personsSubquery = persons.Where(x => x.Key < PersonCount);
+            var rolesSubquery = roles.Where(x => x.Value.Name == "Role_2");
+
             var filtered =
-                from person in GetPersonCache().AsCacheQueryable()
-                from role in GetRoleCache().AsCacheQueryable()
+                from person in persons
+                from role in rolesSubquery
                 where person.Key == role.Key.Foo
-                select new { Person = person.Value.Name, Role = role.Value.Name };
+                select new
+                {
+                    PersonKey = person.Key, Person = person.Value.Name,
+                    RoleFoo = role.Key.Foo, Role = role.Value.Name
+                };
 
             var res = filtered.ToArray();
+            Assert.AreEqual(1, res.Length);
+
+            filtered =
+                from person in personsSubquery
+                from role in rolesSubquery
+                where person.Key == role.Key.Foo
+                select new
+                {
+                    PersonKey = person.Key, Person = person.Value.Name,
+                    RoleFoo = role.Key.Foo, Role = role.Value.Name
+                };
 
+            res = filtered.ToArray();
+            Assert.AreEqual(1, res.Length);
+
+            filtered =
+                from person in personsSubquery
+                from role in roles
+                where person.Key == role.Key.Foo
+                select new
+                {
+                    PersonKey = person.Key, Person = person.Value.Name,
+                    RoleFoo = role.Key.Foo, Role = role.Value.Name
+                };
+
+            res = filtered.ToArray();
             Assert.AreEqual(RoleCount, res.Length);
         }
 
+
+        /// <summary>
+        /// Tests query with two from clause.
+        /// </summary>
+        [Test]
+        public void TestMultipleFromSubquery()
+        {
+            var organizations = GetOrgCache().AsCacheQueryable().Where(x => x.Key == 1001);
+            var persons = GetPersonCache().AsCacheQueryable().Where(x => x.Key < 20);
+            var roles = GetRoleCache().AsCacheQueryable().Where(x => x.Key.Foo >= 0);
+
+            var filtered =
+                from person in persons
+                from role in roles
+                from org in organizations
+                where person.Key == role.Key.Foo && person.Value.OrganizationId == org.Value.Id
+                select new
+                {
+                    PersonKey = person.Key,
+                    Person = person.Value.Name,
+                    RoleFoo = role.Key.Foo,
+                    Role = role.Value.Name,
+                    Org = org.Value.Name
+                };
+
+            var res = filtered.ToArray();
+            Assert.AreEqual(2, res.Length);
+        }
+
         /// <summary>
         /// Tests the join of a table to itself.
         /// </summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ebeee00/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
index c4ef11f..3585281 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/Linq/CacheLinqTest.Misc.cs
@@ -59,7 +59,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
 
             // Multiple values
             Assert.AreEqual(new[] { 0, 1, 2 },
-                cache.Where(x => x.Key < 3).Select(x => x.Value.Address.Zip).ToArray());
+                cache.Where(x => x.Key < 3).OrderBy(x => x.Key).Select(x => x.Value.Address.Zip).ToArray());
 
             // Single value
             Assert.AreEqual(0, cache.Where(x => x.Key < 0).Select(x => x.Value.Age).FirstOrDefault());
@@ -313,19 +313,20 @@ namespace Apache.Ignite.Core.Tests.Cache.Query.Linq
             var persons = personCache.AsCacheQueryable();
             var roles = roleCache.AsCacheQueryable();
 
-            var res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+            // we have role.Keys = [1, 2, 3] and persons.Key = [0, .. PersonCount)
+            var res = persons.Join(roles, person => person.Key % 2, role => role.Key, (person, role) => role)
                 .ToArray();
 
-            Assert.AreEqual(res.Length, RoleCount);
+            Assert.IsTrue(PersonCount / 2 > res.Length);
 
             // Test distributed join: returns complete results
             persons = personCache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true });
             roles = roleCache.AsCacheQueryable(new QueryOptions { EnableDistributedJoins = true });
 
-            res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+            res = persons.Join(roles, person => person.Key % 2, role => role.Key, (person, role) => role)
                 .ToArray();
 
-            Assert.AreEqual(RoleCount, res.Length);
+            Assert.AreEqual(PersonCount / 2, res.Length);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/1ebeee00/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
index 3a3e5fd..56c3ff5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
@@ -394,11 +394,13 @@ namespace Apache.Ignite.Linq.Impl
             ValidateFromClause(fromClause);
             _aliases.AppendAsClause(_builder, fromClause).Append(" ");
 
+            var i = 0;
             foreach (var additionalFrom in queryModel.BodyClauses.OfType<AdditionalFromClause>())
             {
                 _builder.AppendFormat(", ");
                 ValidateFromClause(additionalFrom);
-                _aliases.AppendAsClause(_builder, additionalFrom).Append(" ");
+
+                VisitAdditionalFromClause(additionalFrom, queryModel, i++);
             }
         }
 
@@ -506,6 +508,30 @@ namespace Apache.Ignite.Linq.Impl
             _builder.Append(") ");
         }
 
+        /** <inheritdoc /> */
+        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
+        public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel,
+            int index)
+        {
+            base.VisitAdditionalFromClause(fromClause, queryModel, index);
+
+            var subQuery = fromClause.FromExpression as SubQueryExpression;
+            if (subQuery != null)
+            {
+                _builder.Append("(");
+
+                VisitQueryModel(subQuery.QueryModel, true);
+
+                var alias = _aliases.GetTableAlias(subQuery.QueryModel.MainFromClause);
+                _builder.AppendFormat(") as {0} ", alias);
+            }
+            else
+            {
+                _aliases.AppendAsClause(_builder, fromClause).Append(" ");
+            }
+        }
+
+
         /// <summary>
         /// Visists Join clause in case of join with local collection
         /// </summary>


[39/47] ignite git commit: IGNITE-6337 .NET: Thin client: SQL queries

Posted by sb...@apache.org.
IGNITE-6337 .NET: Thin client: SQL queries

This closes #2832


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

Branch: refs/heads/ignite-zk
Commit: 0bd712ddb3df9408b80bf0da6d19480ef737b7bc
Parents: 25048f8
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Nov 17 17:16:38 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Nov 17 17:16:38 2017 +0300

----------------------------------------------------------------------
 .../odbc/jdbc/JdbcQueryExecuteRequest.java      |   2 +-
 .../processors/odbc/jdbc/JdbcStatementType.java |  13 +
 .../platform/cache/PlatformCache.java           |   2 +-
 .../platform/client/ClientMessageParser.java    |  34 ++-
 .../cache/ClientCacheEntryQueryCursor.java      |  46 ++++
 .../cache/ClientCacheFieldsQueryCursor.java     |  53 ++++
 .../client/cache/ClientCacheQueryCursor.java    | 141 ++++++++++
 .../cache/ClientCacheQueryNextPageRequest.java  |  49 ++++
 .../cache/ClientCacheQueryNextPageResponse.java |  50 ++++
 .../client/cache/ClientCacheQueryResponse.java  |  52 ++++
 .../client/cache/ClientCacheRequest.java        |  30 ++-
 .../cache/ClientCacheScanQueryCursor.java       | 135 ----------
 .../ClientCacheScanQueryNextPageRequest.java    |  49 ----
 .../ClientCacheScanQueryNextPageResponse.java   |  50 ----
 .../cache/ClientCacheScanQueryRequest.java      |   5 +-
 .../cache/ClientCacheScanQueryResponse.java     |  52 ----
 .../cache/ClientCacheSqlFieldsQueryRequest.java | 126 +++++++++
 .../ClientCacheSqlFieldsQueryResponse.java      |  75 ++++++
 .../cache/ClientCacheSqlQueryRequest.java       |  79 ++++++
 .../Apache.Ignite.Core.Tests.csproj             |   1 +
 .../Client/Cache/CacheTestNoMeta.cs             |  11 +-
 .../Client/Cache/Person.cs                      |  29 ++
 .../Client/Cache/SqlQueryTest.cs                | 268 +++++++++++++++++++
 .../Client/ClientTestBase.cs                    |  11 +-
 .../Apache.Ignite.Core.csproj                   |   4 +
 .../Cache/Query/IFieldsQueryCursor.cs           |  34 +++
 .../Client/Cache/ICacheClient.cs                |  14 +
 .../Impl/Cache/Query/FieldsQueryCursor.cs       |  29 +-
 .../Impl/Cache/Query/PlatformQueryQursorBase.cs |   8 +-
 .../Impl/Cache/Query/QueryCursor.cs             |  16 +-
 .../Impl/Cache/Query/QueryCursorBase.cs         |  22 +-
 .../Impl/Client/Cache/CacheClient.cs            |  80 +++++-
 .../Cache/Query/ClientFieldsQueryCursor.cs      |  79 ++++++
 .../Client/Cache/Query/ClientQueryCursor.cs     |  62 +----
 .../Client/Cache/Query/ClientQueryCursorBase.cs |  89 ++++++
 .../Impl/Client/Cache/Query/StatementType.cs    |  42 +++
 .../Apache.Ignite.Core/Impl/Client/ClientOp.cs  |   6 +-
 37 files changed, 1428 insertions(+), 420 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
index 1c6262e..3e54fc8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcQueryExecuteRequest.java
@@ -156,7 +156,7 @@ public class JdbcQueryExecuteRequest extends JdbcRequest {
 
         try {
             if (reader.available() > 0)
-                stmtType = JdbcStatementType.values()[reader.readByte()];
+                stmtType = JdbcStatementType.fromOrdinal(reader.readByte());
             else
                 stmtType = JdbcStatementType.ANY_STATEMENT_TYPE;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
index aec2d12..ebe303f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcStatementType.java
@@ -29,4 +29,17 @@ public enum JdbcStatementType {
 
     /** DML / DDL statement type. */
     UPDATE_STMT_TYPE;
+
+    /** Enumerated values. */
+    private static final JdbcStatementType[] VALS = values();
+
+    /**
+     * Efficiently gets enumerated value from its ordinal.
+     *
+     * @param ord Ordinal value.
+     * @return Enumerated value or {@code null} if ordinal out of range.
+     */
+    public static JdbcStatementType fromOrdinal(int ord) {
+        return ord >= 0 && ord < VALS.length ? VALS[ord] : null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
index 0e227f5..bbdd6d2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
@@ -930,7 +930,7 @@ public class PlatformCache extends PlatformAbstractTarget {
      * @param reader Reader.
      * @return Arguments.
      */
-    @Nullable private Object[] readQueryArgs(BinaryRawReaderEx reader) {
+    @Nullable public static Object[] readQueryArgs(BinaryRawReaderEx reader) {
         int cnt = reader.readInt();
 
         if (cnt > 0) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
index 4ad6a90..626b7ff 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/ClientMessageParser.java
@@ -54,14 +54,16 @@ import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheGe
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCachePutAllRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCachePutIfAbsentRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCachePutRequest;
-import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheRemoveIfEqualsRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheQueryNextPageRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheRemoveAllRequest;
-import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheRemoveKeysRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheRemoveIfEqualsRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheRemoveKeyRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheRemoveKeysRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheReplaceIfEqualsRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheReplaceRequest;
-import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheScanQueryNextPageRequest;
 import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheScanQueryRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheSqlFieldsQueryRequest;
+import org.apache.ignite.internal.processors.platform.client.cache.ClientCacheSqlQueryRequest;
 
 /**
  * Thin client message parser.
@@ -172,6 +174,18 @@ public class ClientMessageParser implements ClientListenerMessageParser {
     /** */
     private static final short OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION = 35;
 
+    /** */
+    private static final short OP_QUERY_SQL = 36;
+
+    /** */
+    private static final short OP_QUERY_SQL_CURSOR_GET_PAGE = 37;
+
+    /** */
+    private static final short OP_QUERY_SQL_FIELDS = 38;
+
+    /** */
+    private static final short OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE = 39;
+
     /** Marshaller. */
     private final GridBinaryMarshaller marsh;
 
@@ -229,7 +243,7 @@ public class ClientMessageParser implements ClientListenerMessageParser {
                 return new ClientCacheScanQueryRequest(reader);
 
             case OP_QUERY_SCAN_CURSOR_GET_PAGE:
-                return new ClientCacheScanQueryNextPageRequest(reader);
+                return new ClientCacheQueryNextPageRequest(reader);
 
             case OP_RESOURCE_CLOSE:
                 return new ClientResourceCloseRequest(reader);
@@ -311,6 +325,18 @@ public class ClientMessageParser implements ClientListenerMessageParser {
 
             case OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION:
                 return new ClientCacheGetOrCreateWithConfigurationRequest(reader);
+
+            case OP_QUERY_SQL:
+                return new ClientCacheSqlQueryRequest(reader);
+
+            case OP_QUERY_SQL_CURSOR_GET_PAGE:
+                return new ClientCacheQueryNextPageRequest(reader);
+
+            case OP_QUERY_SQL_FIELDS:
+                return new ClientCacheSqlFieldsQueryRequest(reader);
+
+            case OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE:
+                return new ClientCacheQueryNextPageRequest(reader);
         }
 
         return new ClientRawRequest(reader.readLong(), ClientStatus.INVALID_OP_CODE,

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheEntryQueryCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheEntryQueryCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheEntryQueryCursor.java
new file mode 100644
index 0000000..5269342
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheEntryQueryCursor.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.platform.client.cache;
+
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+
+import javax.cache.Cache;
+
+/**
+ * Query cursor holder.
+  */
+class ClientCacheEntryQueryCursor extends ClientCacheQueryCursor<Cache.Entry> {
+    /**
+     * Ctor.
+     *
+     * @param cursor   Cursor.
+     * @param pageSize Page size.
+     * @param ctx      Context.
+     */
+    ClientCacheEntryQueryCursor(QueryCursor<Cache.Entry> cursor, int pageSize, ClientConnectionContext ctx) {
+        super(cursor, pageSize, ctx);
+    }
+
+    /** {@inheritDoc} */
+    @Override void writeEntry(BinaryRawWriterEx writer, Cache.Entry e) {
+        writer.writeObjectDetached(e.getKey());
+        writer.writeObjectDetached(e.getValue());
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheFieldsQueryCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheFieldsQueryCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheFieldsQueryCursor.java
new file mode 100644
index 0000000..98b747b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheFieldsQueryCursor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+
+import java.util.List;
+
+/**
+ * Query cursor holder.
+  */
+class ClientCacheFieldsQueryCursor extends ClientCacheQueryCursor<List> {
+    /** Column count. */
+    private final int columnCount;
+
+    /**
+     * Ctor.
+     *
+     * @param cursor   Cursor.
+     * @param pageSize Page size.
+     * @param ctx      Context.
+     */
+    ClientCacheFieldsQueryCursor(FieldsQueryCursor<List> cursor, int pageSize, ClientConnectionContext ctx) {
+        super(cursor, pageSize, ctx);
+
+        columnCount = cursor.getColumnsCount();
+    }
+
+    /** {@inheritDoc} */
+    @Override void writeEntry(BinaryRawWriterEx writer, List e) {
+        assert e.size() == columnCount;
+
+        for (Object o : e)
+            writer.writeObjectDetached(o);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryCursor.java
new file mode 100644
index 0000000..080ab74
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryCursor.java
@@ -0,0 +1,141 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientCloseableResource;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+
+import java.util.Iterator;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Base query cursor holder.
+  */
+abstract class ClientCacheQueryCursor<T> implements ClientCloseableResource {
+    /** Cursor. */
+    private final QueryCursor<T> cursor;
+
+    /** Page size. */
+    private final int pageSize;
+
+    /** Context. */
+    private final ClientConnectionContext ctx;
+
+    /** Id. */
+    private long id;
+
+    /** Iterator. */
+    private Iterator<T> iterator;
+
+    /** Close guard. */
+    private final AtomicBoolean closeGuard = new AtomicBoolean();
+
+    /**
+     * Ctor.
+     *  @param cursor Cursor.
+     * @param pageSize Page size.
+     * @param ctx Context.
+     */
+    ClientCacheQueryCursor(QueryCursor<T> cursor, int pageSize, ClientConnectionContext ctx) {
+        assert cursor != null;
+        assert pageSize > 0;
+        assert ctx != null;
+
+        this.cursor = cursor;
+        this.pageSize = pageSize;
+        this.ctx = ctx;
+    }
+
+    /**
+     * Writes next page to the writer.
+     *
+     * @param writer Writer.
+     */
+    void writePage(BinaryRawWriterEx writer) {
+        Iterator<T> iter = iterator();
+
+        int cntPos = writer.reserveInt();
+        int cnt = 0;
+
+        while (cnt < pageSize && iter.hasNext()) {
+            T e = iter.next();
+
+            writeEntry(writer, e);
+
+            cnt++;
+        }
+
+        writer.writeInt(cntPos, cnt);
+
+        writer.writeBoolean(iter.hasNext());
+
+        if (!iter.hasNext())
+            ctx.resources().release(id);
+    }
+
+    /**
+     * Writes cursor entry.
+     *
+     * @param writer Writer.
+     * @param e Entry.
+     */
+    abstract void writeEntry(BinaryRawWriterEx writer, T e);
+
+    /**
+     * Closes the cursor.
+     */
+    @Override public void close() {
+        if (closeGuard.compareAndSet(false, true)) {
+            cursor.close();
+
+            ctx.decrementCursors();
+        }
+    }
+
+    /**
+     * Sets the cursor id.
+     *
+     * @param id Id.
+     */
+    public void id(long id) {
+        this.id = id;
+    }
+
+    /**
+     * Gets the cursor id.
+     *
+     * @return Id.
+     */
+    public long id() {
+        return id;
+    }
+
+    /**
+     * Gets the iterator.
+     *
+     * @return Iterator.
+     */
+    private Iterator<T> iterator() {
+        if (iterator == null)
+            iterator = cursor.iterator();
+
+        return iterator;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageRequest.java
new file mode 100644
index 0000000..a6aa799
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageRequest.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.platform.client.cache;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientRequest;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Query cursor next page request.
+ */
+public class ClientCacheQueryNextPageRequest extends ClientRequest {
+    /** Cursor id. */
+    private final long cursorId;
+
+    /**
+     * Ctor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheQueryNextPageRequest(BinaryRawReader reader) {
+        super(reader);
+
+        cursorId = reader.readLong();
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        ClientCacheQueryCursor cur = ctx.resources().get(cursorId);
+
+        return new ClientCacheQueryNextPageResponse(requestId(), cur);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageResponse.java
new file mode 100644
index 0000000..af81ac5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryNextPageResponse.java
@@ -0,0 +1,50 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Query cursor next page response.
+ */
+class ClientCacheQueryNextPageResponse extends ClientResponse {
+    /** Cursor. */
+    private final ClientCacheQueryCursor cursor;
+
+    /**
+     * Ctor.
+     *
+     * @param requestId Request id.
+     * @param cursor Cursor.
+     */
+    ClientCacheQueryNextPageResponse(long requestId, ClientCacheQueryCursor cursor) {
+        super(requestId);
+
+        assert cursor != null;
+
+        this.cursor = cursor;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        cursor.writePage(writer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryResponse.java
new file mode 100644
index 0000000..ab76387
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheQueryResponse.java
@@ -0,0 +1,52 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+/**
+ * Scan query response.
+ */
+class ClientCacheQueryResponse extends ClientResponse {
+    /** Cursor. */
+    private final ClientCacheQueryCursor cursor;
+
+    /**
+     * Ctor.
+     *
+     * @param requestId Request id.
+     * @param cursor Cursor.
+     */
+    ClientCacheQueryResponse(long requestId, ClientCacheQueryCursor cursor) {
+        super(requestId);
+
+        assert cursor != null;
+
+        this.cursor = cursor;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        writer.writeLong(cursor.id());
+
+        cursor.writePage(writer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRequest.java
index b290a5b..44416be 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheRequest.java
@@ -77,14 +77,34 @@ class ClientCacheRequest extends ClientRequest {
      * @return Cache.
      */
     protected IgniteCache rawCache(ClientConnectionContext ctx) {
-        DynamicCacheDescriptor cacheDesc = ctx.kernalContext().cache().cacheDescriptor(cacheId);
-
-        if (cacheDesc == null)
-            throw new IgniteClientException(ClientStatus.CACHE_DOES_NOT_EXIST, "Cache does not exist [cacheId= " +
-                cacheId + "]", null);
+        DynamicCacheDescriptor cacheDesc = cacheDescriptor(ctx);
 
         String cacheName = cacheDesc.cacheName();
 
         return ctx.kernalContext().grid().cache(cacheName);
     }
+
+    /**
+     * Gets the cache descriptor.
+     *
+     * @return Cache descriptor.
+     */
+    protected DynamicCacheDescriptor cacheDescriptor(ClientConnectionContext ctx) {
+        DynamicCacheDescriptor desc = ctx.kernalContext().cache().cacheDescriptor(cacheId);
+
+        if (desc == null)
+            throw new IgniteClientException(ClientStatus.CACHE_DOES_NOT_EXIST, "Cache does not exist [cacheId= " +
+                    cacheId + "]", null);
+
+        return desc;
+    }
+
+    /**
+     * Gets the cache id.
+     *
+     * @return Cache id.
+     */
+    protected int cacheId() {
+        return cacheId;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryCursor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryCursor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryCursor.java
deleted file mode 100644
index 9d3d158..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryCursor.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.platform.client.cache;
-
-import org.apache.ignite.internal.binary.BinaryRawWriterEx;
-import org.apache.ignite.internal.processors.cache.query.QueryCursorEx;
-import org.apache.ignite.internal.processors.platform.client.ClientCloseableResource;
-import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
-
-import javax.cache.Cache;
-import java.util.Iterator;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Query cursor holder.
-  */
-class ClientCacheScanQueryCursor implements ClientCloseableResource {
-    /** Cursor. */
-    private final QueryCursorEx<Cache.Entry> cursor;
-
-    /** Page size. */
-    private final int pageSize;
-
-    /** Context. */
-    private final ClientConnectionContext ctx;
-
-    /** Id. */
-    private long id;
-
-    /** Iterator. */
-    private Iterator<Cache.Entry> iterator;
-
-    /** Close guard. */
-    private final AtomicBoolean closeGuard = new AtomicBoolean();
-
-    /**
-     * Ctor.
-     *  @param cursor Cursor.
-     * @param pageSize Page size.
-     * @param ctx Context.
-     */
-    ClientCacheScanQueryCursor(QueryCursorEx<Cache.Entry> cursor, int pageSize, ClientConnectionContext ctx) {
-        assert cursor != null;
-        assert pageSize > 0;
-        assert ctx != null;
-
-        this.cursor = cursor;
-        this.pageSize = pageSize;
-        this.ctx = ctx;
-    }
-
-    /**
-     * Writes next page to the writer.
-     *
-     * @param writer Writer.
-     */
-    void writePage(BinaryRawWriterEx writer) {
-        Iterator<Cache.Entry> iter = iterator();
-
-        int cntPos = writer.reserveInt();
-        int cnt = 0;
-
-        while (cnt < pageSize && iter.hasNext()) {
-            Cache.Entry e = iter.next();
-
-            writer.writeObjectDetached(e.getKey());
-            writer.writeObjectDetached(e.getValue());
-
-            cnt++;
-        }
-
-        writer.writeInt(cntPos, cnt);
-
-        writer.writeBoolean(iter.hasNext());
-
-        if (!iter.hasNext())
-            ctx.resources().release(id);
-    }
-
-    /**
-     * Closes the cursor.
-     */
-    @Override public void close() {
-        if (closeGuard.compareAndSet(false, true)) {
-            cursor.close();
-
-            ctx.decrementCursors();
-        }
-    }
-
-    /**
-     * Sets the cursor id.
-     *
-     * @param id Id.
-     */
-    public void id(long id) {
-        this.id = id;
-    }
-
-    /**
-     * Gets the cursor id.
-     *
-     * @return Id.
-     */
-    public long id() {
-        return id;
-    }
-
-    /**
-     * Gets the iterator.
-     *
-     * @return Iterator.
-     */
-    private Iterator<Cache.Entry> iterator() {
-        if (iterator == null)
-            iterator = cursor.iterator();
-
-        return iterator;
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageRequest.java
deleted file mode 100644
index a9620d2..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageRequest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.platform.client.cache;
-
-import org.apache.ignite.binary.BinaryRawReader;
-import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
-import org.apache.ignite.internal.processors.platform.client.ClientRequest;
-import org.apache.ignite.internal.processors.platform.client.ClientResponse;
-
-/**
- * Query cursor next page request.
- */
-public class ClientCacheScanQueryNextPageRequest extends ClientRequest {
-    /** Cursor id. */
-    private final long cursorId;
-
-    /**
-     * Ctor.
-     *
-     * @param reader Reader.
-     */
-    public ClientCacheScanQueryNextPageRequest(BinaryRawReader reader) {
-        super(reader);
-
-        cursorId = reader.readLong();
-    }
-
-    /** {@inheritDoc} */
-    @Override public ClientResponse process(ClientConnectionContext ctx) {
-        ClientCacheScanQueryCursor cur = ctx.resources().get(cursorId);
-
-        return new ClientCacheScanQueryNextPageResponse(requestId(), cur);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageResponse.java
deleted file mode 100644
index e4ffe6d..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryNextPageResponse.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.platform.client.cache;
-
-import org.apache.ignite.internal.binary.BinaryRawWriterEx;
-import org.apache.ignite.internal.processors.platform.client.ClientResponse;
-
-/**
- * Query cursor next page response.
- */
-class ClientCacheScanQueryNextPageResponse extends ClientResponse {
-    /** Cursor. */
-    private final ClientCacheScanQueryCursor cursor;
-
-    /**
-     * Ctor.
-     *
-     * @param requestId Request id.
-     * @param cursor Cursor.
-     */
-    ClientCacheScanQueryNextPageResponse(long requestId, ClientCacheScanQueryCursor cursor) {
-        super(requestId);
-
-        assert cursor != null;
-
-        this.cursor = cursor;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void encode(BinaryRawWriterEx writer) {
-        super.encode(writer);
-
-        cursor.writePage(writer);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
index 7c163e3..26ab236 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryRequest.java
@@ -23,7 +23,6 @@ import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.ScanQuery;
 import org.apache.ignite.internal.binary.BinaryRawReaderEx;
-import org.apache.ignite.internal.processors.cache.query.QueryCursorEx;
 import org.apache.ignite.internal.processors.platform.PlatformContext;
 import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
 import org.apache.ignite.internal.processors.platform.client.ClientResponse;
@@ -94,13 +93,13 @@ public class ClientCacheScanQueryRequest extends ClientCacheRequest {
         try {
             QueryCursor cur = cache.query(qry);
 
-            ClientCacheScanQueryCursor cliCur = new ClientCacheScanQueryCursor((QueryCursorEx)cur, pageSize, ctx);
+            ClientCacheEntryQueryCursor cliCur = new ClientCacheEntryQueryCursor(cur, pageSize, ctx);
 
             long cursorId = ctx.resources().put(cliCur);
 
             cliCur.id(cursorId);
 
-            return new ClientCacheScanQueryResponse(requestId(), cliCur);
+            return new ClientCacheQueryResponse(requestId(), cliCur);
         }
         catch (Exception e) {
             ctx.decrementCursors();

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryResponse.java
deleted file mode 100644
index 0623804..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheScanQueryResponse.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.platform.client.cache;
-
-import org.apache.ignite.internal.binary.BinaryRawWriterEx;
-import org.apache.ignite.internal.processors.platform.client.ClientResponse;
-
-/**
- * Scan query response.
- */
-class ClientCacheScanQueryResponse extends ClientResponse {
-    /** Cursor. */
-    private final ClientCacheScanQueryCursor cursor;
-
-    /**
-     * Ctor.
-     *
-     * @param requestId Request id.
-     * @param cursor Cursor.
-     */
-    ClientCacheScanQueryResponse(long requestId, ClientCacheScanQueryCursor cursor) {
-        super(requestId);
-
-        assert cursor != null;
-
-        this.cursor = cursor;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void encode(BinaryRawWriterEx writer) {
-        super.encode(writer);
-
-        writer.writeLong(cursor.id());
-
-        cursor.writePage(writer);
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
new file mode 100644
index 0000000..ca3595d
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryRequest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.platform.client.cache;
+
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.binary.BinaryRawReaderEx;
+import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
+import org.apache.ignite.internal.processors.cache.query.SqlFieldsQueryEx;
+import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType;
+import org.apache.ignite.internal.processors.platform.cache.PlatformCache;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+import org.apache.ignite.internal.processors.query.QueryUtils;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Sql query request.
+ */
+@SuppressWarnings("unchecked")
+public class ClientCacheSqlFieldsQueryRequest extends ClientCacheRequest {
+    /** Query. */
+    private final SqlFieldsQuery qry;
+
+    /** Include field names flag. */
+    private final boolean includeFieldNames;
+
+    /**
+     * Ctor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheSqlFieldsQueryRequest(BinaryRawReaderEx reader) {
+        super(reader);
+
+        // Same request format as in JdbcQueryExecuteRequest.
+        String schema = reader.readString();
+        int pageSize = reader.readInt();
+        reader.readInt();  // maxRows
+        String sql = reader.readString();
+        Object[] args = PlatformCache.readQueryArgs(reader);
+        JdbcStatementType stmtType = JdbcStatementType.fromOrdinal(reader.readByte());
+        boolean distributedJoins = reader.readBoolean();
+        boolean loc = reader.readBoolean();
+        boolean replicatedOnly = reader.readBoolean();
+        boolean enforceJoinOrder = reader.readBoolean();
+        boolean collocated = reader.readBoolean();
+        boolean lazy = reader.readBoolean();
+        int timeout = (int) reader.readLong();
+        includeFieldNames = reader.readBoolean();
+
+        SqlFieldsQuery qry = stmtType == JdbcStatementType.ANY_STATEMENT_TYPE
+                ? new SqlFieldsQuery(sql)
+                : new SqlFieldsQueryEx(sql,stmtType == JdbcStatementType.SELECT_STATEMENT_TYPE);
+
+        qry.setSchema(schema)
+                .setPageSize(pageSize)
+                .setArgs(args)
+                .setDistributedJoins(distributedJoins)
+                .setLocal(loc)
+                .setReplicatedOnly(replicatedOnly)
+                .setEnforceJoinOrder(enforceJoinOrder)
+                .setCollocated(collocated)
+                .setLazy(lazy)
+                .setTimeout(timeout, TimeUnit.MILLISECONDS);
+
+        this.qry = qry;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        ctx.incrementCursors();
+
+        try {
+            // If cacheId is provided, we must check the cache for existence.
+            if (cacheId() != 0) {
+                DynamicCacheDescriptor desc = cacheDescriptor(ctx);
+
+                if (qry.getSchema() == null) {
+                    String schema = QueryUtils.normalizeSchemaName(desc.cacheName(),
+                            desc.cacheConfiguration().getSqlSchema());
+
+                    qry.setSchema(schema);
+                }
+            }
+
+            List<FieldsQueryCursor<List<?>>> curs = ctx.kernalContext().query()
+                    .querySqlFieldsNoCache(qry, true, true);
+
+            assert curs.size() == 1;
+
+            FieldsQueryCursor cur = curs.get(0);
+
+            ClientCacheFieldsQueryCursor cliCur = new ClientCacheFieldsQueryCursor(
+                    cur, qry.getPageSize(), ctx);
+
+            long cursorId = ctx.resources().put(cliCur);
+
+            cliCur.id(cursorId);
+
+            return new ClientCacheSqlFieldsQueryResponse(requestId(), cliCur, cur, includeFieldNames);
+        }
+        catch (Exception e) {
+            ctx.decrementCursors();
+
+            throw e;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryResponse.java
new file mode 100644
index 0000000..1ff2ea5
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlFieldsQueryResponse.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.platform.client.cache;
+
+import org.apache.ignite.cache.query.FieldsQueryCursor;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+import java.util.List;
+
+/**
+ * Scan query response.
+ */
+class ClientCacheSqlFieldsQueryResponse extends ClientResponse {
+    /** Cursor. */
+    private final ClientCacheQueryCursor cursor;
+
+    /** Fields cursor. */
+    private final FieldsQueryCursor<List> fieldsCursor;
+
+    /** Include field names flag. */
+    private final boolean includeFieldNames;
+
+    /**
+     * Ctor.
+     * @param requestId Request id.
+     * @param cursor Client cursor.
+     * @param fieldsCursor Fields cursor.
+     * @param includeFieldNames Whether to include field names.
+     */
+    ClientCacheSqlFieldsQueryResponse(long requestId, ClientCacheQueryCursor cursor,
+                                      FieldsQueryCursor<List> fieldsCursor, boolean includeFieldNames) {
+        super(requestId);
+
+        assert cursor != null;
+        assert fieldsCursor != null;
+
+        this.cursor = cursor;
+        this.fieldsCursor = fieldsCursor;
+        this.includeFieldNames = includeFieldNames;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void encode(BinaryRawWriterEx writer) {
+        super.encode(writer);
+
+        writer.writeLong(cursor.id());
+
+        int cnt = fieldsCursor.getColumnsCount();
+        writer.writeInt(cnt);
+
+        if (includeFieldNames) {
+            for (int i = 0; i < cnt; i++) {
+                writer.writeString(fieldsCursor.getFieldName(i));
+            }
+        }
+
+        cursor.writePage(writer);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.java
new file mode 100644
index 0000000..8c21be1
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/client/cache/ClientCacheSqlQueryRequest.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.internal.processors.platform.client.cache;
+
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.internal.binary.BinaryRawReaderEx;
+import org.apache.ignite.internal.processors.platform.cache.PlatformCache;
+import org.apache.ignite.internal.processors.platform.client.ClientConnectionContext;
+import org.apache.ignite.internal.processors.platform.client.ClientResponse;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Sql query request.
+ */
+@SuppressWarnings("unchecked")
+public class ClientCacheSqlQueryRequest extends ClientCacheRequest {
+    /** Query. */
+    private final SqlQuery qry;
+
+    /**
+     * Ctor.
+     *
+     * @param reader Reader.
+     */
+    public ClientCacheSqlQueryRequest(BinaryRawReaderEx reader) {
+        super(reader);
+
+        qry = new SqlQuery(reader.readString(), reader.readString())
+                .setArgs(PlatformCache.readQueryArgs(reader))
+                .setDistributedJoins(reader.readBoolean())
+                .setLocal(reader.readBoolean())
+                .setReplicatedOnly(reader.readBoolean())
+                .setPageSize(reader.readInt())
+                .setTimeout((int) reader.readLong(), TimeUnit.MILLISECONDS);
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClientResponse process(ClientConnectionContext ctx) {
+        IgniteCache cache = cache(ctx);
+
+        ctx.incrementCursors();
+
+        try {
+            QueryCursor cur = cache.query(qry);
+
+            ClientCacheEntryQueryCursor cliCur = new ClientCacheEntryQueryCursor(
+                    cur, qry.getPageSize(), ctx);
+
+            long cursorId = ctx.resources().put(cliCur);
+
+            cliCur.id(cursorId);
+
+            return new ClientCacheQueryResponse(requestId(), cliCur);
+        }
+        catch (Exception e) {
+            ctx.decrementCursors();
+
+            throw e;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 2e34ba2..2d5a54b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -112,6 +112,7 @@
     <Compile Include="Client\Cache\CreateCacheTest.cs" />
     <Compile Include="Client\Cache\ScanQueryTest.cs" />
     <Compile Include="Client\Cache\Person.cs" />
+    <Compile Include="Client\Cache\SqlQueryTest.cs" />
     <Compile Include="Client\ClientTestBase.cs" />
     <Compile Include="Client\RawSocketTest.cs" />
     <Compile Include="Client\ClientConnectionTest.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
index 782e3cc..a2ca65d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/CacheTestNoMeta.cs
@@ -52,16 +52,7 @@ namespace Apache.Ignite.Core.Tests.Client.Cache
             using (var client = Ignition.StartClient(cfg))
             {
                 var serverCache = Ignition.GetIgnite().GetOrCreateCache<int?, Person>(
-                    new CacheConfiguration("person", new QueryEntity
-                    {
-                        KeyType = typeof(int),
-                        ValueType = typeof(Person),
-                        Fields = new[]
-                        {
-                            new QueryField("id", typeof(int)),
-                            new QueryField("name", typeof(string))
-                        }
-                    }));
+                    new CacheConfiguration("person", typeof(Person)));
 
                 var clientCache = client.GetCache<int?, Person>(serverCache.Name);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/Person.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/Person.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/Person.cs
index a6bc9d7..327e707 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/Person.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/Person.cs
@@ -17,22 +17,51 @@
 
 namespace Apache.Ignite.Core.Tests.Client.Cache
 {
+    using System;
+    using Apache.Ignite.Core.Cache.Configuration;
+
     /// <summary>
     /// Test person.
     /// </summary>
     public class Person
     {
         /// <summary>
+        /// Initializes a new instance of the <see cref="Person"/> class.
+        /// </summary>
+        public Person()
+        {
+            DateTime = DateTime.UtcNow;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Person"/> class.
+        /// </summary>
+        public Person(int id)
+        {
+            Id = id;
+            Name = "Person " + id;
+            DateTime = DateTime.UtcNow.AddDays(id);
+        }
+
+        /// <summary>
         /// Gets or sets the identifier.
         /// </summary>
+        [QuerySqlField(IsIndexed = true)]
         public int Id { get; set; }
 
         /// <summary>
         /// Gets or sets the name.
         /// </summary>
+        [QuerySqlField]
         public string Name { get; set; }
 
         /// <summary>
+        /// Gets or sets the date time.
+        /// </summary>
+        [QuerySqlField]
+        public DateTime DateTime { get; set; }
+
+        /// <summary>
         /// Gets or sets the parent.
         /// </summary>
         public Person Parent { get;set; }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SqlQueryTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SqlQueryTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SqlQueryTest.cs
new file mode 100644
index 0000000..720a71b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/Cache/SqlQueryTest.cs
@@ -0,0 +1,268 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Tests.Client.Cache
+{
+    using System;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache.Configuration;
+    using Apache.Ignite.Core.Cache.Query;
+    using Apache.Ignite.Core.Client;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests SQL queries via thin client.
+    /// </summary>
+    public class SqlQueryTest : ClientTestBase
+    {
+        /// <summary>
+        /// Cache item count.
+        /// </summary>
+        private const int Count = 10;
+
+        /// <summary>
+        /// Second cache name.
+        /// </summary>
+        private const string CacheName2 = CacheName + "2";
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ScanQueryTest"/> class.
+        /// </summary>
+        public SqlQueryTest() : base(2)
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Sets up the test.
+        /// </summary>
+        public override void TestSetUp()
+        {
+            InitCache(CacheName);
+            InitCache(CacheName2);
+        }
+
+        /// <summary>
+        /// Tests the SQL query.
+        /// </summary>
+        [Test]
+        public void TestSqlQuery()
+        {
+            var cache = GetClientCache<Person>();
+
+            // All items.
+            var qry = new SqlQuery(typeof(Person), "where 1 = 1");
+            Assert.AreEqual(Count, cache.Query(qry).Count());
+
+            // All items local.
+            qry.Local = true;
+            Assert.Greater(Count, cache.Query(qry).Count());
+
+            // Filter.
+            qry = new SqlQuery(typeof(Person), "where Name like '%7'");
+            Assert.AreEqual(7, cache.Query(qry).Single().Key);
+
+            // Args.
+            qry = new SqlQuery(typeof(Person), "where Id = ?", 3);
+            Assert.AreEqual(3, cache.Query(qry).Single().Value.Id);
+
+            // DateTime.
+            qry = new SqlQuery(typeof(Person), "where DateTime > ?", DateTime.UtcNow.AddDays(Count - 1));
+            Assert.AreEqual(Count, cache.Query(qry).Single().Key);
+
+            // Invalid args.
+            qry.Sql = null;
+            Assert.Throws<ArgumentNullException>(() => cache.Query(qry));
+
+            qry.Sql = "abc";
+            qry.QueryType = null;
+            Assert.Throws<ArgumentNullException>(() => cache.Query(qry));
+        }
+
+        /// <summary>
+        /// Tests the SQL query with distributed joins.
+        /// </summary>
+        [Test]
+        public void TestSqlQueryDistributedJoins()
+        {
+            var cache = GetClientCache<Person>();
+
+            // Non-distributed join returns incomplete results.
+            var qry = new SqlQuery(typeof(Person),
+                string.Format("from \"{0}\".Person, \"{1}\".Person as p2 where Person.Id = 11 - p2.Id",
+                    CacheName, CacheName2));
+            
+            Assert.Greater(Count, cache.Query(qry).Count());
+
+            // Distributed join fixes the problem.
+            qry.EnableDistributedJoins = true;
+            Assert.AreEqual(Count, cache.Query(qry).Count());
+        }
+
+        /// <summary>
+        /// Tests the fields query.
+        /// </summary>
+        [Test]
+        public void TestFieldsQuery()
+        {
+            var cache = GetClientCache<Person>();
+
+            // All items.
+            var qry = new SqlFieldsQuery("select Id from Person");
+            var cursor = cache.Query(qry);
+            CollectionAssert.AreEquivalent(Enumerable.Range(1, Count), cursor.Select(x => (int) x[0]));
+            Assert.AreEqual("ID", cursor.FieldNames.Single());
+
+            // All items local.
+            // TODO: IGNITE-5571 - exception should be fixed.
+            qry.Local = true;
+            Assert.Throws<IgniteClientException>(() => Assert.Greater(Count, cache.Query(qry).Count()));
+
+            // Filter.
+            qry = new SqlFieldsQuery("select Name from Person where Id = ?", 1)
+            {
+                Lazy = true,
+                PageSize = 5,
+            };
+            Assert.AreEqual("Person 1", cache.Query(qry).Single().Single());
+
+            // DateTime.
+            qry = new SqlFieldsQuery("select Id, DateTime from Person where DateTime > ?", DateTime.UtcNow.AddDays(9));
+            Assert.AreEqual(cache[Count].DateTime, cache.Query(qry).Single().Last());
+
+            // Invalid args.
+            qry.Sql = null;
+            Assert.Throws<ArgumentNullException>(() => cache.Query(qry));
+        }
+
+        /// <summary>
+        /// Tests the SQL fields query with distributed joins.
+        /// </summary>
+        [Test]
+        public void TestFieldsQueryDistributedJoins()
+        {
+            var cache = GetClientCache<Person>();
+
+            // Non-distributed join returns incomplete results.
+            var qry = new SqlFieldsQuery(string.Format(
+                "select p2.Name from \"{0}\".Person, \"{1}\".Person as p2 where Person.Id = 11 - p2.Id", 
+                CacheName, CacheName2));
+
+            Assert.Greater(Count, cache.Query(qry).Count());
+
+            // Distributed join fixes the problem.
+            qry.EnableDistributedJoins = true;
+            Assert.AreEqual(Count, cache.Query(qry).Count());
+        }
+
+        /// <summary>
+        /// Tests the fields query timeout.
+        /// </summary>
+        [Test]
+        public void TestFieldsQueryTimeout()
+        {
+            var cache = GetClientCache<Person>();
+
+            cache.PutAll(Enumerable.Range(1, 30000).ToDictionary(x => x, x => new Person(x)));
+
+            var qry = new SqlFieldsQuery("select * from Person where Name like '%ers%'")
+            {
+                Timeout = TimeSpan.FromMilliseconds(1)
+            };
+
+            Assert.Throws<IgniteClientException>(() => cache.Query(qry).GetAll());
+        }
+
+        /// <summary>
+        /// Tests the fields query on a missing cache.
+        /// </summary>
+        [Test]
+        public void TestFieldsQueryMissingCache()
+        {
+            var cache = Client.GetCache<int, Person>("I do not exist");
+            var qry = new SqlFieldsQuery("select name from person")
+            {
+                Schema = CacheName
+            };
+
+            // Schema is set => we still check for cache existence.
+            var ex = Assert.Throws<IgniteClientException>(() => cache.Query(qry).GetAll());
+            Assert.AreEqual("Cache doesn't exist: I do not exist", ex.Message);
+
+            // Schema not set => also exception.
+            qry.Schema = null;
+            ex = Assert.Throws<IgniteClientException>(() => cache.Query(qry).GetAll());
+            Assert.AreEqual("Cache doesn't exist: I do not exist", ex.Message);
+        }
+
+        /// <summary>
+        /// Tests fields query with custom schema.
+        /// </summary>
+        [Test]
+        public void TestFieldsQueryCustomSchema()
+        {
+            var cache1 = Client.GetCache<int, Person>(CacheName);
+            var cache2 = Client.GetCache<int, Person>(CacheName2);
+
+            cache1.RemoveAll();
+
+            var qry = new SqlFieldsQuery("select name from person");
+
+            // Schema not set: cache name is used.
+            Assert.AreEqual(0, cache1.Query(qry).Count());
+            Assert.AreEqual(Count, cache2.Query(qry).Count());
+
+            // Schema set to first cache: no results both cases.
+            qry.Schema = cache1.Name;
+            Assert.AreEqual(0, cache1.Query(qry).Count());
+            Assert.AreEqual(0, cache2.Query(qry).Count());
+
+            // Schema set to second cache: full results both cases.
+            qry.Schema = cache2.Name;
+            Assert.AreEqual(Count, cache1.Query(qry).Count());
+            Assert.AreEqual(Count, cache2.Query(qry).Count());
+        }
+
+        /// <summary>
+        /// Tests the DML.
+        /// </summary>
+        [Test]
+        public void TestDml()
+        {
+            var cache = GetClientCache<Person>();
+
+            var qry = new SqlFieldsQuery("insert into Person (_key, id, name) values (?, ?, ?)", -10, 1, "baz");
+            var res = cache.Query(qry).GetAll();
+
+            Assert.AreEqual(1, res[0][0]);
+            Assert.AreEqual("baz", cache[-10].Name);
+        }
+
+        /// <summary>
+        /// Initializes the cache.
+        /// </summary>
+        private static void InitCache(string cacheName)
+        {
+            var cache = Ignition.GetIgnite().GetOrCreateCache<int, Person>(
+                new CacheConfiguration(cacheName, new QueryEntity(typeof(int), typeof(Person))));
+
+            cache.RemoveAll();
+
+            cache.PutAll(Enumerable.Range(1, Count).ToDictionary(x => x, x => new Person(x)));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
index 9b7a566..e1d30b9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Client/ClientTestBase.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Tests.Client
     using System.Net;
     using Apache.Ignite.Core.Cache;
     using Apache.Ignite.Core.Client;
+    using Apache.Ignite.Core.Client.Cache;
     using NUnit.Framework;
 
     /// <summary>
@@ -81,7 +82,7 @@ namespace Apache.Ignite.Core.Tests.Client
         /// Sets up the test.
         /// </summary>
         [SetUp]
-        public void TestSetUp()
+        public virtual void TestSetUp()
         {
             GetCache<int>().RemoveAll();
         }
@@ -100,6 +101,14 @@ namespace Apache.Ignite.Core.Tests.Client
         }
 
         /// <summary>
+        /// Gets the client cache.
+        /// </summary>
+        protected ICacheClient<int, T> GetClientCache<T>()
+        {
+            return Client.GetCache<int, T>(CacheName);
+        }
+
+        /// <summary>
         /// Gets the client.
         /// </summary>
         protected IIgniteClient GetClient()

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 0076d47..21738a2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -104,6 +104,7 @@
     <Compile Include="Cache\Configuration\MemoryPolicyConfiguration.cs" />
     <Compile Include="Cache\Configuration\PartitionLossPolicy.cs" />
     <Compile Include="Cache\IMemoryMetrics.cs" />
+    <Compile Include="Cache\Query\IFieldsQueryCursor.cs" />
     <Compile Include="Client\Cache\ICacheClient.cs" />
     <Compile Include="Client\IgniteClientConfiguration.cs" />
     <Compile Include="Client\IgniteClientException.cs" />
@@ -121,10 +122,13 @@
     <Compile Include="Impl\Binary\MultidimensionalArraySerializer.cs" />
     <Compile Include="Impl\Client\Cache\CacheFlags.cs" />
     <Compile Include="Impl\Client\Cache\ClientCacheConfigurationSerializer.cs" />
+    <Compile Include="Impl\Client\Cache\Query\ClientFieldsQueryCursor.cs" />
     <Compile Include="Impl\Client\Cache\Query\ClientQueryCursor.cs" />
     <Compile Include="Impl\Cache\Query\PlatformQueryQursorBase.cs" />
     <Compile Include="Impl\Binary\BinaryProcessorClient.cs" />
     <Compile Include="Impl\Binary\IBinaryProcessor.cs" />
+    <Compile Include="Impl\Client\Cache\Query\ClientQueryCursorBase.cs" />
+    <Compile Include="Impl\Client\Cache\Query\StatementType.cs" />
     <Compile Include="Impl\Client\ClientStatus.cs" />
     <Compile Include="Events\LocalEventListener.cs" />
     <Compile Include="Impl\DataStorageMetrics.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/IFieldsQueryCursor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/IFieldsQueryCursor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/IFieldsQueryCursor.cs
new file mode 100644
index 0000000..fbeaf8c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/IFieldsQueryCursor.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Cache.Query
+{
+    using System.Collections.Generic;
+    using System.Diagnostics.CodeAnalysis;
+
+    /// <summary>
+    /// Fields query cursor.
+    /// </summary>
+    [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
+    public interface IFieldsQueryCursor : IQueryCursor<IList<object>>
+    {
+        /// <summary>
+        /// Gets the field names.
+        /// </summary>
+        IList<string> FieldNames { get; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
index a3964c6..eb91b0a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Client/Cache/ICacheClient.cs
@@ -100,6 +100,20 @@ namespace Apache.Ignite.Core.Client.Cache
         IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery);
 
         /// <summary>
+        /// Executes an SQL query.
+        /// </summary>
+        /// <param name="sqlQuery">SQL query.</param>
+        /// <returns>Query cursor.</returns>
+        IQueryCursor<ICacheEntry<TK, TV>> Query(SqlQuery sqlQuery);
+
+        /// <summary>
+        /// Executes an SQL Fields query.
+        /// </summary>
+        /// <param name="sqlFieldsQuery">SQL query.</param>
+        /// <returns>Query cursor.</returns>
+        IFieldsQueryCursor Query(SqlFieldsQuery sqlFieldsQuery);
+
+        /// <summary>
         /// Associates the specified value with the specified key in this cache,
         /// returning an existing value if one existed.
         /// </summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/FieldsQueryCursor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/FieldsQueryCursor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/FieldsQueryCursor.cs
index 17dc93b..c60e010 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/FieldsQueryCursor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/FieldsQueryCursor.cs
@@ -18,19 +18,13 @@
 namespace Apache.Ignite.Core.Impl.Cache.Query
 {
     using System;
-    using System.Diagnostics;
-    using System.Diagnostics.CodeAnalysis;
     using Apache.Ignite.Core.Binary;
-    using Apache.Ignite.Core.Impl.Binary;
 
     /// <summary>
     /// Cursor for entry-based queries.
     /// </summary>
     internal class FieldsQueryCursor<T> : PlatformQueryQursorBase<T>
     {
-        /** */
-        private readonly Func<IBinaryRawReader, int, T> _readerFunc;
-
         /// <summary>
         /// Constructor.
         /// </summary>
@@ -39,23 +33,18 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /// <param name="readerFunc">The reader function.</param>
         public FieldsQueryCursor(IPlatformTargetInternal target, bool keepBinary, 
             Func<IBinaryRawReader, int, T> readerFunc)
-            : base(target, keepBinary)
-        {
-            Debug.Assert(readerFunc != null);
-
-            _readerFunc = readerFunc;
-        }
+            : base(target, keepBinary, r =>
+            {
+                // Reading and skipping row size in bytes.
+                r.ReadInt();
 
-        /** <inheritdoc /> */
-        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
-        protected override T Read(BinaryReader reader)
-        {
-            // Reading and skipping row size in bytes.
-            reader.ReadInt();
+                int cnt = r.ReadInt();
 
-            int cnt = reader.ReadInt();
+                return readerFunc(r, cnt);
 
-            return _readerFunc(reader, cnt);
+            })
+        {
+            // No-op.
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/PlatformQueryQursorBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/PlatformQueryQursorBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/PlatformQueryQursorBase.cs
index 8a51dab..fc78392 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/PlatformQueryQursorBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/PlatformQueryQursorBase.cs
@@ -17,7 +17,9 @@
 
 namespace Apache.Ignite.Core.Impl.Cache.Query
 {
+    using System;
     using System.Collections.Generic;
+    using Apache.Ignite.Core.Impl.Binary;
 
     /// <summary>
     /// Base for platform cursors.
@@ -44,8 +46,10 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /// </summary>
         /// <param name="target">The target.</param>
         /// <param name="keepBinary">Keep binary flag.</param>
-        protected PlatformQueryQursorBase(IPlatformTargetInternal target, bool keepBinary) 
-            : base(target.Marshaller, keepBinary)
+        /// <param name="readFunc"></param>
+        protected PlatformQueryQursorBase(IPlatformTargetInternal target, bool keepBinary, 
+            Func<BinaryReader, T> readFunc) 
+            : base(target.Marshaller, keepBinary, readFunc)
         {
             _target = target;
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursor.cs
index b967d6a..ca773fe 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursor.cs
@@ -17,9 +17,7 @@
 
 namespace Apache.Ignite.Core.Impl.Cache.Query
 {
-    using System.Diagnostics.CodeAnalysis;
     using Apache.Ignite.Core.Cache;
-    using Apache.Ignite.Core.Impl.Binary;
 
     /// <summary>
     /// Cursor for entry-based queries.
@@ -31,19 +29,11 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /// </summary>
         /// <param name="target">Target.</param>
         /// <param name="keepBinary">Keep poratble flag.</param>
-        public QueryCursor(IPlatformTargetInternal target, bool keepBinary) : base(target, keepBinary)
+        public QueryCursor(IPlatformTargetInternal target, bool keepBinary)
+            : base(target, keepBinary,
+                r => new CacheEntry<TK, TV>(r.ReadObject<TK>(), r.ReadObject<TV>()))
         {
             // No-op.
         }
-
-        /** <inheritdoc /> */
-        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
-        protected override ICacheEntry<TK, TV> Read(BinaryReader reader)
-        {
-            TK key = reader.ReadObject<TK>();
-            TV val = reader.ReadObject<TV>();
-
-            return new CacheEntry<TK, TV>(key, val);
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
index 216d7ea..c8c02ad 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Query/QueryCursorBase.cs
@@ -21,7 +21,6 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
     using System.Collections;
     using System.Collections.Generic;
     using System.Diagnostics;
-    using System.Diagnostics.CodeAnalysis;
     using Apache.Ignite.Core.Cache.Query;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Binary.IO;
@@ -40,6 +39,9 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /** Marshaller. */
         private readonly Marshaller _marsh;
 
+        /** Read func. */
+        private readonly Func<BinaryReader, T> _readFunc;
+
         /** Wherther "GetAll" was called. */
         private bool _getAllCalled;
 
@@ -63,14 +65,15 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         /// </summary>
         /// <param name="marsh">Marshaller.</param>
         /// <param name="keepBinary">Keep binary flag.</param>
+        /// <param name="readFunc">The read function.</param>
         /// <param name="initialBatchStream">Optional stream with initial batch.</param>
-        [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors",
-            Justification = "ConvertGetBatch calls Read, which does not rely on constructor being run.")]
-        protected QueryCursorBase(Marshaller marsh, bool keepBinary, IBinaryStream initialBatchStream = null)
+        protected QueryCursorBase(Marshaller marsh, bool keepBinary, Func<BinaryReader, T> readFunc, 
+            IBinaryStream initialBatchStream = null)
         {
             Debug.Assert(marsh != null);
 
             _keepBinary = keepBinary;
+            _readFunc = readFunc;
             _marsh = marsh;
 
             if (initialBatchStream != null)
@@ -198,13 +201,6 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
         protected abstract IList<T> GetAllInternal();
 
         /// <summary>
-        /// Reads entry from the reader.
-        /// </summary> 
-        /// <param name="reader">Reader.</param>
-        /// <returns>Entry.</returns>
-        protected abstract T Read(BinaryReader reader);
-
-        /// <summary>
         /// Requests next batch.
         /// </summary>
         private void RequestBatch()
@@ -233,7 +229,7 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
             var res = new List<T>(size);
 
             for (var i = 0; i < size; i++)
-                res.Add(Read(reader));
+                res.Add(_readFunc(reader));
 
             return res;
         }
@@ -259,7 +255,7 @@ namespace Apache.Ignite.Core.Impl.Cache.Query
 
             for (var i = 0; i < size; i++)
             {
-                res[i] = Read(reader);
+                res[i] = _readFunc(reader);
             }
 
             _hasNext = stream.ReadBool();


[25/47] ignite git commit: ignite-6924: Fixed missed CacheStoreSessionListener#onSessionStart() call

Posted by sb...@apache.org.
ignite-6924: Fixed missed CacheStoreSessionListener#onSessionStart() call


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

Branch: refs/heads/ignite-zk
Commit: e3099cc47e4086605312d88aeda3ca85e1e6aeff
Parents: 1ebeee0
Author: Slava Koptilin <sl...@gmail.com>
Authored: Fri Nov 17 15:05:31 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Nov 17 15:05:31 2017 +0300

----------------------------------------------------------------------
 .../cache/store/CacheStoreManager.java          |  12 +-
 .../store/GridCacheStoreManagerAdapter.java     |   7 ++
 .../cache/store/GridCacheWriteBehindStore.java  |  10 +-
 ...reSessionListenerWriteBehindEnabledTest.java | 117 +++++++++++++++++--
 4 files changed, 135 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e3099cc4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
index 83428b3..e22cb05 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/CacheStoreManager.java
@@ -175,13 +175,23 @@ public interface CacheStoreManager extends GridCacheManager {
     public void sessionEnd(IgniteInternalTx tx, boolean commit, boolean last, boolean storeSessionEnded) throws IgniteCheckedException;
 
     /**
-     * End session initiated by write-behind store.
+     * Start session initiated by write-behind store.
      *
      * @throws IgniteCheckedException If failed.
      */
     public void writeBehindSessionInit() throws IgniteCheckedException;
 
     /**
+     * Notifies cache store session listeners.
+     *
+     * This method is called by write-behind store in case of back-pressure mechanism is initiated.
+     * It is assumed that cache store session was started by CacheStoreManager before.
+     *
+     * @throws IgniteCheckedException If failed.
+     */
+    public void writeBehindCacheStoreSessionListenerStart()  throws IgniteCheckedException;
+
+    /**
      * End session initiated by write-behind store.
      *
      * @param threwEx If exception was thrown.

http://git-wip-us.apache.org/repos/asf/ignite/blob/e3099cc4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
index 22c2381..e862c0a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheStoreManagerAdapter.java
@@ -829,6 +829,13 @@ public abstract class GridCacheStoreManagerAdapter extends GridCacheManagerAdapt
     }
 
     /** {@inheritDoc} */
+    @Override public void writeBehindCacheStoreSessionListenerStart()  throws IgniteCheckedException {
+        assert sesHolder.get() != null;
+
+        notifyCacheStoreSessionListeners(sesHolder.get(), null, true);
+    }
+
+    /** {@inheritDoc} */
     @Override public void writeBehindSessionEnd(boolean threwEx) throws IgniteCheckedException {
         sessionEnd0(null, threwEx);
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/e3099cc4/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
index 831b1b0..d7a13e6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/store/GridCacheWriteBehindStore.java
@@ -798,8 +798,14 @@ public class GridCacheWriteBehindStore<K, V> implements CacheStore<K, V>, Lifecy
         Flusher flusher
     ) {
         try {
-            if (initSes && storeMgr != null)
-                storeMgr.writeBehindSessionInit();
+            if (storeMgr != null) {
+                if (initSes)
+                    storeMgr.writeBehindSessionInit();
+                else
+                    // Back-pressure mechanism is running.
+                    // Cache store session must be initialized by storeMgr.
+                    storeMgr.writeBehindCacheStoreSessionListenerStart();
+            }
 
             boolean threwEx = true;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/e3099cc4/modules/core/src/test/java/org/apache/ignite/cache/store/CacheStoreSessionListenerWriteBehindEnabledTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/store/CacheStoreSessionListenerWriteBehindEnabledTest.java b/modules/core/src/test/java/org/apache/ignite/cache/store/CacheStoreSessionListenerWriteBehindEnabledTest.java
index b9095d0..c9a912a 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/store/CacheStoreSessionListenerWriteBehindEnabledTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/store/CacheStoreSessionListenerWriteBehindEnabledTest.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Logger;
 import javax.cache.Cache;
@@ -34,14 +35,15 @@ import javax.cache.configuration.FactoryBuilder;
 import javax.cache.integration.CacheLoaderException;
 import javax.cache.integration.CacheWriterException;
 import javax.sql.DataSource;
-import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcStoreSessionListener;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.processors.cache.GridCacheAbstractSelfTest;
 import org.apache.ignite.internal.processors.cache.store.GridCacheWriteBehindStore;
-import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.resources.CacheStoreSessionResource;
+import org.apache.ignite.testframework.GridTestUtils;
 
 /**
  * This class tests that calls of {@link CacheStoreSessionListener#onSessionStart(CacheStoreSession)}
@@ -61,6 +63,9 @@ public class CacheStoreSessionListenerWriteBehindEnabledTest extends GridCacheAb
     /** */
     private static final AtomicInteger entryCnt = new AtomicInteger();
 
+    /** */
+    private static final AtomicInteger uninitializedListenerCnt = new AtomicInteger();
+
     /** {@inheritDoc} */
     @Override protected int gridCount() {
         return 1;
@@ -93,6 +98,8 @@ public class CacheStoreSessionListenerWriteBehindEnabledTest extends GridCacheAb
         operations.clear();
 
         entryCnt.set(0);
+
+        uninitializedListenerCnt.set(0);
     }
 
     /**
@@ -136,6 +143,83 @@ public class CacheStoreSessionListenerWriteBehindEnabledTest extends GridCacheAb
     }
 
     /**
+     * Tests that cache store session listeners are notified by write-behind store.
+     */
+    public void testFlushSingleValue() throws Exception {
+        CacheConfiguration cfg = cacheConfiguration(getTestIgniteInstanceName());
+
+        cfg.setName("back-pressure-control");
+        cfg.setWriteBehindBatchSize(2);
+        cfg.setWriteBehindFlushSize(2);
+        cfg.setWriteBehindFlushFrequency(1_000);
+        cfg.setWriteBehindCoalescing(true);
+
+        IgniteCache<Object, Object> cache = grid(0).getOrCreateCache(cfg);
+
+        try {
+            int nUploaders = 5;
+
+            final CyclicBarrier barrier = new CyclicBarrier(nUploaders);
+
+            IgniteInternalFuture[] uploaders = new IgniteInternalFuture[nUploaders];
+
+            for (int i = 0; i < nUploaders; ++i) {
+                uploaders[i] = GridTestUtils.runAsync(
+                    new Uploader(cache, barrier, i * CNT),
+                    "uploader-" + i);
+            }
+
+            for (int i = 0; i < nUploaders; ++i)
+                uploaders[i].get();
+
+            assertEquals("Uninitialized cache store session listener.", 0, uninitializedListenerCnt.get());
+        }
+        finally {
+            cache.destroy();
+        }
+    }
+
+    /**
+     *
+     */
+    public static class Uploader implements Runnable {
+        /** */
+        private final int start;
+
+        /** */
+        private final CyclicBarrier barrier;
+
+        /** */
+        private final IgniteCache<Object, Object> cache;
+
+        /**
+         * @param cache Ignite cache.
+         * @param barrier Cyclic barrier.
+         * @param start Key index.
+         */
+        public Uploader(IgniteCache<Object, Object> cache, CyclicBarrier barrier, int start) {
+            this.cache = cache;
+
+            this.barrier = barrier;
+
+            this.start = start;
+        }
+
+        /** {@inheritDoc} */
+        @Override public void run() {
+            try {
+                barrier.await();
+
+                for (int i = start; i < start + CNT; ++i)
+                    cache.put(i, i);
+            }
+            catch (Exception e) {
+                fail("Unexpected exception [" + e + "]");
+            }
+        }
+    }
+
+    /**
      * @param startedSessions Number of expected sessions.
      */
     private void checkSessionCounters(int startedSessions) {
@@ -145,6 +229,8 @@ public class CacheStoreSessionListenerWriteBehindEnabledTest extends GridCacheAb
 
             assertEquals(CNT, entryCnt.get());
 
+            assertEquals("Uninitialized cache store session listener.", 0, uninitializedListenerCnt.get());
+
             checkOpCount(operations, OperationType.SESSION_START, startedSessions);
 
             checkOpCount(operations, OperationType.SESSION_END, startedSessions);
@@ -201,18 +287,19 @@ public class CacheStoreSessionListenerWriteBehindEnabledTest extends GridCacheAb
      * Test cache store session listener.
      */
     public static class TestCacheStoreSessionListener extends CacheJdbcStoreSessionListener {
-        /** */
-        @IgniteInstanceResource
-        private Ignite ignite;
-
         /** {@inheritDoc} */
         @Override public void onSessionStart(CacheStoreSession ses) {
             operations.add(OperationType.SESSION_START);
+
+            if (ses.attachment() == null)
+                ses.attach(new Object());
         }
 
         /** {@inheritDoc} */
         @Override public void onSessionEnd(CacheStoreSession ses, boolean commit) {
             operations.add(OperationType.SESSION_END);
+
+            ses.attach(null);
         }
     }
 
@@ -224,31 +311,45 @@ public class CacheStoreSessionListenerWriteBehindEnabledTest extends GridCacheAb
      */
     public static class EmptyCacheStore extends CacheStoreAdapter<Object, Object> {
         /** */
-        @IgniteInstanceResource
-        private Ignite ignite;
+        @CacheStoreSessionResource
+        private CacheStoreSession ses;
 
         /** {@inheritDoc} */
         @Override public Object load(Object key) throws CacheLoaderException {
             entryCnt.getAndIncrement();
+
+            if (ses.attachment() == null)
+                uninitializedListenerCnt.incrementAndGet();
+
             return null;
         }
 
         /** {@inheritDoc} */
         @Override public void writeAll(Collection<Cache.Entry<?, ?>> entries) {
             entryCnt.addAndGet(entries.size());
+
+            if (ses.attachment() == null)
+                uninitializedListenerCnt.incrementAndGet();
         }
 
         /** {@inheritDoc} */
         @Override public void write(Cache.Entry entry) throws CacheWriterException {
+            if (ses.attachment() == null)
+                uninitializedListenerCnt.incrementAndGet();
         }
 
         /** {@inheritDoc} */
         @Override public void deleteAll(Collection<?> keys) {
             entryCnt.addAndGet(keys.size());
+
+            if (ses.attachment() == null)
+                uninitializedListenerCnt.incrementAndGet();
         }
 
         /** {@inheritDoc} */
         @Override public void delete(Object key) throws CacheWriterException {
+            if (ses.attachment() == null)
+                uninitializedListenerCnt.incrementAndGet();
         }
     }
 


[16/47] ignite git commit: IGNITE-6896 .NET: support Multidimensional Arrays in binary serializer

Posted by sb...@apache.org.
IGNITE-6896 .NET: support Multidimensional Arrays in binary serializer

This closes #3031


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

Branch: refs/heads/ignite-zk
Commit: fa52789d7679d4c4b65efcdfb86cf146abb920fe
Parents: f992386
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Nov 15 15:47:58 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Nov 15 15:47:58 2017 +0300

----------------------------------------------------------------------
 .../Binary/BinarySelfTest.cs                    |  88 +++++++++++++
 .../Apache.Ignite.Core.csproj                   |   2 +
 .../Impl/Binary/BinaryReflectiveActions.cs      |  16 +++
 .../Impl/Binary/BinarySystemHandlers.cs         |  13 +-
 .../Impl/Binary/BinaryUtils.cs                  |  41 +++++-
 .../Impl/Binary/Marshaller.cs                   |   1 +
 .../Impl/Binary/MultidimensionalArrayHolder.cs  | 132 +++++++++++++++++++
 .../Binary/MultidimensionalArraySerializer.cs   |  48 +++++++
 8 files changed, 330 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
index 3ec1e8c..6ffce38 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
@@ -1532,6 +1532,58 @@ namespace Apache.Ignite.Core.Tests.Binary
         }
 
         /// <summary>
+        /// Tests the jagged arrays.
+        /// </summary>
+        [Test]
+        public void TestJaggedArrays()
+        {
+            int[][] ints = {new[] {1, 2, 3}, new[] {4, 5, 6}};
+            Assert.AreEqual(ints, TestUtils.SerializeDeserialize(ints));
+
+            uint[][][] uints = {new[] {new uint[] {1, 2, 3}, new uint[] {4, 5}}};
+            Assert.AreEqual(uints, TestUtils.SerializeDeserialize(uints));
+
+            PropertyType[][][] objs = {new[] {new[] {new PropertyType {Field1 = 42}}}};
+            Assert.AreEqual(42, TestUtils.SerializeDeserialize(objs)[0][0][0].Field1);
+
+            var obj = new MultidimArrays { JaggedInt = ints, JaggedUInt = uints };
+            var resObj = TestUtils.SerializeDeserialize(obj);
+            Assert.AreEqual(obj.JaggedInt, resObj.JaggedInt);
+            Assert.AreEqual(obj.JaggedUInt, resObj.JaggedUInt);
+
+            var obj2 = new MultidimArraysBinarizable { JaggedInt = ints, JaggedUInt = uints };
+            var resObj2 = TestUtils.SerializeDeserialize(obj);
+            Assert.AreEqual(obj2.JaggedInt, resObj2.JaggedInt);
+            Assert.AreEqual(obj2.JaggedUInt, resObj2.JaggedUInt);
+        }
+
+        /// <summary>
+        /// Tests the multidimensional arrays.
+        /// </summary>
+        [Test]
+        public void TestMultidimensionalArrays()
+        {
+            int[,] ints = {{1, 2, 3}, {4, 5, 6}};
+            Assert.AreEqual(ints, TestUtils.SerializeDeserialize(ints));
+
+            uint[,,] uints = {{{1, 2, 3}, {4, 5, 6}}, {{7, 8, 9}, {10, 11, 12}}};
+            Assert.AreEqual(uints, TestUtils.SerializeDeserialize(uints));
+
+            PropertyType[,] objs = {{new PropertyType {Field1 = 123}}};
+            Assert.AreEqual(123, TestUtils.SerializeDeserialize(objs)[0, 0].Field1);
+            
+            var obj = new MultidimArrays { MultidimInt = ints, MultidimUInt = uints };
+            var resObj = TestUtils.SerializeDeserialize(obj);
+            Assert.AreEqual(obj.MultidimInt, resObj.MultidimInt);
+            Assert.AreEqual(obj.MultidimUInt, resObj.MultidimUInt);
+
+            var obj2 = new MultidimArraysBinarizable { MultidimInt = ints, MultidimUInt = uints };
+            var resObj2 = TestUtils.SerializeDeserialize(obj);
+            Assert.AreEqual(obj2.MultidimInt, resObj2.MultidimInt);
+            Assert.AreEqual(obj2.MultidimUInt, resObj2.MultidimUInt);
+        }
+
+        /// <summary>
         /// Tests the compact footer setting.
         /// </summary>
         [Test]
@@ -2604,5 +2656,41 @@ namespace Apache.Ignite.Core.Tests.Binary
                 return !left.Equals(right);
             }
         }
+
+        private class MultidimArrays
+        {
+            public int[][] JaggedInt { get; set; }
+            public uint[][][] JaggedUInt { get; set; }
+
+            public int[,] MultidimInt { get; set; }
+            public uint[,,] MultidimUInt { get; set; }
+        }
+
+        private class MultidimArraysBinarizable : IBinarizable
+        {
+            public int[][] JaggedInt { get; set; }
+            public uint[][][] JaggedUInt { get; set; }
+
+            public int[,] MultidimInt { get; set; }
+            public uint[,,] MultidimUInt { get; set; }
+            
+            public void WriteBinary(IBinaryWriter writer)
+            {
+                writer.WriteObject("JaggedInt", JaggedInt);
+                writer.WriteObject("JaggedUInt", JaggedUInt);
+
+                writer.WriteObject("MultidimInt", MultidimInt);
+                writer.WriteObject("MultidimUInt", MultidimUInt);
+            }
+
+            public void ReadBinary(IBinaryReader reader)
+            {
+                JaggedInt = reader.ReadObject<int[][]>("JaggedInt");
+                JaggedUInt = reader.ReadObject<uint[][][]>("JaggedUInt");
+
+                MultidimInt = reader.ReadObject<int[,]>("MultidimInt");
+                MultidimUInt = reader.ReadObject<uint[,,]>("MultidimUInt");
+            }
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 165a57e..8a32583 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -116,6 +116,8 @@
     <Compile Include="Configuration\WalMode.cs" />
     <Compile Include="Impl\Binary\BinaryTypeId.cs" />
     <Compile Include="Impl\Binary\IBinaryRawWriteAware.cs" />
+    <Compile Include="Impl\Binary\MultidimensionalArrayHolder.cs" />
+    <Compile Include="Impl\Binary\MultidimensionalArraySerializer.cs" />
     <Compile Include="Impl\Client\Cache\CacheFlags.cs" />
     <Compile Include="Impl\Client\Cache\Query\ClientQueryCursor.cs" />
     <Compile Include="Impl\Cache\Query\PlatformQueryQursorBase.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
index 97964cf..a8ea9f1 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReflectiveActions.cs
@@ -121,7 +121,9 @@ namespace Apache.Ignite.Core.Impl.Binary
             if (type.IsPrimitive)
                 HandlePrimitive(field, out writeAction, out readAction, raw);
             else if (type.IsArray)
+            {
                 HandleArray(field, out writeAction, out readAction, raw);
+            }
             else
                 HandleOther(field, out writeAction, out readAction, raw, forceTimestamp);
         }
@@ -252,6 +254,20 @@ namespace Apache.Ignite.Core.Impl.Binary
         private static void HandleArray(FieldInfo field, out BinaryReflectiveWriteAction writeAction,
             out BinaryReflectiveReadAction readAction, bool raw)
         {
+            if (field.FieldType.GetArrayRank() > 1)
+            {
+                writeAction = raw
+                    ? GetRawWriter<Array>(field, (w, o) => w.WriteObject(
+                        o == null ? null : new MultidimensionalArrayHolder(o)))
+                    : GetWriter<Array>(field, (f, w, o) => w.WriteObject(f,
+                        o == null ? null : new MultidimensionalArrayHolder(o)));
+                readAction = raw
+                    ? GetRawReader(field, r => r.ReadObject<object>())
+                    : GetReader(field, (f, r) => r.ReadObject<object>(f));
+
+                return;
+            }
+
             Type elemType = field.FieldType.GetElementType();
 
             if (elemType == typeof (bool))

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
index 3f16bc0..430b426 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
@@ -178,6 +178,13 @@ namespace Apache.Ignite.Core.Impl.Binary
 
             if (type.IsArray)
             {
+                if (type.GetArrayRank() > 1)
+                {
+                    // int[,]-style arrays are wrapped, see comments in holder.
+                    return new BinarySystemWriteHandler<Array>(
+                        (w, o) => w.WriteObject(new MultidimensionalArrayHolder(o)), true);
+                }
+
                 // We know how to write any array type.
                 Type elemType = type.GetElementType();
                 
@@ -491,11 +498,7 @@ namespace Apache.Ignite.Core.Impl.Binary
                 {
                     // Infer element type from typeId.
                     var typeId = ctx.ReadInt();
-
-                    if (typeId != BinaryUtils.ObjTypeId)
-                    {
-                        elemType = ctx.Marshaller.GetDescriptor(true, typeId, true).Type;
-                    }
+                    elemType = BinaryUtils.GetArrayElementType(typeId, ctx.Marshaller);
 
                     return BinaryUtils.ReadTypedArray(ctx, false, elemType ?? typeof(object));
                 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index 20fea02..3123c07 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -1024,6 +1024,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         public static void WriteArray(Array val, BinaryWriter ctx, int? elemTypeId = null)
         {
             Debug.Assert(val != null && ctx != null);
+            Debug.Assert(val.Rank == 1);
 
             IBinaryStream stream = ctx.Stream;
 
@@ -1034,18 +1035,15 @@ namespace Apache.Ignite.Core.Impl.Binary
             else
             {
                 var elemType = val.GetType().GetElementType();
-
                 Debug.Assert(elemType != null);
 
-                var typeId = ObjTypeId;
-
-                if (elemType != typeof(object))
-                    typeId = ctx.Marshaller.GetDescriptor(elemType).TypeId;
-
+                var typeId = GetArrayElementTypeId(val, ctx.Marshaller);
                 stream.WriteInt(typeId);
 
                 if (typeId == BinaryTypeId.Unregistered)
+                {
                     ctx.WriteString(elemType.FullName);
+                }
             }
 
             stream.WriteInt(val.Length);
@@ -1055,6 +1053,37 @@ namespace Apache.Ignite.Core.Impl.Binary
         }
 
         /// <summary>
+        /// Gets the array element type identifier.
+        /// </summary>
+        public static int GetArrayElementTypeId(Array val, Marshaller marsh)
+        {
+            var elemType = val.GetType().GetElementType();
+            Debug.Assert(elemType != null);
+
+            return GetArrayElementTypeId(elemType, marsh);
+        }
+
+        /// <summary>
+        /// Gets the array element type identifier.
+        /// </summary>
+        public static int GetArrayElementTypeId(Type elemType, Marshaller marsh)
+        {
+            return elemType == typeof(object) 
+                ? ObjTypeId 
+                : marsh.GetDescriptor(elemType).TypeId;
+        }
+
+        /// <summary>
+        /// Gets the type of the array element.
+        /// </summary>
+        public static Type GetArrayElementType(int typeId, Marshaller marsh)
+        {
+            return typeId == ObjTypeId
+                ? typeof(object)
+                : marsh.GetDescriptor(true, typeId, true).Type;
+        }
+
+        /// <summary>
         /// Read array.
         /// </summary>
         /// <param name="ctx">Read context.</param>

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
index 7212cd6..0a7b54c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -725,6 +725,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             AddSystemType(0, r => new AssemblyRequest(r));
             AddSystemType(0, r => new AssemblyRequestResult(r));
             AddSystemType<PeerLoadingObjectHolder>(0, null, serializer: new PeerLoadingObjectHolderSerializer());
+            AddSystemType<MultidimensionalArrayHolder>(0, null, serializer: new MultidimensionalArraySerializer());
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs
new file mode 100644
index 0000000..f9f8df3
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArrayHolder.cs
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System;
+    using System.Collections;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Deployment;
+
+    /// <summary>
+    /// Wrapper for multidimensional arrays (int[,] -style).
+    /// <para />
+    /// Jagged arrays (int[][]) are fully supported by the engine and are interoperable with Java.
+    /// However, there is no int[,]-style arrays in Java, and there is no way to support them in a generic way.
+    /// So we have to wrap them inside an object (so it looks like a BinaryObject in Java).
+    /// </summary>
+    internal sealed class MultidimensionalArrayHolder : IBinaryWriteAware
+    {
+        /** Object. */
+        private readonly Array _array;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PeerLoadingObjectHolder"/> class.
+        /// </summary>
+        /// <param name="o">The object.</param>
+        public MultidimensionalArrayHolder(Array o)
+        {
+            Debug.Assert(o != null);
+            Debug.Assert(o.Rank > 1);
+
+            _array = o;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MultidimensionalArrayHolder"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public MultidimensionalArrayHolder(BinaryReader reader)
+        {
+            var typeId = reader.ReadInt();
+            var type = BinaryUtils.GetArrayElementType(typeId, reader.Marshaller);
+
+            var rank = reader.ReadInt();
+            var lengths = new int[rank];
+            var totalLen = 1;
+
+            for (var i = 0; i < rank; i++)
+            {
+                var len = reader.ReadInt();
+                lengths[i] = len;
+                totalLen *= len;
+            }
+
+            _array = System.Array.CreateInstance(type, lengths);
+
+            for (var i = 0; i < totalLen; i++)
+            {
+                var obj = reader.ReadObject<object>();
+                var idx = GetIndices(i, lengths);
+
+                _array.SetValue(Convert.ChangeType(obj, type), idx);
+            }
+        }
+
+        /// <summary>
+        /// Gets the indices in a multidimensional array from a global index.
+        /// </summary>
+        private static int[] GetIndices(int globalIdx, int[] lengths)
+        {
+            var res = new int[lengths.Length];
+
+            for (var i = lengths.Length - 1; i >= 0; i--)
+            {
+                var len = lengths[i];
+
+                res[i] = globalIdx % len;
+                globalIdx = globalIdx / len;
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the object.
+        /// </summary>
+        public object Array
+        {
+            get { return _array; }
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryWriter writer)
+        {
+            var raw = writer.GetRawWriter();
+
+            // Array type.
+            raw.WriteInt(BinaryUtils.GetArrayElementTypeId(_array, ((BinaryWriter) writer).Marshaller));
+
+            // Number of dimensions.
+            var rank = _array.Rank;
+            raw.WriteInt(rank);
+
+            // Sizes per dimensions.
+            for (var i = 0; i < rank; i++)
+            {
+                raw.WriteInt(_array.GetLength(i));
+            }
+
+            // Data.
+            foreach (var obj in (IEnumerable)_array)
+            {
+                raw.WriteObject(obj);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/fa52789d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs
new file mode 100644
index 0000000..993b9d5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/MultidimensionalArraySerializer.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Binary
+{
+    using System;
+    using Apache.Ignite.Core.Impl.Common;
+
+    /// <summary>
+    /// Serializer for <see cref="MultidimensionalArrayHolder"/>. Unwraps underlying object automatically.
+    /// </summary>
+    internal sealed class MultidimensionalArraySerializer : IBinarySerializerInternal
+    {
+        /** <inheritdoc /> */
+        public void WriteBinary<T>(T obj, BinaryWriter writer)
+        {
+            TypeCaster<MultidimensionalArrayHolder>.Cast(obj).WriteBinary(writer);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadBinary<T>(BinaryReader reader, IBinaryTypeDescriptor desc, int pos, Type typeOverride)
+        {
+            var holder = new MultidimensionalArrayHolder(reader);
+
+            return (T) holder.Array;
+        }
+
+        /** <inheritdoc /> */
+        public bool SupportsHandles
+        {
+            get { return true; }
+        }
+    }
+}


[28/47] ignite git commit: IGNITE-6932: SQL: cache-less query execution now checks for cluster state. This closes #3048.

Posted by sb...@apache.org.
IGNITE-6932: SQL: cache-less query execution now checks for cluster state. This closes #3048.


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

Branch: refs/heads/ignite-zk
Commit: cbd7e39cf34d86bc4fe41ac44a286ba7690b08cb
Parents: 4e04679
Author: tledkov-gridgain <tl...@gridgain.com>
Authored: Fri Nov 17 16:05:35 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Nov 17 16:05:35 2017 +0300

----------------------------------------------------------------------
 .../processors/query/GridQueryProcessor.java    |  8 ++
 ...CheckClusterStateBeforeExecuteQueryTest.java | 89 ++++++++++++++++++++
 .../IgniteCacheQuerySelfTestSuite.java          |  3 +
 3 files changed, 100 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cbd7e39c/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index 7ad95a6..ed5fdd9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1944,6 +1944,8 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      *
      * @param qry Query.
      * @param keepBinary Keep binary flag.
+     * @param failOnMultipleStmts If {@code true} the method must throws exception when query contains
+     *      more then one SQL statement.
      * @return Cursor.
      */
     public List<FieldsQueryCursor<List<?>>> querySqlFieldsNoCache(final SqlFieldsQuery qry,
@@ -1955,6 +1957,12 @@ public class GridQueryProcessor extends GridProcessorAdapter {
         if (qry.isLocal())
             throw new IgniteException("Local query is not supported without specific cache.");
 
+        if (!ctx.state().publicApiActiveState()) {
+            throw new IgniteException("Can not perform the operation because the cluster is inactive. Note, that " +
+                "the cluster is considered inactive by default if Ignite Persistent Store is used to let all the nodes " +
+                "join the cluster. To activate the cluster call Ignite.active(true).");
+        }
+
         if (qry.getSchema() == null)
             qry.setSchema(QueryUtils.DFLT_SCHEMA);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbd7e39c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
new file mode 100644
index 0000000..aae6a0c
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache;
+
+import java.util.concurrent.Callable;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.util.typedef.internal.U;
+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 static org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager.DFLT_STORE_DIR;
+import static org.apache.ignite.testframework.GridTestUtils.assertThrows;
+
+/**
+ *
+ */
+public class IgniteCheckClusterStateBeforeExecuteQueryTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+
+        DataStorageConfiguration pCfg = new DataStorageConfiguration();
+
+        pCfg.setDefaultDataRegionConfiguration(new DataRegionConfiguration()
+            .setPersistenceEnabled(true)
+            .setMaxSize(100 * 1024 * 1024));
+
+        cfg.setDataStorageConfiguration(pCfg);
+
+        return cfg;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        stopAllGrids();
+
+        deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_STORE_DIR, false));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        deleteRecursively(U.resolveWorkDirectory(U.defaultWorkDirectory(), DFLT_STORE_DIR, false));
+    }
+
+    /**
+     * @throws Exception On failed.
+     */
+    public void testDynamicSchemaChangesPersistence() throws Exception {
+        final IgniteEx ig = startGrid(0);
+
+        assertThrows(log, new Callable<Void>() {
+            @Override public Void call() throws Exception {
+                ig.context().query().querySqlFieldsNoCache(new SqlFieldsQuery("SELECT 1"), false);
+
+                return null;
+            }
+        }, IgniteException.class, "Can not perform the operation because the cluster is inactive.");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cbd7e39c/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 16fd5e0..7b3b271 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
@@ -70,6 +70,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheQueryH2IndexingLea
 import org.apache.ignite.internal.processors.cache.IgniteCacheQueryIndexSelfTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheQueryLoadSelfTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheUpdateSqlQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCheckClusterStateBeforeExecuteQueryTest;
 import org.apache.ignite.internal.processors.cache.IgniteCrossCachesJoinsQueryTest;
 import org.apache.ignite.internal.processors.cache.IncorrectQueryEntityTest;
 import org.apache.ignite.internal.processors.cache.QueryEntityCaseMismatchTest;
@@ -366,6 +367,8 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
         suite.addTestSuite(GridCacheQuerySqlFieldInlineSizeSelfTest.class);
         suite.addTestSuite(IgniteSqlParameterizedQueryTest.class);
 
+        suite.addTestSuite(IgniteCheckClusterStateBeforeExecuteQueryTest.class);
+
         return suite;
     }
 }


[32/47] ignite git commit: IGNITE-358: Hadoop: added InputSplit to HadoopV1Reporter. This closes #3059.

Posted by sb...@apache.org.
IGNITE-358: Hadoop: added InputSplit to HadoopV1Reporter. This closes #3059.


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

Branch: refs/heads/ignite-zk
Commit: 64ffa3d4ebc4e56f91e05836642fed2824d192f7
Parents: cbd7e39
Author: Konstantin Dudkov <kd...@ya.ru>
Authored: Fri Nov 17 16:09:10 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Nov 17 16:09:10 2017 +0300

----------------------------------------------------------------------
 .../internal/processors/hadoop/impl/v1/HadoopV1MapTask.java  | 6 +++---
 .../internal/processors/hadoop/impl/v1/HadoopV1Reporter.java | 8 ++++++--
 2 files changed, 9 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/64ffa3d4/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1MapTask.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1MapTask.java b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1MapTask.java
index 2172ff2..039c5cd 100644
--- a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1MapTask.java
+++ b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1MapTask.java
@@ -27,10 +27,10 @@ import org.apache.hadoop.mapred.RecordReader;
 import org.apache.hadoop.mapred.Reporter;
 import org.apache.hadoop.util.ReflectionUtils;
 import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.internal.processors.hadoop.HadoopFileBlock;
-import org.apache.ignite.internal.processors.hadoop.HadoopMapperUtils;
 import org.apache.ignite.hadoop.HadoopInputSplit;
+import org.apache.ignite.internal.processors.hadoop.HadoopFileBlock;
 import org.apache.ignite.internal.processors.hadoop.HadoopJobEx;
+import org.apache.ignite.internal.processors.hadoop.HadoopMapperUtils;
 import org.apache.ignite.internal.processors.hadoop.HadoopTaskCancelledException;
 import org.apache.ignite.internal.processors.hadoop.HadoopTaskContext;
 import org.apache.ignite.internal.processors.hadoop.HadoopTaskInfo;
@@ -83,7 +83,7 @@ public class HadoopV1MapTask extends HadoopV1Task {
 
             assert nativeSplit != null;
 
-            Reporter reporter = new HadoopV1Reporter(taskCtx);
+            Reporter reporter = new HadoopV1Reporter(taskCtx, nativeSplit);
 
             HadoopV1OutputCollector collector = null;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/64ffa3d4/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1Reporter.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1Reporter.java b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1Reporter.java
index f3229e2..8f13ff9 100644
--- a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1Reporter.java
+++ b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/impl/v1/HadoopV1Reporter.java
@@ -30,13 +30,17 @@ public class HadoopV1Reporter implements Reporter {
     /** Context. */
     private final HadoopTaskContext ctx;
 
+    /** Input split */
+    private final InputSplit split;
+
     /**
      * Creates new instance.
      *
      * @param ctx Context.
      */
-    public HadoopV1Reporter(HadoopTaskContext ctx) {
+    public HadoopV1Reporter(HadoopTaskContext ctx, InputSplit split) {
         this.ctx = ctx;
+        this.split = split;
     }
 
     /** {@inheritDoc} */
@@ -66,7 +70,7 @@ public class HadoopV1Reporter implements Reporter {
 
     /** {@inheritDoc} */
     @Override public InputSplit getInputSplit() throws UnsupportedOperationException {
-        throw new UnsupportedOperationException("reporter has no input"); // TODO
+        return split;
     }
 
     /** {@inheritDoc} */


[05/47] ignite git commit: IGNITE-6901: Fixed assertion during IgniteH2Indexing.rebuildIndexesFromHash. This closes #3027.

Posted by sb...@apache.org.
IGNITE-6901: Fixed assertion during IgniteH2Indexing.rebuildIndexesFromHash. This closes #3027.


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

Branch: refs/heads/ignite-zk
Commit: 93038455391aa19d342cd1a7df5ad65b2848c491
Parents: ec85cc0
Author: devozerov <vo...@gridgain.com>
Authored: Tue Nov 14 15:26:31 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Tue Nov 14 15:26:31 2017 +0300

----------------------------------------------------------------------
 .../cache/IgniteCacheOffheapManagerImpl.java         |  4 ++--
 .../cache/query/GridCacheQueryManager.java           |  5 +++--
 .../internal/processors/query/GridQueryIndexing.java |  5 +++--
 .../processors/query/GridQueryProcessor.java         | 11 +++++++----
 .../IgniteClientCacheInitializationFailTest.java     |  2 +-
 .../processors/query/h2/IgniteH2Indexing.java        |  4 ++--
 .../processors/query/h2/opt/GridH2Table.java         | 15 ++++++++++++---
 7 files changed, 30 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
index 7944c50..c85ba1d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java
@@ -1340,7 +1340,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
             int cacheId = grp.sharedGroup() ? cctx.cacheId() : CU.UNDEFINED_CACHE_ID;
 
             if (qryMgr.enabled())
-                qryMgr.store(newRow, oldRow);
+                qryMgr.store(newRow, oldRow, true);
 
             if (oldRow != null) {
                 assert oldRow.link() != 0 : oldRow;
@@ -1372,7 +1372,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager
 
                 GridCacheQueryManager qryMgr = cctx.queries();
 
-                qryMgr.store(row, null);
+                qryMgr.store(row, null, false);
             }
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
index dc4d7e0..063f096 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
@@ -381,9 +381,10 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
     /**
      * @param newRow New row.
      * @param prevRow Previous row.
+     * @param prevRowAvailable Whether previous row is available.
      * @throws IgniteCheckedException In case of error.
      */
-    public void store(CacheDataRow newRow, @Nullable CacheDataRow prevRow)
+    public void store(CacheDataRow newRow, @Nullable CacheDataRow prevRow, boolean prevRowAvailable)
         throws IgniteCheckedException {
         assert enabled();
         assert newRow != null && newRow.value() != null && newRow.link() != 0 : newRow;
@@ -403,7 +404,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
             }
 
             if (qryProcEnabled)
-                qryProc.store(cctx, newRow, prevRow);
+                qryProc.store(cctx, newRow, prevRow, prevRowAvailable);
         }
         finally {
             invalidateResultCache();

http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
index 4a9ee7f..4610025 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
@@ -218,10 +218,11 @@ public interface GridQueryIndexing {
      * @param type Type descriptor.
      * @param row New row.
      * @param prevRow Previous row.
+     * @param prevRowAvailable Whether previous row is available.
      * @throws IgniteCheckedException If failed.
      */
-    public void store(GridCacheContext cctx, GridQueryTypeDescriptor type, CacheDataRow row, CacheDataRow prevRow)
-        throws IgniteCheckedException;
+    public void store(GridCacheContext cctx, GridQueryTypeDescriptor type, CacheDataRow row, CacheDataRow prevRow,
+        boolean prevRowAvailable) throws IgniteCheckedException;
 
     /**
      * Removes index entry by key.

http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index b8c5ffa..7ad95a6 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1704,10 +1704,12 @@ public class GridQueryProcessor extends GridProcessorAdapter {
      * @throws IgniteCheckedException In case of error.
      */
     @SuppressWarnings({"unchecked", "ConstantConditions"})
-    public void store(GridCacheContext cctx, CacheDataRow newRow, @Nullable CacheDataRow prevRow)
+    public void store(GridCacheContext cctx, CacheDataRow newRow, @Nullable CacheDataRow prevRow,
+        boolean prevRowAvailable)
         throws IgniteCheckedException {
         assert cctx != null;
         assert newRow != null;
+        assert prevRowAvailable || prevRow == null;
 
         KeyCacheObject key = newRow.key();
 
@@ -1727,7 +1729,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
 
             QueryTypeDescriptorImpl desc = typeByValue(cacheName, coctx, key, newRow.value(), true);
 
-            if (prevRow != null) {
+            if (prevRowAvailable && prevRow != null) {
                 QueryTypeDescriptorImpl prevValDesc = typeByValue(cacheName,
                     coctx,
                     key,
@@ -1738,14 +1740,15 @@ public class GridQueryProcessor extends GridProcessorAdapter {
                     if (prevValDesc != null)
                         idx.remove(cctx, prevValDesc, prevRow);
 
-                    prevRow = null; // Row has already been removed from another table indexes
+                    // Row has already been removed from another table indexes
+                    prevRow = null;
                 }
             }
 
             if (desc == null)
                 return;
 
-            idx.store(cctx, desc, newRow, prevRow);
+            idx.store(cctx, desc, newRow, prevRow, prevRowAvailable);
         }
         finally {
             busyLock.leaveBusy();

http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
index a9c8e5c..366230d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteClientCacheInitializationFailTest.java
@@ -311,7 +311,7 @@ public class IgniteClientCacheInitializationFailTest extends GridCommonAbstractT
 
         /** {@inheritDoc} */
         @Override public void store(GridCacheContext cctx, GridQueryTypeDescriptor type, CacheDataRow row,
-            CacheDataRow prevRow) {
+            CacheDataRow prevRow, boolean prevRowAvailable) {
             // No-op.
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 52185f4..450ee20 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -570,7 +570,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
 
     /** {@inheritDoc} */
     @Override public void store(GridCacheContext cctx, GridQueryTypeDescriptor type, CacheDataRow row,
-        @Nullable CacheDataRow prevRow) throws IgniteCheckedException {
+        @Nullable CacheDataRow prevRow, boolean prevRowAvailable) throws IgniteCheckedException {
         String cacheName = cctx.name();
 
         H2TableDescriptor tbl = tableDescriptor(schema(cacheName), cacheName, type.name());
@@ -578,7 +578,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
         if (tbl == null)
             return; // Type was rejected.
 
-        tbl.table().update(row, prevRow);
+        tbl.table().update(row, prevRow, prevRowAvailable);
 
         if (tbl.luceneIndex() != null) {
             long expireTime = row.expireTime();

http://git-wip-us.apache.org/repos/asf/ignite/blob/93038455/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index 87e6f3d..cdffa16 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -426,9 +426,10 @@ public class GridH2Table extends TableBase {
      *
      * @param row Row to be updated.
      * @param prevRow Previous row.
+     * @param prevRowAvailable Whether previous row is available.
      * @throws IgniteCheckedException If failed.
      */
-    public void update(CacheDataRow row, @Nullable CacheDataRow prevRow)
+    public void update(CacheDataRow row, @Nullable CacheDataRow prevRow, boolean prevRowAvailable)
         throws IgniteCheckedException {
         assert desc != null;
 
@@ -446,9 +447,17 @@ public class GridH2Table extends TableBase {
             try {
                 ensureNotDestroyed();
 
-                boolean replaced = pk().putx(row0);
+                boolean replaced;
 
-                assert (replaced && prevRow != null) || (!replaced && prevRow == null) : "Replaced: " + replaced;
+                if (prevRowAvailable)
+                    replaced = pk().putx(row0);
+                else {
+                    prevRow0 = (GridH2KeyValueRowOnheap)pk().put(row0);
+
+                    replaced = prevRow0 != null;
+                }
+
+                assert (replaced && prevRow0 != null) || (!replaced && prevRow0 == null) : "Replaced: " + replaced;
 
                 if (!replaced)
                     size.increment();


[12/47] ignite git commit: .NET: Move tests to long category

Posted by sb...@apache.org.
.NET: Move tests to long category


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

Branch: refs/heads/ignite-zk
Commit: cba8fa2f26e1934704046ba073b7f8516d192823
Parents: cdb43d8
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Nov 14 23:27:47 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Nov 14 23:27:47 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs  | 1 +
 .../Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs       | 2 ++
 2 files changed, 3 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cba8fa2f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
index 63a9f47..6d6e9a9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/PersistentStoreTestObsolete.cs
@@ -27,6 +27,7 @@ namespace Apache.Ignite.Core.Tests.Cache
     /// <summary>
     /// Tests the persistent store. Uses the obsolete API. See <see cref="PersistenceTest"/> for the actual API.
     /// </summary>
+    [Category(TestUtils.CategoryIntensive)]
     public class PersistentStoreTestObsolete
     {
         /** Temp dir for WAL. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/cba8fa2f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
index 9c63c73..89185d4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
@@ -754,6 +754,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         /// Tests query timeouts.
         /// </summary>
         [Test]
+        [Category(TestUtils.CategoryIntensive)]
         public void TestSqlQueryTimeout()
         {
             var cache = Cache();
@@ -773,6 +774,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
         /// Tests fields query timeouts.
         /// </summary>
         [Test]
+        [Category(TestUtils.CategoryIntensive)]
         public void TestSqlFieldsQueryTimeout()
         {
             var cache = Cache();


[22/47] ignite git commit: ignite-6858 Fail query if thread has is cache lock and exchange is in progress

Posted by sb...@apache.org.
ignite-6858 Fail query if thread has is cache lock and exchange is in progress


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

Branch: refs/heads/ignite-zk
Commit: caad1e912192d3da0d74395db6cc3625fe2eb804
Parents: 52b46c3
Author: Aleksei Scherbakov <al...@gmail.com>
Authored: Thu Nov 16 12:45:11 2017 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Thu Nov 16 12:45:11 2017 +0300

----------------------------------------------------------------------
 .../cache/distributed/near/GridNearTxLocal.java |  7 +-
 .../processors/query/h2/IgniteH2Indexing.java   | 17 +++++
 .../h2/twostep/GridReduceQueryExecutor.java     | 11 ++-
 .../IgniteCacheQueryNodeRestartSelfTest2.java   | 75 +++++++++++++++++---
 .../IgniteCacheQueryNodeRestartTxSelfTest.java  | 36 ++++++++++
 .../IgniteCacheQuerySelfTestSuite2.java         |  2 +
 6 files changed, 133 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/caad1e91/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 085f0b7..a3fddaf 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
@@ -4122,14 +4122,13 @@ public class GridNearTxLocal extends GridDhtTxLocalAdapter implements GridTimeou
     /** {@inheritDoc} */
     @Override public void onTimeout() {
         if (state(MARKED_ROLLBACK, true) || (state() == MARKED_ROLLBACK)) {
-            if (log.isDebugEnabled())
-                log.debug("Will rollback tx on timeout: " + this);
-
             cctx.kernalContext().closure().runLocalSafe(new Runnable() {
                 @Override public void run() {
-                    // Note: if rollback asynchonously on timeout should not clear thread map
+                    // Note: if rollback asynchronously on timeout should not clear thread map
                     // since thread started tx still should be able to see this tx.
                     rollbackNearTxLocalAsync(true);
+
+                    U.warn(log, "Transaction was rolled back because the timeout is reached: " + GridNearTxLocal.this);
                 }
             });
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/caad1e91/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 450ee20..333a958 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -71,6 +71,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapManager;
 import org.apache.ignite.internal.processors.cache.KeyCacheObject;
 import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtInvalidPartitionException;
+import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionsExchangeFuture;
 import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
 import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO;
 import org.apache.ignite.internal.processors.cache.query.CacheQueryPartitionInfo;
@@ -2477,6 +2478,22 @@ public class IgniteH2Indexing implements GridQueryIndexing {
     }
 
     /**
+     * @param readyVer Ready topology version.
+     *
+     * @return {@code true} If pending distributed exchange exists because server topology is changed.
+     */
+    public boolean serverTopologyChanged(AffinityTopologyVersion readyVer) {
+        GridDhtPartitionsExchangeFuture fut = ctx.cache().context().exchange().lastTopologyFuture();
+
+        if (fut.isDone())
+            return false;
+
+        AffinityTopologyVersion initVer = fut.initialVersion();
+
+        return initVer.compareTo(readyVer) > 0 && !CU.clientNode(fut.firstEvent().node());
+    }
+
+    /**
      * @param topVer Topology version.
      * @throws IgniteCheckedException If failed.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/caad1e91/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
index f85cd94..8e994aa 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
@@ -90,6 +90,7 @@ import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteBiClosure;
 import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.transactions.TransactionException;
 import org.h2.command.ddl.CreateTableData;
 import org.h2.engine.Session;
 import org.h2.index.Index;
@@ -560,9 +561,15 @@ public class GridReduceQueryExecutor {
 
             AffinityTopologyVersion topVer = h2.readyTopologyVersion();
 
+            // Check if topology is changed while retrying on locked topology.
+            if (h2.serverTopologyChanged(topVer) && ctx.cache().context().lockedTopologyVersion(null) != null) {
+                throw new CacheException(new TransactionException("Server topology is changed during query " +
+                    "execution inside a transaction. It's recommended to rollback and retry transaction."));
+            }
+
             List<Integer> cacheIds = qry.cacheIds();
 
-            Collection<ClusterNode> nodes = null;
+            Collection<ClusterNode> nodes;
 
             // Explicit partition mapping for unstable topology.
             Map<ClusterNode, IntArray> partsMap = null;
@@ -1737,4 +1744,4 @@ public class GridReduceQueryExecutor {
             return qryMap;
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/caad1e91/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
index 627b3eb..bda503e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartSelfTest2.java
@@ -32,20 +32,25 @@ import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.cache.query.QueryCancelledException;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.util.GridRandom;
 import org.apache.ignite.internal.util.typedef.CAX;
 import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.U;
 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.TransactionException;
+import org.apache.ignite.transactions.TransactionTimeoutException;
 
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
@@ -224,7 +229,7 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
 
         IgniteInternalFuture<?> fut1 = multithreadedAsync(new CAX() {
             @Override public void applyx() throws IgniteCheckedException {
-                GridRandom rnd = new GridRandom();
+                final GridRandom rnd = new GridRandom();
 
                 while (!qrysDone.get()) {
                     int g;
@@ -235,28 +240,43 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
                     while (!locks.compareAndSet(g, 0, 1));
 
                     try {
+                        final IgniteEx grid = grid(g);
+
                         if (rnd.nextBoolean()) { // Partitioned query.
-                            IgniteCache<?,?> cache = grid(g).cache("pu");
+                            final IgniteCache<?,?> cache = grid.cache("pu");
 
-                            SqlFieldsQuery qry = new SqlFieldsQuery(PARTITIONED_QRY);
+                            final SqlFieldsQuery qry = new SqlFieldsQuery(PARTITIONED_QRY);
 
                             boolean smallPageSize = rnd.nextBoolean();
 
                             if (smallPageSize)
                                 qry.setPageSize(3);
 
+                            final IgniteCache<Integer, Company> co = grid.cache("co");
+
                             try {
-                                assertEquals(pRes, cache.query(qry).getAll());
+                                runQuery(grid, new Runnable() {
+                                    @Override public void run() {
+                                        if (rnd.nextBoolean())
+                                            co.get(rnd.nextInt(COMPANY_CNT)); // Get lock run test with open transaction.
+
+                                        assertEquals(pRes, cache.query(qry).getAll());
+                                    }
+                                });
                             } catch (CacheException e) {
                                 // Interruptions are expected here.
-                                if (e.getCause() instanceof IgniteInterruptedCheckedException)
+                                if (e.getCause() instanceof IgniteInterruptedCheckedException ||
+                                    e.getCause() instanceof InterruptedException ||
+                                    e.getCause() instanceof ClusterTopologyException ||
+                                    e.getCause() instanceof TransactionTimeoutException ||
+                                    e.getCause() instanceof TransactionException)
                                     continue;
 
                                 if (e.getCause() instanceof QueryCancelledException)
                                     fail("Retry is expected");
 
                                 if (!smallPageSize)
-                                    e.printStackTrace();
+                                    U.error(grid.log(), "On large page size must retry.", e);
 
                                 assertTrue("On large page size must retry.", smallPageSize);
 
@@ -286,13 +306,13 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
                                     continue;
 
                                 if (!failedOnRemoteFetch) {
-                                    e.printStackTrace();
+                                    U.error(grid.log(), "Must fail inside of GridResultPage.fetchNextPage or subclass.", e);
 
                                     fail("Must fail inside of GridResultPage.fetchNextPage or subclass.");
                                 }
                             }
                         } else { // Replicated query.
-                            IgniteCache<?, ?> cache = grid(g).cache("co");
+                            IgniteCache<?, ?> cache = grid.cache("co");
 
                             assertEquals(rRes, cache.query(new SqlFieldsQuery(REPLICATED_QRY)).getAll());
                         }
@@ -358,7 +378,14 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
 
         restartsDone.set(true);
 
-        fut2.get();
+        try {
+            fut2.get(20_000);
+        }
+        catch (IgniteFutureTimeoutCheckedException e) {
+            U.dumpThreads(log);
+
+            fail("Stopping restarts timeout.");
+        }
 
         info("Restarts stopped.");
 
@@ -380,12 +407,26 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
     }
 
     /**
+     * Run query closure.
+     *
+     * @param grid Grid.
+     * @param qryRunnable Query runnable.
+     */
+    protected void runQuery(IgniteEx grid, Runnable qryRunnable) {
+        qryRunnable.run();
+    }
+
+    /**
      *
      */
     private static class Person implements Serializable {
+        /** */
         @QuerySqlField(index = true)
         int id;
 
+        /**
+         * @param id Person ID.
+         */
         Person(int id) {
             this.id = id;
         }
@@ -395,12 +436,18 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
      *
      */
     private static class Purchase implements Serializable {
+        /** */
         @QuerySqlField(index = true)
         int personId;
 
+        /** */
         @QuerySqlField(index = true)
         int productId;
 
+        /**
+         * @param personId Person ID.
+         * @param productId Product ID.
+         */
         Purchase(int personId, int productId) {
             this.personId = personId;
             this.productId = productId;
@@ -411,9 +458,13 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
      *
      */
     private static class Company implements Serializable {
+        /** */
         @QuerySqlField(index = true)
         int id;
 
+        /**
+         * @param id ID.
+         */
         Company(int id) {
             this.id = id;
         }
@@ -423,12 +474,18 @@ public class IgniteCacheQueryNodeRestartSelfTest2 extends GridCommonAbstractTest
      *
      */
     private static class Product implements Serializable {
+        /** */
         @QuerySqlField(index = true)
         int id;
 
+        /** */
         @QuerySqlField(index = true)
         int companyId;
 
+        /**
+         * @param id ID.
+         * @param companyId Company ID.
+         */
         Product(int id, int companyId) {
             this.id = id;
             this.companyId = companyId;

http://git-wip-us.apache.org/repos/asf/ignite/blob/caad1e91/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartTxSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartTxSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartTxSelfTest.java
new file mode 100644
index 0000000..ae06c42
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartTxSelfTest.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.internal.processors.cache.distributed.near;
+
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.transactions.Transaction;
+
+import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
+import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
+
+/**
+ * Test for distributed queries with node restarts inside transactions.
+ */
+public class IgniteCacheQueryNodeRestartTxSelfTest extends IgniteCacheQueryNodeRestartSelfTest2 {
+    /** {@inheritDoc} */
+    @Override protected void runQuery(IgniteEx grid, Runnable qryRunnable) {
+        try(Transaction tx = grid.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) {
+            qryRunnable.run();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/caad1e91/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
index 91e4478..abe06ec 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
@@ -31,6 +31,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQ
 import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartDistributedJoinSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartSelfTest2;
+import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartTxSelfTest;
 import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryStopOnCancelOrTimeoutDistributedJoinSelfTest;
 import org.apache.ignite.internal.processors.cache.index.DynamicColumnsConcurrentAtomicPartitionedSelfTest;
 import org.apache.ignite.internal.processors.cache.index.DynamicColumnsConcurrentAtomicReplicatedSelfTest;
@@ -85,6 +86,7 @@ public class IgniteCacheQuerySelfTestSuite2 extends TestSuite {
         suite.addTestSuite(IgniteCacheQueryNodeFailTest.class);
         suite.addTestSuite(IgniteCacheQueryNodeRestartSelfTest.class);
         suite.addTestSuite(IgniteCacheQueryNodeRestartSelfTest2.class);
+        suite.addTestSuite(IgniteCacheQueryNodeRestartTxSelfTest.class);
         suite.addTestSuite(IgniteCacheSqlQueryMultiThreadedSelfTest.class);
         suite.addTestSuite(IgniteCachePartitionedQueryMultiThreadedSelfTest.class);
         suite.addTestSuite(CacheScanPartitionQueryFallbackSelfTest.class);


[27/47] ignite git commit: IGNITE-6496 Client node should release queue semaphore on disconnect - Fixes #2981.

Posted by sb...@apache.org.
IGNITE-6496 Client node should release queue semaphore on disconnect - Fixes #2981.

Signed-off-by: Alexey Goncharuk <al...@gmail.com>


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

Branch: refs/heads/ignite-zk
Commit: 4e046794c5a0274241c1240d73b9f08cf0a83439
Parents: 38f66c7
Author: Slava Koptilin <sl...@gmail.com>
Authored: Fri Nov 17 15:53:15 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Fri Nov 17 15:53:15 2017 +0300

----------------------------------------------------------------------
 .../CacheDataStructuresManager.java             |  12 ++
 .../datastructures/GridCacheQueueAdapter.java   |   5 +
 .../GridCacheQueueClientDisconnectTest.java     | 117 +++++++++++++++++++
 .../IgniteCacheDataStructuresSelfTestSuite.java |   2 +
 4 files changed, 136 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4e046794/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
index 0b81e7a..a9b60228 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/datastructures/CacheDataStructuresManager.java
@@ -65,6 +65,7 @@ import org.apache.ignite.internal.util.GridConcurrentHashSet;
 import org.apache.ignite.internal.util.GridSpinBusyLock;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.resources.IgniteInstanceResource;
 import org.jetbrains.annotations.NotNull;
@@ -161,6 +162,17 @@ public class CacheDataStructuresManager extends GridCacheManagerAdapter {
             q.delegate().onKernalStop();
     }
 
+    /** {@inheritDoc} */
+    @Override public void onDisconnected(IgniteFuture reconnectFut) {
+        super.onDisconnected(reconnectFut);
+
+        for (Map.Entry<IgniteUuid, GridCacheQueueProxy> e : queuesMap.entrySet()) {
+            GridCacheQueueProxy queue = e.getValue();
+
+            queue.delegate().onClientDisconnected();
+        }
+    }
+
     /**
      * @param set Set.
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/4e046794/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheQueueAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheQueueAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheQueueAdapter.java
index c567ac4..e42c00b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheQueueAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheQueueAdapter.java
@@ -479,6 +479,11 @@ public abstract class GridCacheQueueAdapter<T> extends AbstractCollection<T> imp
             onRemoved(true);
     }
 
+    /** Release all semaphores used in blocking operations in case of client disconnect. */
+    public void onClientDisconnected() {
+        releaseSemaphores();
+    }
+
     /**
      * Marks queue as removed.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/4e046794/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheQueueClientDisconnectTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheQueueClientDisconnectTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheQueueClientDisconnectTest.java
new file mode 100644
index 0000000..ed54377
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/GridCacheQueueClientDisconnectTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.datastructures;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteClientDisconnectedException;
+import org.apache.ignite.IgniteQueue;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.configuration.CollectionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.internal.U;
+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;
+
+public class GridCacheQueueClientDisconnectTest extends GridCommonAbstractTest {
+    /** */
+    private static final String IGNITE_QUEUE_NAME = "ignite-queue-client-reconnect-test";
+
+    /** */
+    private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final int FAILURE_DETECTION_TIMEOUT = 10_000;
+
+    /** */
+    private boolean clientMode;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+        TcpDiscoverySpi spi = new TcpDiscoverySpi();
+
+        spi.setIpFinder(ipFinder);
+
+        spi.setClientReconnectDisabled(false);
+
+        cfg.setDiscoverySpi(spi);
+
+        cfg.setFailureDetectionTimeout(FAILURE_DETECTION_TIMEOUT);
+        cfg.setClientFailureDetectionTimeout(FAILURE_DETECTION_TIMEOUT);
+
+        if (clientMode)
+            cfg.setClientMode(true);
+
+        return cfg;
+    }
+
+    private static CollectionConfiguration collectionConfiguration(CacheAtomicityMode cacheAtomicityMode) {
+        CollectionConfiguration colCfg = new CollectionConfiguration();
+
+        colCfg.setAtomicityMode(cacheAtomicityMode);
+
+        return colCfg;
+    }
+
+    public void testClientDisconnect() throws Exception {
+        try {
+            Ignite server = startGrid(0);
+
+            clientMode = true;
+
+            Ignite client = startGrid(1);
+
+            awaitPartitionMapExchange();
+
+            final IgniteQueue queue = client.queue(
+                IGNITE_QUEUE_NAME, 0, collectionConfiguration(CacheAtomicityMode.ATOMIC));
+
+            final CountDownLatch latch = new CountDownLatch(1);
+
+            GridTestUtils.runAsync(new Runnable() {
+                @Override public void run() {
+                    try {
+                        Object value = queue.take();
+                    }
+                    catch (IgniteClientDisconnectedException icd) {
+                        latch.countDown();
+                    }
+                    catch (Exception e) {
+                    }
+                }
+            });
+
+            U.sleep(5000);
+
+            server.close();
+
+            boolean countReachedZero = latch.await(FAILURE_DETECTION_TIMEOUT * 2, TimeUnit.MILLISECONDS);
+
+            assertTrue("IgniteClientDisconnectedException was not thrown", countReachedZero);
+        }
+        finally {
+            stopAllGrids();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/4e046794/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
index 6e16d2e..414f463 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheDataStructuresSelfTestSuite.java
@@ -20,6 +20,7 @@ package org.apache.ignite.testsuites;
 import junit.framework.TestSuite;
 import org.apache.ignite.internal.processors.cache.AtomicCacheAffinityConfigurationTest;
 import org.apache.ignite.internal.processors.cache.datastructures.GridCacheQueueCleanupSelfTest;
+import org.apache.ignite.internal.processors.cache.datastructures.GridCacheQueueClientDisconnectTest;
 import org.apache.ignite.internal.processors.cache.datastructures.GridCacheQueueMultiNodeConsistencySelfTest;
 import org.apache.ignite.internal.processors.cache.datastructures.IgniteClientDataStructuresTest;
 import org.apache.ignite.internal.processors.cache.datastructures.IgniteClientDiscoveryDataStructuresTest;
@@ -121,6 +122,7 @@ public class IgniteCacheDataStructuresSelfTestSuite extends TestSuite {
         suite.addTest(new TestSuite(GridCachePartitionedAtomicQueueApiSelfTest.class));
         suite.addTest(new TestSuite(GridCachePartitionedQueueMultiNodeSelfTest.class));
         suite.addTest(new TestSuite(GridCachePartitionedAtomicQueueMultiNodeSelfTest.class));
+        suite.addTest(new TestSuite(GridCacheQueueClientDisconnectTest.class));
 
         suite.addTest(new TestSuite(GridCachePartitionedQueueCreateMultiNodeSelfTest.class));
         suite.addTest(new TestSuite(GridCachePartitionedAtomicQueueCreateMultiNodeSelfTest.class));


[44/47] ignite git commit: IGNITE-5195 DataStreamer can fails if non-data node enter\leave the grid. This closes #3026.

Posted by sb...@apache.org.
IGNITE-5195 DataStreamer can fails if non-data node enter\leave the grid. This closes #3026.

Signed-off-by: nikolay_tikhonov <nt...@gridgain.com>


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

Branch: refs/heads/ignite-zk
Commit: 5fb04be3942d8a90288fdc75f86693872c918e2d
Parents: 43aa4a8
Author: nikolay_tikhonov <nt...@gridgain.com>
Authored: Mon Nov 20 18:37:44 2017 +0300
Committer: nikolay_tikhonov <nt...@gridgain.com>
Committed: Mon Nov 20 18:39:03 2017 +0300

----------------------------------------------------------------------
 .../cache/GridCacheAffinityManager.java         |  7 ++-
 .../datastreamer/DataStreamerImpl.java          | 20 ++++++-
 .../cache/IgniteCacheDynamicStopSelfTest.java   |  2 +-
 .../datastreamer/DataStreamerImplSelfTest.java  | 60 ++++++++++++++++++++
 4 files changed, 85 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb04be3/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
index 14a1344..c9ee38c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
@@ -123,7 +123,12 @@ public class GridCacheAffinityManager extends GridCacheManagerAdapter {
         if (cctx.isLocal())
             topVer = LOC_CACHE_TOP_VER;
 
-        return aff.assignments(topVer);
+        GridAffinityAssignmentCache aff0 = aff;
+
+        if (aff0 == null)
+            throw new IgniteException(FAILED_TO_FIND_CACHE_ERR_MSG + cctx.name());
+
+        return aff0.assignments(topVer);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb04be3/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
index d38132f..12eb2dc 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
@@ -779,6 +779,8 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
             else
                 topVer = ctx.cache().context().exchange().readyAffinityVersion();
 
+            List<List<ClusterNode>> assignments = cctx.affinity().assignments(topVer);
+
             if (!allowOverwrite() && !cctx.isLocal()) { // Cases where cctx required.
                 gate = cctx.gate();
 
@@ -956,7 +958,7 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
                     final List<GridFutureAdapter<?>> futs;
 
                     try {
-                        futs = buf.update(entriesForNode, topVer, opFut, remap);
+                        futs = buf.update(entriesForNode, topVer, assignments, opFut, remap);
 
                         opFut.markInitialized();
                     }
@@ -1411,6 +1413,7 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
         @Nullable List<GridFutureAdapter<?>> update(
             Iterable<DataStreamerEntry> newEntries,
             AffinityTopologyVersion topVer,
+            List<List<ClusterNode>> assignments,
             GridCompoundFuture opFut,
             boolean remap
         ) throws IgniteInterruptedCheckedException {
@@ -1441,9 +1444,19 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
                         futs[b.partId] = curFut0;
                     }
 
-                    if (b.batchTopVer == null)
+                    if (b.batchTopVer == null) {
+                        b.batchTopVer = topVer;
+
+                        b.assignments = assignments;
+                    }
+
+                    // topology changed, but affinity is the same, no re-map is required.
+                    if (!topVer.equals(b.batchTopVer) && b.assignments.equals(assignments)) {
                         b.batchTopVer = topVer;
 
+                        b.assignments = assignments;
+                    }
+
                     curBatchTopVer = b.batchTopVer;
 
                     b.entries.add(entry);
@@ -2186,6 +2199,9 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
         /** */
         private final IgniteInClosure<? super IgniteInternalFuture<Object>> signalC;
 
+        /** Batch assignments */
+        public List<List<ClusterNode>> assignments;
+
         /**
          * @param partId Partition ID.
          * @param c Signal closure.

http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb04be3/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDynamicStopSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDynamicStopSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDynamicStopSelfTest.java
index 5628c4d..44cd475 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDynamicStopSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDynamicStopSelfTest.java
@@ -142,4 +142,4 @@ public class IgniteCacheDynamicStopSelfTest extends GridCommonAbstractTest {
 
         ignite(0).destroyCache(DEFAULT_CACHE_NAME);
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5fb04be3/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImplSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImplSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImplSelfTest.java
index e90f6b0..940f8ce 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImplSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImplSelfTest.java
@@ -27,6 +27,7 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.CyclicBarrier;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.cache.CacheException;
@@ -38,6 +39,7 @@ import org.apache.ignite.cache.CacheServerNotFoundException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.managers.communication.GridIoMessage;
 import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
@@ -431,6 +433,64 @@ public class DataStreamerImplSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testClientEventsNotCausingRemaps() throws Exception {
+        Ignite ignite = startGrids(2);
+
+        ignite.getOrCreateCache(DEFAULT_CACHE_NAME);
+
+        IgniteDataStreamer<Object, Object> streamer = ignite.dataStreamer(DEFAULT_CACHE_NAME);
+
+        ((DataStreamerImpl)streamer).maxRemapCount(3);
+
+        streamer.addData(1, 1);
+
+        for (int topChanges = 0; topChanges < 30; topChanges++) {
+            IgniteEx node = startGrid(getConfiguration("flapping-client").setClientMode(true));
+
+            streamer.addData(1, 1);
+
+            node.close();
+
+            streamer.addData(1, 1);
+        }
+
+        streamer.flush();
+        streamer.close();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testServerEventsCauseRemaps() throws Exception {
+        Ignite ignite = startGrids(2);
+
+        ignite.getOrCreateCache(DEFAULT_CACHE_NAME);
+
+        IgniteDataStreamer<Object, Object> streamer = ignite.dataStreamer(DEFAULT_CACHE_NAME);
+
+        ((DataStreamerImpl)streamer).maxRemapCount(0);
+
+        streamer.addData(1, 1);
+
+        startGrid(2);
+
+        try {
+            streamer.addData(1, 1);
+
+            streamer.flush();
+        }
+        catch (IllegalStateException ex) {
+            assert ex.getMessage().contains("Data streamer has been closed");
+
+            return;
+        }
+
+        fail("Expected exception wasn't thrown");
+    }
+
+    /**
      * Gets cache configuration.
      *
      * @return Cache configuration.


[08/47] ignite git commit: IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
new file mode 100644
index 0000000..4b87df5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/AppDomains.cs
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics;
+    using System.Runtime.InteropServices;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// AppDomain accessor.
+    /// <para />
+    /// Logic is borrowed from internal .NET Framework classes.
+    /// See System.Deployment.Application.NativeMethods.
+    /// </summary>
+    internal static class AppDomains
+    {
+        // ReSharper disable InconsistentNaming
+        // ReSharper disable UnusedMember.Global
+        /** */
+        private static Guid CLSID_CLRMetaHost = new Guid(
+            0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde);
+
+        /** */
+        private static Guid IID_CLRMetaHost = new Guid(
+            0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);
+
+        /** */
+        private static Guid IID_CLRRuntimeInfo = new Guid(
+            0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);
+
+        /** */
+        private static Guid CLSID_CorRuntimeHost = new Guid(
+            0xcb2f6723, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
+
+        /** */
+        private static Guid IID_CorRuntimeHost = new Guid(
+            0xcb2f6722, 0xab3a, 0x11d2, 0x9c, 0x40, 0x00, 0xc0, 0x4f, 0xa3, 0x0a, 0x3e);
+
+        /// <summary>
+        /// Gets the default application domain.
+        /// </summary>
+        public static _AppDomain GetDefaultAppDomain()
+        {
+            object objHost;
+            int hr = NativeMethods.CLRCreateInstance(ref CLSID_CLRMetaHost, ref IID_CLRMetaHost, out objHost);
+
+            if (hr < 0)
+            {
+                throw new IgniteException("Failed to get default AppDomain. Cannot create meta host: " + hr);
+            }
+            
+            var host = (ICLRMetaHost) objHost;
+            var vers = Environment.Version;
+            var versString = string.Format("v{0}.{1}.{2}", vers.Major, vers.Minor, vers.Build);
+            var runtime = (ICLRRuntimeInfo) host.GetRuntime(versString, ref IID_CLRRuntimeInfo);
+            
+            bool started;
+            uint flags;
+            runtime.IsStarted(out started, out flags);
+            Debug.Assert(started);
+
+            var rtHost = (ICorRuntimeHost) runtime.GetInterface(ref CLSID_CorRuntimeHost, ref IID_CorRuntimeHost);
+
+            _AppDomain domain;
+            rtHost.GetDefaultDomain(out domain);
+
+            return domain;
+        }
+
+        [ComImport, Guid("D332DB9E-B9B3-4125-8207-A14884F53216"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        private interface ICLRMetaHost
+        {
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetRuntime(string version, ref Guid iid);
+        }
+
+        [ComImport, Guid("BD39D1D2-BA2F-486a-89B0-B4B0CB466891"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        private interface ICLRRuntimeInfo
+        {
+            void GetVersionString(char[] buffer, int bufferLength);
+            void GetRuntimeDirectory(char[] buffer, int bufferLength);
+            bool IsLoaded(IntPtr hProcess);
+            void LoadErrorString(uint id, char[] buffer, int bufferLength, int lcid);
+            void LoadLibrary(string path, out IntPtr hMdodule);
+            void GetProcAddress(string name, out IntPtr addr);
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetInterface(ref Guid clsid, ref Guid iid);
+            bool IsLoadable();
+            void SetDefaultStartupFlags(uint flags, string configFile);
+            void GetDefaultStartupFlags(out uint flags, char[] configFile, int configFileLength);
+            void BindAsLegacyV2Runtime();
+            void IsStarted(out bool started, out uint flags);
+        }
+
+        [ComImport, Guid("CB2F6722-AB3A-11d2-9C40-00C04FA30A3E"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        private interface ICorRuntimeHost
+        {
+            void CreateLogicalThreadState();
+            void DeleteLogicalThreadState();
+            void SwitchinLogicalThreadState(IntPtr cookie);
+            void SwitchoutLogicalThreadState(out IntPtr cookie);
+            void LocksHeldByLogicalThread(out int count);
+            void MapFile(IntPtr hFile, out IntPtr address);
+            void GetConfiguration(out IntPtr config);
+            void Start();
+            void Stop();
+            void CreateDomain(string name, object identity, out _AppDomain domain);
+            void GetDefaultDomain(out _AppDomain domain);
+        }
+
+        private static class NativeMethods
+        {
+            [DllImport("mscoree.dll")]
+            public static extern int CLRCreateInstance(ref Guid clsid, ref Guid iid,
+                [MarshalAs(UnmanagedType.Interface)] out object ptr);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
new file mode 100644
index 0000000..4eb1d29
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/CallbackDelegates.cs
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Runtime.InteropServices;
+    using System.Security;
+
+    /// <summary>
+    /// Java -> .NET callback delegates.
+    /// <para />
+    /// Delegates are registered once per JVM.
+    /// Every callback has igniteId argument to identify related Ignite instance
+    /// (this value is passed as EnvPtr to PlatformIgnition.start).
+    /// </summary>
+    [SuppressUnmanagedCodeSecurity]
+    internal static class CallbackDelegates
+    {
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate void LoggerLog(IntPtr env, IntPtr clazz, long igniteId, int level, IntPtr message,
+            IntPtr category, IntPtr error, long memPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long ignteId, int level);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate void ConsoleWrite(IntPtr env, IntPtr clazz, IntPtr message, bool isError);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId, int op, long arg);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz,
+            long igniteId, int op, long arg1, long arg2, long arg3, IntPtr arg);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
new file mode 100644
index 0000000..1e2989f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Callbacks.cs
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Collections.Concurrent;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Linq;
+    using System.Runtime.InteropServices;
+    using System.Threading;
+    using Apache.Ignite.Core.Impl.Handle;
+    using Apache.Ignite.Core.Log;
+
+    /// <summary>
+    /// Java -> .NET callback dispatcher.
+    /// Instance of this class should only exist once per process, in the default AppDomain.
+    /// </summary>
+    internal sealed class Callbacks : MarshalByRefObject
+    {
+        /** Holds delegates so that GC does not collect them. */
+        // ReSharper disable once CollectionNeverQueried.Local
+        private readonly List<Delegate> _delegates = new List<Delegate>();
+
+        /** Holds Ignite instance-specific callbacks. */
+        private readonly HandleRegistry _callbackRegistry = new HandleRegistry(100);
+
+        /** Console writers. */
+        private readonly ConcurrentDictionary<long, ConsoleWriter> _consoleWriters
+            = new ConcurrentDictionary<long, ConsoleWriter>();
+
+        /** Gets the JVM. */
+        private readonly Jvm _jvm;
+
+        /** Console writer id generator. */
+        private long _consoleWriterId;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Callbacks"/> class.
+        /// </summary>
+        public Callbacks(Env env, Jvm jvm)
+        {
+            Debug.Assert(env != null);
+            Debug.Assert(jvm != null);
+
+            _jvm = jvm;
+            RegisterNatives(env);
+        }
+
+        /** <inheritdoc /> */
+        public override object InitializeLifetimeService()
+        {
+            // Ensure that cross-AppDomain reference lives forever.
+            return null;
+        }
+
+        /// <summary>
+        /// Registers callback handlers.
+        /// </summary>
+        public long RegisterHandlers(UnmanagedCallbacks cbs)
+        {
+            Debug.Assert(cbs != null);
+
+            return _callbackRegistry.AllocateCritical(cbs);
+        }
+
+        /// <summary>
+        /// Releases callback handlers.
+        /// </summary>
+        public void ReleaseHandlers(long igniteId)
+        {
+            _callbackRegistry.Release(igniteId);
+        }
+
+        /// <summary>
+        /// Registers the console writer.
+        /// </summary>
+        public long RegisterConsoleWriter(ConsoleWriter writer)
+        {
+            Debug.Assert(writer != null);
+
+            var id = Interlocked.Increment(ref _consoleWriterId);
+
+            var res = _consoleWriters.TryAdd(id, writer);
+            Debug.Assert(res);
+
+            return id;
+        }
+
+        /// <summary>
+        /// Registers the console writer.
+        /// </summary>
+        public void ReleaseConsoleWriter(long id)
+        {
+            ConsoleWriter writer;
+            var res = _consoleWriters.TryRemove(id, out writer);
+            Debug.Assert(res);
+        }
+
+        /// <summary>
+        /// Registers native callbacks.
+        /// </summary>
+        private void RegisterNatives(Env env)
+        {
+            // Native callbacks are per-jvm.
+            // Every callback (except ConsoleWrite) includes envPtr (third arg) to identify Ignite instance.
+
+            using (var callbackUtils = env.FindClass(
+                "org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils"))
+            {
+                // Any signature works, but wrong one will cause segfault eventually.
+                var methods = new[]
+                {
+                    GetNativeMethod("loggerLog", "(JILjava/lang/String;Ljava/lang/String;Ljava/lang/String;J)V",
+                        (CallbackDelegates.LoggerLog) LoggerLog),
+
+                    GetNativeMethod("loggerIsLevelEnabled", "(JI)Z",
+                        (CallbackDelegates.LoggerIsLevelEnabled) LoggerIsLevelEnabled),
+
+                    GetNativeMethod("consoleWrite", "(Ljava/lang/String;Z)V",
+                        (CallbackDelegates.ConsoleWrite) ConsoleWrite),
+
+                    GetNativeMethod("inLongOutLong", "(JIJ)J", (CallbackDelegates.InLongOutLong) InLongOutLong),
+
+                    GetNativeMethod("inLongLongLongObjectOutLong", "(JIJJJLjava/lang/Object;)J",
+                        (CallbackDelegates.InLongLongLongObjectOutLong) InLongLongLongObjectOutLong)
+                };
+
+                try
+                {
+                    env.RegisterNatives(callbackUtils, methods);
+                }
+                finally
+                {
+                    foreach (var nativeMethod in methods)
+                    {
+                        Marshal.FreeHGlobal(nativeMethod.Name);
+                        Marshal.FreeHGlobal(nativeMethod.Signature);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the native method.
+        /// </summary>
+        private unsafe NativeMethod GetNativeMethod(string name, string sig, Delegate d)
+        {
+            _delegates.Add(d);
+
+            return new NativeMethod
+            {
+                Name = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(name),
+                Signature = (IntPtr)IgniteUtils.StringToUtf8Unmanaged(sig),
+                FuncPtr = Marshal.GetFunctionPointerForDelegate(d)
+            };
+        }
+
+        /// <summary>
+        /// <see cref="ILogger.Log"/> callback.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private void LoggerLog(IntPtr envPtr, IntPtr clazz, long igniteId, int level, IntPtr message, IntPtr category,
+            IntPtr errorInfo, long memPtr)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+                var env = _jvm.AttachCurrentThread();
+
+                var message0 = env.JStringToString(message);
+                var category0 = env.JStringToString(category);
+                var errorInfo0 = env.JStringToString(errorInfo);
+
+                cbs.LoggerLog(level, message0, category0, errorInfo0, memPtr);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+            }
+        }
+
+        /// <summary>
+        /// <see cref="ILogger.IsEnabled"/> callback.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private bool LoggerIsLevelEnabled(IntPtr env, IntPtr clazz, long igniteId, int level)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+                return cbs.LoggerIsLevelEnabled(level);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 3 longs + object -> long.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private long InLongLongLongObjectOutLong(IntPtr env, IntPtr clazz, long igniteId,
+            int op, long arg1, long arg2, long arg3, IntPtr arg)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+                return cbs.InLongLongLongObjectOutLong(op, arg1, arg2, arg3, arg);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// long -> long.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private long InLongOutLong(IntPtr env, IntPtr clazz, long igniteId,
+            int op, long arg)
+        {
+            try
+            {
+                var cbs = _callbackRegistry.Get<UnmanagedCallbacks>(igniteId, true);
+
+                return cbs.InLongOutLong(op, arg);
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// System.out.println -> Console.Write.
+        /// <para />
+        /// Java uses system output which can not be accessed with native .NET APIs.
+        /// For example, unit test runners won't show Java console output, and so on.
+        /// To fix this we delegate console output from Java to .NET APIs.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
+        private void ConsoleWrite(IntPtr envPtr, IntPtr clazz, IntPtr message, bool isError)
+        {
+            try
+            {
+                if (message != IntPtr.Zero)
+                {
+                    // Each domain registers it's own writer.
+                    var writer = _consoleWriters.Select(x => x.Value).FirstOrDefault();
+
+                    if (writer != null)
+                    {
+                        var env = _jvm.AttachCurrentThread();
+                        var msg = env.JStringToString(message);
+
+                        writer.Write(msg, isError);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                _jvm.AttachCurrentThread().ThrowToJava(e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
new file mode 100644
index 0000000..ef4be1e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
@@ -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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics.CodeAnalysis;
+
+    /// <summary>
+    /// Console writer.
+    /// </summary>
+    internal sealed class ConsoleWriter : MarshalByRefObject
+    {
+        /// <summary>
+        /// Writes the specified message to console.
+        /// </summary>
+        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+            Justification = "Only instance methods can be called across AppDomain boundaries.")]
+        public void Write(string message, bool isError)
+        {
+            var target = isError ? Console.Error : Console.Out;
+            target.Write(message);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
new file mode 100644
index 0000000..da790d7
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Env.cs
@@ -0,0 +1,500 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Diagnostics;
+    using System.Runtime.InteropServices;
+    using System.Security;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// JNIEnv.
+    /// </summary>
+    [SuppressUnmanagedCodeSecurity]
+    internal sealed unsafe class Env
+    {
+        /** JNIEnv pointer. */
+        private readonly IntPtr _envPtr;
+
+        /** JVM. */
+        private readonly Jvm _jvm;
+
+        /** */
+        private readonly EnvDelegates.CallStaticVoidMethod _callStaticVoidMethod;
+
+        /** */
+        private readonly EnvDelegates.CallStaticBooleanMethod _callStaticBoolMethod;
+
+        /** */
+        private readonly EnvDelegates.FindClass _findClass;
+
+        /** */
+        private readonly EnvDelegates.GetMethodId _getMethodId;
+
+        /** */
+        private readonly EnvDelegates.GetStaticMethodId _getStaticMethodId;
+
+        /** */
+        private readonly EnvDelegates.NewStringUtf _newStringUtf;
+
+        /** */
+        private readonly EnvDelegates.ExceptionOccurred _exceptionOccurred;
+
+        /** */
+        private readonly EnvDelegates.GetObjectClass _getObjectClass;
+
+        /** */
+        private readonly EnvDelegates.CallObjectMethod _callObjectMethod;
+
+        /** */
+        private readonly EnvDelegates.CallLongMethod _callLongMethod;
+
+        /** */
+        private readonly EnvDelegates.CallVoidMethod _callVoidMethod;
+
+        /** */
+        private readonly EnvDelegates.GetStringChars _getStringChars;
+
+        /** */
+        private readonly EnvDelegates.GetStringUtfChars _getStringUtfChars;
+
+        /** */
+        private readonly EnvDelegates.GetStringUtfLength _getStringUtfLength;
+
+        /** */
+        private readonly EnvDelegates.ReleaseStringUtfChars _releaseStringUtfChars;
+
+        /** */
+        private readonly EnvDelegates.ReleaseStringChars _releaseStringChars;
+
+        /** */
+        private readonly EnvDelegates.ExceptionClear _exceptionClear;
+
+        /** */
+        private readonly EnvDelegates.ExceptionCheck _exceptionCheck;
+
+        /** */
+        private readonly EnvDelegates.CallStaticObjectMethod _callStaticObjectMethod;
+
+        /** */
+        private readonly EnvDelegates.RegisterNatives _registerNatives;
+
+        /** */
+        private readonly EnvDelegates.DeleteLocalRef _deleteLocalRef;
+
+        /** */
+        private readonly EnvDelegates.NewGlobalRef _newGlobalRef;
+
+        /** */
+        private readonly EnvDelegates.DeleteGlobalRef _deleteGlobalRef;
+
+        /** */
+        private readonly EnvDelegates.ThrowNew _throwNew;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Env" /> class.
+        /// </summary>
+        internal Env(IntPtr envPtr, Jvm jvm)
+        {
+            Debug.Assert(envPtr != IntPtr.Zero);
+            Debug.Assert(jvm != null);
+
+            _envPtr = envPtr;
+            _jvm = jvm;
+
+            var funcPtr = (EnvInterface**)envPtr;
+            var func = **funcPtr;
+
+            GetDelegate(func.CallStaticVoidMethod, out _callStaticVoidMethod);
+            GetDelegate(func.CallStaticBooleanMethod, out _callStaticBoolMethod);
+            GetDelegate(func.FindClass, out _findClass);
+            GetDelegate(func.GetMethodID, out _getMethodId);
+            GetDelegate(func.GetStaticMethodID, out _getStaticMethodId);
+            GetDelegate(func.NewStringUTF, out _newStringUtf);
+            GetDelegate(func.ExceptionOccurred, out _exceptionOccurred);
+            GetDelegate(func.ExceptionClear, out _exceptionClear);
+            GetDelegate(func.ExceptionCheck, out _exceptionCheck);
+            GetDelegate(func.GetObjectClass, out _getObjectClass);
+            GetDelegate(func.CallObjectMethod, out _callObjectMethod);
+            GetDelegate(func.CallStaticObjectMethod, out _callStaticObjectMethod);
+            GetDelegate(func.CallLongMethod, out _callLongMethod);
+            GetDelegate(func.CallVoidMethod, out _callVoidMethod);
+
+            GetDelegate(func.GetStringChars, out _getStringChars);
+            GetDelegate(func.ReleaseStringChars, out _releaseStringChars);
+
+            GetDelegate(func.GetStringUTFChars, out _getStringUtfChars);
+            GetDelegate(func.ReleaseStringUTFChars, out _releaseStringUtfChars);
+
+            GetDelegate(func.GetStringUTFLength, out _getStringUtfLength);
+
+            GetDelegate(func.RegisterNatives, out _registerNatives);
+            GetDelegate(func.DeleteLocalRef, out _deleteLocalRef);
+            GetDelegate(func.NewGlobalRef, out _newGlobalRef);
+            GetDelegate(func.DeleteGlobalRef, out _deleteGlobalRef);
+            GetDelegate(func.ThrowNew, out _throwNew);
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public Jvm Jvm
+        {
+            get { return _jvm; }
+        }
+
+        /// <summary>
+        /// Calls the static void method.
+        /// </summary>
+        public void CallStaticVoidMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+        {
+            _callStaticVoidMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+        }
+
+        /// <summary>
+        /// Calls the static bool method.
+        /// </summary>
+        public bool CallStaticBoolMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+        {
+            var res = _callStaticBoolMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return res > 0;
+        }
+
+        /// <summary>
+        /// Calls the object method.
+        /// </summary>
+        public GlobalRef CallObjectMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+        {
+            var lref = _callObjectMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return NewGlobalRef(lref);
+        }
+
+        /// <summary>
+        /// Calls the long method.
+        /// </summary>
+        public long CallLongMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+        {
+            var res = _callLongMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return res;
+        }
+
+        /// <summary>
+        /// Calls the void method.
+        /// </summary>
+        public void CallVoidMethod(GlobalRef obj, IntPtr methodId, long* argsPtr = null)
+        {
+            _callVoidMethod(_envPtr, obj.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+        }
+
+        /// <summary>
+        /// Calls the static object method.
+        /// </summary>
+        private GlobalRef CallStaticObjectMethod(GlobalRef cls, IntPtr methodId, long* argsPtr = null)
+        {
+            var res = _callStaticObjectMethod(_envPtr, cls.Target, methodId, argsPtr);
+
+            ExceptionCheck();
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Finds the class.
+        /// </summary>
+        public GlobalRef FindClass(string name)
+        {
+            var res = _findClass(_envPtr, name);
+
+            if (res == IntPtr.Zero)
+            {
+                throw new IgniteException("Java class is not found (did you set IGNITE_HOME environment " +
+                                          "variable?): " + name);
+            }
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Gets the object class.
+        /// </summary>
+        private GlobalRef GetObjectClass(GlobalRef obj)
+        {
+            var res = _getObjectClass(_envPtr, obj.Target);
+
+            ExceptionCheck();
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Gets the static method identifier.
+        /// </summary>
+        public IntPtr GetStaticMethodId(GlobalRef clazz, string name, string signature)
+        {
+            var res = _getStaticMethodId(_envPtr, clazz.Target, name, signature);
+
+            if (res == IntPtr.Zero)
+            {
+                throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " +
+                                          "variable?): " + name + " " + signature);
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the method identifier.
+        /// </summary>
+        public IntPtr GetMethodId(GlobalRef clazz, string name, string signature)
+        {
+            var res = _getMethodId(_envPtr, clazz.Target, name, signature);
+
+            if (res == IntPtr.Zero)
+            {
+                throw new IgniteException("Java class method is not found (did you set IGNITE_HOME environment " +
+                                          "variable?): " + name + " " + signature);
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Creates new jstring from UTF chars.
+        /// </summary>
+        private GlobalRef NewStringUtf(sbyte* utf)
+        {
+            if (utf == null)
+            {
+                return null;
+            }
+
+            var res = _newStringUtf(_envPtr, new IntPtr(utf));
+
+            ExceptionCheck();
+
+            return NewGlobalRef(res);
+        }
+
+        /// <summary>
+        /// Creates new jstring from string.
+        /// </summary>
+        public GlobalRef NewStringUtf(string str)
+        {
+            if (str == null)
+            {
+                return null;
+            }
+
+            var chars = IgniteUtils.StringToUtf8Unmanaged(str);
+
+            try
+            {
+                return NewStringUtf(chars);
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(new IntPtr(chars));
+            }
+        }
+
+        /// <summary>
+        /// Gets the utf chars from jstring.
+        /// </summary>
+        private IntPtr GetStringUtfChars(IntPtr jstring)
+        {
+            Debug.Assert(jstring != IntPtr.Zero);
+
+            byte isCopy;
+            return _getStringUtfChars(_envPtr, jstring, &isCopy);
+        }
+
+        /// <summary>
+        /// Releases the string utf chars allocated by <see cref="GetStringUtfChars"/>.
+        /// </summary>
+        private void ReleaseStringUtfChars(IntPtr jstring, IntPtr chars)
+        {
+            _releaseStringUtfChars(_envPtr, jstring, chars);
+        }
+
+        /// <summary>
+        /// Gets the length of the jstring.
+        /// </summary>
+        private int GetStringUtfLength(IntPtr jstring)
+        {
+            Debug.Assert(jstring != IntPtr.Zero);
+
+            return _getStringUtfLength(_envPtr, jstring);
+        }
+
+        /// <summary>
+        /// Registers the native callbacks.
+        /// </summary>
+        public void RegisterNatives(GlobalRef clazz, NativeMethod[] methods)
+        {
+            Debug.Assert(methods != null);
+
+            fixed (NativeMethod* m = &methods[0])
+            {
+                var res = _registerNatives(_envPtr, clazz.Target, m, methods.Length);
+
+                if (res != JniResult.Success)
+                {
+                    throw new IgniteException("Failed to register natives: " + res);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Converts jstring to string.
+        /// </summary>
+        private string JStringToString(GlobalRef jstring)
+        {
+            if (jstring == null)
+            {
+                return null;
+            }
+
+            return JStringToString(jstring.Target);
+        }
+
+        /// <summary>
+        /// Converts jstring to string.
+        /// </summary>
+        public string JStringToString(IntPtr jstring)
+        {
+            if (jstring == IntPtr.Zero)
+            {
+                return null;
+            }
+
+            var chars = GetStringUtfChars(jstring);
+            var len = GetStringUtfLength(jstring);
+
+            try
+            {
+                return IgniteUtils.Utf8UnmanagedToString((sbyte*) chars, len);
+            }
+            finally 
+            {
+                ReleaseStringUtfChars(jstring, chars);
+            }
+        }
+
+        /// <summary>
+        /// Creates a new global reference from a local reference pointer.
+        /// </summary>
+        public GlobalRef NewGlobalRef(IntPtr lref)
+        {
+            if (lref == IntPtr.Zero)
+            {
+                return null;
+            }
+
+            var res = new GlobalRef(_newGlobalRef(_envPtr, lref), _jvm);
+
+            _deleteLocalRef(_envPtr, lref);
+
+            return res;
+        }
+
+        /// <summary>
+        /// Deletes the global reference.
+        /// </summary>
+        public void DeleteGlobalRef(IntPtr gref)
+        {
+            _deleteGlobalRef(_envPtr, gref);
+        }
+
+        /// <summary>
+        /// Throws an exception to java.
+        /// </summary>
+        public void ThrowToJava(Exception e)
+        {
+            Debug.Assert(e != null);
+            var msgChars = IgniteUtils.StringToUtf8Unmanaged(e.Message);
+
+            try
+            {
+                using (var cls = FindClass("org/apache/ignite/IgniteException"))
+                {
+                    _throwNew(_envPtr, cls.Target, new IntPtr(msgChars));
+                }
+            }
+            finally
+            {
+                Marshal.FreeHGlobal(new IntPtr(msgChars));
+            }
+        }
+
+        /// <summary>
+        /// Checks for the JNI exception and throws.
+        /// </summary>
+        private void ExceptionCheck()
+        {
+            if (!_exceptionCheck(_envPtr))
+            {
+                return;
+            }
+
+            var err = _exceptionOccurred(_envPtr);
+            Debug.Assert(err != IntPtr.Zero);
+
+            _exceptionClear(_envPtr);
+
+            using (var errRef = NewGlobalRef(err))
+            {
+                var errRef0 = (long) errRef.Target;
+                var methodId = _jvm.MethodId;
+
+                using (var cls = GetObjectClass(errRef))
+                using (var clsName = CallObjectMethod(cls, methodId.ClassGetName))
+                using (var msg = CallObjectMethod(errRef, methodId.ThrowableGetMessage))
+                using (var trace = CallStaticObjectMethod(methodId.PlatformUtils,
+                    methodId.PlatformUtilsGetStackTrace, &errRef0))
+                {
+                    throw new JavaException(
+                        JStringToString(clsName),
+                        JStringToString(msg),
+                        JStringToString(trace));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the delegate.
+        /// </summary>
+        private static void GetDelegate<T>(IntPtr ptr, out T del)
+        {
+            del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
new file mode 100644
index 0000000..a2ad499
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvDelegates.cs
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// Delegates for JNI Env entity.
+    /// </summary>
+    internal static unsafe class EnvDelegates
+    {
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        public delegate JniResult CallStaticVoidMethod(
+            IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate byte CallStaticBooleanMethod(
+            IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr NewGlobalRef(IntPtr env, IntPtr lobj);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void DeleteLocalRef(IntPtr env, IntPtr lref);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void DeleteGlobalRef(IntPtr env, IntPtr gref);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr FindClass(IntPtr env, [MarshalAs(UnmanagedType.LPStr)] string name);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetStaticMethodId(IntPtr env, IntPtr clazz,
+            [MarshalAs(UnmanagedType.LPStr)] string name, [MarshalAs(UnmanagedType.LPStr)] string sig);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetMethodId(IntPtr env, IntPtr clazz, [MarshalAs(UnmanagedType.LPStr)] string name,
+            [MarshalAs(UnmanagedType.LPStr)] string sig);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr NewStringUtf(IntPtr env, IntPtr utf);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr ExceptionOccurred(IntPtr env);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void ExceptionClear(IntPtr env);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate bool ExceptionCheck(IntPtr env);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetObjectClass(IntPtr env, IntPtr obj);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr CallObjectMethod(
+            IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate long CallLongMethod(
+            IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void CallVoidMethod(
+            IntPtr env, IntPtr obj, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr CallStaticObjectMethod(
+            IntPtr env, IntPtr clazz, IntPtr methodId, long* argsPtr);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetStringChars(IntPtr env, IntPtr jstring, byte* isCopy);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void ReleaseStringChars(IntPtr env, IntPtr jstring, IntPtr chars);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate IntPtr GetStringUtfChars(IntPtr env, IntPtr jstring, byte* isCopy);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate void ReleaseStringUtfChars(IntPtr env, IntPtr jstring, IntPtr chars);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate int GetStringUtfLength(IntPtr env, IntPtr jstring);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate JniResult RegisterNatives(IntPtr env, IntPtr clazz,
+            NativeMethod* methods, int nMethods);
+
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate JniResult ThrowNew(IntPtr env, IntPtr clazz, IntPtr msg);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
new file mode 100644
index 0000000..01f8634
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/EnvInterface.cs
@@ -0,0 +1,263 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// JNIEnv interface.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct EnvInterface
+    {
+        // ReSharper disable MemberCanBePrivate.Global
+        public IntPtr reserved0;
+        public IntPtr reserved1;
+        public IntPtr reserved2;
+        public IntPtr reserved3;
+        public IntPtr GetVersion;
+        public IntPtr DefineClass;
+        public IntPtr FindClass;
+        public IntPtr FromReflectedMethod;
+        public IntPtr FromReflectedField;
+        public IntPtr ToReflectedMethod;
+        public IntPtr GetSuperclass;
+        public IntPtr IsAssignableFrom;
+        public IntPtr ToReflectedField;
+        public IntPtr Throw;
+        public IntPtr ThrowNew;
+        public IntPtr ExceptionOccurred;
+        public IntPtr ExceptionDescribe;
+        public IntPtr ExceptionClear;
+        public IntPtr FatalError;
+        public IntPtr PushLocalFrame;
+        public IntPtr PopLocalFrame;
+        public IntPtr NewGlobalRef;
+        public IntPtr DeleteGlobalRef;
+        public IntPtr DeleteLocalRef;
+        public IntPtr IsSameObject;
+        public IntPtr NewLocalRef;
+        public IntPtr EnsureLocalCapacity;
+        public IntPtr AllocObject;
+        public IntPtr __NewObject;
+        public IntPtr __NewObjectV;
+        public IntPtr NewObject;
+        public IntPtr GetObjectClass;
+        public IntPtr IsInstanceOf;
+        public IntPtr GetMethodID;
+        public IntPtr __CallObjectMethod;
+        public IntPtr __CallObjectMethodV;
+        public IntPtr CallObjectMethod;
+        public IntPtr __CallBooleanMethod;
+        public IntPtr __CallBooleanMethodV;
+        public IntPtr CallBooleanMethod;
+        public IntPtr __CallByteMethod;
+        public IntPtr __CallByteMethodV;
+        public IntPtr CallByteMethod;
+        public IntPtr __CallCharMethod;
+        public IntPtr __CallCharMethodV;
+        public IntPtr CallCharMethod;
+        public IntPtr __CallShortMethod;
+        public IntPtr __CallShortMethodV;
+        public IntPtr CallShortMethod;
+        public IntPtr __CallIntMethod;
+        public IntPtr __CallIntMethodV;
+        public IntPtr CallIntMethod;
+        public IntPtr __CallLongMethod;
+        public IntPtr __CallLongMethodV;
+        public IntPtr CallLongMethod;
+        public IntPtr __CallFloatMethod;
+        public IntPtr __CallFloatMethodV;
+        public IntPtr CallFloatMethod;
+        public IntPtr __CallDoubleMethod;
+        public IntPtr __CallDoubleMethodV;
+        public IntPtr CallDoubleMethod;
+        public IntPtr __CallVoidMethod;
+        public IntPtr __CallVoidMethodV;
+        public IntPtr CallVoidMethod;
+        public IntPtr __CallNonvirtualObjectMethod;
+        public IntPtr __CallNonvirtualObjectMethodV;
+        public IntPtr CallNonvirtualObjectMethod;
+        public IntPtr __CallNonvirtualBooleanMethod;
+        public IntPtr __CallNonvirtualBooleanMethodV;
+        public IntPtr CallNonvirtualBooleanMethod;
+        public IntPtr __CallNonvirtualByteMethod;
+        public IntPtr __CallNonvirtualByteMethodV;
+        public IntPtr CallNonvirtualByteMethod;
+        public IntPtr __CallNonvirtualCharMethod;
+        public IntPtr __CallNonvirtualCharMethodV;
+        public IntPtr CallNonvirtualCharMethod;
+        public IntPtr __CallNonvirtualShortMethod;
+        public IntPtr __CallNonvirtualShortMethodV;
+        public IntPtr CallNonvirtualShortMethod;
+        public IntPtr __CallNonvirtualIntMethod;
+        public IntPtr __CallNonvirtualIntMethodV;
+        public IntPtr CallNonvirtualIntMethod;
+        public IntPtr __CallNonvirtualLongMethod;
+        public IntPtr __CallNonvirtualLongMethodV;
+        public IntPtr CallNonvirtualLongMethod;
+        public IntPtr __CallNonvirtualFloatMethod;
+        public IntPtr __CallNonvirtualFloatMethodV;
+        public IntPtr CallNonvirtualFloatMethod;
+        public IntPtr __CallNonvirtualDoubleMethod;
+        public IntPtr __CallNonvirtualDoubleMethodV;
+        public IntPtr CallNonvirtualDoubleMethod;
+        public IntPtr __CallNonvirtualVoidMethod;
+        public IntPtr __CallNonvirtualVoidMethodV;
+        public IntPtr CallNonvirtualVoidMethod;
+        public IntPtr GetFieldID;
+        public IntPtr GetObjectField;
+        public IntPtr GetBooleanField;
+        public IntPtr GetByteField;
+        public IntPtr GetCharField;
+        public IntPtr GetShortField;
+        public IntPtr GetIntField;
+        public IntPtr GetLongField;
+        public IntPtr GetFloatField;
+        public IntPtr GetDoubleField;
+        public IntPtr SetObjectField;
+        public IntPtr SetBooleanField;
+        public IntPtr SetByteField;
+        public IntPtr SetCharField;
+        public IntPtr SetShortField;
+        public IntPtr SetIntField;
+        public IntPtr SetLongField;
+        public IntPtr SetFloatField;
+        public IntPtr SetDoubleField;
+        public IntPtr GetStaticMethodID;
+        public IntPtr __CallStaticObjectMethod;
+        public IntPtr __CallStaticObjectMethodV;
+        public IntPtr CallStaticObjectMethod;
+        public IntPtr __CallStaticBooleanMethod;
+        public IntPtr __CallStaticBooleanMethodV;
+        public IntPtr CallStaticBooleanMethod;
+        public IntPtr __CallStaticByteMethod;
+        public IntPtr __CallStaticByteMethodV;
+        public IntPtr CallStaticByteMethod;
+        public IntPtr __CallStaticCharMethod;
+        public IntPtr __CallStaticCharMethodV;
+        public IntPtr CallStaticCharMethod;
+        public IntPtr __CallStaticShortMethod;
+        public IntPtr __CallStaticShortMethodV;
+        public IntPtr CallStaticShortMethod;
+        public IntPtr __CallStaticIntMethod;
+        public IntPtr __CallStaticIntMethodV;
+        public IntPtr CallStaticIntMethod;
+        public IntPtr __CallStaticLongMethod;
+        public IntPtr __CallStaticLongMethodV;
+        public IntPtr CallStaticLongMethod;
+        public IntPtr __CallStaticFloatMethod;
+        public IntPtr __CallStaticFloatMethodV;
+        public IntPtr CallStaticFloatMethod;
+        public IntPtr __CallStaticDoubleMethod;
+        public IntPtr __CallStaticDoubleMethodV;
+        public IntPtr CallStaticDoubleMethod;
+        public IntPtr __CallStaticVoidMethod;
+        public IntPtr __CallStaticVoidMethodV;
+        public IntPtr CallStaticVoidMethod;
+        public IntPtr GetStaticFieldID;
+        public IntPtr GetStaticObjectField;
+        public IntPtr GetStaticBooleanField;
+        public IntPtr GetStaticByteField;
+        public IntPtr GetStaticCharField;
+        public IntPtr GetStaticShortField;
+        public IntPtr GetStaticIntField;
+        public IntPtr GetStaticLongField;
+        public IntPtr GetStaticFloatField;
+        public IntPtr GetStaticDoubleField;
+        public IntPtr SetStaticObjectField;
+        public IntPtr SetStaticBooleanField;
+        public IntPtr SetStaticByteField;
+        public IntPtr SetStaticCharField;
+        public IntPtr SetStaticShortField;
+        public IntPtr SetStaticIntField;
+        public IntPtr SetStaticLongField;
+        public IntPtr SetStaticFloatField;
+        public IntPtr SetStaticDoubleField;
+        public IntPtr NewString;
+        public IntPtr GetStringLength;
+        public IntPtr GetStringChars;
+        public IntPtr ReleaseStringChars;
+        public IntPtr NewStringUTF;
+        public IntPtr GetStringUTFLength;
+        public IntPtr GetStringUTFChars;
+        public IntPtr ReleaseStringUTFChars;
+        public IntPtr GetArrayLength;
+        public IntPtr NewObjectArray;
+        public IntPtr GetObjectArrayElement;
+        public IntPtr SetObjectArrayElement;
+        public IntPtr NewBooleanArray;
+        public IntPtr NewByteArray;
+        public IntPtr NewCharArray;
+        public IntPtr NewShortArray;
+        public IntPtr NewIntArray;
+        public IntPtr NewLongArray;
+        public IntPtr NewFloatArray;
+        public IntPtr NewDoubleArray;
+        public IntPtr GetBooleanArrayElements;
+        public IntPtr GetByteArrayElements;
+        public IntPtr GetCharArrayElements;
+        public IntPtr GetShortArrayElements;
+        public IntPtr GetIntArrayElements;
+        public IntPtr GetLongArrayElements;
+        public IntPtr GetFloatArrayElements;
+        public IntPtr GetDoubleArrayElements;
+        public IntPtr ReleaseBooleanArrayElements;
+        public IntPtr ReleaseByteArrayElements;
+        public IntPtr ReleaseCharArrayElements;
+        public IntPtr ReleaseShortArrayElements;
+        public IntPtr ReleaseIntArrayElements;
+        public IntPtr ReleaseLongArrayElements;
+        public IntPtr ReleaseFloatArrayElements;
+        public IntPtr ReleaseDoubleArrayElements;
+        public IntPtr GetBooleanArrayRegion;
+        public IntPtr GetByteArrayRegion;
+        public IntPtr GetCharArrayRegion;
+        public IntPtr GetShortArrayRegion;
+        public IntPtr GetIntArrayRegion;
+        public IntPtr GetLongArrayRegion;
+        public IntPtr GetFloatArrayRegion;
+        public IntPtr GetDoubleArrayRegion;
+        public IntPtr SetBooleanArrayRegion;
+        public IntPtr SetByteArrayRegion;
+        public IntPtr SetCharArrayRegion;
+        public IntPtr SetShortArrayRegion;
+        public IntPtr SetIntArrayRegion;
+        public IntPtr SetLongArrayRegion;
+        public IntPtr SetFloatArrayRegion;
+        public IntPtr SetDoubleArrayRegion;
+        public IntPtr RegisterNatives;
+        public IntPtr UnregisterNatives;
+        public IntPtr MonitorEnter;
+        public IntPtr MonitorExit;
+        public IntPtr GetJavaVM;
+        public IntPtr GetStringRegion;
+        public IntPtr GetStringUTFRegion;
+        public IntPtr GetPrimitiveArrayCritical;
+        public IntPtr ReleasePrimitiveArrayCritical;
+        public IntPtr GetStringCritical;
+        public IntPtr ReleaseStringCritical;
+        public IntPtr NewWeakGlobalRef;
+        public IntPtr DeleteWeakGlobalRef;
+        public IntPtr ExceptionCheck;
+        public IntPtr NewDirectByteBuffer;
+        public IntPtr GetDirectBufferAddress;
+        public IntPtr GetDirectBufferCapacity;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
new file mode 100644
index 0000000..c33a53b
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/GlobalRef.cs
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+using System;
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics;
+
+    /// <summary>
+    /// JNI Global Reference.
+    /// <para />
+    /// We should always convert local reference to global and delete local one immediately,
+    /// otherwise these local references may cause memory leaks (false GC roots).
+    /// </summary>
+    internal sealed class GlobalRef : IDisposable
+    {
+        /** Reference. */
+        private readonly IntPtr _target;
+
+        /** JVM. */
+        private readonly Jvm _jvm;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="GlobalRef"/> class.
+        /// </summary>
+        public GlobalRef(IntPtr target, Jvm jvm)
+        {
+            Debug.Assert(target != IntPtr.Zero);
+            Debug.Assert(jvm != null);
+
+            _target = target;
+            _jvm = jvm;
+        }
+
+        /// <summary>
+        /// Gets the target.
+        /// </summary>
+        public IntPtr Target
+        {
+            get { return _target; }
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public Jvm Jvm
+        {
+            get { return _jvm; }
+        }
+
+        /// <summary>
+        /// Releases the unmanaged resources.
+        /// </summary>
+        private void ReleaseUnmanagedResources()
+        {
+            _jvm.AttachCurrentThread().DeleteGlobalRef(_target);
+        }
+
+        /** <inheritdoc /> */
+        public void Dispose()
+        {
+            ReleaseUnmanagedResources();
+            GC.SuppressFinalize(this);
+        }
+
+        /** <inheritdoc /> */
+        ~GlobalRef()
+        {
+            ReleaseUnmanagedResources();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs
new file mode 100644
index 0000000..0370d5c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JniResult.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    /// <summary>
+    /// JNI call result.
+    /// </summary>
+    internal enum JniResult
+    {
+        Success = 0,
+        // ReSharper disable UnusedMember.Global
+        // Some statuses are not used directly, but will be displayed as part of error message.
+        Error = -1,
+        ThreadDetached = -2,
+        VersionError = -3,
+        NotEnoughMemory = -4,
+        AlreadyExists = -5,
+        InvalidArguments = -6
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
new file mode 100644
index 0000000..10c7468
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
@@ -0,0 +1,335 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.Diagnostics.CodeAnalysis;
+    using System.Reflection;
+    using System.Runtime.InteropServices;
+    using System.Security;
+    using System.Threading;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// JVM holder. Should exist once per domain.
+    /// </summary>
+    [SuppressUnmanagedCodeSecurity]
+    internal sealed unsafe class Jvm
+    {
+        /** */
+        // ReSharper disable once InconsistentNaming
+        private const int JNI_VERSION_1_6 = 0x00010006;
+
+        /** */
+        private readonly IntPtr _jvmPtr;
+
+        /** */
+        private readonly JvmDelegates.AttachCurrentThread _attachCurrentThread;
+
+        /** */
+        private readonly MethodId _methodId;
+
+        /** Callbacks. */
+        private readonly Callbacks _callbacks;
+
+        /** Static instamce */
+        private static volatile Jvm _instance;
+
+        /** Sync. */
+        private static readonly object SyncRoot = new object();
+
+        /** Console writer. */
+        private static readonly ConsoleWriter ConsoleWriter = new ConsoleWriter();
+
+        /** Env for current thread. */
+        [ThreadStatic] private static Env _env;
+
+        /** Console writer flag. */
+        private int _isConsoleWriterEnabled;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="_instance"/> class.
+        /// </summary>
+        private Jvm(IntPtr jvmPtr)
+        {
+            Debug.Assert(jvmPtr != IntPtr.Zero);
+
+            _jvmPtr = jvmPtr;
+
+            var funcPtr = (JvmInterface**)jvmPtr;
+            var func = **funcPtr;
+            GetDelegate(func.AttachCurrentThread, out _attachCurrentThread);
+
+            var env = AttachCurrentThread();
+            _methodId = new MethodId(env);
+            _callbacks = GetCallbacks(env, this);
+        }
+
+        /// <summary>
+        /// Gets the callbacks.
+        /// </summary>
+        private static Callbacks GetCallbacks(Env env, Jvm jvm)
+        {
+            if (AppDomain.CurrentDomain.IsDefaultAppDomain())
+            {
+                return new Callbacks(env, jvm);
+            }
+
+            // JVM exists once per process, and JVM callbacks exist once per process.
+            // We should register callbacks ONLY from the default AppDomain (which can't be unloaded).
+            // Non-default appDomains should delegate this logic to the default one.
+            var defDomain = AppDomains.GetDefaultAppDomain();
+
+            // In some cases default AppDomain is not able to locate Apache.Ignite.Core assembly.
+            // First, use CreateInstanceFrom to set up the AssemblyResolve handler.
+            var resHelpType = typeof(AssemblyResolver);
+            var resHelp = (AssemblyResolver)defDomain.CreateInstanceFrom(resHelpType.Assembly.Location, resHelpType.FullName)
+                .Unwrap();
+            resHelp.TrackResolve(resHelpType.Assembly.FullName, resHelpType.Assembly.Location);
+
+            // Now use CreateInstance to get the domain helper of a properly loaded class.
+            var type = typeof(CallbackAccessor);
+            var helper = (CallbackAccessor)defDomain.CreateInstance(type.Assembly.FullName, type.FullName).Unwrap();
+
+            return helper.GetCallbacks();
+        }
+
+        /// <summary>
+        /// Gets or creates the JVM.
+        /// </summary>
+        /// <param name="options">JVM options.</param>
+        public static Jvm GetOrCreate(IList<string> options)
+        {
+            lock (SyncRoot)
+            {
+                return _instance ?? (_instance = new Jvm(GetJvmPtr(options)));
+            }
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public static Jvm Get()
+        {
+            var res = _instance;
+
+            if (res == null)
+            {
+                throw new IgniteException("JVM has not been created.");
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the method IDs.
+        /// </summary>
+        public MethodId MethodId
+        {
+            get { return _methodId; }
+        }
+
+        /// <summary>
+        /// Attaches current thread to the JVM and returns JNIEnv.
+        /// </summary>
+        public Env AttachCurrentThread()
+        {
+            if (_env == null)
+            {
+                IntPtr envPtr;
+                var res = _attachCurrentThread(_jvmPtr, out envPtr, IntPtr.Zero);
+
+                if (res != JniResult.Success)
+                {
+                    throw new IgniteException("AttachCurrentThread failed: " + res);
+                }
+
+                _env = new Env(envPtr, this);
+            }
+
+            return _env;
+        }
+
+        /// <summary>
+        /// Registers the callbacks.
+        /// </summary>
+        public void RegisterCallbacks(UnmanagedCallbacks cbs)
+        {
+            var id = _callbacks.RegisterHandlers(cbs);
+            cbs.SetContext(id);
+        }
+
+        /// <summary>
+        /// Releases the callbacks.
+        /// </summary>
+        public void ReleaseCallbacks(long igniteId)
+        {
+            _callbacks.ReleaseHandlers(igniteId);
+        }
+
+        /// <summary>
+        /// Enables the Java console output propagation.
+        /// </summary>
+        public void EnableJavaConsoleWriter()
+        {
+            if (Interlocked.CompareExchange(ref _isConsoleWriterEnabled, 1, 0) == 0)
+            {
+                var writerId = _callbacks.RegisterConsoleWriter(ConsoleWriter);
+                AppDomain.CurrentDomain.DomainUnload += (s, a) => _callbacks.ReleaseConsoleWriter(writerId);
+            }
+        }
+
+        /// <summary>
+        /// Gets the JVM pointer.
+        /// </summary>
+        private static IntPtr GetJvmPtr(IList<string> options)
+        {
+            IntPtr jvm;
+            int existingJvmCount;
+
+            // Use existing JVM if present.
+            var res = JniNativeMethods.JNI_GetCreatedJavaVMs(out jvm, 1, out existingJvmCount);
+            if (res != JniResult.Success)
+            {
+                throw new IgniteException("JNI_GetCreatedJavaVMs failed: " + res);
+            }
+
+            if (existingJvmCount > 0)
+            {
+                return jvm;
+            }
+
+            var args = new JvmInitArgs
+            {
+                version = JNI_VERSION_1_6
+            };
+
+            if (options != null && options.Count > 0)
+            {
+                args.nOptions = options.Count;
+                var opt = new JvmOption[options.Count];
+
+                for (int i = 0; i < options.Count; i++)
+                {
+                    opt[i].optionString = Marshal.StringToHGlobalAnsi(options[i]);
+                }
+
+                fixed (JvmOption* a = &opt[0])
+                {
+                    args.options = a;
+                }
+            }
+
+            IntPtr env;
+            res = JniNativeMethods.JNI_CreateJavaVM(out jvm, out env, &args);
+            if (res != JniResult.Success)
+            {
+                throw new IgniteException("JNI_CreateJavaVM failed: " + res);
+            }
+
+            return jvm;
+        }
+
+        /// <summary>
+        /// Gets the delegate.
+        /// </summary>
+        private static void GetDelegate<T>(IntPtr ptr, out T del)
+        {
+            del = (T) (object) Marshal.GetDelegateForFunctionPointer(ptr, typeof(T));
+        }
+
+        /// <summary>
+        /// JavaVMOption.
+        /// </summary>
+        [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+        [StructLayout(LayoutKind.Sequential, Pack = 0)]
+        private struct JvmOption
+        {
+            public IntPtr optionString;
+            private readonly IntPtr extraInfo;
+        }
+
+        /// <summary>
+        /// JavaVMInitArgs.
+        /// </summary>
+        [StructLayout(LayoutKind.Sequential, Pack = 0)]
+        private struct JvmInitArgs
+        {
+            public int version;
+            public int nOptions;
+            public JvmOption* options;
+            private readonly byte ignoreUnrecognized;
+        }
+
+        /// <summary>
+        /// DLL imports.
+        /// </summary>
+        private static class JniNativeMethods
+        {
+            [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)]
+            internal static extern JniResult JNI_CreateJavaVM(out IntPtr pvm, out IntPtr penv,
+                JvmInitArgs* args);
+
+            [DllImport("jvm.dll", CallingConvention = CallingConvention.StdCall)]
+            internal static extern JniResult JNI_GetCreatedJavaVMs(out IntPtr pvm, int size,
+                [Out] out int size2);
+        }
+
+        /// <summary>
+        /// Provides access to <see cref="Callbacks"/> instance in the default AppDomain.
+        /// </summary>
+        private class CallbackAccessor : MarshalByRefObject
+        {
+            /// <summary>
+            /// Gets the callbacks.
+            /// </summary>
+            [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+                Justification = "Only instance methods can be called across AppDomain boundaries.")]
+            public Callbacks GetCallbacks()
+            {
+                return GetOrCreate(null)._callbacks;
+            }
+        }
+
+        /// <summary>
+        /// Resolves Apache.Ignite.Core assembly in the default AppDomain when needed.
+        /// </summary>
+        private class AssemblyResolver : MarshalByRefObject
+        {
+            /// <summary>
+            /// Tracks the AssemblyResolve event.
+            /// </summary>
+            [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic",
+                Justification = "Only instance methods can be called across AppDomain boundaries.")]
+            public void TrackResolve(string name, string path)
+            {
+                AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
+                {
+                    if (args.Name == name)
+                    {
+                        return Assembly.LoadFrom(path);
+                    }
+
+                    return null;
+                };
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs
new file mode 100644
index 0000000..9686888
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmDelegates.cs
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// Delegates for JavaVM JNI entity.
+    /// </summary>
+    internal static class JvmDelegates
+    {
+        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+        internal delegate JniResult AttachCurrentThread(IntPtr jvm, out IntPtr env, IntPtr args);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
new file mode 100644
index 0000000..74d5ba1
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/JvmInterface.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// JavaVM interface.
+    /// </summary>
+    [StructLayout(LayoutKind.Sequential)]
+    internal struct JvmInterface
+    {
+        // ReSharper disable MemberCanBePrivate.Global
+        public IntPtr reserved0;
+        public IntPtr reserved1;
+        public IntPtr reserved2;
+
+        public IntPtr DestroyJavaVM;
+        public IntPtr AttachCurrentThread;
+        public IntPtr DetachCurrentThread;
+        public IntPtr GetEnv;
+        public IntPtr AttachCurrentThreadAsDaemon;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
new file mode 100644
index 0000000..12a4dff
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/MethodId.cs
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System;
+    using System.Diagnostics;
+
+    /// <summary>
+    /// Cached JNI method ids: initialized once on JVM start.
+    /// </summary>
+    internal sealed class MethodId
+    {
+        /// <summary>
+        /// Class.getName().
+        /// </summary>
+        public IntPtr ClassGetName { get; private set; }
+
+        /// <summary>
+        /// Throwable.getMessage().
+        /// </summary>
+        public IntPtr ThrowableGetMessage { get; private set; }
+
+        /// <summary>
+        /// PlatformIgnition.
+        /// </summary>
+        public GlobalRef PlatformIgnition { get; private set; }
+
+        /// <summary>
+        /// PlatformIgnition.start().
+        /// </summary>
+        public IntPtr PlatformIgnitionStart { get; private set; }
+
+        /// <summary>
+        /// PlatformIgnition.stop().
+        /// </summary>
+        public IntPtr PlatformIgnitionStop { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutObjectAsync().
+        /// </summary>
+        public IntPtr TargetInStreamOutObjectAsync { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamAsync().
+        /// </summary>
+        public IntPtr TargetInStreamAsync { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.outObject ().
+        /// </summary>
+        public IntPtr TargetOutObject { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.outStream().
+        /// </summary>
+        public IntPtr TargetOutStream { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutStream().
+        /// </summary>
+        public IntPtr TargetInStreamOutStream { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inObjectStreamOutObjectStream().
+        /// </summary>
+        public IntPtr TargetInObjectStreamOutObjectStream { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutObject().
+        /// </summary>
+        public IntPtr TargetInStreamOutObject { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inStreamOutLong().
+        /// </summary>
+        public IntPtr TargetInStreamOutLong { get; private set; }
+
+        /// <summary>
+        /// PlatformTargetProxy.inLongOutLong().
+        /// </summary>
+        public IntPtr TargetInLongOutLong { get; private set; }
+
+        /// <summary>
+        /// PlatformUtils class.
+        /// </summary>
+        public GlobalRef PlatformUtils { get; private set; }
+
+        /// <summary>
+        /// PlatformUtils.getFullStackTrace.
+        /// </summary>
+        public IntPtr PlatformUtilsGetStackTrace { get; private set; }
+
+        /// <summary>
+        /// PlatformUtils.reallocate.
+        /// </summary>
+        public IntPtr PlatformUtilsReallocate { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MethodId"/> class.
+        /// </summary>
+        public MethodId(Env env)
+        {
+            Debug.Assert(env != null);
+
+            using (var classCls = env.FindClass("java/lang/Class"))
+            {
+                ClassGetName = env.GetMethodId(classCls, "getName", "()Ljava/lang/String;");
+            }
+
+            using (var throwableCls = env.FindClass("java/lang/Throwable"))
+            {
+                ThrowableGetMessage = env.GetMethodId(throwableCls, "getMessage", "()Ljava/lang/String;");
+            }
+
+            PlatformIgnition = env.FindClass(
+                "org/apache/ignite/internal/processors/platform/PlatformIgnition");
+            PlatformIgnitionStart = env.GetStaticMethodId(PlatformIgnition,
+                "start", "(Ljava/lang/String;Ljava/lang/String;IJJ)V");
+            PlatformIgnitionStop = env.GetStaticMethodId(PlatformIgnition, "stop", "(Ljava/lang/String;Z)Z");
+
+            using (var target = env.FindClass("org/apache/ignite/internal/processors/platform/PlatformTargetProxy"))
+            {
+                TargetInLongOutLong = env.GetMethodId(target, "inLongOutLong", "(IJ)J");
+                TargetInStreamOutLong = env.GetMethodId(target, "inStreamOutLong", "(IJ)J");
+                TargetInStreamOutObject = env.GetMethodId(target, "inStreamOutObject", "(IJ)Ljava/lang/Object;");
+                TargetInStreamOutStream = env.GetMethodId(target, "inStreamOutStream", "(IJJ)V");
+                TargetInObjectStreamOutObjectStream = env.GetMethodId(target, "inObjectStreamOutObjectStream",
+                    "(ILjava/lang/Object;JJ)Ljava/lang/Object;");
+                TargetOutStream = env.GetMethodId(target, "outStream", "(IJ)V");
+                TargetOutObject = env.GetMethodId(target, "outObject", "(I)Ljava/lang/Object;");
+                TargetInStreamAsync = env.GetMethodId(target, "inStreamAsync", "(IJ)V");
+                TargetInStreamOutObjectAsync =
+                    env.GetMethodId(target, "inStreamOutObjectAsync", "(IJ)Ljava/lang/Object;");
+            }
+
+            PlatformUtils = env.FindClass("org/apache/ignite/internal/processors/platform/utils/PlatformUtils");
+            PlatformUtilsGetStackTrace = env.GetStaticMethodId(PlatformUtils, "getFullStackTrace",
+                "(Ljava/lang/Throwable;)Ljava/lang/String;");
+            PlatformUtilsReallocate = env.GetStaticMethodId(PlatformUtils, "reallocate", "(JI)V");
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
new file mode 100644
index 0000000..b8a8f89
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/NativeMethod.cs
@@ -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.
+ */
+
+using System;
+
+#pragma warning disable 414  // Unused FuncPtr
+
+namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
+{
+    using System.Diagnostics.CodeAnalysis;
+    using System.Runtime.InteropServices;
+
+    /// <summary>
+    /// JNINativeMethod structure for registering Java -> .NET callbacks.
+    /// </summary>
+    [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable")]
+    internal struct NativeMethod
+    {
+        /// <summary>
+        /// Method name, char*.
+        /// </summary>
+        public IntPtr Name;
+
+        /// <summary>
+        /// Method signature, char*.
+        /// </summary>
+        public IntPtr Signature;
+
+        /// <summary>
+        /// Function pointer (from <see cref="Marshal.GetFunctionPointerForDelegate"/>).
+        /// </summary>
+        public IntPtr FuncPtr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
deleted file mode 100644
index 32e0a29..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System.Runtime.InteropServices;
-
-    /// <summary>
-    /// Unmanaged callback handler function pointers.
-    /// </summary>
-    [StructLayout(LayoutKind.Sequential, Pack = 0)]
-    internal unsafe struct UnmanagedCallbackHandlers
-    {
-        internal void* target;
-
-        internal void* error;
-
-        internal void* loggerLog;
-        internal void* loggerIsLevelEnabled;
-
-        internal void* inLongOutLong;
-        internal void* inLongLongObjectOutLong;
-    }
-}


[35/47] ignite git commit: IGNITE-2662 .NET: add version override to build script

Posted by sb...@apache.org.
IGNITE-2662 .NET: add version override to build script


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

Branch: refs/heads/ignite-zk
Commit: dee8b400a6ce4f9d7f9a08b7aa3243ce2afc82b3
Parents: 8ee6cb5
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Nov 17 17:02:44 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Nov 17 17:02:44 2017 +0300

----------------------------------------------------------------------
 modules/platforms/dotnet/build.ps1 | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/dee8b400/modules/platforms/dotnet/build.ps1
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/build.ps1 b/modules/platforms/dotnet/build.ps1
index c037574..7ff7278 100644
--- a/modules/platforms/dotnet/build.ps1
+++ b/modules/platforms/dotnet/build.ps1
@@ -63,6 +63,9 @@ Java jar files source folders, default is "modules\indexing\target,modules\core\
 .PARAMETER nugetPath
 Path to nuget.exe.
 
+.PARAMETER version
+NuGet version override (normally inferred from assembly version).
+
 .EXAMPLE
 .\build.ps1 -clean  
 # Full rebuild of Java, .NET and NuGet packages.
@@ -86,7 +89,8 @@ param (
     [string]$mavenOpts="-U -P-lgpl,-scala,-examples,-test,-benchmarks -Dmaven.javadoc.skip=true",
 	[string]$jarDirs="modules\indexing\target,modules\core\target,modules\spring\target",
     [string]$asmDirs="",
-    [string]$nugetPath=""
+    [string]$nugetPath="",
+	[string]$version=""
  )
 
 # 1) Build Java (Maven)
@@ -133,7 +137,7 @@ else {
 }
 
 # Copy (relevant) jars
-$libsDir = "$PSScriptRoot\bin\Libs"
+$libsDir = "$PSScriptRoot\bin\libs"
 mkdir -Force $libsDir; del -Force $libsDir\*.*
 
 ls $jarDirs.Split(',') *.jar -recurse `
@@ -237,7 +241,7 @@ if (!$skipNuGet) {
     mkdir -Force $nupkgDir; del -Force $nupkgDir\*.*
 
     # Detect version
-    $ver = (gi Apache.Ignite.Core\bin\Release\Apache.Ignite.Core.dll).VersionInfo.ProductVersion
+    $ver = if ($version) { $version } else { (gi Apache.Ignite.Core\bin\Release\Apache.Ignite.Core.dll).VersionInfo.ProductVersion }
 
     # Find all nuspec files and run 'nuget pack' either directly, or on corresponding csproj files (if present)
     ls *.nuspec -Recurse  `


[23/47] ignite git commit: IGNITE-6920 Added direct-install build for Web Console.

Posted by sb...@apache.org.
IGNITE-6920 Added direct-install build for Web Console.


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

Branch: refs/heads/ignite-zk
Commit: 69eced65909f7ab72197e5a256c1ccde68167e7a
Parents: caad1e9
Author: Andrey Novikov <an...@gridgain.com>
Authored: Fri Nov 17 13:28:14 2017 +0700
Committer: Andrey Novikov <an...@gridgain.com>
Committed: Fri Nov 17 13:28:14 2017 +0700

----------------------------------------------------------------------
 modules/web-console/.gitignore                  |  11 +-
 modules/web-console/DEVNOTES.txt                |  13 +-
 modules/web-console/backend/.gitignore          |   6 -
 modules/web-console/backend/app/apiServer.js    |  76 ++--
 .../web-console/backend/app/browsersHandler.js  | 442 +++++++++----------
 modules/web-console/backend/app/mongo.js        |  73 ++-
 modules/web-console/backend/app/nconf.js        |  44 +-
 modules/web-console/backend/app/routes.js       |  26 +-
 modules/web-console/backend/app/settings.js     |  84 ++--
 modules/web-console/backend/index.js            |  25 +-
 modules/web-console/backend/injector.js         |   4 +-
 modules/web-console/backend/package.json        |  22 +-
 .../compose/frontend/nginx/web-console.conf     |   1 -
 .../docker/standalone/nginx/web-console.conf    |   1 -
 modules/web-console/frontend/.gitignore         |   8 +-
 .../generator/JavaTransformer.service.js        |   2 +
 .../frontend/webpack/webpack.dev.babel.js       |   5 +-
 17 files changed, 466 insertions(+), 377 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-console/.gitignore b/modules/web-console/.gitignore
index 9ddddc4..8648ae5 100644
--- a/modules/web-console/.gitignore
+++ b/modules/web-console/.gitignore
@@ -1,6 +1,5 @@
-docker/standalone/backend/build
-docker/standalone/frontend/build
-docker/standalone/data
-docker/compose/backend/build
-docker/compose/frontend/build
-docker/dev/data
+.npmrc
+package-lock.json
+build/
+node_modules/
+data/

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index aa8702e..4ff68a7 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -1,8 +1,5 @@
-Ignite Web Console Instructions
-======================================
-
-How to deploy locally:
-
+Ignite Web Console Build Instructions
+=====================================
 1. Install locally MongoDB (version >=3.2.x) follow instructions from site http://docs.mongodb.org/manual/installation.
 2. Install locally NodeJS (version >=6.5.x) using installer from site https://nodejs.org/en/download/current for your OS.
 3. Change directory to '$IGNITE_HOME/modules/web-console/backend' and
@@ -13,10 +10,10 @@ How to deploy locally:
 6. Copy ignite-web-agent-<version>.zip from '$IGNITE_HOME/modules/web-console/web-agent/target'
  to '$IGNITE_HOME/modules/web-console/backend/agent_dists' folder.
 
-Steps 1 - 6 should be executed once.
-
-How to run console in development mode:
+Steps 1 - 4 should be executed once.
 
+Ignite Web Console Run In Development Mode
+==========================================
 1. Configure MongoDB to run as service or in terminal change dir to $MONGO_INSTALL_DIR/server/3.2/bin
   and start MongoDB by executing "mongod".
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/.gitignore b/modules/web-console/backend/.gitignore
index 0aa3ece..e5b9047 100644
--- a/modules/web-console/backend/.gitignore
+++ b/modules/web-console/backend/.gitignore
@@ -1,8 +1,2 @@
-*.idea
-*.log
-.npmrc
-node_modules
 agent_dists/*.zip
 config/*.json
-yarn.lock
-package-lock.json

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/apiServer.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/apiServer.js b/modules/web-console/backend/app/apiServer.js
index affb9c9..cb09750 100644
--- a/modules/web-console/backend/app/apiServer.js
+++ b/modules/web-console/backend/app/apiServer.js
@@ -21,48 +21,64 @@
 
 module.exports = {
     implements: 'api-server',
-    inject: ['require(express)', 'configure', 'routes']
-};
-
-module.exports.factory = function(Express, configure, routes) {
-    /**
-     * Connected agents manager.
-     */
-    class ApiServer {
+    inject: ['require(fs)', 'require(path)', 'require(express)', 'settings', 'configure', 'routes'],
+    factory(fs, path, Express, settings, configure, routes) {
         /**
-         * @param {Server} srv
+         * Connected agents manager.
          */
-        attach(srv) {
-            const app = new Express();
+        class ApiServer {
+            /**
+             * @param {Server} srv
+             */
+            attach(srv) {
+                const app = new Express();
+
+                configure.express(app);
 
-            configure.express(app);
+                routes.register(app);
 
-            routes.register(app);
+                if (settings.packaged) {
+                    const staticDir = path.join(process.cwd(), 'libs/frontend');
 
-            // Catch 404 and forward to error handler.
-            app.use((req, res, next) => {
-                const err = new Error('Not Found: ' + req.originalUrl);
+                    try {
+                        fs.accessSync(staticDir, fs.F_OK);
 
-                err.status = 404;
+                        app.use('/', Express.static(staticDir));
 
-                next(err);
-            });
+                        app.get('*', function(req, res) {
+                            res.sendFile(path.join(staticDir, 'index.html'));
+                        });
+                    }
+                    catch (e) {
+                        console.log(`Failed to find folder with frontend files: ${staticDir}`);
+                    }
+                }
 
-            // Production error handler: no stacktraces leaked to user.
-            app.use((err, req, res) => {
-                res.status(err.status || 500);
+                // Catch 404 and forward to error handler.
+                app.use((req, res, next) => {
+                    const err = new Error('Not Found: ' + req.originalUrl);
 
-                res.render('error', {
-                    message: err.message,
-                    error: {}
+                    err.status = 404;
+
+                    next(err);
                 });
-            });
 
-            srv.addListener('request', app);
+                // Production error handler: no stacktraces leaked to user.
+                app.use((err, req, res) => {
+                    res.status(err.status || 500);
 
-            return app;
+                    res.render('error', {
+                        message: err.message,
+                        error: {}
+                    });
+                });
+
+                srv.addListener('request', app);
+
+                return app;
+            }
         }
-    }
 
-    return new ApiServer();
+        return new ApiServer();
+    }
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/browsersHandler.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/browsersHandler.js b/modules/web-console/backend/app/browsersHandler.js
index f4ff23c..8b1385d 100644
--- a/modules/web-console/backend/app/browsersHandler.js
+++ b/modules/web-console/backend/app/browsersHandler.js
@@ -24,291 +24,289 @@
  */
 module.exports = {
     implements: 'browsers-handler',
-    inject: ['require(lodash)', 'require(socket.io)', 'configure', 'errors', 'mongo']
-};
+    inject: ['require(lodash)', 'require(socket.io)', 'configure', 'errors', 'mongo'],
+    factory: (_, socketio, configure, errors, mongo) => {
+        class BrowserSockets {
+            constructor() {
+                this.sockets = new Map();
+            }
 
-module.exports.factory = (_, socketio, configure, errors, mongo) => {
-    class BrowserSockets {
-        constructor() {
-            this.sockets = new Map();
-        }
+            /**
+             * @param {Socket} sock
+             */
+            add(sock) {
+                const token = sock.request.user.token;
 
-        /**
-         * @param {Socket} sock
-         */
-        add(sock) {
-            const token = sock.request.user.token;
+                if (this.sockets.has(token))
+                    this.sockets.get(token).push(sock);
+                else
+                    this.sockets.set(token, [sock]);
 
-            if (this.sockets.has(token))
-                this.sockets.get(token).push(sock);
-            else
-                this.sockets.set(token, [sock]);
+                return this.sockets.get(token);
+            }
 
-            return this.sockets.get(token);
-        }
+            /**
+             * @param {Socket} sock
+             */
+            remove(sock) {
+                const token = sock.request.user.token;
 
-        /**
-         * @param {Socket} sock
-         */
-        remove(sock) {
-            const token = sock.request.user.token;
+                const sockets = this.sockets.get(token);
 
-            const sockets = this.sockets.get(token);
+                _.pull(sockets, sock);
 
-            _.pull(sockets, sock);
+                return sockets;
+            }
 
-            return sockets;
-        }
+            get(token) {
+                if (this.sockets.has(token))
+                    return this.sockets.get(token);
 
-        get(token) {
-            if (this.sockets.has(token))
-                return this.sockets.get(token);
+                return [];
+            }
 
-            return [];
+            demo(token) {
+                return _.filter(this.sockets.get(token), (sock) => sock.request._query.IgniteDemoMode === 'true');
+            }
         }
 
-        demo(token) {
-            return _.filter(this.sockets.get(token), (sock) => sock.request._query.IgniteDemoMode === 'true');
-        }
-    }
+        class BrowsersHandler {
+            /**
+             * @constructor
+             */
+            constructor() {
+                /**
+                 * Connected browsers.
+                 * @type {BrowserSockets}
+                 */
+                this._browserSockets = new BrowserSockets();
+
+                /**
+                 * Registered Visor task.
+                 * @type {Map}
+                 */
+                this._visorTasks = new Map();
+            }
 
-    class BrowsersHandler {
-        /**
-         * @constructor
-         */
-        constructor() {
             /**
-             * Connected browsers.
-             * @type {BrowserSockets}
+             * @param {Error} err
+             * @return {{code: number, message: *}}
              */
-            this._browserSockets = new BrowserSockets();
+            errorTransformer(err) {
+                return {
+                    code: err.code || 1,
+                    message: err.message || err
+                };
+            }
 
             /**
-             * Registered Visor task.
-             * @type {Map}
+             * @param {String} token
+             * @param {Array.<Socket>} [socks]
              */
-            this._visorTasks = new Map();
-        }
+            agentStats(token, socks = this._browserSockets.get(token)) {
+                return this._agentHnd.agents(token)
+                    .then((agentSocks) => {
+                        const stat = _.reduce(agentSocks, (acc, agentSock) => {
+                            acc.count += 1;
+                            acc.hasDemo |= _.get(agentSock, 'demo.enabled');
 
-        /**
-         * @param {Error} err
-         * @return {{code: number, message: *}}
-         */
-        errorTransformer(err) {
-            return {
-                code: err.code || 1,
-                message: err.message || err
-            };
-        }
+                            if (agentSock.cluster)
+                                acc.clusters.push(agentSock.cluster);
 
-        /**
-         * @param {String} token
-         * @param {Array.<Socket>} [socks]
-         */
-        agentStats(token, socks = this._browserSockets.get(token)) {
-            return this._agentHnd.agents(token)
-                .then((agentSocks) => {
-                    const stat = _.reduce(agentSocks, (acc, agentSock) => {
-                        acc.count += 1;
-                        acc.hasDemo |= _.get(agentSock, 'demo.enabled');
-
-                        if (agentSock.cluster)
-                            acc.clusters.push(agentSock.cluster);
-
-                        return acc;
-                    }, {count: 0, hasDemo: false, clusters: []});
-
-                    stat.clusters = _.uniqWith(stat.clusters, _.isEqual);
-
-                    return stat;
-                })
-                .catch(() => ({count: 0, hasDemo: false, clusters: []}))
-                .then((stat) => _.forEach(socks, (sock) => sock.emit('agents:stat', stat)));
-        }
+                            return acc;
+                        }, {count: 0, hasDemo: false, clusters: []});
 
-        emitNotification(sock) {
-            sock.emit('user:notifications', this.notification);
-        }
+                        stat.clusters = _.uniqWith(stat.clusters, _.isEqual);
 
-        /**
-         * @param {String} notification Notification message.
-         */
-        updateNotification(notification) {
-            this.notification = notification;
+                        return stat;
+                    })
+                    .catch(() => ({count: 0, hasDemo: false, clusters: []}))
+                    .then((stat) => _.forEach(socks, (sock) => sock.emit('agents:stat', stat)));
+            }
 
-            for (const socks of this._browserSockets.sockets.values()) {
-                for (const sock of socks)
-                    this.emitNotification(sock);
+            emitNotification(sock) {
+                sock.emit('user:notifications', this.notification);
             }
-        }
 
-        executeOnAgent(token, demo, event, ...args) {
-            const cb = _.last(args);
+            /**
+             * @param {String} notification Notification message.
+             */
+            updateNotification(notification) {
+                this.notification = notification;
 
-            return this._agentHnd.agent(token, demo)
-                .then((agentSock) => agentSock.emitEvent(event, ..._.dropRight(args)))
-                .then((res) => cb(null, res))
-                .catch((err) => cb(this.errorTransformer(err)));
-        }
+                for (const socks of this._browserSockets.sockets.values()) {
+                    for (const sock of socks)
+                        this.emitNotification(sock);
+                }
+            }
 
-        agentListeners(sock) {
-            const demo = sock.request._query.IgniteDemoMode === 'true';
-            const token = () => sock.request.user.token;
+            executeOnAgent(token, demo, event, ...args) {
+                const cb = _.last(args);
 
-            // Return available drivers to browser.
-            sock.on('schemaImport:drivers', (...args) => {
-                this.executeOnAgent(token(), demo, 'schemaImport:drivers', ...args);
-            });
+                return this._agentHnd.agent(token, demo)
+                    .then((agentSock) => agentSock.emitEvent(event, ..._.dropRight(args)))
+                    .then((res) => cb(null, res))
+                    .catch((err) => cb(this.errorTransformer(err)));
+            }
 
-            // Return schemas from database to browser.
-            sock.on('schemaImport:schemas', (...args) => {
-                this.executeOnAgent(token(), demo, 'schemaImport:schemas', ...args);
-            });
+            agentListeners(sock) {
+                const demo = sock.request._query.IgniteDemoMode === 'true';
+                const token = () => sock.request.user.token;
 
-            // Return tables from database to browser.
-            sock.on('schemaImport:metadata', (...args) => {
-                this.executeOnAgent(token(), demo, 'schemaImport:metadata', ...args);
-            });
-        }
+                // Return available drivers to browser.
+                sock.on('schemaImport:drivers', (...args) => {
+                    this.executeOnAgent(token(), demo, 'schemaImport:drivers', ...args);
+                });
 
-        /**
-         * @param {Promise.<AgentSocket>} agent
-         * @param {Boolean} demo
-         * @param {Object.<String, String>} params
-         * @return {Promise.<T>}
-         */
-        executeOnNode(agent, demo, params) {
-            return agent
-                .then((agentSock) => agentSock.emitEvent('node:rest', {uri: 'ignite', demo, params}))
-                .then((res) => {
-                    if (res.status === 0) {
-                        if (res.zipped)
-                            return res;
-
-                        return JSON.parse(res.data);
-                    }
-
-                    throw new Error(res.error);
+                // Return schemas from database to browser.
+                sock.on('schemaImport:schemas', (...args) => {
+                    this.executeOnAgent(token(), demo, 'schemaImport:schemas', ...args);
                 });
-        }
 
-        registerVisorTask(taskId, taskCls, ...argCls) {
-            this._visorTasks.set(taskId, {
-                taskCls,
-                argCls
-            });
-        }
+                // Return tables from database to browser.
+                sock.on('schemaImport:metadata', (...args) => {
+                    this.executeOnAgent(token(), demo, 'schemaImport:metadata', ...args);
+                });
+            }
 
-        nodeListeners(sock) {
-            // Return command result from grid to browser.
-            sock.on('node:rest', (clusterId, params, cb) => {
-                const demo = sock.request._query.IgniteDemoMode === 'true';
-                const token = sock.request.user.token;
+            /**
+             * @param {Promise.<AgentSocket>} agent
+             * @param {Boolean} demo
+             * @param {Object.<String, String>} params
+             * @return {Promise.<T>}
+             */
+            executeOnNode(agent, demo, params) {
+                return agent.then((agentSock) => agentSock.emitEvent('node:rest', {uri: 'ignite', demo, params}))
+                    .then((res) => {
+                        if (res.status === 0) {
+                            if (res.zipped)
+                                return res;
 
-                const agent = this._agentHnd.agent(token, demo, clusterId);
+                            return JSON.parse(res.data);
+                        }
 
-                this.executeOnNode(agent, demo, params)
-                    .then((data) => cb(null, data))
-                    .catch((err) => cb(this.errorTransformer(err)));
-            });
+                        throw new Error(res.error);
+                    });
+            }
 
-            const internalVisor = (postfix) => `org.apache.ignite.internal.visor.${postfix}`;
+            registerVisorTask(taskId, taskCls, ...argCls) {
+                this._visorTasks.set(taskId, {
+                    taskCls,
+                    argCls
+                });
+            }
 
-            this.registerVisorTask('querySql', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArg'));
-            this.registerVisorTask('querySqlV2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV2'));
-            this.registerVisorTask('querySqlV3', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV3'));
-            this.registerVisorTask('querySqlX2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryTaskArg'));
+            nodeListeners(sock) {
+                // Return command result from grid to browser.
+                sock.on('node:rest', (clusterId, params, cb) => {
+                    const demo = sock.request._query.IgniteDemoMode === 'true';
+                    const token = sock.request.user.token;
 
-            this.registerVisorTask('queryScanX2', internalVisor('query.VisorScanQueryTask'), internalVisor('query.VisorScanQueryTaskArg'));
+                    const agent = this._agentHnd.agent(token, demo, clusterId);
 
-            this.registerVisorTask('queryFetch', internalVisor('query.VisorQueryNextPageTask'), 'org.apache.ignite.lang.IgniteBiTuple', 'java.lang.String', 'java.lang.Integer');
-            this.registerVisorTask('queryFetchX2', internalVisor('query.VisorQueryNextPageTask'), internalVisor('query.VisorQueryNextPageTaskArg'));
+                    this.executeOnNode(agent, demo, params)
+                        .then((data) => cb(null, data))
+                        .catch((err) => cb(this.errorTransformer(err)));
+                });
 
-            this.registerVisorTask('queryClose', internalVisor('query.VisorQueryCleanupTask'), 'java.util.Map', 'java.util.UUID', 'java.util.Set');
-            this.registerVisorTask('queryCloseX2', internalVisor('query.VisorQueryCleanupTask'), internalVisor('query.VisorQueryCleanupTaskArg'));
+                const internalVisor = (postfix) => `org.apache.ignite.internal.visor.${postfix}`;
 
+                this.registerVisorTask('querySql', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArg'));
+                this.registerVisorTask('querySqlV2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV2'));
+                this.registerVisorTask('querySqlV3', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryArgV3'));
+                this.registerVisorTask('querySqlX2', internalVisor('query.VisorQueryTask'), internalVisor('query.VisorQueryTaskArg'));
 
-            // Return command result from grid to browser.
-            sock.on('node:visor', (clusterId, taskId, nids, ...args) => {
-                const demo = sock.request._query.IgniteDemoMode === 'true';
-                const token = sock.request.user.token;
+                this.registerVisorTask('queryScanX2', internalVisor('query.VisorScanQueryTask'), internalVisor('query.VisorScanQueryTaskArg'));
 
-                const cb = _.last(args);
-                args = _.dropRight(args);
+                this.registerVisorTask('queryFetch', internalVisor('query.VisorQueryNextPageTask'), 'org.apache.ignite.lang.IgniteBiTuple', 'java.lang.String', 'java.lang.Integer');
+                this.registerVisorTask('queryFetchX2', internalVisor('query.VisorQueryNextPageTask'), internalVisor('query.VisorQueryNextPageTaskArg'));
 
-                const desc = this._visorTasks.get(taskId);
+                this.registerVisorTask('queryClose', internalVisor('query.VisorQueryCleanupTask'), 'java.util.Map', 'java.util.UUID', 'java.util.Set');
+                this.registerVisorTask('queryCloseX2', internalVisor('query.VisorQueryCleanupTask'), internalVisor('query.VisorQueryCleanupTaskArg'));
 
-                if (_.isNil(desc))
-                    return cb(this.errorTransformer(new errors.IllegalArgumentException(`Failed to find Visor task for id: ${taskId}`)));
 
-                const params = {
-                    cmd: 'exe',
-                    name: 'org.apache.ignite.internal.visor.compute.VisorGatewayTask',
-                    p1: nids,
-                    p2: desc.taskCls
-                };
+                // Return command result from grid to browser.
+                sock.on('node:visor', (clusterId, taskId, nids, ...args) => {
+                    const demo = sock.request._query.IgniteDemoMode === 'true';
+                    const token = sock.request.user.token;
 
-                _.forEach(_.concat(desc.argCls, args), (param, idx) => { params[`p${idx + 3}`] = param; });
+                    const cb = _.last(args);
+                    args = _.dropRight(args);
 
-                const agent = this._agentHnd.agent(token, demo, clusterId);
+                    const desc = this._visorTasks.get(taskId);
 
-                this.executeOnNode(agent, demo, params)
-                    .then((data) => {
-                        if (data.zipped)
-                            return cb(null, data);
+                    if (_.isNil(desc))
+                        return cb(this.errorTransformer(new errors.IllegalArgumentException(`Failed to find Visor task for id: ${taskId}`)));
 
-                        if (data.finished)
-                            return cb(null, data.result);
+                    const params = {
+                        cmd: 'exe',
+                        name: 'org.apache.ignite.internal.visor.compute.VisorGatewayTask',
+                        p1: nids,
+                        p2: desc.taskCls
+                    };
 
-                        cb(this.errorTransformer(data.error));
-                    })
-                    .catch((err) => cb(this.errorTransformer(err)));
-            });
-        }
+                    _.forEach(_.concat(desc.argCls, args), (param, idx) => { params[`p${idx + 3}`] = param; });
 
-        /**
-         *
-         * @param server
-         * @param {AgentsHandler} agentHnd
-         */
-        attach(server, agentHnd) {
-            this._agentHnd = agentHnd;
+                    const agent = this._agentHnd.agent(token, demo, clusterId);
 
-            if (this.io)
-                throw 'Browser server already started!';
+                    this.executeOnNode(agent, demo, params)
+                        .then((data) => {
+                            if (data.zipped)
+                                return cb(null, data);
 
-            mongo.Notifications.findOne().sort('-date').exec()
-                .then((notification) => {
-                    this.notification = notification;
-                })
-                .then(() => {
-                    const io = socketio(server);
+                            if (data.finished)
+                                return cb(null, data.result);
 
-                    configure.socketio(io);
+                            cb(this.errorTransformer(data.error));
+                        })
+                        .catch((err) => cb(this.errorTransformer(err)));
+                });
+            }
 
-                    // Handle browser connect event.
-                    io.sockets.on('connection', (sock) => {
-                        this._browserSockets.add(sock);
+            /**
+             *
+             * @param server
+             * @param {AgentsHandler} agentHnd
+             */
+            attach(server, agentHnd) {
+                this._agentHnd = agentHnd;
 
-                        // Handle browser disconnect event.
-                        sock.on('disconnect', () => {
-                            this._browserSockets.remove(sock);
+                if (this.io)
+                    throw 'Browser server already started!';
 
-                            const demo = sock.request._query.IgniteDemoMode === 'true';
+                mongo.Notifications.findOne().sort('-date').exec()
+                    .then((notification) => {
+                        this.notification = notification;
+                    })
+                    .then(() => {
+                        const io = socketio(server);
 
-                            // Stop demo if latest demo tab for this token.
-                            demo && agentHnd.tryStopDemo(sock);
-                        });
+                        configure.socketio(io);
 
-                        this.agentListeners(sock);
-                        this.nodeListeners(sock);
+                        // Handle browser connect event.
+                        io.sockets.on('connection', (sock) => {
+                            this._browserSockets.add(sock);
 
-                        this.agentStats(sock.request.user.token, [sock]);
-                        this.emitNotification(sock);
+                            // Handle browser disconnect event.
+                            sock.on('disconnect', () => {
+                                this._browserSockets.remove(sock);
+
+                                const demo = sock.request._query.IgniteDemoMode === 'true';
+
+                                // Stop demo if latest demo tab for this token.
+                                demo && agentHnd.tryStopDemo(sock);
+                            });
+
+                            this.agentListeners(sock);
+                            this.nodeListeners(sock);
+
+                            this.agentStats(sock.request.user.token, [sock]);
+                            this.emitNotification(sock);
+                        });
                     });
-                });
+            }
         }
-    }
 
-    return new BrowsersHandler();
+        return new BrowsersHandler();
+    }
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/mongo.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/mongo.js b/modules/web-console/backend/app/mongo.js
index 7043fcd..81076af 100644
--- a/modules/web-console/backend/app/mongo.js
+++ b/modules/web-console/backend/app/mongo.js
@@ -24,16 +24,10 @@
  */
 module.exports = {
     implements: 'mongo',
-    inject: ['require(passport-local-mongoose)', 'settings', 'ignite_modules/mongo:*', 'mongoose']
+    inject: ['require(passport-local-mongoose)', 'settings', 'mongoose']
 };
 
-module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose) {
-    // Use native promises
-    mongoose.Promise = global.Promise;
-
-    // Connect to mongoDB database.
-    mongoose.connect(settings.mongoUrl, {server: {poolSize: 4}});
-
+const defineSchema = (passportMongo, mongoose) => {
     const Schema = mongoose.Schema;
     const ObjectId = mongoose.Schema.Types.ObjectId;
     const result = { connection: mongoose.connection };
@@ -1147,12 +1141,6 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
     // Define Notifications model.
     result.Notifications = mongoose.model('Notifications', NotificationsSchema);
 
-    // Registering the routes of all plugin modules
-    for (const name in pluginMongo) {
-        if (pluginMongo.hasOwnProperty(name))
-            pluginMongo[name].register(mongoose, result);
-    }
-
     result.handleError = function(res, err) {
         // TODO IGNITE-843 Send error to admin
         res.status(err.code || 500).send(err.message);
@@ -1160,3 +1148,60 @@ module.exports.factory = function(passportMongo, settings, pluginMongo, mongoose
 
     return result;
 };
+
+module.exports.factory = function(passportMongo, settings, mongoose) {
+    // Use native promises
+    mongoose.Promise = global.Promise;
+
+    console.log('Trying to connect to local MongoDB...');
+
+    // Connect to mongoDB database.
+    return mongoose.connect(settings.mongoUrl, {server: {poolSize: 4}})
+        .catch(() => {
+            console.log('Failed to connect to local MongoDB, will try to download and start embedded MongoDB');
+
+            const {MongodHelper} = require('mongodb-prebuilt');
+            const {MongoDBDownload} = require('mongodb-download');
+
+            const helper = new MongodHelper(['--port', '27017', '--dbpath', `${process.cwd()}/user_data`]);
+
+            helper.mongoBin.mongoDBPrebuilt.mongoDBDownload = new MongoDBDownload({
+                downloadDir: `${process.cwd()}/libs/mongodb`,
+                version: '3.4.7'
+            });
+
+            let mongodRun;
+
+            if (settings.packaged) {
+                mongodRun = new Promise((resolve, reject) => {
+                    helper.resolveLink = resolve;
+                    helper.rejectLink = reject;
+
+                    helper.mongoBin.runCommand()
+                        .then(() => {
+                            helper.mongoBin.childProcess.removeAllListeners('close');
+
+                            helper.mongoBin.childProcess.stderr.on('data', (data) => helper.stderrHandler(data));
+                            helper.mongoBin.childProcess.stdout.on('data', (data) => helper.stdoutHandler(data));
+                            helper.mongoBin.childProcess.on('close', (code) => helper.closeHandler(code));
+                        });
+                });
+            }
+            else
+                mongodRun = helper.run();
+
+            return mongodRun
+                .catch((err) => console.log('Failed to start embedded MongoDB', err))
+                .then(() => {
+                    console.log('Embedded MongoDB successfully started');
+
+                    return mongoose.connect(settings.mongoUrl, {server: {poolSize: 4}});
+                })
+                .catch((err) => {
+                    console.log('Failed to connect to embedded MongoDB', err);
+
+                    return Promise.reject(err);
+                });
+        })
+        .then(() => defineSchema(passportMongo, mongoose));
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/nconf.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/nconf.js b/modules/web-console/backend/app/nconf.js
index c585ac6..6813f0f 100644
--- a/modules/web-console/backend/app/nconf.js
+++ b/modules/web-console/backend/app/nconf.js
@@ -24,25 +24,29 @@
  */
 module.exports = {
     implements: 'nconf',
-    inject: ['require(nconf)', 'require(fs)']
-};
-
-module.exports.factory = function(nconf, fs) {
-    const default_config = './config/settings.json';
-    const file = process.env.SETTINGS || default_config;
-
-    nconf.env({separator: '_'});
-
-    try {
-        fs.accessSync(file, fs.F_OK);
-
-        nconf.file({file});
-    } catch (ignore) {
-        nconf.file({file: default_config});
+    inject: ['require(nconf)', 'require(fs)'],
+    factory(nconf, fs) {
+        nconf.env({separator: '_'}).argv();
+
+        const dfltFile = 'config/settings.json';
+        const customFile = nconf.get('settings') || dfltFile;
+
+        try {
+            fs.accessSync(customFile, fs.F_OK);
+
+            nconf.file({file: customFile});
+        }
+        catch (ignored) {
+            try {
+                fs.accessSync(dfltFile, fs.F_OK);
+
+                nconf.file({file: dfltFile});
+            }
+            catch (ignored2) {
+                // No-op.
+            }
+        }
+
+        return nconf;
     }
-
-    if (process.env.CONFIG_PATH && fs.existsSync(process.env.CONFIG_PATH))
-        nconf.file({file: process.env.CONFIG_PATH});
-
-    return nconf;
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/routes.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/routes.js b/modules/web-console/backend/app/routes.js
index 826407b..aa6efae 100644
--- a/modules/web-console/backend/app/routes.js
+++ b/modules/web-console/backend/app/routes.js
@@ -44,22 +44,22 @@ module.exports.factory = function(publicRoute, adminRoute, profilesRoute, demoRo
             };
 
             // Registering the standard routes
-            app.use('/', publicRoute);
-            app.use('/admin', _mustAuthenticated, _adminOnly, adminRoute);
-            app.use('/profile', _mustAuthenticated, profilesRoute);
-            app.use('/demo', _mustAuthenticated, demoRoute);
+            app.use('/api/v1/', publicRoute);
+            app.use('/api/v1/admin', _mustAuthenticated, _adminOnly, adminRoute);
+            app.use('/api/v1/profile', _mustAuthenticated, profilesRoute);
+            app.use('/api/v1/demo', _mustAuthenticated, demoRoute);
 
-            app.all('/configuration/*', _mustAuthenticated);
+            app.all('/api/v1/configuration/*', _mustAuthenticated);
 
-            app.use('/configuration', configurationsRoute);
-            app.use('/configuration/clusters', clustersRoute);
-            app.use('/configuration/domains', domainsRoute);
-            app.use('/configuration/caches', cachesRoute);
-            app.use('/configuration/igfs', igfssRoute);
+            app.use('/api/v1/configuration', configurationsRoute);
+            app.use('/api/v1/configuration/clusters', clustersRoute);
+            app.use('/api/v1/configuration/domains', domainsRoute);
+            app.use('/api/v1/configuration/caches', cachesRoute);
+            app.use('/api/v1/configuration/igfs', igfssRoute);
 
-            app.use('/notebooks', _mustAuthenticated, notebooksRoute);
-            app.use('/downloads', _mustAuthenticated, downloadsRoute);
-            app.use('/activities', _mustAuthenticated, activitiesRoute);
+            app.use('/api/v1/notebooks', _mustAuthenticated, notebooksRoute);
+            app.use('/api/v1/downloads', _mustAuthenticated, downloadsRoute);
+            app.use('/api/v1/activities', _mustAuthenticated, activitiesRoute);
         }
     };
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/app/settings.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/app/settings.js b/modules/web-console/backend/app/settings.js
index 05cb7f6..5032443 100644
--- a/modules/web-console/backend/app/settings.js
+++ b/modules/web-console/backend/app/settings.js
@@ -24,50 +24,56 @@
  */
 module.exports = {
     implements: 'settings',
-    inject: ['nconf', 'require(fs)']
-};
+    inject: ['nconf', 'require(fs)'],
+    factory(nconf, fs) {
+        /**
+         * Normalize a port into a number, string, or false.
+         */
+        const _normalizePort = function(val) {
+            const port = parseInt(val, 10);
+
+            // named pipe
+            if (isNaN(port))
+                return val;
 
-module.exports.factory = function(nconf, fs) {
-    /**
-     * Normalize a port into a number, string, or false.
-     */
-    const _normalizePort = function(val) {
-        const port = parseInt(val, 10);
+            // port number
+            if (port >= 0)
+                return port;
 
-        // named pipe
-        if (isNaN(port))
-            return val;
+            return false;
+        };
 
-        // port number
-        if (port >= 0)
-            return port;
+        const mail = nconf.get('mail') || {};
 
-        return false;
-    };
+        mail.address = (username, email) => username ? '"' + username + '" <' + email + '>' : email;
 
-    const mail = nconf.get('mail') || {};
+        const packaged = __dirname.startsWith('/snapshot/') || __dirname.startsWith('C:\\snapshot\\');
 
-    mail.address = (username, email) => username ? '"' + username + '" <' + email + '>' : email;
+        const dfltAgentDists = packaged ? 'libs/agent_dists' : 'agent_dists';
+        const dfltHost = packaged ? '0.0.0.0' : '127.0.0.1';
+        const dfltPort = packaged ? 80 : 3000;
 
-    return {
-        agent: {
-            dists: 'agent_dists'
-        },
-        server: {
-            host: nconf.get('server:host') || '127.0.0.1',
-            port: _normalizePort(nconf.get('server:port') || 3000),
-            SSLOptions: nconf.get('server:ssl') && {
-                enable301Redirects: true,
-                trustXFPHeader: true,
-                key: fs.readFileSync(nconf.get('server:key')),
-                cert: fs.readFileSync(nconf.get('server:cert')),
-                passphrase: nconf.get('server:keyPassphrase')
-            }
-        },
-        mail,
-        mongoUrl: nconf.get('mongodb:url') || 'mongodb://127.0.0.1/console',
-        cookieTTL: 3600000 * 24 * 30,
-        sessionSecret: nconf.get('server:sessionSecret') || 'keyboard cat',
-        tokenLength: 20
-    };
+        return {
+            agent: {
+                dists: nconf.get('agent:dists') || dfltAgentDists
+            },
+            packaged,
+            server: {
+                host: nconf.get('server:host') || dfltHost,
+                port: _normalizePort(nconf.get('server:port') || dfltPort),
+                SSLOptions: nconf.get('server:ssl') && {
+                    enable301Redirects: true,
+                    trustXFPHeader: true,
+                    key: fs.readFileSync(nconf.get('server:key')),
+                    cert: fs.readFileSync(nconf.get('server:cert')),
+                    passphrase: nconf.get('server:keyPassphrase')
+                }
+            },
+            mail,
+            mongoUrl: nconf.get('mongodb:url') || 'mongodb://127.0.0.1/console',
+            cookieTTL: 3600000 * 24 * 30,
+            sessionSecret: nconf.get('server:sessionSecret') || 'keyboard cat',
+            tokenLength: 20
+        };
+    }
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/index.js b/modules/web-console/backend/index.js
index 8454789..266fa54 100644
--- a/modules/web-console/backend/index.js
+++ b/modules/web-console/backend/index.js
@@ -17,14 +17,21 @@
 
 'use strict';
 
-const _ = require('lodash');
 const fs = require('fs');
 const path = require('path');
+
+require('app-module-path').addPath(path.join(__dirname, 'node_modules'));
+
+const _ = require('lodash');
+const getos = require('getos');
 const http = require('http');
 const https = require('https');
 const MigrateMongoose = require('migrate-mongoose');
 
-const igniteModules = process.env.IGNITE_MODULES ?
+
+const packaged = __dirname.startsWith('/snapshot/') || __dirname.startsWith('C:\\snapshot\\');
+
+const igniteModules = !packaged && process.env.IGNITE_MODULES ?
     path.join(path.normalize(process.env.IGNITE_MODULES), 'backend') : path.join(__dirname, 'ignite_modules');
 
 let injector;
@@ -34,6 +41,8 @@ try {
 
     fs.accessSync(igniteModulesInjector, fs.F_OK);
 
+    process.env.NODE_PATH = path.join(__dirname, 'node_modules');
+
     injector = require(igniteModulesInjector);
 }
 catch (ignore) {
@@ -93,7 +102,7 @@ const init = ([settings, apiSrv, agentsHnd, browsersHnd]) => {
 
 /**
  * Run mongo model migration.
- * 
+ *
  * @param dbConnectionUri Mongo connection url.
  * @param group Migrations group.
  * @param migrationsPath Migrations path.
@@ -122,6 +131,16 @@ const migrate = (dbConnectionUri, group, migrationsPath) => {
         });
 };
 
+getos(function(e, os) {
+    if (e)
+        return console.log(e);
+
+    console.log('Your OS is: ' + JSON.stringify(os));
+});
+
+injector.log.info = () => {};
+injector.log.debug = () => {};
+
 Promise.all([injector('settings'), injector('mongo')])
     .then(([{mongoUrl}]) => {
         return migrate(mongoUrl, 'Ignite', path.join(__dirname, 'migrations'))

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/injector.js
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/injector.js b/modules/web-console/backend/injector.js
index a5996b3..754967f 100644
--- a/modules/web-console/backend/injector.js
+++ b/modules/web-console/backend/injector.js
@@ -21,10 +21,10 @@ module.exports = fireUp.newInjector({
     basePath: __dirname,
     modules: [
         './app/**/*.js',
-        './config/**/*.js',
         './errors/**/*.js',
         './middlewares/**/*.js',
         './routes/**/*.js',
-        './services/**/*.js'
+        './services/**/*.js',
+        './ignite_modules/**/*.js'
     ]
 });

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/backend/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/backend/package.json b/modules/web-console/backend/package.json
index 29aa734..f0b2b5e 100644
--- a/modules/web-console/backend/package.json
+++ b/modules/web-console/backend/package.json
@@ -7,7 +7,8 @@
     "ci-test": "cross-env NODE_ENV=test MOCHA_REPORTER=mocha-teamcity-reporter node ./test/index.js",
     "test": "cross-env NODE_ENV=test CONFIG_PATH='./test/config/settings.json' node ./test/index.js",
     "eslint": "eslint --env node --format node_modules/eslint-friendly-formatter ./ -- --eff-by-issue",
-    "start": "node ./index.js"
+    "start": "node ./index.js",
+    "build": "pkg . --out-path build"
   },
   "author": "",
   "contributors": [
@@ -30,7 +31,23 @@
     "linux",
     "win32"
   ],
+  "bin": "index.js",
+  "pkg": {
+    "assets": [
+      "app/*.js",
+      "errors/*.js",
+      "ignite_modules/*",
+      "injector.js",
+      "middlewares/*.js",
+      "migrations/*",
+      "node_modules/getos/logic/*.js",
+      "routes/*.js",
+      "routes/**/*.json",
+      "services/*.js"
+    ]
+  },
   "dependencies": {
+    "app-module-path": "2.2.0",
     "body-parser": "1.17.2",
     "connect-mongo": "1.3.2",
     "cookie-parser": "1.4.3",
@@ -38,9 +55,11 @@
     "express-session": "1.15.4",
     "fire-up": "1.0.0",
     "glob": "7.1.2",
+    "getos": "3.1.0",
     "jszip": "3.1.3",
     "lodash": "4.17.4",
     "migrate-mongoose": "3.2.2",
+    "mongodb-prebuilt": "6.3.3",
     "mongoose": "4.11.4",
     "morgan": "1.8.2",
     "nconf": "0.8.4",
@@ -59,6 +78,7 @@
     "mocha": "3.4.2",
     "mocha-teamcity-reporter": "1.1.1",
     "mockgoose": "6.0.8",
+    "pkg": "4.2.4",
     "supertest": "3.0.0"
   }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/docker/compose/frontend/nginx/web-console.conf
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/compose/frontend/nginx/web-console.conf b/modules/web-console/docker/compose/frontend/nginx/web-console.conf
index 323826e..3f5157d 100644
--- a/modules/web-console/docker/compose/frontend/nginx/web-console.conf
+++ b/modules/web-console/docker/compose/frontend/nginx/web-console.conf
@@ -39,7 +39,6 @@ server {
   }
 
   location /api/v1 {
-    rewrite /api/v1/(.*) /$1 break;
     proxy_set_header Host $http_host;
     proxy_pass http://backend-api;
   }

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/docker/standalone/nginx/web-console.conf
----------------------------------------------------------------------
diff --git a/modules/web-console/docker/standalone/nginx/web-console.conf b/modules/web-console/docker/standalone/nginx/web-console.conf
index 3d83075..6e36eed 100644
--- a/modules/web-console/docker/standalone/nginx/web-console.conf
+++ b/modules/web-console/docker/standalone/nginx/web-console.conf
@@ -34,7 +34,6 @@ server {
   }
 
   location /api/v1 {
-    rewrite /api/v1/(.*) /$1 break;
     proxy_set_header Host $http_host;
     proxy_pass http://backend-api;
   }

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/frontend/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/.gitignore b/modules/web-console/frontend/.gitignore
index 138a2cf..4fc11f46 100644
--- a/modules/web-console/frontend/.gitignore
+++ b/modules/web-console/frontend/.gitignore
@@ -1,9 +1,3 @@
-*.idea
-*.log
 *.log.*
-.npmrc
-build/*
-node_modules
 public/stylesheets/*.css
-yarn.lock
-package-lock.json
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
index 4e6204f..e5f4804 100644
--- a/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
+++ b/modules/web-console/frontend/app/modules/configuration/generator/JavaTransformer.service.js
@@ -1654,6 +1654,8 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
         }
 
         if ((_.nonEmpty(clientNearCaches) || demo) && shortFactoryCls) {
+            imports.push('org.apache.ignite.Ignite');
+
             sb.append(`Ignite ignite = Ignition.start(${cfgRef});`);
 
             _.forEach(clientNearCaches, (cache, idx) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/69eced65/modules/web-console/frontend/webpack/webpack.dev.babel.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/webpack/webpack.dev.babel.js b/modules/web-console/frontend/webpack/webpack.dev.babel.js
index 56371cda..88bf5c6 100644
--- a/modules/web-console/frontend/webpack/webpack.dev.babel.js
+++ b/modules/web-console/frontend/webpack/webpack.dev.babel.js
@@ -77,10 +77,7 @@ export default merge(commonCfg, {
                 ws: true
             },
             '/api/v1/*': {
-                target: `http://localhost:${backendPort}`,
-                pathRewrite: {
-                    '^/api/v1': ''
-                }
+                target: `http://localhost:${backendPort}`
             }
         },
         watchOptions: {


[07/47] ignite git commit: IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
index 2cc3659..77f7e3d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -23,7 +23,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     using System.Diagnostics.CodeAnalysis;
     using System.Globalization;
     using System.Linq;
-    using System.Runtime.InteropServices;
     using System.Threading;
     using Apache.Ignite.Core.Cache.Affinity;
     using Apache.Ignite.Core.Cluster;
@@ -44,6 +43,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     using Apache.Ignite.Core.Impl.Messaging;
     using Apache.Ignite.Core.Impl.Resource;
     using Apache.Ignite.Core.Impl.Services;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
     using Apache.Ignite.Core.Lifecycle;
     using Apache.Ignite.Core.Log;
     using Apache.Ignite.Core.Services;
@@ -52,32 +52,26 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     /// <summary>
     /// Unmanaged callbacks.
     /// </summary>
-    [SuppressMessage("ReSharper", "UnusedMember.Local")]
     [SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable",
         Justification = "This class instance usually lives as long as the app runs.")]
     [SuppressMessage("Microsoft.Design", "CA1049:TypesThatOwnNativeResourcesShouldBeDisposable",
         Justification = "This class instance usually lives as long as the app runs.")]
-    internal unsafe class UnmanagedCallbacks
+    internal unsafe class UnmanagedCallbacks : MarshalByRefObject
     {
-        /** Console write delegate. */
-        private static readonly ConsoleWriteDelegate ConsoleWriteDel = ConsoleWrite;
-
-        /** Console write pointer. */
-        private static readonly void* ConsoleWritePtr =
-            Marshal.GetFunctionPointerForDelegate(ConsoleWriteDel).ToPointer();
-
-        /** Unmanaged context. */
-        private volatile UnmanagedContext _ctx;
+        /** */
+        private long _igniteId;
 
         /** Handle registry. */
         private readonly HandleRegistry _handleRegistry = new HandleRegistry();
 
+        /** JVM. */
+        private readonly Jvm _jvm;
+
         /** Grid. */
         private volatile Ignite _ignite;
 
-        /** Keep references to created delegates. */
-        // ReSharper disable once CollectionNeverQueried.Local
-        private readonly List<Delegate> _delegates = new List<Delegate>(5);
+        /** Log. */
+        private volatile ILogger _log;
 
         /** Max op code. */
         private static readonly int MaxOpCode = Enum.GetValues(typeof(UnmanagedCallbackOp)).Cast<int>().Max();
@@ -95,38 +89,9 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /** Actions to be called upon Ignite initialization. */
         private readonly List<Action<Ignite>> _initActions = new List<Action<Ignite>>();
 
-        /** GC handle to UnmanagedCallbacks instance to prevent it from being GCed. */
-        private readonly GCHandle _thisHnd;
-
-        /** Callbacks pointer. */
-        [SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")]
-        private readonly IntPtr _cbsPtr;
-
-        /** Log. */
-        private readonly ILogger _log;
-
-        /** Error type: generic. */
-        private const int ErrGeneric = 1;
-
-        /** Error type: initialize. */
-        private const int ErrJvmInit = 2;
-
-        /** Error type: attach. */
-        private const int ErrJvmAttach = 3;
-
         /** Operation: prepare .Net. */
         private const int OpPrepareDotNet = 1;
 
-        private delegate void ErrorCallbackDelegate(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars, int errMsgCharsLen, sbyte* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen);
-
-        private delegate void LoggerLogDelegate(void* target, int level, sbyte* messageChars, int messageCharsLen, sbyte* categoryChars, int categoryCharsLen, sbyte* errorInfoChars, int errorInfoCharsLen, long memPtr);
-        private delegate bool LoggerIsLevelEnabledDelegate(void* target, int level);
-
-        private delegate void ConsoleWriteDelegate(sbyte* chars, int charsLen, bool isErr);
-
-        private delegate long InLongOutLongDelegate(void* target, int type, long val);
-        private delegate long InLongLongLongObjectOutLongDelegate(void* target, int type, long val1, long val2, long val3, void* arg);
-
         private delegate long InLongOutLongFunc(long val);
         private delegate long InLongLongLongObjectOutLongFunc(long val1, long val2, long val3, void* arg);
 
@@ -134,30 +99,14 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /// Constructor.
         /// </summary>
         /// <param name="log">Logger.</param>
-        public UnmanagedCallbacks(ILogger log)
+        /// <param name="jvm"></param>
+        public UnmanagedCallbacks(ILogger log, Jvm jvm)
         {
             Debug.Assert(log != null);
+            Debug.Assert(jvm != null);
 
             _log = log;
-
-            var cbs = new UnmanagedCallbackHandlers
-            {
-                target = IntPtr.Zero.ToPointer(), // Target is not used in .Net as we rely on dynamic FP creation.
-
-                error = CreateFunctionPointer((ErrorCallbackDelegate)Error),
-
-                loggerLog = CreateFunctionPointer((LoggerLogDelegate)LoggerLog),
-                loggerIsLevelEnabled = CreateFunctionPointer((LoggerIsLevelEnabledDelegate)LoggerIsLevelEnabled),
-
-                inLongOutLong = CreateFunctionPointer((InLongOutLongDelegate)InLongOutLong),
-                inLongLongObjectOutLong = CreateFunctionPointer((InLongLongLongObjectOutLongDelegate)InLongLongLongObjectOutLong)
-            };
-
-            _cbsPtr = Marshal.AllocHGlobal(UU.HandlersSize());
-
-            Marshal.StructureToPtr(cbs, _cbsPtr, false);
-
-            _thisHnd = GCHandle.Alloc(this);
+            _jvm = jvm;
 
             InitHandlers();
         }
@@ -170,6 +119,22 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             get { return _handleRegistry; }
         }
 
+        /// <summary>
+        /// Gets the ignite identifier.
+        /// </summary>
+        public long IgniteId
+        {
+            get { return _igniteId; }
+        }
+
+        /// <summary>
+        /// Gets the JVM.
+        /// </summary>
+        public Jvm Jvm
+        {
+            get { return _jvm; }
+        }
+
         #region HANDLERS
 
         /// <summary>
@@ -266,7 +231,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         #region IMPLEMENTATION: GENERAL PURPOSE
 
         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
-        private long InLongOutLong(void* target, int type, long val)
+        internal long InLongOutLong(int type, long val)
         {
             try
             {
@@ -286,15 +251,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
-
-                return 0;
+                throw;
             }
         }
 
         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
-        private long InLongLongLongObjectOutLong(void* target, int type, long val1, long val2, long val3, void* arg)
+        internal long InLongLongLongObjectOutLong(int type, long val1, long val2, long val3, IntPtr arg)
         {
             try
             {
@@ -309,15 +271,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
                 if (!hnd.AllowUninitialized)
                     _initEvent.Wait();
 
-                return hnd.Handler(val1, val2, val3, arg);
+                return hnd.Handler(val1, val2, val3, arg.ToPointer());
             }
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
-
-                return 0;
+                throw;
             }
         }
 
@@ -680,8 +639,8 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
                 if (receiver != null)
                 {
-                    var target = new PlatformJniTarget(new UnmanagedNonReleaseableTarget(_ctx, cache), 
-                        _ignite.Marshaller);
+                    var cacheRef = _jvm.AttachCurrentThread().NewGlobalRef((IntPtr) cache);
+                    var target = new PlatformJniTarget(cacheRef, _ignite.Marshaller);
                     receiver.Receive(_ignite, target, stream, keepBinary);
                 }
 
@@ -1069,7 +1028,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         private long OnStart(long memPtr, long unused, long unused1, void* proc)
         {
-            var proc0 = UU.Acquire(_ctx, proc);
+            var proc0 = _jvm.AttachCurrentThread().NewGlobalRef((IntPtr) proc);
 
             using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
             {
@@ -1081,14 +1040,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         private long OnStop(long unused)
         {
-            Marshal.FreeHGlobal(_cbsPtr);
-
-            // ReSharper disable once ImpureMethodCallOnReadonlyValueField
-            _thisHnd.Free();
-
-            // Allow context to be collected, which will cause resource cleanup in finalizer.
-            _ctx = null;
-
             // Notify grid
             var ignite = _ignite;
 
@@ -1098,34 +1049,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             return 0;
         }
 
-        private void Error(void* target, int errType, sbyte* errClsChars, int errClsCharsLen, sbyte* errMsgChars,
-            int errMsgCharsLen, sbyte* stackTraceChars, int stackTraceCharsLen, void* errData, int errDataLen)
-        {
-            // errData mechanism is only needed for CachePartialUpdateException and is no longer used,
-            // since CacheImpl handles all errors itself.
-            Debug.Assert(errDataLen == 0);
-            Debug.Assert(errData == null);
-
-            string errCls = IgniteUtils.Utf8UnmanagedToString(errClsChars, errClsCharsLen);
-            string errMsg = IgniteUtils.Utf8UnmanagedToString(errMsgChars, errMsgCharsLen);
-            string stackTrace = IgniteUtils.Utf8UnmanagedToString(stackTraceChars, stackTraceCharsLen);
-
-            switch (errType)
-            {
-                case ErrGeneric:
-                    throw ExceptionUtils.GetException(_ignite, errCls, errMsg, stackTrace);
-
-                case ErrJvmInit:
-                    throw ExceptionUtils.GetJvmInitializeException(errCls, errMsg, stackTrace);
-
-                case ErrJvmAttach:
-                    throw new IgniteException("Failed to attach to JVM.");
-
-                default:
-                    throw new IgniteException("Unknown exception [cls=" + errCls + ", msg=" + errMsg + ']');
-            }
-        }
-
         private long OnClientDisconnected(long unused)
         {
             _ignite.OnClientDisconnected();
@@ -1140,18 +1063,13 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             return 0;
         }
 
-        private void LoggerLog(void* target, int level, sbyte* messageChars, int messageCharsLen, sbyte* categoryChars,
-            int categoryCharsLen, sbyte* errorInfoChars, int errorInfoCharsLen, long memPtr)
+        internal void LoggerLog(int level, string message, string category, string nativeError, long memPtr)
         {
             // When custom logger in .NET is not defined, Java should not call us.
             Debug.Assert(!(_log is JavaLogger));
 
             SafeCall(() =>
             {
-                var message = IgniteUtils.Utf8UnmanagedToString(messageChars, messageCharsLen);
-                var category = IgniteUtils.Utf8UnmanagedToString(categoryChars, categoryCharsLen);
-                var nativeError = IgniteUtils.Utf8UnmanagedToString(errorInfoChars, errorInfoCharsLen);
-
                 Exception ex = null;
 
                 if (memPtr != 0 && _ignite != null)
@@ -1166,7 +1084,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             }, true);
         }
 
-        private bool LoggerIsLevelEnabled(void* target, int level)
+        internal bool LoggerIsLevelEnabled(int level)
         {
             // When custom logger in .NET is not defined, Java should not call us.
             Debug.Assert(!(_log is JavaLogger));
@@ -1174,24 +1092,6 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             return SafeCall(() => _log.IsEnabled((LogLevel) level), true);
         }
 
-        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
-        private static void ConsoleWrite(sbyte* chars, int charsLen, bool isErr)
-        {
-            try
-            {
-                var str = IgniteUtils.Utf8UnmanagedToString(chars, charsLen);
-
-                var target = isErr ? Console.Error : Console.Out;
-
-                target.Write(str);
-
-            }
-            catch (Exception ex)
-            {
-                Console.Error.WriteLine("ConsoleWrite unmanaged callback failed: " + ex);
-            }
-        }
-
         private long PluginProcessorIgniteStop(long val)
         {
             _ignite.PluginProcessor.OnIgniteStop(val != 0);
@@ -1225,7 +1125,8 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
                 if (affBase != null)
                 {
-                    var baseFunc0 = new PlatformJniTarget(UU.Acquire(_ctx, baseFunc), _ignite.Marshaller);
+                    var baseFuncRef = _jvm.AttachCurrentThread().NewGlobalRef((IntPtr) baseFunc);
+                    var baseFunc0 = new PlatformJniTarget(baseFuncRef, _ignite.Marshaller);
 
                     affBase.SetBaseFunction(new PlatformAffinityFunction(baseFunc0));
                 }
@@ -1312,8 +1213,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
+                throw;
             }
         }
 
@@ -1330,32 +1230,13 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             catch (Exception e)
             {
                 _log.Error(e, "Failure in Java callback");
-
-                UU.ThrowToJava(_ctx.NativeContext, e);
-
-                return default(T);
+                throw;
             }
         }
 
         #endregion
         
         /// <summary>
-        /// Callbacks pointer.
-        /// </summary>
-        public void* CallbacksPointer
-        {
-            get { return _cbsPtr.ToPointer(); }
-        }
-
-        /// <summary>
-        /// Gets the context.
-        /// </summary>
-        public UnmanagedContext Context
-        {
-            get { return _ctx; }
-        }
-
-        /// <summary>
         /// Gets the log.
         /// </summary>
         public ILogger Log
@@ -1364,22 +1245,11 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         }
 
         /// <summary>
-        /// Create function pointer for the given function.
+        /// Sets the context.
         /// </summary>
-        private void* CreateFunctionPointer(Delegate del)
-        {
-            _delegates.Add(del); // Prevent delegate from being GC-ed.
-
-            return Marshal.GetFunctionPointerForDelegate(del).ToPointer();
-        }
-
-        /// <param name="context">Context.</param>
-        public void SetContext(void* context)
+        public void SetContext(long igniteId)
         {
-            Debug.Assert(context != null);
-            Debug.Assert(_ctx == null);
-
-            _ctx = new UnmanagedContext(context);
+            _igniteId = igniteId;
         }
 
         /// <summary>
@@ -1409,17 +1279,15 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /// </summary>
         public void Cleanup()
         {
+            // This instance crosses AppDomain boundaries and is GCed with a delay.
+            // Release all external references.
+
             _ignite = null;
+            _log = null;
 
-            _handleRegistry.Close();
-        }
+            _jvm.ReleaseCallbacks(_igniteId);
 
-        /// <summary>
-        /// Gets the console write handler.
-        /// </summary>
-        public static void* ConsoleWriteHandler
-        {
-            get { return ConsoleWritePtr; }
+            _handleRegistry.Close();
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedContext.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedContext.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedContext.cs
deleted file mode 100644
index 89d2071..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedContext.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    /// <summary>
-    /// Unmanaged context.
-    /// Wrapper around native ctx pointer to track finalization.
-    /// </summary>
-    internal unsafe class UnmanagedContext
-    {
-        /** Context */
-        private readonly void* _nativeCtx;
-
-        /// <summary>
-        /// Constructor.
-        /// </summary>
-        public UnmanagedContext(void* ctx)
-        {
-            _nativeCtx = ctx;
-        }
-
-        /// <summary>
-        /// Gets the native context pointer.
-        /// </summary>
-        public void* NativeContext
-        {
-            get { return _nativeCtx; }
-        }
-
-        /// <summary>
-        /// Destructor.
-        /// </summary>
-        ~UnmanagedContext()
-        {
-            UnmanagedUtils.DeleteContext(_nativeCtx); // Release CPP object.
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs
deleted file mode 100644
index d044c5f..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedNonReleaseableTarget.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System.Diagnostics.CodeAnalysis;
-
-    /// <summary>
-    /// Unmanaged target which does not require explicit release.
-    /// </summary>
-    internal unsafe class UnmanagedNonReleaseableTarget : IUnmanagedTarget
-    {
-        /** Context. */
-        private readonly UnmanagedContext _ctx;
-
-        /** Target. */
-        private readonly void* _target;
-
-        /// <summary>
-        /// Constructor.
-        /// </summary>
-        /// <param name="ctx">Context.</param>
-        /// <param name="target">Target.</param>
-        public UnmanagedNonReleaseableTarget(UnmanagedContext ctx, void* target)
-        {
-            _ctx = ctx;
-            _target = target;
-        }
-
-        /** <inheritdoc /> */
-        public void* Context
-        {
-            get { return _ctx.NativeContext; }
-        }
-
-        /** <inheritdoc /> */
-        public void* Target
-        {
-            get { return _target; }
-        }
-
-        /** <inheritdoc /> */
-        public IUnmanagedTarget ChangeTarget(void* target)
-        {
-            return new UnmanagedTarget(_ctx, target);
-        }
-
-        /** <inheritdoc /> */
-        [SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly",
-            Justification = "There is no finalizer.")]
-        public void Dispose()
-        {
-            // No-op.
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs
deleted file mode 100644
index a5e2cb0..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedTarget.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Impl.Unmanaged
-{
-    using System;
-    using System.Runtime.InteropServices;
-    using UU = UnmanagedUtils;
-
-    /// <summary>
-    /// Base unmanaged target implementation.
-    /// </summary>
-    internal sealed unsafe class UnmanagedTarget : CriticalHandle, IUnmanagedTarget
-    {
-        /** Context. */
-        private readonly UnmanagedContext _ctx;
-        
-        /// <summary>
-        /// Constructor.
-        /// </summary>
-        /// <param name="ctx">Context.</param>
-        /// <param name="target">Target.</param>
-        public UnmanagedTarget(UnmanagedContext ctx, void* target)
-            : base(IntPtr.Zero)
-        {
-            _ctx = ctx;
-            
-            SetHandle(new IntPtr(target));
-        }
-
-        /** <inheritdoc /> */
-        public void* Context
-        {
-            get { return _ctx.NativeContext; }
-        }
-
-        /** <inheritdoc /> */
-        public void* Target
-        {
-            get { return handle.ToPointer(); }
-        }
-
-        /** <inheritdoc /> */
-        public IUnmanagedTarget ChangeTarget(void* target)
-        {
-            return new UnmanagedTarget(_ctx, target);
-        }
-
-        /** <inheritdoc /> */
-        protected override bool ReleaseHandle()
-        {
-            UU.Release(this);
-            
-            return true;
-        }
-
-        /** <inheritdoc /> */
-        public override bool IsInvalid
-        {
-            get { return handle == IntPtr.Zero; }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
index 511bb7a..58586a9 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
@@ -17,13 +17,7 @@
 
 namespace Apache.Ignite.Core.Impl.Unmanaged
 {
-    using System;
-    using System.Diagnostics;
-    using System.Diagnostics.CodeAnalysis;
-    using System.Runtime.InteropServices;
-    using System.Threading.Tasks;
-    using Apache.Ignite.Core.Common;
-    using JNI = IgniteJniNativeMethods;
+    using Apache.Ignite.Core.Impl.Unmanaged.Jni;
 
     /// <summary>
     /// Unmanaged utility classes.
@@ -33,93 +27,47 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         /** Interop factory ID for .Net. */
         private const int InteropFactoryId = 1;
 
-        /// <summary>
-        /// Initializer.
-        /// </summary>
-        [SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")]
-        static UnmanagedUtils()
-        {
-            var platform = Environment.Is64BitProcess ? "x64" : "x86";
-
-            var resName = string.Format("{0}.{1}", platform, IgniteUtils.FileIgniteJniDll);
-
-            var path = IgniteUtils.UnpackEmbeddedResource(resName, IgniteUtils.FileIgniteJniDll);
-
-            var ptr = NativeMethods.LoadLibrary(path);
-
-            if (ptr == IntPtr.Zero)
-            {
-                var err = Marshal.GetLastWin32Error();
-
-                throw new IgniteException(string.Format("Failed to load {0} from {1}: [{2}]",
-                    IgniteUtils.FileIgniteJniDll, path, IgniteUtils.FormatWin32Error(err)));
-            }
-
-            AppDomain.CurrentDomain.DomainUnload += CurrentDomain_DomainUnload;
-
-            JNI.SetConsoleHandler(UnmanagedCallbacks.ConsoleWriteHandler);
-
-            // Clean directories in background to avoid extra work on start.
-            Task.Factory.StartNew(IgniteUtils.TryCleanTempDirectories);
-        }
-
-        /// <summary>
-        /// Handles the DomainUnload event of the current AppDomain.
-        /// </summary>
-        private static void CurrentDomain_DomainUnload(object sender, EventArgs e)
-        {
-            // Clean the handler to avoid JVM crash.
-            var removedCnt = JNI.RemoveConsoleHandler(UnmanagedCallbacks.ConsoleWriteHandler);
-
-            Debug.Assert(removedCnt == 1);
-        }
-
-        /// <summary>
-        /// No-op initializer used to force type loading and static constructor call.
-        /// </summary>
-        internal static void Initialize()
-        {
-            // No-op.
-        }
-
         #region NATIVE METHODS: PROCESSOR
 
-        internal static void IgnitionStart(UnmanagedContext ctx, string cfgPath, string gridName,
-            bool clientMode, bool userLogger)
+        internal static void IgnitionStart(Env env, string cfgPath, string gridName,
+            bool clientMode, bool userLogger, long igniteId)
         {
             using (var mem = IgniteManager.Memory.Allocate().GetStream())
+            using (var cfgPath0 = env.NewStringUtf(cfgPath))
+            using (var gridName0 = env.NewStringUtf(gridName))
             {
                 mem.WriteBool(clientMode);
                 mem.WriteBool(userLogger);
 
-                sbyte* cfgPath0 = IgniteUtils.StringToUtf8Unmanaged(cfgPath);
-                sbyte* gridName0 = IgniteUtils.StringToUtf8Unmanaged(gridName);
-
-                try
-                {
-                    // OnStart receives InteropProcessor referece and stores it.
-                    JNI.IgnitionStart(ctx.NativeContext, cfgPath0, gridName0, InteropFactoryId,
-                        mem.SynchronizeOutput());
-                }
-                finally
-                {
-                    Marshal.FreeHGlobal(new IntPtr(cfgPath0));
-                    Marshal.FreeHGlobal(new IntPtr(gridName0));
-                }
+                // Additional data.
+                mem.WriteBool(false);
+                mem.WriteBool(false);
+
+                long* args = stackalloc long[5];
+                args[0] = cfgPath == null ? 0 : cfgPath0.Target.ToInt64();
+                args[1] = gridName == null ? 0 : gridName0.Target.ToInt64();
+                args[2] = InteropFactoryId;
+                args[3] = igniteId;
+                args[4] = mem.SynchronizeOutput();
+
+                // OnStart receives InteropProcessor reference and stores it.
+                var methodId = env.Jvm.MethodId;
+                env.CallStaticVoidMethod(methodId.PlatformIgnition, methodId.PlatformIgnitionStart, args);
             }
         }
 
-        internal static bool IgnitionStop(void* ctx, string gridName, bool cancel)
+        internal static bool IgnitionStop(string gridName, bool cancel)
         {
-            sbyte* gridName0 = IgniteUtils.StringToUtf8Unmanaged(gridName);
+            var env = Jvm.Get().AttachCurrentThread();
+            var methodId = env.Jvm.MethodId;
 
-            try
+            using (var gridName1 = env.NewStringUtf(gridName))
             {
-                return JNI.IgnitionStop(ctx, gridName0, cancel);
-            }
-            finally
-            {
-                Marshal.FreeHGlobal(new IntPtr(gridName0));
+                long* args = stackalloc long[2];
+                args[0] = gridName == null ? 0 : gridName1.Target.ToInt64();
+                args[1] = cancel ? 1 : 0;
+
+                return env.CallStaticBoolMethod(methodId.PlatformIgnition, methodId.PlatformIgnitionStop, args);
             }
         }
 
@@ -127,122 +75,127 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         #region NATIVE METHODS: TARGET
 
-        internal static long TargetInLongOutLong(IUnmanagedTarget target, int opType, long memPtr)
+        internal static long TargetInLongOutLong(GlobalRef target, int opType, long memPtr)
         {
-            return JNI.TargetInLongOutLong(target.Context, target.Target, opType, memPtr);
-        }
+            var jvm = target.Jvm;
 
-        internal static long TargetInStreamOutLong(IUnmanagedTarget target, int opType, long memPtr)
-        {
-            return JNI.TargetInStreamOutLong(target.Context, target.Target, opType, memPtr);
-        }
+            long* args = stackalloc long[2];
+            args[0] = opType;
+            args[1] = memPtr;
 
-        internal static void TargetInStreamOutStream(IUnmanagedTarget target, int opType, long inMemPtr, long outMemPtr)
-        {
-            JNI.TargetInStreamOutStream(target.Context, target.Target, opType, inMemPtr, outMemPtr);
+            return jvm.AttachCurrentThread().CallLongMethod(target, jvm.MethodId.TargetInLongOutLong, args);
         }
 
-        internal static IUnmanagedTarget TargetInStreamOutObject(IUnmanagedTarget target, int opType, long inMemPtr)
+        internal static long TargetInStreamOutLong(GlobalRef target, int opType, long memPtr)
         {
-            void* res = JNI.TargetInStreamOutObject(target.Context, target.Target, opType, inMemPtr);
+            var jvm = target.Jvm;
 
-            if (res == null)
-                return null;
+            long* args = stackalloc long[2];
+            args[0] = opType;
+            args[1] = memPtr;
 
-            return target.ChangeTarget(res);
+            return jvm.AttachCurrentThread().CallLongMethod(target, jvm.MethodId.TargetInStreamOutLong, args);
         }
 
-        internal static IUnmanagedTarget TargetInObjectStreamOutObjectStream(IUnmanagedTarget target, int opType, void* arg, long inMemPtr, long outMemPtr)
+        internal static void TargetInStreamOutStream(GlobalRef target, int opType, long inMemPtr,
+            long outMemPtr)
         {
-            void* res = JNI.TargetInObjectStreamOutObjectStream(target.Context, target.Target, opType, arg, inMemPtr, outMemPtr);
+            var jvm = target.Jvm;
 
-            if (res == null)
-                return null;
+            long* args = stackalloc long[3];
+            args[0] = opType;
+            args[1] = inMemPtr;
+            args[2] = outMemPtr;
 
-            return target.ChangeTarget(res);
+            jvm.AttachCurrentThread().CallVoidMethod(target, jvm.MethodId.TargetInStreamOutStream, args);
         }
 
-        internal static void TargetOutStream(IUnmanagedTarget target, int opType, long memPtr)
+        internal static GlobalRef TargetInStreamOutObject(GlobalRef target, int opType, long inMemPtr)
         {
-            JNI.TargetOutStream(target.Context, target.Target, opType, memPtr);
-        }
+            var jvm = target.Jvm;
 
-        internal static IUnmanagedTarget TargetOutObject(IUnmanagedTarget target, int opType)
-        {
-            void* res = JNI.TargetOutObject(target.Context, target.Target, opType);
+            long* args = stackalloc long[2];
+            args[0] = opType;
+            args[1] = inMemPtr;
 
-            return target.ChangeTarget(res);
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetInStreamOutObject, args);
         }
 
-        internal static void TargetInStreamAsync(IUnmanagedTarget target, int opType, long memPtr)
+        internal static GlobalRef TargetInObjectStreamOutObjectStream(GlobalRef target, int opType, 
+            GlobalRef arg, long inMemPtr, long outMemPtr)
         {
-            JNI.TargetInStreamAsync(target.Context, target.Target, opType, memPtr);
-        }
+            var jvm = target.Jvm;
 
-        internal static IUnmanagedTarget TargetInStreamOutObjectAsync(IUnmanagedTarget target, int opType, long memPtr)
-        {
-            void* res = JNI.TargetInStreamOutObjectAsync(target.Context, target.Target, opType, memPtr);
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = (long) arg.Target;
+            args[2] = inMemPtr;
+            args[3] = outMemPtr;
 
-            return target.ChangeTarget(res);
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetInObjectStreamOutObjectStream, args);
         }
 
-        #endregion
-
-        #region NATIVE METHODS: MISCELANNEOUS
-
-        internal static void Reallocate(long memPtr, int cap)
+        internal static void TargetOutStream(GlobalRef target, int opType, long memPtr)
         {
-            int res = JNI.Reallocate(memPtr, cap);
+            var jvm = target.Jvm;
 
-            if (res != 0)
-                throw new IgniteException("Failed to reallocate external memory [ptr=" + memPtr + 
-                    ", capacity=" + cap + ']');
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = memPtr;
+
+            jvm.AttachCurrentThread().CallVoidMethod(target, jvm.MethodId.TargetOutStream, args);
         }
 
-        internal static IUnmanagedTarget Acquire(UnmanagedContext ctx, void* target)
+        internal static GlobalRef TargetOutObject(GlobalRef target, int opType)
         {
-            void* target0 = JNI.Acquire(ctx.NativeContext, target);
+            var jvm = target.Jvm;
 
-            return new UnmanagedTarget(ctx, target0);
-        }
+            long opType0 = opType;
 
-        internal static void Release(IUnmanagedTarget target)
-        {
-            JNI.Release(target.Target);
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetOutObject, &opType0);
         }
 
-        internal static void ThrowToJava(void* ctx, Exception e)
+        internal static void TargetInStreamAsync(GlobalRef target, int opType, long memPtr)
         {
-            char* msgChars = (char*)IgniteUtils.StringToUtf8Unmanaged(e.Message);
+            var jvm = target.Jvm;
 
-            try
-            {
-                JNI.ThrowToJava(ctx, msgChars);
-            }
-            finally
-            {
-                Marshal.FreeHGlobal(new IntPtr(msgChars));
-            }
-        }
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = memPtr;
 
-        internal static int HandlersSize()
-        {
-            return JNI.HandlersSize();
+            jvm.AttachCurrentThread().CallVoidMethod(target, jvm.MethodId.TargetInStreamAsync, args);
         }
 
-        internal static void* CreateContext(void* opts, int optsLen, void* cbs)
+        internal static GlobalRef TargetInStreamOutObjectAsync(GlobalRef target, int opType, long memPtr)
         {
-            return JNI.CreateContext(opts, optsLen, cbs);
-        }
+            var jvm = target.Jvm;
 
-        internal static void DeleteContext(void* ctx)
-        {
-            JNI.DeleteContext(ctx);
+            long* args = stackalloc long[4];
+            args[0] = opType;
+            args[1] = memPtr;
+
+            return jvm.AttachCurrentThread().CallObjectMethod(
+                target, jvm.MethodId.TargetInStreamOutObjectAsync, args);
         }
 
-        internal static void DestroyJvm(void* ctx)
+        #endregion
+
+        #region NATIVE METHODS: MISCELANNEOUS
+
+        internal static void Reallocate(long memPtr, int cap)
         {
-            JNI.DestroyJvm(ctx);
+            var jvm = Jvm.Get();
+            var methodId = jvm.MethodId;
+
+            long* args = stackalloc long[4];
+            args[0] = memPtr;
+            args[1] = cap;
+
+            jvm.AttachCurrentThread().CallStaticVoidMethod(methodId.PlatformUtils, methodId.PlatformUtilsReallocate,
+                args);
         }
 
         #endregion

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1 b/modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1
deleted file mode 100644
index db24751..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/build-common.ps1
+++ /dev/null
@@ -1,77 +0,0 @@
-param([string]$configuration="Debug", [string]$msbuildexe = "MSBuild.exe")
-
-$x64 = [System.Environment]::Is64BitOperatingSystem
-$jdkRegKey = 'Software\JavaSoft\Java Development Kit'
-
-# Fisrt, check if JAVA_HOME env vars are set
-if (Test-Path Env:\JAVA_HOME) {
-    if ($x64 -and !$env:JAVA_HOME64) {
-        $env:JAVA_HOME64 = $env:JAVA_HOME
-    }
-    elseif (!$env:JAVA_HOME32) {
-        $env:JAVA_HOME32 = $env:JAVA_HOME
-    }
-}
-
-# Next, check registry
-Function GetJavaHome([string]$path, [Microsoft.Win32.RegistryView] $mode) {
-    $key = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $mode).OpenSubKey($path)
-
-    if ($key -eq $null) {
-        return $null
-    }
-
-    $subKeys = $key.GetSubKeyNames()
-    $curVer = $key.GetValue("CurrentVersion")
-
-    if ($subKeys.Length -eq 0) {
-        return $null
-    }
-
-    if ($curVer -eq $null -or !$subKeys.Contains($curVer)) {
-        $curVer = $subKeys[0]
-    }
-            
-    return $key.OpenSubKey($curVer).GetValue("JavaHome")
-}
-
-# do not read registry if env vars are already set
-if (!$env:JAVA_HOME32) {
-    $env:JAVA_HOME32 = GetJavaHome $jdkRegKey Registry32
-}
-
-
-if ($x64 -and !$env:JAVA_HOME64) {
-    $env:JAVA_HOME64 = GetJavaHome $jdkRegKey Registry64
-}
-
-echo "JAVA_HOME64: $env:JAVA_HOME64"
-echo "JAVA_HOME32: $env:JAVA_HOME32"
-echo "msbuildexe: $msbuildexe"
-echo "x64: $x64"
-
-# build common project
-if ($env:JAVA_HOME64) {
-    $env:JAVA_HOME = $env:JAVA_HOME64
-
-    & $msbuildexe "..\..\cpp\common\project\vs\common.vcxproj" /p:Platform=x64 /p:Configuration=$Configuration /t:Rebuild
-}
-
-if ($env:JAVA_HOME32) {
-    $env:JAVA_HOME = $env:JAVA_HOME32
-
-    & $msbuildexe "..\..\cpp\common\project\vs\common.vcxproj" /p:Platform=Win32 /p:Configuration=$Configuration /t:Rebuild
-}
-
-# build jni project
-if ($env:JAVA_HOME64) {
-    $env:JAVA_HOME = $env:JAVA_HOME64
-
-    & $msbuildexe "..\..\cpp\jni\project\vs\jni.vcxproj" /p:Platform=x64 /p:Configuration=$Configuration /t:Rebuild
-}
-
-if ($env:JAVA_HOME32) {
-    $env:JAVA_HOME = $env:JAVA_HOME32
-
-    & $msbuildexe "..\..\cpp\jni\project\vs\jni.vcxproj" /p:Platform=Win32 /p:Configuration=$Configuration /t:Rebuild
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Apache.Ignite.EntityFramework.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Apache.Ignite.EntityFramework.csproj b/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Apache.Ignite.EntityFramework.csproj
index 372c2ed..4b302cc 100644
--- a/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Apache.Ignite.EntityFramework.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.EntityFramework/Apache.Ignite.EntityFramework.csproj
@@ -20,7 +20,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <DocumentationFile>bin\Debug\Apache.Ignite.EntityFramework.XML</DocumentationFile>
@@ -35,6 +35,7 @@
     <DebugType>none</DebugType>
     <DocumentationFile>bin\Release\Apache.Ignite.EntityFramework.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
   </PropertyGroup>
   <PropertyGroup>
     <SignAssembly>true</SignAssembly>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.Log4Net/Apache.Ignite.Log4Net.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Log4Net/Apache.Ignite.Log4Net.csproj b/modules/platforms/dotnet/Apache.Ignite.Log4Net/Apache.Ignite.Log4Net.csproj
index 142ce73..af87404 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Log4Net/Apache.Ignite.Log4Net.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Log4Net/Apache.Ignite.Log4Net.csproj
@@ -20,7 +20,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
-    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
     <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
@@ -32,6 +32,8 @@
     <WarningLevel>4</WarningLevel>
     <DocumentationFile>bin\Release\Apache.Ignite.Log4Net.XML</DocumentationFile>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <RunCodeAnalysis>false</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
   </PropertyGroup>
   <PropertyGroup>
     <SignAssembly>true</SignAssembly>

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.ndproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.ndproj b/modules/platforms/dotnet/Apache.Ignite.ndproj
index 9f5287b..34aaa4c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.ndproj
+++ b/modules/platforms/dotnet/Apache.Ignite.ndproj
@@ -2347,7 +2347,8 @@ warnif count > 0
 from t in JustMyCode.Types.Where(t =>
    !t.IsStatic && !t.IsInterface &&
    !t.IsEnumeration && !t.IsDelegate &&
-   !t.IsGeneratedByCompiler)
+   !t.IsGeneratedByCompiler &&
+   !t.FullName.Contains(".Jni."))
 
 let methodsThatCanBeMadeStatic = 
    from m in t.InstanceMethods
@@ -2477,7 +2478,7 @@ select new {
       <Query Active="True" DisplayList="True" DisplayStat="False" DisplaySelectionView="False" IsCriticalRule="False"><![CDATA[//<Name>Avoid the Singleton pattern</Name>
 warnif count > 0
 from t in Application.Types
-where !t.IsStatic && !t.IsAbstract && (t.IsClass || t.IsStructure)
+where !t.IsStatic && !t.IsAbstract && (t.IsClass || t.IsStructure) && t.Name != "Jvm"
 
 // All ctors of a singleton are private
 where t.Constructors.Where(ctor => !ctor.IsPrivate).Count() == 0
@@ -5641,7 +5642,8 @@ from f in JustMyCode.Fields where
    !f.IsEnumValue &&  // The IL code never explicitly uses enumeration value.
     f.Name != "value__"  && // Field named 'value__' are relative to enumerations and the IL code never explicitly uses them.
    !f.HasAttribute("NDepend.Attributes.IsNotDeadCodeAttribute".AllowNoMatch()) &&
-   !f.IsGeneratedByCompiler
+   !f.IsGeneratedByCompiler &&
+   !f.ParentType.Name.StartsWith("Jvm")
    // If you don't want to link NDepend.API.dll, you can use your own IsNotDeadCodeAttribute
    // and adapt the source code of this rule.
 select new {

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite.sln
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.sln b/modules/platforms/dotnet/Apache.Ignite.sln
index fe83ccd..1ca7b14 100644
--- a/modules/platforms/dotnet/Apache.Ignite.sln
+++ b/modules/platforms/dotnet/Apache.Ignite.sln
@@ -2,14 +2,9 @@
 Microsoft Visual Studio Solution File, Format Version 11.00
 # Visual Studio 2010
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Core", "Apache.Ignite.Core\Apache.Ignite.Core.csproj", "{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}"
-	ProjectSection(ProjectDependencies) = postProject
-		{4F7E4917-4612-4B96-9838-025711ADE391} = {4F7E4917-4612-4B96-9838-025711ADE391}
-	EndProjectSection
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Core.Tests", "Apache.Ignite.Core.Tests\Apache.Ignite.Core.Tests.csproj", "{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}"
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "..\cpp\common\project\vs\common.vcxproj", "{B63F2E01-5157-4719-8491-0E1C7CD3B701}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Core.Tests.TestDll", "Apache.Ignite.Core.Tests.TestDll\Apache.Ignite.Core.Tests.TestDll.csproj", "{F4A69E2D-908E-4F0F-A794-84D508D60E5F}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite", "Apache.Ignite\Apache.Ignite.csproj", "{27F7F3C6-BDDE-43A9-B565-856F8395A04B}"
@@ -40,8 +35,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 		README.md = README.md
 	EndProjectSection
 EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jni", "..\cpp\jni\project\vs\jni.vcxproj", "{4F7E4917-4612-4B96-9838-025711ADE391}"
-EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.Linq", "Apache.Ignite.Linq\Apache.Ignite.Linq.csproj", "{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}"
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Apache.Ignite.AspNet", "Apache.Ignite.AspNet\Apache.Ignite.AspNet.csproj", "{13EA96FC-CC83-4164-A7C0-4F30ED797460}"
@@ -59,201 +52,65 @@ EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
-		Debug|x64 = Debug|x64
-		Debug|x86 = Debug|x86
 		Release|Any CPU = Release|Any CPU
-		Release|x64 = Release|x64
-		Release|x86 = Release|x86
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
 		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x64.ActiveCfg = Debug|x64
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x64.Build.0 = Debug|x64
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x86.ActiveCfg = Debug|x86
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Debug|x86.Build.0 = Debug|x86
 		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|Any CPU.Build.0 = Release|Any CPU
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x64.ActiveCfg = Release|x64
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x64.Build.0 = Release|x64
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x86.ActiveCfg = Release|x86
-		{4CD2F726-7E2B-46C4-A5BA-057BB82EECB6}.Release|x86.Build.0 = Release|x86
 		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x64.Build.0 = Debug|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Debug|x86.Build.0 = Debug|Any CPU
 		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|Any CPU.Build.0 = Release|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x64.ActiveCfg = Release|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x64.Build.0 = Release|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x86.ActiveCfg = Release|Any CPU
-		{6A62F66C-DA5B-4FBB-8CE7-A95F740FDC7A}.Release|x86.Build.0 = Release|Any CPU
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|Any CPU.ActiveCfg = Debug|x64
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x64.ActiveCfg = Debug|x64
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x64.Build.0 = Debug|x64
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x86.ActiveCfg = Debug|Win32
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Debug|x86.Build.0 = Debug|Win32
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|Any CPU.ActiveCfg = Release|x64
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x64.ActiveCfg = Release|x64
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x64.Build.0 = Release|x64
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x86.ActiveCfg = Release|Win32
-		{B63F2E01-5157-4719-8491-0E1C7CD3B701}.Release|x86.Build.0 = Release|Win32
 		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x64.Build.0 = Debug|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Debug|x86.Build.0 = Debug|Any CPU
 		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|Any CPU.Build.0 = Release|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x64.ActiveCfg = Release|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x64.Build.0 = Release|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x86.ActiveCfg = Release|Any CPU
-		{F4A69E2D-908E-4F0F-A794-84D508D60E5F}.Release|x86.Build.0 = Release|Any CPU
 		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x64.Build.0 = Debug|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Debug|x86.Build.0 = Debug|Any CPU
 		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|Any CPU.Build.0 = Release|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x64.ActiveCfg = Release|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x64.Build.0 = Release|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x86.ActiveCfg = Release|Any CPU
-		{27F7F3C6-BDDE-43A9-B565-856F8395A04B}.Release|x86.Build.0 = Release|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x64.Build.0 = Debug|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|x86.Build.0 = Debug|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.Build.0 = Release|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x64.ActiveCfg = Release|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x64.Build.0 = Release|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x86.ActiveCfg = Release|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|x86.Build.0 = Release|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|x64.Build.0 = Debug|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|x86.Build.0 = Debug|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.Build.0 = Release|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Release|x64.ActiveCfg = Release|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Release|x64.Build.0 = Release|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Release|x86.ActiveCfg = Release|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Release|x86.Build.0 = Release|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x64.Build.0 = Debug|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|x86.Build.0 = Debug|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|Any CPU.Build.0 = Release|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x64.ActiveCfg = Release|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x64.Build.0 = Release|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x86.ActiveCfg = Release|Any CPU
-		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|x86.Build.0 = Release|Any CPU
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Debug|Any CPU.ActiveCfg = Debug|x64
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x64.ActiveCfg = Debug|x64
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x64.Build.0 = Debug|x64
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x86.ActiveCfg = Debug|Win32
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Debug|x86.Build.0 = Debug|Win32
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Release|Any CPU.ActiveCfg = Release|x64
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Release|x64.ActiveCfg = Release|x64
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Release|x64.Build.0 = Release|x64
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Release|x86.ActiveCfg = Release|Win32
-		{4F7E4917-4612-4B96-9838-025711ADE391}.Release|x86.Build.0 = Release|Win32
 		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x64.Build.0 = Debug|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Debug|x86.Build.0 = Debug|Any CPU
 		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|Any CPU.Build.0 = Release|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x64.ActiveCfg = Release|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x64.Build.0 = Release|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x86.ActiveCfg = Release|Any CPU
-		{5B571661-17F4-4F29-8C7D-0EDB38CA9B55}.Release|x86.Build.0 = Release|Any CPU
 		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x64.Build.0 = Debug|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Debug|x86.Build.0 = Debug|Any CPU
 		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|Any CPU.Build.0 = Release|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x64.ActiveCfg = Release|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x64.Build.0 = Release|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x86.ActiveCfg = Release|Any CPU
-		{13EA96FC-CC83-4164-A7C0-4F30ED797460}.Release|x86.Build.0 = Release|Any CPU
 		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x64.Build.0 = Debug|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Debug|x86.Build.0 = Debug|Any CPU
 		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|Any CPU.Build.0 = Release|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x64.ActiveCfg = Release|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x64.Build.0 = Release|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x86.ActiveCfg = Release|Any CPU
-		{18EA4C71-A11D-4AB1-8042-418F7559D84F}.Release|x86.Build.0 = Release|Any CPU
 		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x64.Build.0 = Debug|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Debug|x86.Build.0 = Debug|Any CPU
 		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|Any CPU.Build.0 = Release|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x64.ActiveCfg = Release|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x64.Build.0 = Release|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x86.ActiveCfg = Release|Any CPU
-		{C6B58E4A-A2E9-4554-AD02-68CE6DA5CFB7}.Release|x86.Build.0 = Release|Any CPU
 		{6F82D669-382E-4435-8092-68C4440146D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{6F82D669-382E-4435-8092-68C4440146D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Debug|x64.Build.0 = Debug|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Debug|x86.Build.0 = Debug|Any CPU
 		{6F82D669-382E-4435-8092-68C4440146D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{6F82D669-382E-4435-8092-68C4440146D8}.Release|Any CPU.Build.0 = Release|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Release|x64.ActiveCfg = Release|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Release|x64.Build.0 = Release|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Release|x86.ActiveCfg = Release|Any CPU
-		{6F82D669-382E-4435-8092-68C4440146D8}.Release|x86.Build.0 = Release|Any CPU
 		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x64.Build.0 = Debug|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Debug|x86.Build.0 = Debug|Any CPU
 		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|Any CPU.Build.0 = Release|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x64.ActiveCfg = Release|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x64.Build.0 = Release|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x86.ActiveCfg = Release|Any CPU
-		{C558518A-C1A0-4224-AAA9-A8688474B4DC}.Release|x86.Build.0 = Release|Any CPU
 		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x64.Build.0 = Debug|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x86.ActiveCfg = Debug|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Debug|x86.Build.0 = Debug|Any CPU
 		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|Any CPU.Build.0 = Release|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x64.ActiveCfg = Release|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x64.Build.0 = Release|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x86.ActiveCfg = Release|Any CPU
-		{CDA5700E-78F3-4A9E-A9B0-704CBE94651C}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/Apache.Ignite/IgniteRunner.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite/IgniteRunner.cs b/modules/platforms/dotnet/Apache.Ignite/IgniteRunner.cs
index 5703aa6..6d8aa6b 100644
--- a/modules/platforms/dotnet/Apache.Ignite/IgniteRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/IgniteRunner.cs
@@ -22,6 +22,7 @@ namespace Apache.Ignite
     using System.Configuration;
     using System.Linq;
     using System.ServiceProcess;
+    using System.Threading;
     using Apache.Ignite.Config;
     using Apache.Ignite.Core;
     using Apache.Ignite.Core.Impl;
@@ -97,9 +98,12 @@ namespace Apache.Ignite
                         IgniteService.DoInstall(allArgs);
                     else
                     {
-                        Ignition.Start(Configurator.GetConfiguration(allArgs));
+                        var ignite = Ignition.Start(Configurator.GetConfiguration(allArgs));
 
-                        IgniteManager.DestroyJvm();
+                        // Wait until stopped.
+                        var evt = new ManualResetEventSlim(false);
+                        ignite.Stopped += (s, a) => evt.Set();
+                        evt.Wait();
                     }
 
                     return;

http://git-wip-us.apache.org/repos/asf/ignite/blob/ec38564a/modules/platforms/dotnet/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/DEVNOTES.txt b/modules/platforms/dotnet/DEVNOTES.txt
index df0ebb5..db5bc6c 100644
--- a/modules/platforms/dotnet/DEVNOTES.txt
+++ b/modules/platforms/dotnet/DEVNOTES.txt
@@ -6,7 +6,7 @@ Requirements:
 * Oracle JDK 7 and above
 * .NET Framework 4.0
 * PowerShell 3.0+
-* Visual Studio 2010 (later versions require upgrading "common" C++ project, see below)
+* Visual Studio 2010+
 * JAVA_HOME environment variable set to the corresponding JDK (x64 or x86)
 * Apache Maven bin directory in PATH, or MAVEN_HOME environment variable
 
@@ -15,15 +15,4 @@ Building binaries:
 Resulting binaries will be in bin folder, and NuGet packages in nupkg folder.
 
 Running built binaries: resulting "bin" folder in self contained, you can copy it anywhere and run
-  bin\Apache.Ignite.exe  
-
-NOTE: 
-* x86 solution platform requires x86 Oracle JDK.
-* x64 solution platform requires x64 Oracle JDK.
-* AnyCPU platform requires at least one of the above. 
-To build truly universal AnyCPU binaries (suitable for x86 and x64 modes), both x64 and x86 Oracle JDKs should be installed.
-
-Building in later versions of Visual Studio:
-* Open Apache.Ignite.sln in Visual Studio
-* You will be prompted to "Update VC++ Compiler and Libraries", click "Update"
-* OR, right-click "common" project in the Solution Explorer and select "Upgrade VC++ Compiler and Libraries"
\ No newline at end of file
+  bin\Apache.Ignite.exe  
\ No newline at end of file


[13/47] ignite git commit: IGNITE-6859 Web Console: Do not split base64 strings to multiple lines because IE11 atob() implementation does not work with these.

Posted by sb...@apache.org.
IGNITE-6859 Web Console: Do not split base64 strings to multiple lines because IE11 atob() implementation does not work with these.


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

Branch: refs/heads/ignite-zk
Commit: 4589ff2d42f0553e311f4fb4dfd545fce38374dc
Parents: cba8fa2
Author: Ilya Borisov <kl...@gmail.com>
Authored: Wed Nov 15 16:03:13 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Wed Nov 15 16:03:13 2017 +0700

----------------------------------------------------------------------
 .../org/apache/ignite/console/agent/handlers/AbstractListener.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4589ff2d/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
----------------------------------------------------------------------
diff --git a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
index fc4daef..ace2087 100644
--- a/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
+++ b/modules/web-console/web-agent/src/main/java/org/apache/ignite/console/agent/handlers/AbstractListener.java
@@ -82,7 +82,7 @@ abstract class AbstractListener implements Emitter.Listener {
 
                             if (restRes.getData() != null) {
                                 ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
-                                Base64OutputStream b64os = new Base64OutputStream(baos);
+                                Base64OutputStream b64os = new Base64OutputStream(baos, true, 0, null);
                                 GZIPOutputStream gzip = new GZIPOutputStream(b64os);
 
                                 gzip.write(restRes.getData().getBytes(UTF8));


[41/47] ignite git commit: Revert ".NET: Do not build examples as part of the main solution in Release mode"

Posted by sb...@apache.org.
Revert ".NET: Do not build examples as part of the main solution in Release mode"

This reverts commit 81ee3622d1b33b005806661ab87ee2b7e07a5bcc.


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

Branch: refs/heads/ignite-zk
Commit: aca1ce37009f4f866d0aed3098fa3763714139ee
Parents: 81ee362
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Nov 17 22:16:48 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Nov 17 22:16:48 2017 +0300

----------------------------------------------------------------------
 modules/platforms/dotnet/Apache.Ignite.sln | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/aca1ce37/modules/platforms/dotnet/Apache.Ignite.sln
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.sln b/modules/platforms/dotnet/Apache.Ignite.sln
index 70be796..1ca7b14 100644
--- a/modules/platforms/dotnet/Apache.Ignite.sln
+++ b/modules/platforms/dotnet/Apache.Ignite.sln
@@ -74,9 +74,11 @@ Global
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.Build.0 = Release|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.Build.0 = Release|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|Any CPU.ActiveCfg = Release|Any CPU


[10/47] ignite git commit: IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer Fix UnmanagedCallbacks lifetime

Posted by sb...@apache.org.
IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer
Fix UnmanagedCallbacks lifetime

This closes #2985


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

Branch: refs/heads/ignite-zk
Commit: d272a0b65806242aecfeed5589549ddf9ae74c8a
Parents: ec38564
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Nov 14 19:41:49 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Nov 14 19:41:49 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs   | 7 +++++++
 1 file changed, 7 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d272a0b6/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
index 77f7e3d..855d11d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -111,6 +111,13 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             InitHandlers();
         }
 
+        /** <inheritdoc /> */
+        public override object InitializeLifetimeService()
+        {
+            // Ensure that cross-AppDomain reference lives forever.
+            return null;
+        }
+
         /// <summary>
         /// Gets the handle registry.
         /// </summary>


[40/47] ignite git commit: .NET: Do not build examples as part of the main solution in Release mode

Posted by sb...@apache.org.
.NET: Do not build examples as part of the main solution in Release mode


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

Branch: refs/heads/ignite-zk
Commit: 81ee3622d1b33b005806661ab87ee2b7e07a5bcc
Parents: 0bd712d
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Nov 17 21:16:03 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Nov 17 21:16:03 2017 +0300

----------------------------------------------------------------------
 modules/platforms/dotnet/Apache.Ignite.sln | 2 --
 1 file changed, 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/81ee3622/modules/platforms/dotnet/Apache.Ignite.sln
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.sln b/modules/platforms/dotnet/Apache.Ignite.sln
index 1ca7b14..70be796 100644
--- a/modules/platforms/dotnet/Apache.Ignite.sln
+++ b/modules/platforms/dotnet/Apache.Ignite.sln
@@ -74,11 +74,9 @@ Global
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{069FA680-3C4D-43A9-B84F-E67513B87827}.Release|Any CPU.Build.0 = Release|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{DFB08363-202E-412D-8812-349EF10A8702}.Release|Any CPU.Build.0 = Release|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{8F507DBE-56F9-437F-82D4-74C02EC44E41}.Release|Any CPU.ActiveCfg = Release|Any CPU


[11/47] ignite git commit: IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer Fix ConsoleWriter lifetime

Posted by sb...@apache.org.
IGNITE-5343 .NET: Work with JNI directly, get rid of C++ layer
Fix ConsoleWriter lifetime

This closes #2985


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

Branch: refs/heads/ignite-zk
Commit: cdb43d843f3b8fa10a3198c8b82c4967171765be
Parents: d272a0b
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Nov 14 22:50:57 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Nov 14 22:50:57 2017 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs    | 7 +++++++
 .../dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs       | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cdb43d84/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
index ef4be1e..b1baf79 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/ConsoleWriter.cs
@@ -36,5 +36,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
             var target = isError ? Console.Error : Console.Out;
             target.Write(message);
         }
+
+        /** <inheritdoc /> */
+        public override object InitializeLifetimeService()
+        {
+            // Ensure that cross-AppDomain reference lives forever.
+            return null;
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/cdb43d84/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
index 10c7468..55331c7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/Jni/Jvm.cs
@@ -49,7 +49,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged.Jni
         /** Callbacks. */
         private readonly Callbacks _callbacks;
 
-        /** Static instamce */
+        /** Static instance */
         private static volatile Jvm _instance;
 
         /** Sync. */


[45/47] ignite git commit: IGNITE-6876: Added in ODBC support for SQL_ATTR_CONNECTION_TIMEOUT

Posted by sb...@apache.org.
IGNITE-6876: Added in ODBC support for SQL_ATTR_CONNECTION_TIMEOUT


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

Branch: refs/heads/ignite-zk
Commit: db343b649e4289ac28b769a741eee7ea77db8018
Parents: 5fb04be
Author: Igor Sapego <is...@gridgain.com>
Authored: Mon Nov 20 20:15:37 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Mon Nov 20 20:15:37 2017 +0300

----------------------------------------------------------------------
 .../cpp/odbc-test/src/attributes_test.cpp       |  22 +++
 .../cpp/odbc-test/src/queries_test.cpp          | 113 +++++++++++++++
 .../cpp/odbc/include/ignite/odbc/common_types.h |   3 +
 .../cpp/odbc/include/ignite/odbc/connection.h   |  81 +++++++++--
 .../include/ignite/odbc/system/socket_client.h  |  55 +++++++-
 .../odbc/os/linux/src/system/socket_client.cpp  | 141 +++++++++++++++++--
 .../odbc/os/win/src/system/socket_client.cpp    | 134 ++++++++++++++++--
 modules/platforms/cpp/odbc/src/connection.cpp   | 141 ++++++++++++++-----
 .../odbc/src/diagnostic/diagnostic_record.cpp   |   6 +
 .../cpp/odbc/src/query/batch_query.cpp          |  12 +-
 .../platforms/cpp/odbc/src/query/data_query.cpp |  12 +-
 11 files changed, 644 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
index b87f4b9..c4c2433 100644
--- a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
@@ -227,4 +227,26 @@ BOOST_AUTO_TEST_CASE(StatementAttributeQueryTimeout)
     BOOST_REQUIRE_EQUAL(timeout, 7);
 }
 
+BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionTimeout)
+{
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
+
+    SQLUINTEGER timeout = -1;
+    SQLRETURN ret = SQLGetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, &timeout, 0, 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+    BOOST_REQUIRE_EQUAL(timeout, 0);
+
+    ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(42), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    timeout = -1;
+
+    ret = SQLGetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, &timeout, 0, 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+    BOOST_REQUIRE_EQUAL(timeout, 42);
+}
+
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc-test/src/queries_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
index 6fcf7c9..dafab1a 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -2404,5 +2404,118 @@ BOOST_AUTO_TEST_CASE(TestCloseAfterEmptyUpdate)
         BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
 }
 
+BOOST_AUTO_TEST_CASE(TestConnectionTimeoutQuery)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    InsertTestStrings(10, false);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionTimeoutBatch)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectionTimeoutBoth)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    InsertTestStrings(10, false);
+    InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestQueryTimeoutQuery)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    InsertTestStrings(10, false);
+}
+
+BOOST_AUTO_TEST_CASE(TestQueryTimeoutBatch)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestQueryTimeoutBoth)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    InsertTestStrings(10, false);
+    InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestQueryAndConnectionTimeoutQuery)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(3), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    InsertTestStrings(10, false);
+}
+
+BOOST_AUTO_TEST_CASE(TestQueryAndConnectionTimeoutBatch)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(3), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    InsertTestBatch(11, 20, 9);
+}
+
+BOOST_AUTO_TEST_CASE(TestQueryAndConnectionTimeoutBoth)
+{
+    Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache");
+
+    SQLRETURN ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(5), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    ret = SQLSetConnectAttr(dbc, SQL_ATTR_CONNECTION_TIMEOUT, reinterpret_cast<SQLPOINTER>(3), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+    InsertTestStrings(10, false);
+    InsertTestBatch(11, 20, 9);
+}
 
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h
index 349147f..9c8c433 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h
@@ -190,6 +190,9 @@ namespace ignite
                  */
                 SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
 
+                /** The timeout period expired before the data source responded to the request. */
+                SHYT00_TIMEOUT_EXPIRED,
+
                 /**
                  * The connection timeout period expired before the data source
                  * responded to the request.

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
index 34fed5f..1577ee7 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
@@ -27,6 +27,7 @@
 #include "ignite/odbc/config/connection_info.h"
 #include "ignite/odbc/config/configuration.h"
 #include "ignite/odbc/diagnostic/diagnosable_adapter.h"
+#include "ignite/odbc/odbc_error.h"
 
 namespace ignite
 {
@@ -42,6 +43,19 @@ namespace ignite
             friend class Environment;
         public:
             /**
+             * Operation with timeout result.
+             */
+            struct OperationResult
+            {
+                enum T
+                {
+                    SUCCESS,
+                    FAIL,
+                    TIMEOUT
+                };
+            };
+
+            /**
              * Destructor.
              */
             ~Connection();
@@ -96,15 +110,21 @@ namespace ignite
              *
              * @param data Data buffer.
              * @param len Data length.
+             * @param timeout Timeout.
+             * @return @c true on success, @c false on timeout.
+             * @throw OdbcError on error.
              */
-            void Send(const int8_t* data, size_t len);
+            bool Send(const int8_t* data, size_t len, int32_t timeout);
 
             /**
              * Receive next message.
              *
              * @param msg Buffer for message.
+             * @param timeout Timeout.
+             * @return @c true on success, @c false on timeout.
+             * @throw OdbcError on error.
              */
-            void Receive(std::vector<int8_t>& msg);
+            bool Receive(std::vector<int8_t>& msg, int32_t timeout);
 
             /**
              * Get name of the assotiated schema.
@@ -134,9 +154,43 @@ namespace ignite
 
             /**
              * Synchronously send request message and receive response.
+             * Uses provided timeout.
              *
              * @param req Request message.
              * @param rsp Response message.
+             * @param timeout Timeout.
+             * @return @c true on success, @c false on timeout.
+             * @throw OdbcError on error.
+             */
+            template<typename ReqT, typename RspT>
+            bool SyncMessage(const ReqT& req, RspT& rsp, int32_t timeout)
+            {
+                std::vector<int8_t> tempBuffer;
+
+                parser.Encode(req, tempBuffer);
+
+                bool success = Send(tempBuffer.data(), tempBuffer.size(), timeout);
+
+                if (!success)
+                    return false;
+
+                success = Receive(tempBuffer, timeout);
+
+                if (!success)
+                    return false;
+
+                parser.Decode(rsp, tempBuffer);
+
+                return true;
+            }
+
+            /**
+             * Synchronously send request message and receive response.
+             * Uses connection timeout.
+             *
+             * @param req Request message.
+             * @param rsp Response message.
+             * @throw OdbcError on error.
              */
             template<typename ReqT, typename RspT>
             void SyncMessage(const ReqT& req, RspT& rsp)
@@ -145,9 +199,15 @@ namespace ignite
 
                 parser.Encode(req, tempBuffer);
 
-                Send(tempBuffer.data(), tempBuffer.size());
+                bool success = Send(tempBuffer.data(), tempBuffer.size(), timeout);
+
+                if (!success)
+                    throw OdbcError(SqlState::SHYT01_CONNECTION_TIMEOUT, "Send operation timed out");
+
+                success = Receive(tempBuffer, timeout);
 
-                Receive(tempBuffer);
+                if (!success)
+                    throw OdbcError(SqlState::SHYT01_CONNECTION_TIMEOUT, "Receive operation timed out");
 
                 parser.Decode(rsp, tempBuffer);
             }
@@ -280,18 +340,20 @@ namespace ignite
              *
              * @param dst Buffer for data.
              * @param len Number of bytes to receive.
-             * @return Number of successfully received bytes.
+             * @param timeout Timeout.
+             * @return Operation result.
              */
-            size_t ReceiveAll(void* dst, size_t len);
+            OperationResult::T ReceiveAll(void* dst, size_t len, int32_t timeout);
 
             /**
              * Send specified number of bytes.
              *
              * @param data Data buffer.
              * @param len Data length.
-             * @return Number of successfully sent bytes.
+             * @param timeout Timeout.
+             * @return Operation result.
              */
-            size_t SendAll(const int8_t* data, size_t len);
+            OperationResult::T SendAll(const int8_t* data, size_t len, int32_t timeout);
 
             /**
              * Perform handshake request.
@@ -311,6 +373,9 @@ namespace ignite
             /** State flag. */
             bool connected;
 
+            /** Connection timeout in seconds. */
+            int32_t timeout;
+
             /** Message parser. */
             Parser parser;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
index 946605e..2a3cfa3 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
@@ -44,6 +44,22 @@ namespace ignite
                 /** The time in seconds between individual keepalive probes. */
                 enum { KEEP_ALIVE_PROBES_PERIOD = 1 };
 
+                /** Connection establishment timeout in seconds. */
+                enum { CONNECT_TIMEOUT = 5 };
+
+                /**
+                 * Non-negative timeout operation result.
+                 */
+                struct WaitResult
+                {
+                    enum T
+                    {
+                        TIMEOUT = 0,
+
+                        SUCCESS = 1
+                    };
+                };
+
                 /**
                  * Constructor.
                  */
@@ -76,20 +92,31 @@ namespace ignite
                  *
                  * @param data Pointer to data to be sent.
                  * @param size Size of the data in bytes.
-                 * @return Number of bytes that have been sent on success and negative
-                 *         value on failure.
+                 * @param timeout Timeout.
+                 * @return Number of bytes that have been sent on success, 
+                 *     WaitResult::TIMEOUT on timeout and -errno on failure.
                  */
-                int Send(const int8_t* data, size_t size);
+                int Send(const int8_t* data, size_t size, int32_t timeout);
 
                 /**
                  * Receive data from established connection.
                  *
                  * @param buffer Pointer to data buffer.
                  * @param size Size of the buffer in bytes.
-                 * @return Number of bytes that have been received on success and negative
-                 *         value on failure.
+                 * @param timeout Timeout.
+                 * @return Number of bytes that have been sent on success,
+                 *     WaitResult::TIMEOUT on timeout and -errno on failure.
                  */
-                int Receive(int8_t* buffer, size_t size);
+                int Receive(int8_t* buffer, size_t size, int32_t timeout);
+
+                /**
+                 * Check if the socket is blocking or not.
+                 * @return @c true if the socket is blocking and false otherwise.
+                 */
+                bool IsBlocking() const
+                {
+                    return blocking;
+                }
 
             private:
                 /**
@@ -97,8 +124,24 @@ namespace ignite
                  */
                 void TrySetOptions(diagnostic::Diagnosable& diag);
 
+                /**
+                 * Wait on the socket for any event for specified time.
+                 * This function uses poll to achive timeout functionality
+                 * for every separate socket operation.
+                 *
+                 * @param timeout Timeout.
+                 * @param rd Wait for read if @c true, or for write if @c false.
+                 * @return -errno on error, WaitResult::TIMEOUT on timeout and
+                 *     WaitResult::SUCCESS on success.
+                 */
+                int WaitOnSocket(int32_t timeout, bool rd);
+
+                /** Handle. */
                 intptr_t socketHandle;
 
+                /** Blocking flag. */
+                bool blocking;
+
                 IGNITE_NO_COPY_ASSIGNMENT(SocketClient)
             };
         }

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp b/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
index 5a9b03a..a6d6151 100644
--- a/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
+++ b/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
@@ -20,6 +20,7 @@
 #include <netinet/tcp.h>
 #include <netdb.h>
 #include <unistd.h>
+#include <fcntl.h>
 
 #include <cstring>
 
@@ -35,26 +36,36 @@ namespace
 {
     /**
      * Get last socket error message.
+     * @param error Error code.
      * @return Last socket error message string.
      */
-    std::string GetLastSocketErrorMessage()
+    std::string GetSocketErrorMessage(int error)
     {
-        int lastError = errno;
         std::stringstream res;
 
-        res << "error_code=" << lastError;
+        res << "error_code=" << error;
 
-        if (lastError == 0)
+        if (error == 0)
             return res.str();
 
         char buffer[1024] = "";
 
-        strerror_r(lastError, buffer, sizeof(buffer));
-
-        res << ", msg=" << buffer;
+        if (!strerror_r(error, buffer, sizeof(buffer)))
+            res << ", msg=" << buffer;
 
         return res.str();
     }
+
+    /**
+     * Get last socket error message.
+     * @return Last socket error message string.
+     */
+    std::string GetLastSocketErrorMessage()
+    {
+        int lastError = errno;
+
+        return GetSocketErrorMessage(lastError);
+    }
 }
 
 namespace ignite
@@ -64,7 +75,9 @@ namespace ignite
         namespace tcp
         {
 
-            SocketClient::SocketClient() : socketHandle(SOCKET_ERROR)
+            SocketClient::SocketClient() :
+                socketHandle(SOCKET_ERROR),
+                blocking(true)
             {
                 // No-op.
             }
@@ -129,11 +142,27 @@ namespace ignite
                     res = connect(socketHandle, it->ai_addr, static_cast<int>(it->ai_addrlen));
                     if (SOCKET_ERROR == res)
                     {
-                        LOG_MSG("Connection failed: " << GetLastSocketErrorMessage());
+                        int lastError = errno;
+
+                        if (lastError != EWOULDBLOCK && lastError != EINPROGRESS)
+                        {
+                            LOG_MSG("Connection failed: " << GetSocketErrorMessage(lastError));
+
+                            Close();
 
-                        Close();
+                            continue;
+                        }
 
-                        continue;
+                        res = WaitOnSocket(CONNECT_TIMEOUT, false);
+
+                        if (res < 0 || res == WaitResult::TIMEOUT)
+                        {
+                            LOG_MSG("Connection timeout expired: " << GetSocketErrorMessage(-res));
+
+                            Close();
+
+                            continue;
+                        }
                     }
                     break;
                 }
@@ -153,13 +182,29 @@ namespace ignite
                 }
             }
 
-            int SocketClient::Send(const int8_t* data, size_t size)
+            int SocketClient::Send(const int8_t* data, size_t size, int32_t timeout)
             {
+                if (!blocking)
+                {
+                    int res = WaitOnSocket(timeout, false);
+
+                    if (res < 0 || res == WaitResult::TIMEOUT)
+                        return res;
+                }
+
                 return send(socketHandle, reinterpret_cast<const char*>(data), static_cast<int>(size), 0);
             }
 
-            int SocketClient::Receive(int8_t* buffer, size_t size)
+            int SocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout)
             {
+                if (!blocking)
+                {
+                    int res = WaitOnSocket(timeout, true);
+
+                    if (res < 0 || res == WaitResult::TIMEOUT)
+                        return res;
+                }
+
                 return recv(socketHandle, reinterpret_cast<char*>(buffer), static_cast<int>(size), 0);
             }
 
@@ -203,6 +248,30 @@ namespace ignite
                         "Can not set up TCP no-delay mode");
                 }
 
+                res = setsockopt(socketHandle, SOL_SOCKET, SO_OOBINLINE,
+                    reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP out-of-bound data inlining setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP out-of-bound data inlining");
+                }
+
+                blocking = false;
+
+                int flags;
+                if (((flags = fcntl(socketHandle, F_GETFL, 0)) < 0) ||
+                    (fcntl(socketHandle, F_SETFL, flags | O_NONBLOCK) < 0))
+                {
+                    blocking = true;
+                    LOG_MSG("Non-blocking mode setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up non-blocking mode. Timeouts are not available.");
+                }
+
                 res = setsockopt(socketHandle, SOL_SOCKET, SO_KEEPALIVE,
                     reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
 
@@ -238,6 +307,52 @@ namespace ignite
                     diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
                         "Can not set up TCP keep-alive probes period");
                 }
+
+            }
+
+            int SocketClient::WaitOnSocket(int32_t timeout, bool rd)
+            {
+                int ready = 0;
+                int lastError = 0;
+
+                fd_set fds;
+
+                do {
+                    struct timeval tv = { 0 };
+                    tv.tv_sec = timeout;
+
+                    FD_ZERO(&fds);
+                    FD_SET(socketHandle, &fds);
+
+                    fd_set* readFds = 0;
+                    fd_set* writeFds = 0;
+
+                    if (rd)
+                        readFds = &fds;
+                    else
+                        writeFds = &fds;
+
+                    ready = select(static_cast<int>((socketHandle) + 1),
+                        readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv));
+
+                    if (ready == SOCKET_ERROR)
+                        lastError = errno;
+
+                } while (ready == SOCKET_ERROR && lastError == EINTR);
+
+                if (ready == SOCKET_ERROR)
+                    return -lastError;
+
+                socklen_t size = sizeof(lastError);
+                int res = getsockopt(socketHandle, SOL_SOCKET, SO_ERROR, reinterpret_cast<char*>(&lastError), &size);
+
+                if (res != SOCKET_ERROR && lastError != 0)
+                    return -lastError;
+
+                if (ready == 0)
+                    return WaitResult::TIMEOUT;
+
+                return WaitResult::SUCCESS;
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp b/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
index 30fb7d7..6f87b93 100644
--- a/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
+++ b/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
@@ -34,17 +34,17 @@
 namespace
 {
     /**
-     * Get last socket error message.
-     * @return Last socket error message string.
+     * Get socket error message for the error code.
+     * @param error Error code.
+     * @return Socket error message string.
      */
-    std::string GetLastSocketErrorMessage()
+    std::string GetSocketErrorMessage(HRESULT error)
     {
-        HRESULT lastError = WSAGetLastError();
         std::stringstream res;
 
-        res << "error_code=" << lastError;
+        res << "error_code=" << error;
 
-        if (lastError == 0)
+        if (error == 0)
             return res.str();
 
         LPTSTR errorText = NULL;
@@ -58,7 +58,7 @@ namespace
             | FORMAT_MESSAGE_IGNORE_INSERTS,
             // unused with FORMAT_MESSAGE_FROM_SYSTEM
             NULL,
-            lastError,
+            error,
             MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
             // output
             reinterpret_cast<LPTSTR>(&errorText),
@@ -77,6 +77,17 @@ namespace
 
         return res.str();
     }
+
+    /**
+     * Get last socket error message.
+     * @return Last socket error message string.
+     */
+    std::string GetLastSocketErrorMessage()
+    {
+        HRESULT lastError = WSAGetLastError();
+
+        return GetSocketErrorMessage(lastError);
+    }
 }
 
 namespace ignite
@@ -86,7 +97,9 @@ namespace ignite
         namespace tcp
         {
 
-            SocketClient::SocketClient() : socketHandle(INVALID_SOCKET)
+            SocketClient::SocketClient() :
+                socketHandle(INVALID_SOCKET),
+                blocking(true)
             {
                 // No-op.
             }
@@ -170,11 +183,27 @@ namespace ignite
                     res = connect(socketHandle, it->ai_addr, static_cast<int>(it->ai_addrlen));
                     if (SOCKET_ERROR == res)
                     {
-                        LOG_MSG("Connection failed: " << GetLastSocketErrorMessage());
+                        int lastError = WSAGetLastError();
 
-                        Close();
+                        if (lastError != WSAEWOULDBLOCK)
+                        {
+                            LOG_MSG("Connection failed: " << GetSocketErrorMessage(lastError));
 
-                        continue;
+                            Close();
+
+                            continue;
+                        }
+
+                        res = WaitOnSocket(CONNECT_TIMEOUT, false);
+
+                        if (res < 0 || res == WaitResult::TIMEOUT)
+                        {
+                            LOG_MSG("Connection timeout expired: " << GetSocketErrorMessage(-res));
+
+                            Close();
+
+                            continue;
+                        }
                     }
                     break;
                 }
@@ -194,21 +223,39 @@ namespace ignite
                 }
             }
 
-            int SocketClient::Send(const int8_t* data, size_t size)
+            int SocketClient::Send(const int8_t* data, size_t size, int32_t timeout)
             {
+                if (!blocking)
+                {
+                    int res = WaitOnSocket(timeout, false);
+
+                    if (res < 0 || res == WaitResult::TIMEOUT)
+                        return res;
+                }
+
                 return send(socketHandle, reinterpret_cast<const char*>(data), static_cast<int>(size), 0);
             }
 
-            int SocketClient::Receive(int8_t* buffer, size_t size)
+            int SocketClient::Receive(int8_t* buffer, size_t size, int32_t timeout)
             {
+                if (!blocking)
+                {
+                    int res = WaitOnSocket(timeout, true);
+
+                    if (res < 0 || res == WaitResult::TIMEOUT)
+                        return res;
+                }
+
                 return recv(socketHandle, reinterpret_cast<char*>(buffer), static_cast<int>(size), 0);
             }
 
             void SocketClient::TrySetOptions(diagnostic::Diagnosable& diag)
             {
                 BOOL trueOpt = TRUE;
+                ULONG uTrueOpt = TRUE;
                 int bufSizeOpt = BUFFER_SIZE;
 
+
                 int res = setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF,
                     reinterpret_cast<char*>(&bufSizeOpt), sizeof(bufSizeOpt));
 
@@ -242,6 +289,29 @@ namespace ignite
                         "Can not set up TCP no-delay mode");
                 }
 
+                res = setsockopt(socketHandle, SOL_SOCKET, SO_OOBINLINE,
+                    reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP out-of-bound data inlining setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP out-of-bound data inlining");
+                }
+
+                blocking = false;
+                res = ioctlsocket(socketHandle, FIONBIO, &uTrueOpt);
+
+                if (res == SOCKET_ERROR)
+                {
+                    blocking = true;
+                    LOG_MSG("Non-blocking mode setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up non-blocking mode. Timeouts are not available.");
+                }
+
                 res = setsockopt(socketHandle, SOL_SOCKET, SO_KEEPALIVE,
                     reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
 
@@ -318,6 +388,44 @@ namespace ignite
 #endif
             }
 
+            int SocketClient::WaitOnSocket(int32_t timeout, bool rd)
+            {
+                int ready = 0;
+                int lastError = 0;
+
+                fd_set fds;
+
+                do {
+                    struct timeval tv = { 0 };
+                    tv.tv_sec = timeout;
+
+                    FD_ZERO(&fds);
+                    FD_SET(socketHandle, &fds);
+
+                    fd_set* readFds = 0;
+                    fd_set* writeFds = 0;
+
+                    if (rd)
+                        readFds = &fds;
+                    else
+                        writeFds = &fds;
+
+                    ready = select(static_cast<int>((socketHandle) + 1),
+                        readFds, writeFds, NULL, (timeout == 0 ? NULL : &tv));
+
+                    if (ready == SOCKET_ERROR)
+                        lastError = WSAGetLastError();
+
+                } while (ready == SOCKET_ERROR && lastError == WSAEINTR);
+
+                if (ready == SOCKET_ERROR)
+                    return -lastError;
+
+                if (ready == 0)
+                    return WaitResult::TIMEOUT;
+
+                return WaitResult::SUCCESS;
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index b99d768..8b03876 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -16,6 +16,7 @@
  */
 
 #include <cstring>
+#include <cstddef>
 
 #include <sstream>
 
@@ -27,7 +28,6 @@
 #include "ignite/odbc/connection.h"
 #include "ignite/odbc/message.h"
 #include "ignite/odbc/config/configuration.h"
-#include "ignite/odbc/odbc_error.h"
 
 namespace
 {
@@ -46,6 +46,7 @@ namespace ignite
         Connection::Connection() :
             socket(),
             connected(false),
+            timeout(0),
             parser(),
             config(),
             info(config)
@@ -194,7 +195,7 @@ namespace ignite
             return SqlResult::AI_SUCCESS;
         }
 
-        void Connection::Send(const int8_t* data, size_t len)
+        bool Connection::Send(const int8_t* data, size_t len, int32_t timeout)
         {
             if (!connected)
                 throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established");
@@ -209,38 +210,45 @@ namespace ignite
 
             memcpy(msg.GetData() + sizeof(OdbcProtocolHeader), data, len);
 
-            size_t sent = SendAll(msg.GetData(), msg.GetSize());
+            OperationResult::T res = SendAll(msg.GetData(), msg.GetSize(), timeout);
 
-            if (sent != len + sizeof(OdbcProtocolHeader))
+            if (res == OperationResult::TIMEOUT)
+                return false;
+
+            if (res == OperationResult::FAIL)
                 throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not send message due to connection failure");
 
             LOG_MSG("message sent: (" <<  msg.GetSize() << " bytes)" << utility::HexDump(msg.GetData(), msg.GetSize()));
+
+            return true;
         }
 
-        size_t Connection::SendAll(const int8_t* data, size_t len)
+        Connection::OperationResult::T Connection::SendAll(const int8_t* data, size_t len, int32_t timeout)
         {
             int sent = 0;
 
             while (sent != static_cast<int64_t>(len))
             {
-                int res = socket.Send(data + sent, len - sent);
+                int res = socket.Send(data + sent, len - sent, timeout);
 
                 LOG_MSG("Sent: " << res);
 
-                if (res <= 0)
+                if (res < 0 || res == tcp::SocketClient::WaitResult::TIMEOUT)
                 {
                     Close();
 
-                    return sent;
+                    return res < 0 ? OperationResult::FAIL : OperationResult::TIMEOUT;
                 }
 
                 sent += res;
             }
 
-            return sent;
+            assert(static_cast<size_t>(sent) == len);
+
+            return OperationResult::SUCCESS;
         }
 
-        void Connection::Receive(std::vector<int8_t>& msg)
+        bool Connection::Receive(std::vector<int8_t>& msg, int32_t timeout)
         {
             if (!connected)
                 throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established");
@@ -249,36 +257,40 @@ namespace ignite
 
             OdbcProtocolHeader hdr;
 
-            size_t received = ReceiveAll(reinterpret_cast<int8_t*>(&hdr), sizeof(hdr));
+            OperationResult::T res = ReceiveAll(reinterpret_cast<int8_t*>(&hdr), sizeof(hdr), timeout);
+
+            if (res == OperationResult::TIMEOUT)
+                return false;
 
-            if (received != sizeof(hdr))
+            if (res == OperationResult::FAIL)
                 throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message header");
 
             if (hdr.len < 0)
             {
                 Close();
 
-                throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Protocol error: Message length is negative");
+                throw OdbcError(SqlState::SHY000_GENERAL_ERROR, "Protocol error: Message length is negative");
             }
 
             if (hdr.len == 0)
-                return;
+                return false;
 
             msg.resize(hdr.len);
 
-            received = ReceiveAll(&msg[0], hdr.len);
+            res = ReceiveAll(&msg[0], hdr.len, timeout);
 
-            if (received != hdr.len)
-            {
-                msg.resize(received);
+            if (res == OperationResult::TIMEOUT)
+                return false;
 
+            if (res == OperationResult::FAIL)
                 throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message body");
-            }
 
             LOG_MSG("Message received: " << utility::HexDump(&msg[0], msg.size()));
+
+            return true;
         }
 
-        size_t Connection::ReceiveAll(void* dst, size_t len)
+        Connection::OperationResult::T Connection::ReceiveAll(void* dst, size_t len, int32_t timeout)
         {
             size_t remain = len;
             int8_t* buffer = reinterpret_cast<int8_t*>(dst);
@@ -287,20 +299,20 @@ namespace ignite
             {
                 size_t received = len - remain;
 
-                int res = socket.Receive(buffer + received, remain);
+                int res = socket.Receive(buffer + received, remain, timeout);
                 LOG_MSG("Receive res: " << res << " remain: " << remain);
 
-                if (res <= 0)
+                if (res < 0 || res == tcp::SocketClient::WaitResult::TIMEOUT)
                 {
                     Close();
 
-                    return received;
+                    return res < 0 ? OperationResult::FAIL : OperationResult::TIMEOUT;
                 }
 
                 remain -= static_cast<size_t>(res);
             }
 
-            return len;
+            return OperationResult::SUCCESS;
         }
 
         const std::string& Connection::GetSchema() const
@@ -334,6 +346,14 @@ namespace ignite
             IGNITE_ODBC_API_CALL(InternalTransactionRollback());
         }
 
+        SqlResult::Type Connection::InternalTransactionRollback()
+        {
+            AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
+                "Rollback operation is not supported.");
+
+            return SqlResult::AI_ERROR;
+        }
+
         void Connection::GetAttribute(int attr, void* buf, SQLINTEGER bufLen, SQLINTEGER* valueLen)
         {
             IGNITE_ODBC_API_CALL(InternalGetAttribute(attr, buf, bufLen, valueLen));
@@ -343,7 +363,7 @@ namespace ignite
         {
             if (!buf)
             {
-                AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Data buffer is NULL.");
+                AddStatusRecord(SqlState::SHY009_INVALID_USE_OF_NULL_POINTER, "Data buffer is null.");
 
                 return SqlResult::AI_ERROR;
             }
@@ -362,6 +382,18 @@ namespace ignite
                     break;
                 }
 
+                case SQL_ATTR_CONNECTION_TIMEOUT:
+                {
+                    SQLUINTEGER *val = reinterpret_cast<SQLUINTEGER*>(buf);
+
+                    *val = static_cast<SQLUINTEGER>(timeout);
+
+                    if (valueLen)
+                        *valueLen = SQL_IS_INTEGER;
+
+                    break;
+                }
+
                 default:
                 {
                     AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
@@ -381,6 +413,13 @@ namespace ignite
 
         SqlResult::Type Connection::InternalSetAttribute(int attr, void* value, SQLINTEGER valueLen)
         {
+            if (!value)
+            {
+                AddStatusRecord(SqlState::SHY009_INVALID_USE_OF_NULL_POINTER, "Value pointer is null.");
+
+                return SqlResult::AI_ERROR;
+            }
+
             switch (attr)
             {
                 case SQL_ATTR_CONNECTION_DEAD:
@@ -390,6 +429,39 @@ namespace ignite
                     return SqlResult::AI_ERROR;
                 }
 
+                case SQL_ATTR_CONNECTION_TIMEOUT:
+                {
+                    SQLUINTEGER uTimeout = static_cast<SQLUINTEGER>(reinterpret_cast<ptrdiff_t>(value));
+
+                    if (uTimeout != 0 && connected && socket.IsBlocking())
+                    {
+                        timeout = 0;
+
+                        AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, "Can not set timeout, because can not "
+                            "enable non-blocking mode on TCP connection. Setting to 0.");
+
+                        return SqlResult::AI_SUCCESS_WITH_INFO;
+                    }
+
+                    if (uTimeout > INT32_MAX)
+                    {
+                        timeout = INT32_MAX;
+
+                        std::stringstream ss;
+
+                        ss << "Value is too big: " << uTimeout << ", changing to " << timeout << ".";
+                        std::string msg = ss.str();
+
+                        AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, msg);
+
+                        return SqlResult::AI_SUCCESS_WITH_INFO;
+                    }
+
+                    timeout = static_cast<int32_t>(uTimeout);
+
+                    break;
+                }
+
                 default:
                 {
                     AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
@@ -402,14 +474,6 @@ namespace ignite
             return SqlResult::AI_SUCCESS;
         }
 
-        SqlResult::Type Connection::InternalTransactionRollback()
-        {
-            AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
-                "Rollback operation is not supported.");
-
-            return SqlResult::AI_ERROR;
-        }
-
         SqlResult::Type Connection::MakeRequestHandshake()
         {
             bool distributedJoins = false;
@@ -451,7 +515,16 @@ namespace ignite
 
             try
             {
-                SyncMessage(req, rsp);
+                // Workaround for some Linux systems that report connection on non-blocking
+                // sockets as successfull but fail to establish real connection.
+                bool sent = SyncMessage(req, rsp, tcp::SocketClient::CONNECT_TIMEOUT);
+
+                if (!sent)
+                {
+                    AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with the host.");
+
+                    return SqlResult::AI_ERROR;
+                }
             }
             catch (const OdbcError& err)
             {

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp
index 0a02310..7fa7669 100644
--- a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp
+++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp
@@ -133,6 +133,9 @@ namespace
     /** SQL state HYC00 constant. */
     const std::string STATE_HYC00 = "HYC00";
 
+    /** SQL state HYT00 constant. */
+    const std::string STATE_HYT00 = "HYT00";
+
     /** SQL state HYT01 constant. */
     const std::string STATE_HYT01 = "HYT01";
 
@@ -365,6 +368,9 @@ namespace ignite
                     case SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED:
                         return STATE_HYC00;
 
+                    case SqlState::SHYT00_TIMEOUT_EXPIRED:
+                        return STATE_HYT00;
+
                     case SqlState::SHYT01_CONNECTION_TIMEOUT:
                         return STATE_HYT01;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/src/query/batch_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/batch_query.cpp b/modules/platforms/cpp/odbc/src/query/batch_query.cpp
index 07d42d4..a9db8d8 100644
--- a/modules/platforms/cpp/odbc/src/query/batch_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/batch_query.cpp
@@ -153,7 +153,17 @@ namespace ignite
 
                 try
                 {
-                    connection.SyncMessage(req, rsp);
+                    // Setting connection timeout to 1 second more than query timeout itself.
+                    int32_t connectionTimeout = timeout ? timeout + 1 : 0;
+
+                    bool success = connection.SyncMessage(req, rsp, connectionTimeout);
+
+                    if (!success)
+                    {
+                        diag.AddStatusRecord(SqlState::SHYT00_TIMEOUT_EXPIRED, "Query timeout expired");
+
+                        return SqlResult::AI_ERROR;
+                    }
                 }
                 catch (const OdbcError& err)
                 {

http://git-wip-us.apache.org/repos/asf/ignite/blob/db343b64/modules/platforms/cpp/odbc/src/query/data_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/data_query.cpp b/modules/platforms/cpp/odbc/src/query/data_query.cpp
index 0539af5..e7bf5a0 100644
--- a/modules/platforms/cpp/odbc/src/query/data_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -222,7 +222,17 @@ namespace ignite
 
                 try
                 {
-                    connection.SyncMessage(req, rsp);
+                    // Setting connection timeout to 1 second more than query timeout itself.
+                    int32_t connectionTimeout = timeout ? timeout + 1 : 0;
+
+                    bool success = connection.SyncMessage(req, rsp, connectionTimeout);
+
+                    if (!success)
+                    {
+                        diag.AddStatusRecord(SqlState::SHYT00_TIMEOUT_EXPIRED, "Query timeout expired");
+
+                        return SqlResult::AI_ERROR;
+                    }
                 }
                 catch (const OdbcError& err)
                 {


[14/47] ignite git commit: IGNITE-6836: Implemented query timeout. This closes #3015

Posted by sb...@apache.org.
IGNITE-6836: Implemented query timeout.
This closes #3015


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

Branch: refs/heads/ignite-zk
Commit: 8c278ca9b67cd17dfd882e0eb65e19745798876d
Parents: 4589ff2
Author: Igor Sapego <is...@gridgain.com>
Authored: Wed Nov 15 13:41:31 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Wed Nov 15 13:41:31 2017 +0300

----------------------------------------------------------------------
 .../processors/odbc/odbc/OdbcMessageParser.java | 14 ++++++-
 .../odbc/odbc/OdbcQueryExecuteBatchRequest.java | 16 +++++++-
 .../odbc/odbc/OdbcQueryExecuteRequest.java      | 16 +++++++-
 .../odbc/odbc/OdbcRequestHandler.java           |  9 ++--
 .../cpp/odbc-test/src/attributes_test.cpp       | 22 ++++++++++
 .../platforms/cpp/odbc-test/src/parser_test.cpp |  2 +-
 .../cpp/odbc/include/ignite/odbc/message.h      | 33 ++++++++++-----
 .../cpp/odbc/include/ignite/odbc/parser.h       |  2 +-
 .../include/ignite/odbc/query/batch_query.h     |  8 +++-
 .../odbc/include/ignite/odbc/query/data_query.h |  8 +++-
 .../cpp/odbc/include/ignite/odbc/statement.h    |  4 ++
 modules/platforms/cpp/odbc/src/message.cpp      | 34 ++++++++++------
 .../cpp/odbc/src/query/batch_query.cpp          |  9 ++--
 .../platforms/cpp/odbc/src/query/data_query.cpp |  9 ++--
 modules/platforms/cpp/odbc/src/statement.cpp    | 43 ++++++++++++++++++--
 15 files changed, 180 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
index fb17d2a..c2137bd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java
@@ -96,7 +96,12 @@ public class OdbcMessageParser implements ClientListenerMessageParser {
 
                 Object[] params = readParameterRow(reader, paramNum);
 
-                res = new OdbcQueryExecuteRequest(schema, sql, params);
+                int timeout = 0;
+
+                if (ver.compareTo(OdbcConnectionContext.VER_2_3_2) >= 0)
+                    timeout = reader.readInt();
+
+                res = new OdbcQueryExecuteRequest(schema, sql, params, timeout);
 
                 break;
             }
@@ -113,7 +118,12 @@ public class OdbcMessageParser implements ClientListenerMessageParser {
                 for (int i = 0; i < rowNum; ++i)
                     params[i] = readParameterRow(reader, paramRowLen);
 
-                res = new OdbcQueryExecuteBatchRequest(schema, sql, last, params);
+                int timeout = 0;
+
+                if (ver.compareTo(OdbcConnectionContext.VER_2_3_2) >= 0)
+                    timeout = reader.readInt();
+
+                res = new OdbcQueryExecuteBatchRequest(schema, sql, last, params, timeout);
 
                 break;
             }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
index 50d16e5..0e4effd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchRequest.java
@@ -41,13 +41,19 @@ public class OdbcQueryExecuteBatchRequest extends OdbcRequest {
     @GridToStringExclude
     private final Object[][] args;
 
+    /** Query timeout in seconds. */
+    @GridToStringInclude
+    private final int timeout;
+
     /**
      * @param schema Schema.
      * @param sqlQry SQL query.
      * @param last Last page flag.
      * @param args Arguments list.
+     * @param timeout Timeout in seconds.
      */
-    public OdbcQueryExecuteBatchRequest(@Nullable String schema, String sqlQry, boolean last, Object[][] args) {
+    public OdbcQueryExecuteBatchRequest(@Nullable String schema, String sqlQry, boolean last, Object[][] args,
+        int timeout) {
         super(QRY_EXEC_BATCH);
 
         assert sqlQry != null : "SQL query should not be null";
@@ -57,6 +63,7 @@ public class OdbcQueryExecuteBatchRequest extends OdbcRequest {
         this.sqlQry = sqlQry;
         this.last = last;
         this.args = args;
+        this.timeout = timeout;
     }
 
     /**
@@ -88,6 +95,13 @@ public class OdbcQueryExecuteBatchRequest extends OdbcRequest {
         return last;
     }
 
+    /**
+     * @return Timeout in seconds.
+     */
+    public int timeout() {
+        return timeout;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(OdbcQueryExecuteBatchRequest.class, this, "args", args, true);

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
index 26d3328..1fde908 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteRequest.java
@@ -37,12 +37,17 @@ public class OdbcQueryExecuteRequest extends OdbcRequest {
     @GridToStringExclude
     private final Object[] args;
 
+    /** Query timeout in seconds. */
+    @GridToStringInclude
+    private final int timeout;
+
     /**
      * @param schema Schema.
      * @param sqlQry SQL query.
      * @param args Arguments list.
+     * @param timeout Timeout in seconds.
      */
-    public OdbcQueryExecuteRequest(@Nullable String schema, String sqlQry, Object[] args) {
+    public OdbcQueryExecuteRequest(@Nullable String schema, String sqlQry, Object[] args, int timeout) {
         super(QRY_EXEC);
 
         assert sqlQry != null : "SQL query should not be null";
@@ -50,6 +55,7 @@ public class OdbcQueryExecuteRequest extends OdbcRequest {
         this.schema = schema;
         this.sqlQry = sqlQry;
         this.args = args;
+        this.timeout = timeout;
     }
 
     /**
@@ -73,8 +79,16 @@ public class OdbcQueryExecuteRequest extends OdbcRequest {
         return schema;
     }
 
+    /**
+     * @return Timeout in seconds.
+     */
+    public int timeout() {
+        return timeout;
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(OdbcQueryExecuteRequest.class, this, "args", args, true);
     }
+
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
index 7f6b48d..3bc5a23 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
@@ -203,7 +204,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler {
      * @param args Arguments.
      * @return Query instance.
      */
-    private SqlFieldsQueryEx makeQuery(String schema, String sql, Object[] args) {
+    private SqlFieldsQueryEx makeQuery(String schema, String sql, Object[] args, int timeout) {
         SqlFieldsQueryEx qry = new SqlFieldsQueryEx(sql, null);
 
         qry.setArgs(args);
@@ -216,6 +217,8 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler {
         qry.setSchema(schema);
         qry.setSkipReducerOnUpdate(skipReducerOnUpdate);
 
+        qry.setTimeout(timeout, TimeUnit.SECONDS);
+
         return qry;
     }
 
@@ -243,7 +246,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler {
                 log.debug("ODBC query parsed [reqId=" + req.requestId() + ", original=" + req.sqlQuery() +
                     ", parsed=" + sql + ']');
 
-            SqlFieldsQuery qry = makeQuery(req.schema(), sql, req.arguments());
+            SqlFieldsQuery qry = makeQuery(req.schema(), sql, req.arguments(), req.timeout());
 
             List<FieldsQueryCursor<List<?>>> cursors = ctx.query().querySqlFieldsNoCache(qry, true, false);
 
@@ -285,7 +288,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler {
                 log.debug("ODBC query parsed [reqId=" + req.requestId() + ", original=" + req.sqlQuery() +
                         ", parsed=" + sql + ']');
 
-            SqlFieldsQuery qry = makeQuery(req.schema(), sql, req.arguments());
+            SqlFieldsQuery qry = makeQuery(req.schema(), sql, req.arguments(), req.timeout());
 
             Object[][] paramSet = req.arguments();
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
index f8cb5ac..b87f4b9 100644
--- a/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/attributes_test.cpp
@@ -205,4 +205,26 @@ BOOST_AUTO_TEST_CASE(ConnectionAttributeConnectionDeadSet)
     CheckSQLConnectionDiagnosticError("HY092");
 }
 
+BOOST_AUTO_TEST_CASE(StatementAttributeQueryTimeout)
+{
+    Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
+
+    SQLULEN timeout = -1;
+    SQLRETURN ret = SQLGetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, &timeout, 0, 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+    BOOST_REQUIRE_EQUAL(timeout, 0);
+
+    ret = SQLSetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, reinterpret_cast<SQLPOINTER>(7), 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+
+    timeout = -1;
+
+    ret = SQLGetStmtAttr(stmt, SQL_ATTR_QUERY_TIMEOUT, &timeout, 0, 0);
+
+    ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
+    BOOST_REQUIRE_EQUAL(timeout, 7);
+}
+
 BOOST_AUTO_TEST_SUITE_END()

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc-test/src/parser_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/parser_test.cpp b/modules/platforms/cpp/odbc-test/src/parser_test.cpp
index 51539ae..af11369 100644
--- a/modules/platforms/cpp/odbc-test/src/parser_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/parser_test.cpp
@@ -42,7 +42,7 @@ struct TestMessage
         // No-op.
     }
 
-    void Write(ignite::impl::binary::BinaryWriterImpl& writer) const
+    void Write(ignite::impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
     {
         writer.WriteInt32(a);
         writer.WriteString(b.data(), static_cast<int32_t>(b.size()));

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
index 8d6c906..51c0b41 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h
@@ -95,7 +95,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Protocol version. */
@@ -132,8 +132,10 @@ namespace ignite
              * @param schema Schema.
              * @param sql SQL query.
              * @param params Query arguments.
+             * @param timeout Timeout.
              */
-            QueryExecuteRequest(const std::string& schema, const std::string& sql, const app::ParameterSet& params);
+            QueryExecuteRequest(const std::string& schema, const std::string& sql, const app::ParameterSet& params,
+                int32_t timeout);
 
             /**
              * Destructor.
@@ -143,8 +145,9 @@ namespace ignite
             /**
              * Write request using provided writer.
              * @param writer Writer.
+             * @param ver Version.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion& ver) const;
 
         private:
             /** Schema name. */
@@ -155,6 +158,9 @@ namespace ignite
 
             /** Parameters bindings. */
             const app::ParameterSet& params;
+
+            /** Timeout. */
+            int32_t timeout;
         };
 
         /**
@@ -171,9 +177,10 @@ namespace ignite
              * @param params Query arguments.
              * @param begin Beginng of the interval.
              * @param end End of the interval.
+             * @param timeout Timeout.
              */
             QueryExecuteBatchtRequest(const std::string& schema, const std::string& sql,
-                                          const app::ParameterSet& params, SqlUlen begin, SqlUlen end, bool last);
+                const app::ParameterSet& params, SqlUlen begin, SqlUlen end, bool last, int32_t timeout);
 
             /**
              * Destructor.
@@ -183,8 +190,9 @@ namespace ignite
             /**
              * Write request using provided writer.
              * @param writer Writer.
+             * @param ver Version.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion& ver) const;
 
         private:
             /** Schema name. */
@@ -204,6 +212,9 @@ namespace ignite
 
             /** Last page flag. */
             bool last;
+
+            /** Timeout. */
+            int32_t timeout;
         };
 
         /**
@@ -228,7 +239,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Query ID. */
@@ -258,7 +269,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Query ID. */
@@ -292,7 +303,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Schema search pattern. */
@@ -331,7 +342,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Column search pattern. */
@@ -378,7 +389,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Schema. */
@@ -419,7 +430,7 @@ namespace ignite
              * Write request using provided writer.
              * @param writer Writer.
              */
-            void Write(impl::binary::BinaryWriterImpl& writer) const;
+            void Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const;
 
         private:
             /** Query ID. */

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h b/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h
index bfea67c..5ffb44c 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h
@@ -79,7 +79,7 @@ namespace ignite
 
                 BinaryWriterImpl writer(&outStream, 0);
 
-                msg.Write(writer);
+                msg.Write(writer, protocolVer);
 
                 buf.resize(outStream.Position());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/include/ignite/odbc/query/batch_query.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/query/batch_query.h b/modules/platforms/cpp/odbc/include/ignite/odbc/query/batch_query.h
index 1e6c869..af319ab 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/query/batch_query.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/query/batch_query.h
@@ -44,9 +44,10 @@ namespace ignite
                  * @param connection Associated connection.
                  * @param sql SQL query string.
                  * @param params SQL params.
+                 * @param timeout Timeout in seconds.
                  */
-                BatchQuery(diagnostic::Diagnosable& diag, Connection& connection,
-                    const std::string& sql, const app::ParameterSet& params);
+                BatchQuery(diagnostic::Diagnosable& diag, Connection& connection, const std::string& sql,
+                    const app::ParameterSet& params, int32_t& timeout);
 
                 /**
                  * Destructor.
@@ -156,6 +157,9 @@ namespace ignite
 
                 /** Query executed. */
                 bool executed;
+
+                /** Timeout. */
+                int32_t& timeout;
             };
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/include/ignite/odbc/query/data_query.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/query/data_query.h b/modules/platforms/cpp/odbc/include/ignite/odbc/query/data_query.h
index c476000..af39bdb 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/query/data_query.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/query/data_query.h
@@ -44,9 +44,10 @@ namespace ignite
                  * @param connection Associated connection.
                  * @param sql SQL query string.
                  * @param params SQL params.
+                 * @param timeout Timeout.
                  */
-                DataQuery(diagnostic::Diagnosable& diag, Connection& connection,
-                    const std::string& sql, const app::ParameterSet& params);
+                DataQuery(diagnostic::Diagnosable& diag, Connection& connection, const std::string& sql,
+                    const app::ParameterSet& params, int32_t& timeout);
 
                 /**
                  * Destructor.
@@ -184,6 +185,9 @@ namespace ignite
 
                 /** Cached next result page. */
                 std::auto_ptr<ResultPage> cachedNextPage;
+
+                /** Timeout. */
+                int32_t& timeout;
             };
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h b/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
index 6d4b3ab..4cc30c3 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/statement.h
@@ -666,7 +666,11 @@ namespace ignite
             /** Offset added to pointers to change binding of column data. */
             int* columnBindOffset;
 
+            /** Parameters. */
             app::ParameterSet parameters;
+
+            /** Query timeout in seconds. */
+            int32_t timeout;
         };
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/src/message.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/message.cpp b/modules/platforms/cpp/odbc/src/message.cpp
index 32a5d91..57b7210 100644
--- a/modules/platforms/cpp/odbc/src/message.cpp
+++ b/modules/platforms/cpp/odbc/src/message.cpp
@@ -63,7 +63,7 @@ namespace ignite
             // No-op.
         }
 
-        void HandshakeRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void HandshakeRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::HANDSHAKE);
 
@@ -86,10 +86,11 @@ namespace ignite
         }
 
         QueryExecuteRequest::QueryExecuteRequest(const std::string& schema, const std::string& sql,
-            const app::ParameterSet& params):
+            const app::ParameterSet& params, int32_t timeout):
             schema(schema),
             sql(sql),
-            params(params)
+            params(params),
+            timeout(timeout)
         {
             // No-op.
         }
@@ -99,7 +100,7 @@ namespace ignite
             // No-op.
         }
 
-        void QueryExecuteRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryExecuteRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion& ver) const
         {
             writer.WriteInt8(RequestType::EXECUTE_SQL_QUERY);
 
@@ -111,16 +112,20 @@ namespace ignite
             writer.WriteObject<std::string>(sql);
 
             params.Write(writer);
+
+            if (ver >= ProtocolVersion::VERSION_2_3_2)
+                writer.WriteInt32(timeout);
         }
 
         QueryExecuteBatchtRequest::QueryExecuteBatchtRequest(const std::string& schema, const std::string& sql,
-            const app::ParameterSet& params, SqlUlen begin, SqlUlen end, bool last):
+            const app::ParameterSet& params, SqlUlen begin, SqlUlen end, bool last, int32_t timeout):
             schema(schema),
             sql(sql),
             params(params),
             begin(begin),
             end(end),
-            last(last)
+            last(last),
+            timeout(timeout)
         {
             // No-op.
         }
@@ -130,7 +135,7 @@ namespace ignite
             // No-op.
         }
 
-        void QueryExecuteBatchtRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryExecuteBatchtRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion& ver) const
         {
             writer.WriteInt8(RequestType::EXECUTE_SQL_QUERY_BATCH);
 
@@ -142,6 +147,9 @@ namespace ignite
             writer.WriteObject<std::string>(sql);
 
             params.Write(writer, begin, end, last);
+
+            if (ver >= ProtocolVersion::VERSION_2_3_2)
+                writer.WriteInt32(timeout);
         }
 
         QueryCloseRequest::QueryCloseRequest(int64_t queryId): queryId(queryId)
@@ -154,7 +162,7 @@ namespace ignite
             // No-op.
         }
 
-        void QueryCloseRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryCloseRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::CLOSE_SQL_QUERY);
             writer.WriteInt64(queryId);
@@ -172,7 +180,7 @@ namespace ignite
             // No-op.
         }
 
-        void QueryFetchRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryFetchRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::FETCH_SQL_QUERY);
 
@@ -194,7 +202,7 @@ namespace ignite
             // No-op.
         }
 
-        void QueryGetColumnsMetaRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryGetColumnsMetaRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::GET_COLUMNS_METADATA);
 
@@ -218,7 +226,7 @@ namespace ignite
             // No-op.
         }
 
-        void QueryGetTablesMetaRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryGetTablesMetaRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::GET_TABLES_METADATA);
 
@@ -228,7 +236,7 @@ namespace ignite
             writer.WriteObject<std::string>(tableTypes);
         }
 
-        void QueryGetParamsMetaRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryGetParamsMetaRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::GET_PARAMS_METADATA);
 
@@ -236,7 +244,7 @@ namespace ignite
             writer.WriteObject<std::string>(sqlQuery);
         }
 
-        void QueryMoreResultsRequest::Write(impl::binary::BinaryWriterImpl& writer) const
+        void QueryMoreResultsRequest::Write(impl::binary::BinaryWriterImpl& writer, const ProtocolVersion&) const
         {
             writer.WriteInt8(RequestType::QUERY_MORE_RESULTS);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/src/query/batch_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/batch_query.cpp b/modules/platforms/cpp/odbc/src/query/batch_query.cpp
index 29d11ca..07d42d4 100644
--- a/modules/platforms/cpp/odbc/src/query/batch_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/batch_query.cpp
@@ -27,8 +27,8 @@ namespace ignite
     {
         namespace query
         {
-            BatchQuery::BatchQuery(diagnostic::Diagnosable& diag, Connection& connection,
-                const std::string& sql, const app::ParameterSet& params) :
+            BatchQuery::BatchQuery(diagnostic::Diagnosable& diag, Connection& connection, const std::string& sql,
+                const app::ParameterSet& params, int32_t& timeout) :
                 Query(diag, QueryType::BATCH),
                 connection(connection),
                 sql(sql),
@@ -36,7 +36,8 @@ namespace ignite
                 resultMeta(),
                 rowsAffected(),
                 rowsAffectedIdx(0),
-                executed(false)
+                executed(false),
+                timeout(timeout)
             {
                 // No-op.
             }
@@ -147,7 +148,7 @@ namespace ignite
             {
                 const std::string& schema = connection.GetSchema();
 
-                QueryExecuteBatchtRequest req(schema, sql, params, begin, end, last);
+                QueryExecuteBatchtRequest req(schema, sql, params, begin, end, last, timeout);
                 QueryExecuteBatchResponse rsp;
 
                 try

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/src/query/data_query.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/query/data_query.cpp b/modules/platforms/cpp/odbc/src/query/data_query.cpp
index 012b026..0539af5 100644
--- a/modules/platforms/cpp/odbc/src/query/data_query.cpp
+++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp
@@ -28,8 +28,8 @@ namespace ignite
     {
         namespace query
         {
-            DataQuery::DataQuery(diagnostic::Diagnosable& diag, Connection& connection,
-                const std::string& sql, const app::ParameterSet& params) :
+            DataQuery::DataQuery(diagnostic::Diagnosable& diag, Connection& connection, const std::string& sql,
+                const app::ParameterSet& params, int32_t& timeout) :
                 Query(diag, QueryType::DATA),
                 connection(connection),
                 sql(sql),
@@ -38,7 +38,8 @@ namespace ignite
                 cursor(),
                 rowsAffected(),
                 rowsAffectedIdx(0),
-                cachedNextPage()
+                cachedNextPage(),
+                timeout(timeout)
             {
                 // No-op.
             }
@@ -216,7 +217,7 @@ namespace ignite
             {
                 const std::string& schema = connection.GetSchema();
 
-                QueryExecuteRequest req(schema, sql, params);
+                QueryExecuteRequest req(schema, sql, params, timeout);
                 QueryExecuteResponse rsp;
 
                 try

http://git-wip-us.apache.org/repos/asf/ignite/blob/8c278ca9/modules/platforms/cpp/odbc/src/statement.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/statement.cpp b/modules/platforms/cpp/odbc/src/statement.cpp
index b167d44..898d44d 100644
--- a/modules/platforms/cpp/odbc/src/statement.cpp
+++ b/modules/platforms/cpp/odbc/src/statement.cpp
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+#include <limits>
+
 #include "ignite/odbc/system/odbc_constants.h"
 #include "ignite/odbc/query/batch_query.h"
 #include "ignite/odbc/query/data_query.h"
@@ -42,7 +44,8 @@ namespace ignite
             rowsFetched(0),
             rowStatuses(0),
             columnBindOffset(0),
-            parameters()
+            parameters(),
+            timeout(0)
         {
             // No-op.
         }
@@ -282,6 +285,29 @@ namespace ignite
                     break;
                 }
 
+                case SQL_ATTR_QUERY_TIMEOUT:
+                {
+                    SqlUlen uTimeout = reinterpret_cast<SqlUlen>(value);
+
+                    if (uTimeout > INT32_MAX)
+                    {
+                        timeout = INT32_MAX;
+
+                        std::stringstream ss;
+
+                        ss << "Value is too big: " << uTimeout << ", changing to " << timeout << ".";
+                        std::string msg = ss.str();
+
+                        AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, msg);
+
+                        return SqlResult::AI_SUCCESS_WITH_INFO;
+                    }
+
+                    timeout = static_cast<int32_t>(uTimeout);
+
+                    break;
+                }
+
                 default:
                 {
                     AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
@@ -409,6 +435,15 @@ namespace ignite
                     break;
                 }
 
+                case SQL_ATTR_QUERY_TIMEOUT:
+                {
+                    SqlUlen *uTimeout = reinterpret_cast<SqlUlen*>(buf);
+
+                    *uTimeout = static_cast<SqlUlen>(timeout);
+
+                    break;
+                }
+
                 default:
                 {
                     AddStatusRecord(SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED,
@@ -496,7 +531,7 @@ namespace ignite
             // Resetting parameters types as we are changing the query.
             parameters.Prepare();
 
-            currentQuery.reset(new query::DataQuery(*this, connection, query, parameters));
+            currentQuery.reset(new query::DataQuery(*this, connection, query, parameters, timeout));
 
             return SqlResult::AI_SUCCESS;
         }
@@ -534,13 +569,13 @@ namespace ignite
             {
                 query::DataQuery& qry = static_cast<query::DataQuery&>(*currentQuery);
 
-                currentQuery.reset(new query::BatchQuery(*this, connection, qry.GetSql(), parameters));
+                currentQuery.reset(new query::BatchQuery(*this, connection, qry.GetSql(), parameters, timeout));
             }
             else if (parameters.GetParamSetSize() == 1 && currentQuery->GetType() == query::QueryType::BATCH)
             {
                 query::BatchQuery& qry = static_cast<query::BatchQuery&>(*currentQuery);
 
-                currentQuery.reset(new query::DataQuery(*this, connection, qry.GetSql(), parameters));
+                currentQuery.reset(new query::DataQuery(*this, connection, qry.GetSql(), parameters, timeout));
             }
 
             if (parameters.IsDataAtExecNeeded())


[43/47] ignite git commit: IGNITE-6416: SQL: dynamic columns tests refactoring. This closes #2774.

Posted by sb...@apache.org.
IGNITE-6416: SQL: dynamic columns tests refactoring. This closes #2774.


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

Branch: refs/heads/ignite-zk
Commit: 43aa4a8938bae9c77921764826ceb9e10c59404b
Parents: 9a0e36b
Author: devozerov <vo...@gridgain.com>
Authored: Mon Nov 20 11:02:09 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Nov 20 11:02:09 2017 +0300

----------------------------------------------------------------------
 ...ynamicColumnsAbstractConcurrentSelfTest.java |  25 +--
 .../cache/index/DynamicColumnsAbstractTest.java | 180 ++++---------------
 .../H2DynamicColumnsAbstractBasicSelfTest.java  |  35 ++--
 3 files changed, 66 insertions(+), 174 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/43aa4a89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java
index 3d4b2a3..0263f5c 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractConcurrentSelfTest.java
@@ -149,7 +149,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
         // Start servers.
         Ignite srv1 = ignitionStart(serverConfiguration(1), null);
         Ignite srv2 = ignitionStart(serverConfiguration(2), null);
-        ignitionStart(serverConfiguration(3, true), finishLatch);
+        Ignite srv3 = ignitionStart(serverConfiguration(3, true), finishLatch);
 
         UUID srv1Id = srv1.cluster().localNode().id();
         UUID srv2Id = srv2.cluster().localNode().id();
@@ -175,7 +175,8 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
 
         colFut1.get();
 
-        checkNodesState(TBL_NAME, c("age", Integer.class.getName()));
+        // Port number is for srv2.
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, 10801, c("age", Integer.class.getName()));
 
         // Test migration from normal server to non-affinity server.
         idxLatch = blockIndexing(srv2Id);
@@ -191,7 +192,11 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
 
         colFut2.get();
 
-        checkNodesState(TBL_NAME, c("city", String.class.getName()));
+        // Let's actually create cache on non affinity server.
+        srv3.cache(QueryUtils.createTableCacheName(QueryUtils.DFLT_SCHEMA, "PERSON"));
+
+        // Port number is for srv3.
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, 10802, c("city", String.class.getName()));
     }
 
     /**
@@ -239,7 +244,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
 
         U.await(finishLatch);
 
-        checkNodesState(TBL_NAME, c1, c2);
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, c1, c2);
     }
 
     /**
@@ -276,7 +281,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
 
         U.await(finishLatch);
 
-        checkNodesState(TBL_NAME, c);
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, c);
     }
 
     /**
@@ -335,7 +340,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
         finishLatch.await();
 
         // Make sure new column is there.
-        checkNodesState(TBL_NAME, c("v", Integer.class.getName()));
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, c("v", Integer.class.getName()));
 
         run(srv1, "update person set \"v\" = case when mod(id, 2) <> 0 then substring(name, 7, length(name) - 6) " +
             "else null end");
@@ -429,7 +434,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
         CountDownLatch idxLatch1 = blockIndexing(srv1);
         CountDownLatch idxLatch2 = blockIndexing(srv2);
 
-        QueryField c = c("salary", Float.class.getName());
+        QueryField c = c("salary", Double.class.getName());
 
         final IgniteInternalFuture<?> idxFut = addCols(srv1, QueryUtils.DFLT_SCHEMA, c);
 
@@ -449,7 +454,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
         // Validate index state.
         idxFut.get();
 
-        checkNodesState(TBL_NAME, c);
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, c);
     }
 
     /**
@@ -655,7 +660,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
             }
         });
 
-        checkNodeState((IgniteEx)cli, schemaName, TBL_NAME, cols);
+        checkTableState(schemaName, TBL_NAME, cols);
     }
 
     /**
@@ -844,7 +849,7 @@ public abstract class DynamicColumnsAbstractConcurrentSelfTest extends DynamicCo
 
         idxQry += ')';
 
-        checkNodesState(TBL_NAME, expCols);
+        checkTableState(QueryUtils.DFLT_SCHEMA, TBL_NAME, expCols);
 
         put(cli, 0, 500);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/43aa4a89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
index 2beea8b..34be76e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
@@ -17,41 +17,34 @@
 
 package org.apache.ignite.internal.processors.cache.index;
 
-import java.util.Arrays;
-import java.util.Collection;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.Callable;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
-import org.apache.ignite.Ignition;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.query.SqlFieldsQuery;
 import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ClientConnectorConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.DataRegionConfiguration;
 import org.apache.ignite.internal.IgniteEx;
-import org.apache.ignite.internal.processors.cache.DynamicCacheDescriptor;
-import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
 import org.apache.ignite.internal.processors.query.IgniteSQLException;
 import org.apache.ignite.internal.processors.query.QueryField;
-import org.apache.ignite.internal.processors.query.QuerySchema;
 import org.apache.ignite.internal.processors.query.QueryUtils;
-import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
-import org.apache.ignite.internal.util.typedef.F;
 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.h2.table.Column;
 import org.h2.value.DataType;
 
 /**
@@ -68,158 +61,61 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
     private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
 
     /**
-     * Check that given columns have been added to all related structures on target node exactly where needed
-     *    (namely, schema in cache descriptor, type descriptor on started cache, and H2 state on started cache).
-     * @param node Target node.
+     * Check that given columns are seen by client.
      * @param schemaName Schema name to look for the table in.
      * @param tblName Table name to check.
      * @param cols Columns whose presence must be checked.
      */
-    static void checkNodeState(IgniteEx node, String schemaName, String tblName, QueryField... cols) {
-        String cacheName = F.eq(schemaName, QueryUtils.DFLT_SCHEMA) ?
-            QueryUtils.createTableCacheName(schemaName, tblName) : schemaName;
-
-        // Schema state check - should pass regardless of cache state.
-        {
-            DynamicCacheDescriptor desc = node.context().cache().cacheDescriptor(cacheName);
-
-            assertNotNull("Cache descriptor not found", desc);
-
-            assertTrue(desc.sql() == F.eq(schemaName, QueryUtils.DFLT_SCHEMA));
-
-            QuerySchema schema = desc.schema();
-
-            assertNotNull(schema);
-
-            QueryEntity entity = null;
-
-            for (QueryEntity e : schema.entities()) {
-                if (F.eq(tblName, e.getTableName())) {
-                    entity = e;
-
-                    break;
-                }
-            }
-
-            assertNotNull("Query entity not found", entity);
-
-            Iterator<Map.Entry<String, String>> it = entity.getFields().entrySet().iterator();
-
-            for (int i = entity.getFields().size() - cols.length; i > 0 && it.hasNext(); i--)
-                it.next();
-
-            for (QueryField col : cols) {
-                assertTrue("New column not found in query entity: " + col.name(), it.hasNext());
-
-                Map.Entry<String, String> e = it.next();
-
-                assertEquals(col.name(), e.getKey());
-
-                assertEquals(col.typeName(), e.getValue());
-
-                if (!col.isNullable()) {
-                    assertNotNull(entity.getNotNullFields());
+    static void checkTableState(String schemaName, String tblName, QueryField... cols) throws SQLException {
+        checkTableState(schemaName, tblName, ClientConnectorConfiguration.DFLT_PORT, cols);
+    }
 
-                    assertTrue(entity.getNotNullFields().contains(col.name()));
-                }
-                else if (entity.getNotNullFields() != null)
-                    assertFalse(entity.getNotNullFields().contains(col.name()));
-            }
-        }
+    /**
+     * Check that given columns are seen by client.
+     * @param schemaName Schema name to look for the table in.
+     * @param tblName Table name to check.
+     * @param port Port number.
+     * @param cols Columns whose presence must be checked.
+     */
+    static void checkTableState(String schemaName, String tblName, int port, QueryField... cols) throws SQLException {
+        List<QueryField> flds = new ArrayList<>();
 
-        // Start cache on this node if we haven't yet.
-        node.cache(cacheName);
+        try (Connection c = DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:" + port)) {
+            try (ResultSet rs = c.getMetaData().getColumns(null, schemaName, tblName, "%")) {
+                while (rs.next()) {
+                    String name = rs.getString("COLUMN_NAME");
 
-        // Type descriptor state check.
-        {
-            Collection<GridQueryTypeDescriptor> descs = node.context().query().types(cacheName);
+                    short type = rs.getShort("DATA_TYPE");
 
-            GridQueryTypeDescriptor desc = null;
+                    String typeClsName = DataType.getTypeClassName(DataType.convertSQLTypeToValueType(type));
 
-            for (GridQueryTypeDescriptor d : descs) {
-                if (F.eq(tblName, d.tableName())) {
-                    desc = d;
+                    short nullable = rs.getShort("NULLABLE");
 
-                    break;
+                    flds.add(new QueryField(name, typeClsName, nullable == 1));
                 }
             }
-
-            assertNotNull("Type descriptor not found", desc);
-
-            Iterator<Map.Entry<String, Class<?>>> it = desc.fields().entrySet().iterator();
-
-            for (int i = desc.fields().size() - cols.length; i > 0 && it.hasNext(); i--)
-                it.next();
-
-            for (QueryField col : cols) {
-                assertTrue("New column not found in type descriptor: " + col.name(), it.hasNext());
-
-                Map.Entry<String, Class<?>> e = it.next();
-
-                assertEquals(col.name(), e.getKey());
-
-                assertEquals(col.typeName(), e.getValue().getName());
-
-                assertTrue(col.isNullable() || desc.property(col.name()).notNull());
-            }
         }
 
-        // H2 table state check.
-        {
-            GridH2Table tbl = ((IgniteH2Indexing)node.context().query().getIndexing()).dataTable(schemaName,
-                tblName);
-
-            assertNotNull("Table not found", tbl);
-
-            Iterator<Column> colIt = Arrays.asList(tbl.getColumns()).iterator();
-
-            GridH2RowDescriptor rowDesc = tbl.rowDescriptor();
-
-            int i = 0;
+        Iterator<QueryField> it = flds.iterator();
 
-            for (; i < tbl.getColumns().length - cols.length && colIt.hasNext(); i++)
-                colIt.next();
+        for (int i = flds.size() - cols.length; i > 0 && it.hasNext(); i--)
+            it.next();
 
-            for (QueryField col : cols) {
-                assertTrue("New column not found in H2 table: " + col.name(), colIt.hasNext());
+        for (QueryField exp : cols) {
+            assertTrue("New column not found in metadata: " + exp.name(), it.hasNext());
 
-                assertTrue(colIt.hasNext());
+            QueryField act = it.next();
 
-                Column c = colIt.next();
+            assertEquals(exp.name(), act.name());
 
-                assertEquals(col.name(), c.getName());
+            assertEquals(exp.typeName(), act.typeName());
 
-                assertEquals(col.typeName(), DataType.getTypeClassName(c.getType()));
-
-                assertFalse(rowDesc.isKeyValueOrVersionColumn(i));
-
-                assertEquals(col.isNullable(), c.isNullable());
-
-                try {
-                    assertEquals(DataType.getTypeFromClass(Class.forName(col.typeName())),
-                        rowDesc.fieldType(i - GridH2KeyValueRowOnheap.DEFAULT_COLUMNS_COUNT));
-                }
-                catch (ClassNotFoundException e) {
-                    throw new AssertionError(e);
-                }
-
-                i++;
-            }
+            // TODO uncomment after IGNITE-6529 is implemented.
+            //assertEquals(exp.isNullable(), act.isNullable());
         }
     }
 
     /**
-     * Check that given columns have been added to all related structures on all started nodes (namely, schema
-     *     in cache descriptor, type descriptor on started cache, and H2 state on started cache).
-     * @param tblName Table name to check.
-     * @param cols Columns whose presence must be checked.
-     */
-    static void checkNodesState(String tblName, QueryField... cols) {
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, tblName, cols);
-    }
-
-    /**
      * @param name New column name.
      * @param typeName Class name for this new column's data type.
      * @return New column with given name and type.

http://git-wip-us.apache.org/repos/asf/ignite/blob/43aa4a89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
index b9f8c61..e4681ae 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicColumnsAbstractBasicSelfTest.java
@@ -17,17 +17,16 @@
 
 package org.apache.ignite.internal.processors.cache.index;
 
+import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.Ignition;
 import org.apache.ignite.binary.BinaryObject;
 import org.apache.ignite.cache.query.annotations.QuerySqlField;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.processors.query.QueryField;
 import org.apache.ignite.internal.processors.query.QueryUtils;
 import org.apache.ignite.testframework.config.GridTestProperties;
@@ -97,29 +96,25 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum
     /**
      * Test column addition to the end of the columns list.
      */
-    public void testAddColumnSimple() {
+    public void testAddColumnSimple() throws SQLException {
         run("ALTER TABLE Person ADD COLUMN age int");
 
         doSleep(500);
 
         QueryField c = c("AGE", Integer.class.getName());
 
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, "PERSON", c);
+        checkTableState(QueryUtils.DFLT_SCHEMA, "PERSON", c);
     }
 
     /**
      * Test column addition to the end of the columns list.
      */
-    public void testAddFewColumnsSimple() {
+    public void testAddFewColumnsSimple() throws SQLException {
         run("ALTER TABLE Person ADD COLUMN (age int, \"city\" varchar)");
 
         doSleep(500);
 
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, "PERSON",
-                c("AGE", Integer.class.getName()),
-                c("city", String.class.getName()));
+        checkTableState(QueryUtils.DFLT_SCHEMA, "PERSON", c("AGE", Integer.class.getName()), c("city", String.class.getName()));
     }
 
     /**
@@ -217,22 +212,21 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum
     /**
      * Test that we can add columns dynamically to tables associated with non dynamic caches as well.
      */
-    public void testAddColumnToNonDynamicCache() {
+    public void testAddColumnToNonDynamicCache() throws SQLException {
         run("ALTER TABLE \"idx\".PERSON ADD COLUMN CITY varchar");
 
         doSleep(500);
 
         QueryField c = c("CITY", String.class.getName());
 
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, "idx", "PERSON", c);
+        checkTableState("idx", "PERSON", c);
     }
 
     /**
      * Test that we can add columns dynamically to tables associated with non dynamic caches storing user types as well.
      */
     @SuppressWarnings("unchecked")
-    public void testAddColumnToNonDynamicCacheWithRealValueType() {
+    public void testAddColumnToNonDynamicCacheWithRealValueType() throws SQLException {
         CacheConfiguration<Integer, City> ccfg = defaultCacheConfiguration().setName("City")
             .setIndexedTypes(Integer.class, City.class);
 
@@ -244,8 +238,7 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum
 
         QueryField c = c("POPULATION", Integer.class.getName());
 
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, "City", "CITY", c);
+        checkTableState("City", "CITY", c);
 
         run(cache, "INSERT INTO \"City\".City (_key, id, name, state, population) values " +
             "(1, 1, 'Washington', 'DC', 2500000)");
@@ -276,29 +269,27 @@ public abstract class H2DynamicColumnsAbstractBasicSelfTest extends DynamicColum
     /**
      * Test addition of column with not null constraint.
      */
-    public void testAddNotNullColumn() {
+    public void testAddNotNullColumn() throws SQLException {
         run("ALTER TABLE Person ADD COLUMN age int NOT NULL");
 
         doSleep(500);
 
         QueryField c = new QueryField("AGE", Integer.class.getName(), false);
 
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, "PERSON", c);
+        checkTableState(QueryUtils.DFLT_SCHEMA, "PERSON", c);
     }
 
     /**
      * Test addition of column explicitly defined as nullable.
      */
-    public void testAddNullColumn() {
+    public void testAddNullColumn() throws SQLException {
         run("ALTER TABLE Person ADD COLUMN age int NULL");
 
         doSleep(500);
 
         QueryField c = new QueryField("AGE", Integer.class.getName(), true);
 
-        for (Ignite node : Ignition.allGrids())
-            checkNodeState((IgniteEx)node, QueryUtils.DFLT_SCHEMA, "PERSON", c);
+        checkTableState(QueryUtils.DFLT_SCHEMA, "PERSON", c);
     }
 
     /**


[06/47] ignite git commit: IGNITE-6835 ODBC driver now handles ungraceful TCP disconnects This closes #2997

Posted by sb...@apache.org.
IGNITE-6835 ODBC driver now handles ungraceful TCP disconnects
This closes #2997


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

Branch: refs/heads/ignite-zk
Commit: 46c480b46cb6c86ebcc3a94659c689057f9e1464
Parents: 9303845
Author: Igor Sapego <is...@gridgain.com>
Authored: Tue Nov 14 15:48:02 2017 +0300
Committer: Igor Sapego <is...@gridgain.com>
Committed: Tue Nov 14 15:49:04 2017 +0300

----------------------------------------------------------------------
 .../include/ignite/odbc/system/socket_client.h  |  20 +-
 .../odbc/os/linux/src/system/socket_client.cpp  | 140 ++++++++++++-
 .../odbc/os/win/src/system/socket_client.cpp    | 194 ++++++++++++++++++-
 modules/platforms/cpp/odbc/src/connection.cpp   |   2 +-
 4 files changed, 341 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/46c480b4/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h b/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
index ee58927..946605e 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/system/socket_client.h
@@ -21,6 +21,7 @@
 #include <stdint.h>
 
 #include "ignite/common/common.h"
+#include "ignite/odbc/diagnostic/diagnosable.h"
 
 namespace ignite
 {
@@ -34,6 +35,15 @@ namespace ignite
             class SocketClient
             {
             public:
+                /** Buffers size */
+                enum { BUFFER_SIZE = 0x10000 };
+
+                /** The time in seconds the connection needs to remain idle before starts sending keepalive probes. */
+                enum { KEEP_ALIVE_IDLE_TIME = 60 };
+
+                /** The time in seconds between individual keepalive probes. */
+                enum { KEEP_ALIVE_PROBES_PERIOD = 1 };
+
                 /**
                  * Constructor.
                  */
@@ -49,9 +59,10 @@ namespace ignite
                  *
                  * @param hostname Remote host name.
                  * @param port TCP service port.
+                 * @param diag Diagnostics collector.
                  * @return True on success.
                  */
-                bool Connect(const char* hostname, uint16_t port);
+                bool Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag);
 
                 /**
                  * Close established connection.
@@ -73,7 +84,7 @@ namespace ignite
                 /**
                  * Receive data from established connection.
                  *
-                 * @param data Pointer to data buffer.
+                 * @param buffer Pointer to data buffer.
                  * @param size Size of the buffer in bytes.
                  * @return Number of bytes that have been received on success and negative
                  *         value on failure.
@@ -81,6 +92,11 @@ namespace ignite
                 int Receive(int8_t* buffer, size_t size);
 
             private:
+                /**
+                 * Tries set socket options.
+                 */
+                void TrySetOptions(diagnostic::Diagnosable& diag);
+
                 intptr_t socketHandle;
 
                 IGNITE_NO_COPY_ASSIGNMENT(SocketClient)

http://git-wip-us.apache.org/repos/asf/ignite/blob/46c480b4/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp b/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
index 9bdf1d7..5a9b03a 100644
--- a/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
+++ b/modules/platforms/cpp/odbc/os/linux/src/system/socket_client.cpp
@@ -17,7 +17,7 @@
 
 #include <sys/socket.h>
 #include <sys/types.h>
-#include <sys/socket.h>
+#include <netinet/tcp.h>
 #include <netdb.h>
 #include <unistd.h>
 
@@ -31,6 +31,32 @@
 
 #define SOCKET_ERROR (-1)
 
+namespace
+{
+    /**
+     * Get last socket error message.
+     * @return Last socket error message string.
+     */
+    std::string GetLastSocketErrorMessage()
+    {
+        int lastError = errno;
+        std::stringstream res;
+
+        res << "error_code=" << lastError;
+
+        if (lastError == 0)
+            return res.str();
+
+        char buffer[1024] = "";
+
+        strerror_r(lastError, buffer, sizeof(buffer));
+
+        res << ", msg=" << buffer;
+
+        return res.str();
+    }
+}
+
 namespace ignite
 {
     namespace odbc
@@ -48,11 +74,12 @@ namespace ignite
                 Close();
             }
 
-            bool SocketClient::Connect(const char* hostname, uint16_t port)
+            bool SocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag)
             {
                 LOG_MSG("Host: " << hostname << ", port: " << port);
 
                 addrinfo hints;
+
                 memset(&hints, 0, sizeof(hints));
                 hints.ai_family = AF_UNSPEC;
                 hints.ai_socktype = SOCK_STREAM;
@@ -66,26 +93,44 @@ namespace ignite
                 int res = getaddrinfo(hostname, converter.str().c_str(), &hints, &result);
 
                 if (res != 0)
+                {
+                    LOG_MSG("Address resolving failed: " << gai_strerror(res));
+
+                    diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not resolve host address.");
+
                     return false;
+                }
 
                 // Attempt to connect to an address until one succeeds
-                for (addrinfo *it = result; it != NULL; it = it->ai_next) 
+                for (addrinfo *it = result; it != NULL; it = it->ai_next)
                 {
-                    LOG_MSG("Addr: " << it->ai_addr->sa_data[2] << "."
-                                     << it->ai_addr->sa_data[3] << "."
-                                     << it->ai_addr->sa_data[4] << "."
-                                     << it->ai_addr->sa_data[5]);
+                    LOG_MSG("Addr: " << (it->ai_addr->sa_data[2] & 0xFF) << "."
+                                     << (it->ai_addr->sa_data[3] & 0xFF) << "."
+                                     << (it->ai_addr->sa_data[4] & 0xFF) << "."
+                                     << (it->ai_addr->sa_data[5] & 0xFF));
 
                     // Create a SOCKET for connecting to server
                     socketHandle = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
 
                     if (socketHandle == SOCKET_ERROR)
+                    {
+                        LOG_MSG("Socket creation failed: " << GetLastSocketErrorMessage());
+
+                        diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create new socket.");
+
                         return false;
+                    }
+
+                    diag.GetDiagnosticRecords().Reset();
+
+                    TrySetOptions(diag);
 
                     // Connect to server.
-                    res = connect(socketHandle, it->ai_addr, (int)it->ai_addrlen);
-                    if (res == SOCKET_ERROR) 
+                    res = connect(socketHandle, it->ai_addr, static_cast<int>(it->ai_addrlen));
+                    if (SOCKET_ERROR == res)
                     {
+                        LOG_MSG("Connection failed: " << GetLastSocketErrorMessage());
+
                         Close();
 
                         continue;
@@ -117,6 +162,83 @@ namespace ignite
             {
                 return recv(socketHandle, reinterpret_cast<char*>(buffer), static_cast<int>(size), 0);
             }
+
+            void SocketClient::TrySetOptions(diagnostic::Diagnosable& diag)
+            {
+                int trueOpt = 1;
+                int bufSizeOpt = BUFFER_SIZE;
+                int idleOpt = KEEP_ALIVE_IDLE_TIME;
+                int idleRetryOpt = KEEP_ALIVE_PROBES_PERIOD;
+
+                int res = setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF,
+                    reinterpret_cast<char*>(&bufSizeOpt), sizeof(bufSizeOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP socket send buffer size setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP socket send buffer size");
+                }
+
+                res = setsockopt(socketHandle, SOL_SOCKET, SO_RCVBUF,
+                    reinterpret_cast<char*>(&bufSizeOpt), sizeof(bufSizeOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP socket receive buffer size setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP socket receive buffer size");
+                }
+
+                res = setsockopt(socketHandle, IPPROTO_TCP, TCP_NODELAY,
+                    reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP no-delay mode setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP no-delay mode");
+                }
+
+                res = setsockopt(socketHandle, SOL_SOCKET, SO_KEEPALIVE,
+                    reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive mode setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive mode");
+
+                    // There is no sense in configuring keep alive params if we faileed to set up keep alive mode.
+                    return;
+                }
+
+                res = setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPIDLE,
+                    reinterpret_cast<char*>(&idleOpt), sizeof(idleOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive idle timeout setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive idle timeout");
+                }
+
+                res = setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPINTVL,
+                    reinterpret_cast<char*>(&idleRetryOpt), sizeof(idleRetryOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive probes period setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive probes period");
+                }
+            }
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/46c480b4/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp b/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
index 4c440e2..30fb7d7 100644
--- a/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
+++ b/modules/platforms/cpp/odbc/os/win/src/system/socket_client.cpp
@@ -21,6 +21,7 @@
 #include <windows.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
+#include <mstcpip.h>
 
 #include <cstring>
 
@@ -30,6 +31,54 @@
 #include "ignite/odbc/utility.h"
 #include "ignite/odbc/log.h"
 
+namespace
+{
+    /**
+     * Get last socket error message.
+     * @return Last socket error message string.
+     */
+    std::string GetLastSocketErrorMessage()
+    {
+        HRESULT lastError = WSAGetLastError();
+        std::stringstream res;
+
+        res << "error_code=" << lastError;
+
+        if (lastError == 0)
+            return res.str();
+
+        LPTSTR errorText = NULL;
+
+        DWORD len = FormatMessage(
+            // use system message tables to retrieve error text
+            FORMAT_MESSAGE_FROM_SYSTEM
+            // allocate buffer on local heap for error text
+            | FORMAT_MESSAGE_ALLOCATE_BUFFER
+            // We're not passing insertion parameters
+            | FORMAT_MESSAGE_IGNORE_INSERTS,
+            // unused with FORMAT_MESSAGE_FROM_SYSTEM
+            NULL,
+            lastError,
+            MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+            // output
+            reinterpret_cast<LPTSTR>(&errorText),
+            // minimum size for output buffer
+            0,
+            // arguments - see note
+            NULL);
+
+        if (NULL != errorText)
+        {
+            if (len != 0)
+                res << ", msg=" << std::string(errorText, len);
+
+            LocalFree(errorText);
+        }
+
+        return res.str();
+    }
+}
+
 namespace ignite
 {
     namespace odbc
@@ -47,7 +96,7 @@ namespace ignite
                 Close();
             }
 
-            bool SocketClient::Connect(const char* hostname, uint16_t port)
+            bool SocketClient::Connect(const char* hostname, uint16_t port, diagnostic::Diagnosable& diag)
             {
                 static bool networkInited = false;
 
@@ -59,10 +108,15 @@ namespace ignite
                     networkInited = (WSAStartup(MAKEWORD(2, 2), &wsaData) == 0);
 
                     if (!networkInited)
+                    {
+                        LOG_MSG("Networking initialisation failed: " << GetLastSocketErrorMessage());
+
+                        diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not initialize Windows networking.");
+
                         return false;
+                    }
                 }
 
-                addrinfo *result = NULL;
                 addrinfo hints;
 
                 LOG_MSG("Host: " << hostname << " port: " << port);
@@ -76,10 +130,17 @@ namespace ignite
                 converter << port;
 
                 // Resolve the server address and port
+                addrinfo *result = NULL;
                 int res = getaddrinfo(hostname, converter.str().c_str(), &hints, &result);
 
                 if (res != 0)
+                {
+                    LOG_MSG("Address resolving failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not resolve host address.");
+
                     return false;
+                }
 
                 // Attempt to connect to an address until one succeeds
                 for (addrinfo *it = result; it != NULL; it = it->ai_next)
@@ -93,12 +154,24 @@ namespace ignite
                     socketHandle = socket(it->ai_family, it->ai_socktype, it->ai_protocol);
 
                     if (socketHandle == INVALID_SOCKET)
+                    {
+                        LOG_MSG("Socket creation failed: " << GetLastSocketErrorMessage());
+
+                        diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, "Can not create new socket.");
+
                         return false;
+                    }
+
+                    diag.GetDiagnosticRecords().Reset();
+
+                    TrySetOptions(diag);
 
                     // Connect to server.
                     res = connect(socketHandle, it->ai_addr, static_cast<int>(it->ai_addrlen));
-                    if (res == SOCKET_ERROR)
+                    if (SOCKET_ERROR == res)
                     {
+                        LOG_MSG("Connection failed: " << GetLastSocketErrorMessage());
+
                         Close();
 
                         continue;
@@ -130,6 +203,121 @@ namespace ignite
             {
                 return recv(socketHandle, reinterpret_cast<char*>(buffer), static_cast<int>(size), 0);
             }
+
+            void SocketClient::TrySetOptions(diagnostic::Diagnosable& diag)
+            {
+                BOOL trueOpt = TRUE;
+                int bufSizeOpt = BUFFER_SIZE;
+
+                int res = setsockopt(socketHandle, SOL_SOCKET, SO_SNDBUF,
+                    reinterpret_cast<char*>(&bufSizeOpt), sizeof(bufSizeOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP socket send buffer size setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP socket send buffer size");
+                }
+
+                res = setsockopt(socketHandle, SOL_SOCKET, SO_RCVBUF,
+                    reinterpret_cast<char*>(&bufSizeOpt), sizeof(bufSizeOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP socket receive buffer size setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP socket receive buffer size");
+                }
+
+                res = setsockopt(socketHandle, IPPROTO_TCP, TCP_NODELAY,
+                    reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP no-delay mode setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP no-delay mode");
+                }
+
+                res = setsockopt(socketHandle, SOL_SOCKET, SO_KEEPALIVE,
+                    reinterpret_cast<char*>(&trueOpt), sizeof(trueOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive mode setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive mode");
+
+                    // There is no sense in configuring keep alive params if we faileed to set up keep alive mode.
+                    return;
+                }
+
+                // This option is available starting with Windows 10, version 1709.
+#if defined(TCP_KEEPIDLE) && defined(TCP_KEEPINTVL)
+                DWORD idleOpt = KEEP_ALIVE_IDLE_TIME;
+                DWORD idleRetryOpt = KEEP_ALIVE_PROBES_PERIOD;
+
+                res = setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPIDLE,
+                    reinterpret_cast<char*>(&idleOpt), sizeof(idleOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive idle timeout setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive idle timeout");
+                }
+
+                res = setsockopt(socketHandle, IPPROTO_TCP, TCP_KEEPINTVL,
+                    reinterpret_cast<char*>(&idleRetryOpt), sizeof(idleRetryOpt));
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive probes period setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive probes period");
+                }
+#else // use old hardcore WSAIoctl
+
+                // WinSock structure for KeepAlive timing settings
+                struct tcp_keepalive settings = {0};
+                settings.onoff = 1;
+                settings.keepalivetime = KEEP_ALIVE_IDLE_TIME * 1000;
+                settings.keepaliveinterval = KEEP_ALIVE_PROBES_PERIOD * 1000;
+
+                // pointers for WinSock call
+                DWORD bytesReturned;
+                WSAOVERLAPPED overlapped;
+                overlapped.hEvent = NULL;
+
+                // Set KeepAlive settings
+                res = WSAIoctl(
+                    socketHandle,
+                    SIO_KEEPALIVE_VALS,
+                    &settings,
+                    sizeof(struct tcp_keepalive),
+                    NULL,
+                    0,
+                    &bytesReturned,
+                    &overlapped,
+                    NULL
+                );
+
+                if (SOCKET_ERROR == res)
+                {
+                    LOG_MSG("TCP keep-alive params setup failed: " << GetLastSocketErrorMessage());
+
+                    diag.AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED,
+                        "Can not set up TCP keep-alive idle timeout and probes period");
+                }
+#endif
+            }
+
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/46c480b4/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index 8f4bf14..b99d768 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -126,7 +126,7 @@ namespace ignite
                 return SqlResult::AI_ERROR;
             }
 
-            connected = socket.Connect(cfg.GetHost().c_str(), cfg.GetTcpPort());
+            connected = socket.Connect(cfg.GetHost().c_str(), cfg.GetTcpPort(), *this);
 
             if (!connected)
             {


[37/47] ignite git commit: Merge remote-tracking branch 'origin/master'

Posted by sb...@apache.org.
Merge remote-tracking branch 'origin/master'


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

Branch: refs/heads/ignite-zk
Commit: 25048f8bc792c75f44076d1eaca192e10dc5e43d
Parents: 4f77ef2 dee8b40
Author: devozerov <vo...@gridgain.com>
Authored: Fri Nov 17 17:09:54 2017 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Fri Nov 17 17:09:54 2017 +0300

----------------------------------------------------------------------
 modules/platforms/dotnet/build.ps1 | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
----------------------------------------------------------------------



[02/47] ignite git commit: IGNITE-6795 WebConsole: Improved file name with query export results.

Posted by sb...@apache.org.
IGNITE-6795 WebConsole: Improved file name with query export results.


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

Branch: refs/heads/ignite-zk
Commit: 02ccc9f38cc4c30a21ce69dabff9be03168ccaab
Parents: 69acdaa
Author: Alexey Kuznetsov <ak...@apache.org>
Authored: Tue Nov 14 08:39:26 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Tue Nov 14 08:39:26 2017 +0700

----------------------------------------------------------------------
 .../frontend/app/modules/sql/sql.controller.js  | 39 +++++++++++++++++---
 1 file changed, 33 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/02ccc9f3/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index 332d4d2..8d27d30 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -212,6 +212,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
         $ctrl.cacheMetadataTemplateUrl = cacheMetadataTemplateUrl;
         $ctrl.chartSettingsTemplateUrl = chartSettingsTemplateUrl;
 
+        $ctrl.demoStarted = false;
+
         let stopTopology = null;
 
         const _tryStopRefresh = function(paragraph) {
@@ -836,7 +838,6 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
 
         /**
          * Update caches list.
-         * @private
          */
         const _refreshFn = () =>
             agentMgr.topology(true)
@@ -873,6 +874,15 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                         if (!_.includes(cacheNames, paragraph.cacheName))
                             paragraph.cacheName = _.head(cacheNames);
                     });
+
+                    // Await for demo caches.
+                    if (!$ctrl.demoStarted && $root.IgniteDemoMode && _.nonEmpty(cacheNames)) {
+                        $ctrl.demoStarted = true;
+
+                        Loading.finish('sqlLoading');
+
+                        _.forEach($scope.notebook.paragraphs, (paragraph) => $scope.execute(paragraph));
+                    }
                 })
                 .catch((err) => Messages.showError(err));
 
@@ -880,10 +890,11 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             agentMgr.startClusterWatch('Back to Configuration', 'base.configuration.tabs.advanced.clusters')
                 .then(() => Loading.start('sqlLoading'))
                 .then(_refreshFn)
-                .then(() => Loading.finish('sqlLoading'))
                 .then(() => {
-                    $root.IgniteDemoMode && _.forEach($scope.notebook.paragraphs, (paragraph) => $scope.execute(paragraph));
-
+                    if (!$root.IgniteDemoMode)
+                        Loading.finish('sqlLoading');
+                })
+                .then(() => {
                     stopTopology = $interval(_refreshFn, 5000, 0, false);
                 });
 
@@ -1626,8 +1637,24 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             LegacyUtils.download('application/octet-stream;charset=utf-8', fileName, escape(csvContent));
         };
 
+        /**
+         * Generate file name with query results.
+         *
+         * @param paragraph {Object} Query paragraph .
+         * @param all {Boolean} All result export flag.
+         * @returns {string}
+         */
+        const exportFileName = (paragraph, all) => {
+            const args = paragraph.queryArgs;
+
+            if (args.type === 'SCAN')
+                return `export-scan-${args.cacheName}-${paragraph.name}${all ? '-all' : ''}.csv`;
+
+            return `export-query-${paragraph.name}${all ? '-all' : ''}.csv`;
+        };
+
         $scope.exportCsv = function(paragraph) {
-            _export(paragraph.name + '.csv', paragraph.gridOptions.columnDefs, paragraph.meta, paragraph.rows);
+            _export(exportFileName(paragraph, false), paragraph.gridOptions.columnDefs, paragraph.meta, paragraph.rows);
 
             // paragraph.gridOptions.api.exporter.csvExport(uiGridExporterConstants.ALL, uiGridExporterConstants.VISIBLE);
         };
@@ -1643,7 +1670,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                 .then((nid) => args.type === 'SCAN'
                     ? agentMgr.queryScanGetAll(nid, args.cacheName, args.query, !!args.regEx, !!args.caseSensitive, !!args.near, !!args.localNid)
                     : agentMgr.querySqlGetAll(nid, args.cacheName, args.query, !!args.nonCollocatedJoins, !!args.enforceJoinOrder, false, !!args.localNid, !!args.lazy))
-                .then((res) => _export(paragraph.name + '-all.csv', paragraph.gridOptions.columnDefs, res.columns, res.rows))
+                .then((res) => _export(exportFileName(paragraph, true), paragraph.gridOptions.columnDefs, res.columns, res.rows))
                 .catch(Messages.showError)
                 .then(() => paragraph.ace && paragraph.ace.focus());
         };


[04/47] ignite git commit: .NET: Fix missing project file

Posted by sb...@apache.org.
.NET: Fix missing project file


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

Branch: refs/heads/ignite-zk
Commit: ec85cc05e625d32032d291c49311523d8cc6600e
Parents: e489e37
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Nov 14 13:47:29 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Nov 14 13:47:29 2017 +0300

----------------------------------------------------------------------
 .../dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ec85cc05/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index e7302bb..6c7e2b8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -94,6 +94,7 @@
     <Compile Include="Cache\Query\Linq\CacheLinqTest.CompiledQuery.cs" />
     <Compile Include="Cache\Query\Linq\CacheLinqTest.DateTime.cs" />
     <Compile Include="Cache\Query\Linq\CacheLinqTest.Aggregates.cs" />
+    <Compile Include="Cache\Query\Linq\CacheLinqTest.Join.cs" />
     <Compile Include="Cache\Query\Linq\CacheLinqTest.Join.LocalCollection.cs" />
     <Compile Include="Cache\Query\Linq\CacheLinqTest.Strings.cs" />
     <Compile Include="Cache\Query\Linq\CacheLinqTest.Functions.cs" />


[42/47] ignite git commit: IGNITE-6927 Added Web Console direct-install build. - Fixes #3058.

Posted by sb...@apache.org.
IGNITE-6927 Added Web Console direct-install build. - Fixes #3058.

Signed-off-by: Andrey Novikov <an...@gridgain.com>


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

Branch: refs/heads/ignite-zk
Commit: 9a0e36b23402785699c25a1b8a79574f0d943b8b
Parents: aca1ce3
Author: oleg-ostanin <oo...@gridgain.com>
Authored: Mon Nov 20 14:52:25 2017 +0700
Committer: Andrey Novikov <an...@gridgain.com>
Committed: Mon Nov 20 14:52:25 2017 +0700

----------------------------------------------------------------------
 modules/web-console/DEVNOTES.txt                |  20 ++--
 modules/web-console/assembly/README.txt         |  60 +++++++++++
 modules/web-console/assembly/direct-install.xml |  91 ++++++++++++++++
 modules/web-console/pom.xml                     | 103 ++++++++++++++++---
 4 files changed, 256 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/9a0e36b2/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index 4ff68a7..6dbb15a 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -2,13 +2,13 @@ Ignite Web Console Build Instructions
 =====================================
 1. Install locally MongoDB (version >=3.2.x) follow instructions from site http://docs.mongodb.org/manual/installation.
 2. Install locally NodeJS (version >=6.5.x) using installer from site https://nodejs.org/en/download/current for your OS.
-3. Change directory to '$IGNITE_HOME/modules/web-console/backend' and
+3. Change directory to '/modules/web-console/backend' and
  run "npm install --no-optional" for download backend dependencies.
-4. Change directory to '$IGNITE_HOME/modules/web-console/frontend' and
+4. Change directory to '/modules/web-console/frontend' and
  run "npm install --no-optional" for download frontend dependencies.
 5. Build ignite-web-agent module follow instructions from 'modules/web-console/web-agent/README.txt'.
-6. Copy ignite-web-agent-<version>.zip from '$IGNITE_HOME/modules/web-console/web-agent/target'
- to '$IGNITE_HOME/modules/web-console/backend/agent_dists' folder.
+6. Copy ignite-web-agent-<version>.zip from '/modules/web-console/web-agent/target'
+ to '/modules/web-console/backend/agent_dists' folder.
 
 Steps 1 - 4 should be executed once.
 
@@ -17,10 +17,10 @@ Ignite Web Console Run In Development Mode
 1. Configure MongoDB to run as service or in terminal change dir to $MONGO_INSTALL_DIR/server/3.2/bin
   and start MongoDB by executing "mongod".
 
-2. In new terminal change directory to '$IGNITE_HOME/modules/web-console/backend'.
+2. In new terminal change directory to '/modules/web-console/backend'.
    If needed run "npm install --no-optional" (if dependencies changed) and run "npm start" to start backend.
 
-3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/frontend'.
+3. In new terminal change directory to '/modules/web-console/frontend'.
   If needed run "npm install --no-optional" (if dependencies changed) and start webpack in development mode "npm run dev".
 
 4. In browser open: http://localhost:9000
@@ -30,3 +30,11 @@ How to migrate model:
 1. Model will be upgraded on first start.
 2. To downgrade model execute in terminal following command: "./node_modules/.bin/migrate down <migration-name> -d <dbConnectionUri>".
    Example: "./node_modules/.bin/migrate down add_index -d mongodb://localhost/console".
+
+
+Ignite Web Console Direct-Install Maven Build Instructions
+==========================================================
+To build direct-install archive from sources run following command in Ignite project root folder:
+"mvn clean package -pl :ignite-web-agent,:ignite-web-console -am -P web-console -DskipTests=true"
+
+Assembled archive can be found here: `/modules/web-console/target/ignite-web-console-direct-install-*.zip`.

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a0e36b2/modules/web-console/assembly/README.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/assembly/README.txt b/modules/web-console/assembly/README.txt
new file mode 100644
index 0000000..2b64a73
--- /dev/null
+++ b/modules/web-console/assembly/README.txt
@@ -0,0 +1,60 @@
+Requirements
+-------------------------------------
+1. JDK 7 bit for your platform, or newer.
+2. Supported browsers: Chrome, Firefox, Safari, Edge.
+3. Ignite cluster should be started with `ignite-rest-http` module in classpath. For this copy `ignite-rest-http` folder from `libs\optional` to `libs` folder.
+
+
+How to run
+-------------------------------------
+1. Unpack ignite-web-console-x.x.x.zip to some folder.
+2. Start ignite-web-console-xxx executable for you platform:
+	For Linux: ignite-web-console-linux
+	For MacOS: ignite-web-console-macos
+	For Windows: ignite-web-console-win.exe
+
+Note: on Linux and Mac OS X `root` permission is required to bind to 80 port, but you may always start Web Console on another port if you don't have such permission.
+
+3. Open URL `localhost` in browser.
+4. Login with user `admin@admin` and password `admin`.
+5. Start web agent from folder `web agent`. For Web Agent settings see `web-agent\README.txt`.
+Cluster URL should be specified in `web-agent\default.properties` in `node-uri` parameter.
+
+Technical details
+-------------------------------------
+1. Package content:
+	`libs` - this folder contains Web Console and MongoDB binaries.
+	`user_data` - this folder contains all Web Console data (registered users, created objects, ...) and should be preserved in case of update to new version.
+2. Package already contains MongoDB for Mac OS X, Windows, RHEL, CentOs and Ubuntu on other platforms MongoDB will be downloaded on first start. MongoDB executables will be downloaded to `libs\mogodb` folder.
+3. Web console will start on default HTTP port `80` and bind to all interfaces `0.0.0.0`.
+3. To bind Web Console to specific network interface:
+	On Linux: `./ignite-web-console-linux --server:host 192.168.0.1`
+	On Windows: `ignite-web-console-win.exe --server:host 192.168.0.1`
+4. To start Web Console on another port, for example `3000`:
+	On Linux: `sudo ./ignite-web-console-linux --server:port 3000`
+	On Windows: `ignite-web-console-win.exe --server:port 3000`
+
+All available parameters with defaults:
+	Web Console host:			--server:host 0.0.0.0
+	Web Console port:			--server:port 80
+	Enable HTTPS:				--server:ssl false
+	HTTPS key:					--server:key "serve/keys/test.key"
+	HTTPS cetificate:			--server:cert "serve/keys/test.crt"
+	HTTPS passphrase:			--server:keyPassphrase "password"
+	MongoDB URL:				--mongodb:url mongodb://localhost/console
+	Mail service:				--mail:service "gmail"
+	Signature text:				--mail:sign "Kind regards, Apache Ignite Team"
+	Greeting text:				--mail:greeting "Apache Ignite Web Console"
+	Mail FROM:					--mail:from "Apache Ignite Web Console <so...@somecompany.somedomain>"
+	User to send e-mail:		--mail:auth:user "someusername@somecompany.somedomain"
+	E-mail service password:	--mail:auth:pass ""
+
+Troubleshooting
+-------------------------------------
+1. On Windows check that MongoDB is not blocked by Antivirus/Firewall/Smartscreen.
+2. Root permission is required to bind to 80 port under Mac OS X and Linux, but you may always start Web Console on another port if you don't have such permission.
+3. For extended debug output start Web Console as following:
+	On Linux execute command in terminal: `DEBUG=mongodb-* ./ignite-web-console-linux`
+	On Windows execute two commands in terminal:
+		`SET DEBUG=mongodb-*`
+		`ignite-web-console-win.exe`

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a0e36b2/modules/web-console/assembly/direct-install.xml
----------------------------------------------------------------------
diff --git a/modules/web-console/assembly/direct-install.xml b/modules/web-console/assembly/direct-install.xml
new file mode 100644
index 0000000..d34cd07
--- /dev/null
+++ b/modules/web-console/assembly/direct-install.xml
@@ -0,0 +1,91 @@
+<?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.
+-->
+
+<assembly xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+    <id>release-ignite-web-agent</id>
+
+    <formats>
+        <format>zip</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <directory>${project.basedir}/target</directory>
+            <outputDirectory>/libs/agent_dists</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${project.basedir}/target</directory>
+            <outputDirectory>/libs/mongodb/mongodb-download</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${project.basedir}/target</directory>
+            <outputDirectory>/user_data</outputDirectory>
+            <excludes>
+                <exclude>**/*</exclude>
+            </excludes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/assembly</directory>
+            <outputDirectory>/</outputDirectory>
+            <includes>
+                <include>**/README*</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/backend/build</directory>
+            <outputDirectory>/</outputDirectory>
+            <includes>
+                <include>ignite-web-console-win.exe</include>
+            </includes>
+        </fileSet>
+        <fileSet>
+            <directory>${basedir}/backend/build</directory>
+            <outputDirectory>/</outputDirectory>
+            <fileMode>0755</fileMode>
+            <includes>
+                <include>ignite-web-console-*</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/web-agent/target</directory>
+            <outputDirectory>/libs/agent_dists</outputDirectory>
+            <includes>
+                <include>ignite-web-agent-${project.version}.zip</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <directory>${basedir}/frontend/build</directory>
+            <outputDirectory>/libs/frontend</outputDirectory>
+        </fileSet>
+    </fileSets>
+</assembly>

http://git-wip-us.apache.org/repos/asf/ignite/blob/9a0e36b2/modules/web-console/pom.xml
----------------------------------------------------------------------
diff --git a/modules/web-console/pom.xml b/modules/web-console/pom.xml
index 677b60a..f935ca6 100644
--- a/modules/web-console/pom.xml
+++ b/modules/web-console/pom.xml
@@ -34,49 +34,120 @@
     <version>2.3.0-SNAPSHOT</version>
     <url>http://ignite.apache.org</url>
 
+    <properties>
+        <node.version>v8.9.0</node.version>
+    </properties>
+
+    <dependencies>
+        <!-- Ignite dependencies -->
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-web-agent</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
     <build>
+        <pluginManagement>
+            <plugins>
+                 <plugin>
+                     <groupId>com.github.eirslett</groupId>
+                     <artifactId>frontend-maven-plugin</artifactId>
+                     <version>1.6</version>
+                     <configuration>
+                         <nodeVersion>${node.version}</nodeVersion>
+                         <installDirectory>target</installDirectory>
+                     </configuration>
+                 </plugin>
+            </plugins>
+        </pluginManagement>
+
         <plugins>
             <plugin>
                 <groupId>com.github.eirslett</groupId>
                 <artifactId>frontend-maven-plugin</artifactId>
-                <version>1.0</version>
-
-                <configuration>
-                    <workingDirectory>frontend</workingDirectory>
-                </configuration>
 
                 <executions>
                     <execution>
-                        <id>install node and npm</id>
+                        <id>install node and npm for frontend</id>
                         <goals>
                             <goal>install-node-and-npm</goal>
                         </goals>
+                    </execution>
+
+                    <execution>
+                        <id>download dependencies for frontend</id>
+                        <goals>
+                            <goal>npm</goal>
+                        </goals>
+
+                        <configuration>
+                            <workingDirectory>frontend</workingDirectory>
+                            <arguments>install --no-optional --prod</arguments>
+                        </configuration>
+                    </execution>
+
+                    <execution>
+                        <id>build frontend</id>
+                        <goals>
+                            <goal>npm</goal>
+                        </goals>
+
                         <configuration>
-                            <nodeVersion>v4.4.7</nodeVersion>
-                            <npmVersion>3.8.6</npmVersion>
                             <workingDirectory>frontend</workingDirectory>
+                            <arguments>run build</arguments>
+                            <environmentVariables>
+                                <NODE_ENV>production</NODE_ENV>
+                            </environmentVariables>
                         </configuration>
                     </execution>
 
                     <execution>
-                        <id>npm install</id>
+                        <id>download dependencies for backend</id>
                         <goals>
                             <goal>npm</goal>
                         </goals>
 
                         <configuration>
+                            <workingDirectory>backend</workingDirectory>
                             <arguments>install --no-optional</arguments>
                         </configuration>
                     </execution>
 
                     <execution>
-                        <id>gulp build</id>
+                        <id>build backend</id>
                         <goals>
-                            <goal>gulp</goal>
+                            <goal>npm</goal>
                         </goals>
 
                         <configuration>
-                            <arguments>build</arguments>
+                            <workingDirectory>backend</workingDirectory>
+                            <arguments>run build</arguments>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <version>2.4</version>
+                <inherited>false</inherited>
+
+                <executions>
+                    <execution>
+                        <id>release-web-agent</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>assembly/direct-install.xml</descriptor>
+                            </descriptors>
+                            <finalName>ignite-web-console-direct-install-${project.version}</finalName>
+                            <outputDirectory>target</outputDirectory>
+                            <appendAssemblyId>false</appendAssemblyId>
                         </configuration>
                     </execution>
                 </executions>
@@ -84,6 +155,14 @@
 
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-deploy-plugin</artifactId>
                 <configuration>
                     <skip>true</skip>


[38/47] ignite git commit: IGNITE-6337 .NET: Thin client: SQL queries

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
index a3b42b8..76c7b00 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/CacheClient.cs
@@ -37,7 +37,7 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
     /// <summary>
     /// Client cache implementation.
     /// </summary>
-    internal class CacheClient<TK, TV> : ICacheClient<TK, TV>
+    internal sealed class CacheClient<TK, TV> : ICacheClient<TK, TV>
     {
         /** Scan query filter platform code: .NET filter. */
         private const byte FilterPlatformDotnet = 2;
@@ -159,14 +159,39 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
         /** <inheritDoc /> */
         public IQueryCursor<ICacheEntry<TK, TV>> Query(ScanQuery<TK, TV> scanQuery)
         {
-            IgniteArgumentCheck.NotNull(scanQuery, "query");
+            IgniteArgumentCheck.NotNull(scanQuery, "scanQuery");
 
             // Filter is a binary object for all platforms.
             // For .NET it is a CacheEntryFilterHolder with a predefined id (BinaryTypeId.CacheEntryPredicateHolder).
             return DoOutInOp(ClientOp.QueryScan, w => WriteScanQuery(w, scanQuery),
-                s => new ClientQueryCursor<TK, TV>(_ignite, s.ReadLong(), _keepBinary, s));
+                s => new ClientQueryCursor<TK, TV>(
+                    _ignite, s.ReadLong(), _keepBinary, s, ClientOp.QueryScanCursorGetPage));
         }
-        
+
+        /** <inheritDoc /> */
+        public IQueryCursor<ICacheEntry<TK, TV>> Query(SqlQuery sqlQuery)
+        {
+            IgniteArgumentCheck.NotNull(sqlQuery, "sqlQuery");
+            IgniteArgumentCheck.NotNull(sqlQuery.Sql, "sqlQuery.Sql");
+            IgniteArgumentCheck.NotNull(sqlQuery.QueryType, "sqlQuery.QueryType");
+
+            return DoOutInOp(ClientOp.QuerySql, w => WriteSqlQuery(w, sqlQuery),
+                s => new ClientQueryCursor<TK, TV>(
+                    _ignite, s.ReadLong(), _keepBinary, s, ClientOp.QuerySqlCursorGetPage));
+        }
+
+        /** <inheritDoc /> */
+        public IFieldsQueryCursor Query(SqlFieldsQuery sqlFieldsQuery)
+        {
+            IgniteArgumentCheck.NotNull(sqlFieldsQuery, "sqlFieldsQuery");
+            IgniteArgumentCheck.NotNull(sqlFieldsQuery.Sql, "sqlFieldsQuery.Sql");
+
+            return DoOutInOp(ClientOp.QuerySqlFields, w => WriteSqlFieldsQuery(w, sqlFieldsQuery),
+                s => new ClientFieldsQueryCursor(
+                    _ignite, s.ReadLong(), _keepBinary, s, ClientOp.QuerySqlFieldsCursorGetPage,
+                    ClientFieldsQueryCursor.ReadColumns(_marsh.StartUnmarshal(s))));
+        }
+
         /** <inheritDoc /> */
         public CacheResult<TV> GetAndPut(TK key, TV val)
         {
@@ -426,6 +451,53 @@ namespace Apache.Ignite.Core.Impl.Client.Cache
         }
 
         /// <summary>
+        /// Writes the SQL query.
+        /// </summary>
+        private static void WriteSqlQuery(IBinaryRawWriter writer, SqlQuery qry)
+        {
+            Debug.Assert(qry != null);
+
+            writer.WriteString(qry.QueryType);
+            writer.WriteString(qry.Sql);
+            QueryBase.WriteQueryArgs(writer, qry.Arguments);
+            writer.WriteBoolean(qry.EnableDistributedJoins);
+            writer.WriteBoolean(qry.Local);
+            writer.WriteBoolean(qry.ReplicatedOnly);
+            writer.WriteInt(qry.PageSize);
+            writer.WriteTimeSpanAsLong(qry.Timeout);
+        }
+
+        /// <summary>
+        /// Writes the SQL fields query.
+        /// </summary>
+        private static void WriteSqlFieldsQuery(IBinaryRawWriter writer, SqlFieldsQuery qry)
+        {
+            Debug.Assert(qry != null);
+
+            writer.WriteString(qry.Schema);
+            writer.WriteInt(qry.PageSize);
+            writer.WriteInt(-1);  // maxRows: unlimited
+            writer.WriteString(qry.Sql);
+            QueryBase.WriteQueryArgs(writer, qry.Arguments);
+
+            // .NET client does not discern between different statements for now.
+            // We cound have ExecuteNonQuery method, which uses StatementType.Update, for example.
+            writer.WriteByte((byte)StatementType.Any);
+
+            writer.WriteBoolean(qry.EnableDistributedJoins);
+            writer.WriteBoolean(qry.Local);
+            writer.WriteBoolean(qry.ReplicatedOnly);
+            writer.WriteBoolean(qry.EnforceJoinOrder);
+            writer.WriteBoolean(qry.Colocated);
+            writer.WriteBoolean(qry.Lazy);
+            writer.WriteTimeSpanAsLong(qry.Timeout);
+
+            // Always include field names.
+            writer.WriteBoolean(true);
+
+        }
+
+        /// <summary>
         /// Handles the error.
         /// </summary>
         private T HandleError<T>(ClientStatus status, string msg)

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientFieldsQueryCursor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientFieldsQueryCursor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientFieldsQueryCursor.cs
new file mode 100644
index 0000000..2e57863
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientFieldsQueryCursor.cs
@@ -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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Client.Cache.Query
+{
+    using System.Collections.Generic;
+    using System.Collections.ObjectModel;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cache.Query;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+
+    /// <summary>
+    /// Client fields cursor.
+    /// </summary>
+    internal class ClientFieldsQueryCursor : ClientQueryCursorBase<IList<object>>, IFieldsQueryCursor
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ClientQueryCursor{TK, TV}" /> class.
+        /// </summary>
+        /// <param name="ignite">The ignite.</param>
+        /// <param name="cursorId">The cursor identifier.</param>
+        /// <param name="keepBinary">Keep binary flag.</param>
+        /// <param name="initialBatchStream">Optional stream with initial batch.</param>
+        /// <param name="getPageOp">The get page op.</param>
+        /// <param name="columns">The columns.</param>
+        public ClientFieldsQueryCursor(IgniteClient ignite, long cursorId, bool keepBinary,
+            IBinaryStream initialBatchStream, ClientOp getPageOp, IList<string> columns)
+            : base(ignite, cursorId, keepBinary, initialBatchStream, getPageOp,
+                r =>
+                {
+                    var res = new List<object>(columns.Count);
+
+                    for (var i = 0; i < columns.Count; i++)
+                    {
+                        res.Add(r.ReadObject<object>());
+                    }
+
+                    return res;
+                })
+        {
+            Debug.Assert(columns != null);
+
+            FieldNames = new ReadOnlyCollection<string>(columns);
+        }
+
+        /** <inheritdoc /> */
+        public IList<string> FieldNames { get; private set; }
+
+        /// <summary>
+        /// Reads the columns.
+        /// </summary>
+        internal static string[] ReadColumns(IBinaryRawReader reader)
+        {
+            var res = new string[reader.ReadInt()];
+
+            for (var i = 0; i < res.Length; i++)
+            {
+                res[i] = reader.ReadString();
+            }
+
+            return res;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
index ff891db..8e09af7 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursor.cs
@@ -17,27 +17,16 @@
 
 namespace Apache.Ignite.Core.Impl.Client.Cache.Query
 {
-    using System.Collections.Generic;
-    using System.Diagnostics.CodeAnalysis;
-    using System.Linq;
     using Apache.Ignite.Core.Cache;
-    using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Binary.IO;
     using Apache.Ignite.Core.Impl.Cache;
-    using Apache.Ignite.Core.Impl.Cache.Query;
     using Apache.Ignite.Core.Impl.Client;
 
     /// <summary>
     /// Client query cursor.
     /// </summary>
-    internal class ClientQueryCursor<TK, TV> : QueryCursorBase<ICacheEntry<TK, TV>>
+    internal sealed class ClientQueryCursor<TK, TV> : ClientQueryCursorBase<ICacheEntry<TK, TV>>
     {
-        /** Ignite. */
-        private readonly IgniteClient _ignite;
-
-        /** Cursor ID. */
-        private readonly long _cursorId;
-
         /// <summary>
         /// Initializes a new instance of the <see cref="ClientQueryCursor{TK, TV}" /> class.
         /// </summary>
@@ -45,52 +34,13 @@ namespace Apache.Ignite.Core.Impl.Client.Cache.Query
         /// <param name="cursorId">The cursor identifier.</param>
         /// <param name="keepBinary">Keep binary flag.</param>
         /// <param name="initialBatchStream">Optional stream with initial batch.</param>
-        public ClientQueryCursor(IgniteClient ignite, long cursorId, bool keepBinary, 
-            IBinaryStream initialBatchStream) 
-            : base(ignite.Marshaller, keepBinary, initialBatchStream)
-        {
-            _ignite = ignite;
-            _cursorId = cursorId;
-        }
-
-        /** <inheritdoc /> */
-        protected override void InitIterator()
+        /// <param name="getPageOp">The get page op.</param>
+        public ClientQueryCursor(IgniteClient ignite, long cursorId, bool keepBinary,
+            IBinaryStream initialBatchStream, ClientOp getPageOp)
+            : base(ignite, cursorId, keepBinary, initialBatchStream, getPageOp,
+                r => new CacheEntry<TK, TV>(r.ReadObject<TK>(), r.ReadObject<TV>()))
         {
             // No-op.
         }
-
-        /** <inheritdoc /> */
-        protected override IList<ICacheEntry<TK, TV>> GetAllInternal()
-        {
-            return this.ToArray();
-        }
-
-        /** <inheritdoc /> */
-        [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
-        protected override ICacheEntry<TK, TV> Read(BinaryReader reader)
-        {
-            return new CacheEntry<TK, TV>(reader.ReadObject<TK>(), reader.ReadObject<TV>());
-        }
-
-        /** <inheritdoc /> */
-        protected override ICacheEntry<TK, TV>[] GetBatch()
-        {
-            return _ignite.Socket.DoOutInOp(ClientOp.QueryScanCursorGetPage,
-                w => w.WriteLong(_cursorId),
-                s => ConvertGetBatch(s));
-        }
-
-        /** <inheritdoc /> */
-        protected override void Dispose(bool disposing)
-        {
-            try
-            {
-                _ignite.Socket.DoOutInOp<object>(ClientOp.ResourceClose, w => w.WriteLong(_cursorId), null);
-            }
-            finally
-            {
-                base.Dispose(disposing);
-            }
-        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursorBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursorBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursorBase.cs
new file mode 100644
index 0000000..5123537
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/ClientQueryCursorBase.cs
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+namespace Apache.Ignite.Core.Impl.Client.Cache.Query
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Cache.Query;
+
+    /// <summary>
+    /// Client query cursor base.
+    /// </summary>
+    internal abstract class ClientQueryCursorBase<T> : QueryCursorBase<T>
+    {
+        /** Ignite. */
+        private readonly IgniteClient _ignite;
+
+        /** Cursor ID. */
+        private readonly long _cursorId;
+
+        /** Page op code. */
+        private readonly ClientOp _getPageOp;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ClientQueryCursorBase{T}" /> class.
+        /// </summary>
+        /// <param name="ignite">The ignite.</param>
+        /// <param name="cursorId">The cursor identifier.</param>
+        /// <param name="keepBinary">Keep binary flag.</param>
+        /// <param name="initialBatchStream">Optional stream with initial batch.</param>
+        /// <param name="getPageOp">The get page op.</param>
+        /// <param name="readFunc">Read func.</param>
+        protected ClientQueryCursorBase(IgniteClient ignite, long cursorId, bool keepBinary, 
+            IBinaryStream initialBatchStream, ClientOp getPageOp, Func<BinaryReader, T> readFunc) 
+            : base(ignite.Marshaller, keepBinary, readFunc, initialBatchStream)
+        {
+            _ignite = ignite;
+            _cursorId = cursorId;
+            _getPageOp = getPageOp;
+        }
+
+        /** <inheritdoc /> */
+        protected override void InitIterator()
+        {
+            // No-op.
+        }
+
+        /** <inheritdoc /> */
+        protected override IList<T> GetAllInternal()
+        {
+            return this.ToArray();
+        }
+
+        /** <inheritdoc /> */
+        protected override T[] GetBatch()
+        {
+            return _ignite.Socket.DoOutInOp(_getPageOp, w => w.WriteLong(_cursorId), s => ConvertGetBatch(s));
+        }
+
+        /** <inheritdoc /> */
+        protected override void Dispose(bool disposing)
+        {
+            try
+            {
+                _ignite.Socket.DoOutInOp<object>(ClientOp.ResourceClose, w => w.WriteLong(_cursorId), null);
+            }
+            finally
+            {
+                base.Dispose(disposing);
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/StatementType.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/StatementType.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/StatementType.cs
new file mode 100644
index 0000000..c5143ea
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/Cache/Query/StatementType.cs
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Core.Impl.Client.Cache.Query
+{
+    /// <summary>
+    /// Query request type.
+    /// <para />
+    /// When the client knows expected kind of query, we can fail earlier on server.
+    /// </summary>
+    internal enum StatementType : byte
+    {
+        /// <summary>
+        /// Any query, SQL or DML.
+        /// </summary>
+        Any = 0,
+
+        /// <summary>
+        /// Select query, "SELECT .. FROM".
+        /// </summary>
+        Select = 1,
+
+        /// <summary>
+        /// Update (DML) query, "UPDATE .. ", "INSERT INTO ..".
+        /// </summary>
+        Update = 2
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0bd712dd/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
index 779b73e..3af089a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Client/ClientOp.cs
@@ -56,6 +56,10 @@ namespace Apache.Ignite.Core.Impl.Client
         CacheGetNames = 32,
         CacheGetConfiguration = 33,
         CacheCreateWithConfiguration = 34,
-        CacheGetOrCreateWithConfiguration = 35
+        CacheGetOrCreateWithConfiguration = 35,
+        QuerySql = 36,
+        QuerySqlCursorGetPage = 37,
+        QuerySqlFields = 38,
+        QuerySqlFieldsCursorGetPage = 39
     }
 }


[19/47] ignite git commit: IGNITE-6911 .NET: Optionally disable Java console redirect

Posted by sb...@apache.org.
IGNITE-6911 .NET: Optionally disable Java console redirect

This closes #3039


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

Branch: refs/heads/ignite-zk
Commit: af6b9337206a2be18eed99b5b4fbb922308b349c
Parents: 50b384b
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Thu Nov 16 11:05:59 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Thu Nov 16 11:05:59 2017 +0300

----------------------------------------------------------------------
 .../platform/PlatformAbstractBootstrap.java     | 18 ++++++------
 .../processors/platform/PlatformBootstrap.java  |  7 ++---
 .../processors/platform/PlatformIgnition.java   |  4 +--
 .../dotnet/PlatformDotNetBootstrap.java         | 26 ++++++++----------
 .../PlatformDotNetConfigurationClosure.java     | 22 +++++++++------
 .../Config/full-config.xml                      |  2 +-
 .../ConsoleRedirectTest.cs                      | 29 ++++++++++++++++++++
 .../IgniteConfigurationSerializerTest.cs        |  1 +
 .../Apache.Ignite.Core.Tests/TestUtils.cs       | 16 +++++++++--
 .../Apache.Ignite.Core/IgniteConfiguration.cs   | 23 ++++++++++++++++
 .../IgniteConfigurationSection.xsd              |  5 ++++
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |  4 ++-
 .../Apache.Ignite.Core/Impl/IgniteManager.cs    |  6 +++-
 .../Impl/Unmanaged/UnmanagedUtils.cs            |  7 ++---
 14 files changed, 120 insertions(+), 50 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformAbstractBootstrap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformAbstractBootstrap.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformAbstractBootstrap.java
index 38cf36b..bf6caf2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformAbstractBootstrap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformAbstractBootstrap.java
@@ -35,12 +35,7 @@ import org.jetbrains.annotations.Nullable;
 public abstract class PlatformAbstractBootstrap implements PlatformBootstrap {
     /** {@inheritDoc} */
     @Override public PlatformProcessor start(IgniteConfiguration cfg, @Nullable GridSpringResourceContext springCtx,
-        long envPtr, long dataPtr) {
-        final PlatformInputStream input = new PlatformExternalMemory(null, dataPtr).input();
-
-        Ignition.setClientMode(input.readBoolean());
-
-        processInput(input, cfg);
+        long envPtr) {
 
         IgniteConfiguration cfg0 = closure(envPtr).apply(cfg);
 
@@ -55,8 +50,12 @@ public abstract class PlatformAbstractBootstrap implements PlatformBootstrap {
     }
 
     /** {@inheritDoc} */
-    @Override public void init() {
-        // No-op.
+    @Override public void init(long dataPtr) {
+        final PlatformInputStream input = new PlatformExternalMemory(null, dataPtr).input();
+
+        Ignition.setClientMode(input.readBoolean());
+
+        processInput(input);
     }
 
     /**
@@ -71,9 +70,8 @@ public abstract class PlatformAbstractBootstrap implements PlatformBootstrap {
      * Processes any additional input data.
      *
      * @param input Input stream.
-     * @param cfg Config.
      */
-    protected void processInput(PlatformInputStream input, IgniteConfiguration cfg) {
+    protected void processInput(PlatformInputStream input) {
         // No-op.
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformBootstrap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformBootstrap.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformBootstrap.java
index 07847a7..407e8c8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformBootstrap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformBootstrap.java
@@ -31,15 +31,14 @@ public interface PlatformBootstrap {
      * @param cfg Configuration.
      * @param springCtx Optional Spring resource context.
      * @param envPtr Environment pointer.
-     * @param dataPtr Optional pointer to additional data required for startup.
      * @return Platform processor.
      */
-    public PlatformProcessor start(IgniteConfiguration cfg, @Nullable GridSpringResourceContext springCtx,
-        long envPtr, long dataPtr);
+    public PlatformProcessor start(IgniteConfiguration cfg, @Nullable GridSpringResourceContext springCtx, long envPtr);
 
     /**
      * Init the bootstrap.
      *
+     * @param dataPtr Optional pointer to additional data required for startup.
      */
-    public void init();
+    public void init(long dataPtr);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformIgnition.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformIgnition.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformIgnition.java
index 754c69e..46c4a2d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformIgnition.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformIgnition.java
@@ -63,7 +63,7 @@ public class PlatformIgnition {
             PlatformBootstrap bootstrap = bootstrap(factoryId);
 
             // This should be done before Spring XML initialization so that redirected stream is picked up.
-            bootstrap.init();
+            bootstrap.init(dataPtr);
 
             IgniteBiTuple<IgniteConfiguration, GridSpringResourceContext> cfg = configuration(springCfgPath);
 
@@ -72,7 +72,7 @@ public class PlatformIgnition {
             else
                 igniteInstanceName = cfg.get1().getIgniteInstanceName();
 
-            PlatformProcessor proc = bootstrap.start(cfg.get1(), cfg.get2(), envPtr, dataPtr);
+            PlatformProcessor proc = bootstrap.start(cfg.get1(), cfg.get2(), envPtr);
 
             PlatformProcessor old = instances.put(igniteInstanceName, proc);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetBootstrap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetBootstrap.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetBootstrap.java
index 84a4577..b53a2b8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetBootstrap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetBootstrap.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.internal.processors.platform.dotnet;
 
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.logger.platform.PlatformLogger;
 import org.apache.ignite.internal.processors.platform.PlatformAbstractBootstrap;
 import org.apache.ignite.internal.processors.platform.PlatformAbstractConfigurationClosure;
 import org.apache.ignite.internal.processors.platform.memory.PlatformInputStream;
@@ -29,24 +27,22 @@ import java.io.PrintStream;
  * Interop .Net bootstrap.
  */
 public class PlatformDotNetBootstrap extends PlatformAbstractBootstrap {
-    /** {@inheritDoc} */
-    @Override public void init() {
-        // Initialize console propagation.
-        // This call is idempotent, doing it on each node start is fine.
-        System.setOut(new PrintStream(new PlatformDotNetConsoleStream(false)));
-        System.setErr(new PrintStream(new PlatformDotNetConsoleStream(true)));
-
-        super.init();
-    }
+    private boolean useLogger;
 
     /** {@inheritDoc} */
     @Override protected PlatformAbstractConfigurationClosure closure(long envPtr) {
-        return new PlatformDotNetConfigurationClosure(envPtr);
+        return new PlatformDotNetConfigurationClosure(envPtr, useLogger);
     }
 
     /** {@inheritDoc} */
-    @Override protected void processInput(PlatformInputStream input, IgniteConfiguration cfg) {
-        if (input.readBoolean())
-            cfg.setGridLogger(new PlatformLogger());
+    @Override protected void processInput(PlatformInputStream input) {
+        useLogger = input.readBoolean();
+
+        if (input.readBoolean()) {
+            // Initialize console propagation.
+            // This call is idempotent, doing it on each node start is fine.
+            System.setOut(new PrintStream(new PlatformDotNetConsoleStream(false)));
+            System.setErr(new PrintStream(new PlatformDotNetConsoleStream(true)));
+        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
index 5b4f1cc..9ee2f5e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
@@ -53,6 +53,9 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
     /** */
     private static final long serialVersionUID = 0L;
 
+    /** Whether to use platform logger (when custom logger is defined on .NET side). */
+    private final boolean useLogger;
+
     /** Configuration. */
     private IgniteConfiguration cfg;
 
@@ -64,14 +67,16 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
      *
      * @param envPtr Environment pointer.
      */
-    public PlatformDotNetConfigurationClosure(long envPtr) {
+    public PlatformDotNetConfigurationClosure(long envPtr, boolean useLogger) {
         super(envPtr);
+
+        this.useLogger = useLogger;
     }
 
     /** {@inheritDoc} */
     @SuppressWarnings("deprecation")
     @Override protected void apply0(IgniteConfiguration igniteCfg) {
-        // 3. Validate and copy Interop configuration setting environment pointer along the way.
+        // Validate and copy Interop configuration setting environment pointer along the way.
         PlatformConfiguration interopCfg = igniteCfg.getPlatformConfiguration();
 
         if (interopCfg != null && !(interopCfg instanceof PlatformDotNetConfiguration))
@@ -85,15 +90,16 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
 
         memMgr = new PlatformMemoryManagerImpl(gate, 1024);
 
-        PlatformLogger userLogger = null;
+        PlatformLogger logger = null;
 
-        if (igniteCfg.getGridLogger() instanceof PlatformLogger) {
-            userLogger = (PlatformLogger)igniteCfg.getGridLogger();
-            userLogger.setGateway(gate);
+        if (useLogger) {
+            logger = new PlatformLogger();
+            logger.setGateway(gate);
+            igniteCfg.setGridLogger(logger);
         }
 
         PlatformDotNetConfigurationEx dotNetCfg0 = new PlatformDotNetConfigurationEx(dotNetCfg, gate, memMgr,
-            userLogger);
+            logger);
 
         igniteCfg.setPlatformConfiguration(dotNetCfg0);
 
@@ -103,7 +109,7 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
         if (ggHome != null)
             U.setIgniteHome(ggHome);
 
-        // 4. Callback to .Net.
+        // Callback to .Net.
         prepare(igniteCfg, dotNetCfg0);
 
         // Make sure binary config is right.

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
index b808bbe..24f519e 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/full-config.xml
@@ -23,7 +23,7 @@
               workDirectory='c:' JvmMaxMemoryMb='1024' MetricsLogFrequency='0:0:10' isDaemon='true' 
               isLateAffinityAssignment='false' springConfigUrl='c:\myconfig.xml' autoGenerateIgniteInstanceName='true' 
               peerAssemblyLoadingMode='CurrentAppDomain' longQueryWarningTimeout='1:2:3' isActiveOnStart='false' 
-              consistentId='someId012'>
+              consistentId='someId012' redirectJavaConsoleOutput='false'>
     <localhost>127.1.1.1</localhost>
     <binaryConfiguration compactFooter='false' keepDeserialized='true'>
         <nameMapper type='Apache.Ignite.Core.Tests.IgniteConfigurationSerializerTest+NameMapper' bar='testBar' />

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
index ed556b4..2e389c3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/ConsoleRedirectTest.cs
@@ -116,6 +116,35 @@ namespace Apache.Ignite.Core.Tests
         }
 
         /// <summary>
+        /// Tests the disabled redirect.
+        /// </summary>
+        [Test]
+        public void TestDisabledRedirect()
+        {
+            // Run test in new process because JVM is initialized only once.
+            const string envVar = "ConsoleRedirectTest.TestDisabledRedirect";
+
+            if (Environment.GetEnvironmentVariable(envVar) == "true")
+            {
+                var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration(false));
+                Assert.IsTrue(cfg.RedirectJavaConsoleOutput);
+
+                cfg.RedirectJavaConsoleOutput = false;
+
+                using (Ignition.Start(cfg))
+                {
+                    Assert.AreEqual("", _errSb.ToString());
+                    Assert.AreEqual("", _outSb.ToString());
+                }
+            }
+            else
+            {
+                Environment.SetEnvironmentVariable(envVar, "true");
+                TestUtils.RunTestInNewProcess(GetType().FullName, "TestDisabledRedirect");
+            }
+        }
+
+        /// <summary>
         /// Tests multiple appdomains and multiple console handlers.
         /// </summary>
         [Test]

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
index 4cd3760..27e55f3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSerializerTest.cs
@@ -98,6 +98,7 @@ namespace Apache.Ignite.Core.Tests
             Assert.AreEqual(new TimeSpan(1, 2, 3), cfg.LongQueryWarningTimeout);
             Assert.IsFalse(cfg.IsActiveOnStart);
             Assert.AreEqual("someId012", cfg.ConsistentId);
+            Assert.IsFalse(cfg.RedirectJavaConsoleOutput);
 
             Assert.AreEqual("secondCache", cfg.CacheConfiguration.Last().Name);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
index 03e8bf7..26caf53 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestUtils.cs
@@ -380,10 +380,20 @@ namespace Apache.Ignite.Core.Tests
             var proc = System.Diagnostics.Process.Start(procStart);
             Assert.IsNotNull(proc);
 
-            IgniteProcess.AttachProcessConsoleReader(proc);
+            try
+            {
+                IgniteProcess.AttachProcessConsoleReader(proc);
 
-            Assert.IsTrue(proc.WaitForExit(19000));
-            Assert.AreEqual(0, proc.ExitCode);
+                Assert.IsTrue(proc.WaitForExit(19000));
+                Assert.AreEqual(0, proc.ExitCode);
+            }
+            finally
+            {
+                if (!proc.HasExited)
+                {
+                    proc.Kill();
+                }
+            }
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
index e890577..f8c42e5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfiguration.cs
@@ -215,6 +215,11 @@ namespace Apache.Ignite.Core
         public const bool DefaultIsActiveOnStart = true;
 
         /// <summary>
+        /// Default value for <see cref="RedirectJavaConsoleOutput"/> property.
+        /// </summary>
+        public const bool DefaultRedirectJavaConsoleOutput = true;
+
+        /// <summary>
         /// Initializes a new instance of the <see cref="IgniteConfiguration"/> class.
         /// </summary>
         public IgniteConfiguration()
@@ -222,6 +227,7 @@ namespace Apache.Ignite.Core
             JvmInitialMemoryMb = DefaultJvmInitMem;
             JvmMaxMemoryMb = DefaultJvmMaxMem;
             ClientConnectorConfigurationEnabled = DefaultClientConnectorConfigurationEnabled;
+            RedirectJavaConsoleOutput = DefaultRedirectJavaConsoleOutput;
         }
 
         /// <summary>
@@ -760,6 +766,7 @@ namespace Apache.Ignite.Core
             AutoGenerateIgniteInstanceName = cfg.AutoGenerateIgniteInstanceName;
             PeerAssemblyLoadingMode = cfg.PeerAssemblyLoadingMode;
             LocalEventListeners = cfg.LocalEventListeners;
+            RedirectJavaConsoleOutput = cfg.RedirectJavaConsoleOutput;
 
             if (CacheConfiguration != null && cfg.CacheConfiguration != null)
             {
@@ -1420,5 +1427,21 @@ namespace Apache.Ignite.Core
         /// Gets or sets consistent globally unique node identifier which survives node restarts.
         /// </summary>
         public object ConsistentId { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether Java console output should be redirected
+        /// to <see cref="Console.Out"/> and <see cref="Console.Error"/>, respectively.
+        /// <para />
+        /// Default is <see cref="DefaultRedirectJavaConsoleOutput"/>.
+        /// <para />
+        /// Java code outputs valuable information to console. However, since that is Java console,
+        /// it is not possible to capture that output with standard .NET APIs (<see cref="Console.SetOut"/>).
+        /// As a result, many tools (IDEs, test runners) are not able to display Ignite console output in UI.
+        /// <para />
+        /// This property is enabled by default and redirects Java console output to standard .NET console.
+        /// It is recommended to disable this in production.
+        /// </summary>
+        [DefaultValue(DefaultRedirectJavaConsoleOutput)]
+        public bool RedirectJavaConsoleOutput { get; set; }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
index 5050806..98607b6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/IgniteConfigurationSection.xsd
@@ -2125,6 +2125,11 @@
                     <xs:documentation>Whether client connector should be enabled (allow thin clients, ODBC and JDBC drivers to work with Ignite).</xs:documentation>
                 </xs:annotation>
             </xs:attribute>
+            <xs:attribute name="redirectJavaConsoleOutput" type="xs:boolean">
+              <xs:annotation>
+                <xs:documentation>Whether Java console output should be redirected to Console.Out and Console.Error.</xs:documentation>
+              </xs:annotation>
+            </xs:attribute>
         </xs:complexType>
     </xs:element>
 </xs:schema>

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index bc14fdd..41419ac 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -248,7 +248,8 @@ namespace Apache.Ignite.Core
                 try
                 {
                     // 4. Initiate Ignite start.
-                    UU.IgnitionStart(env, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null, cbs.IgniteId);
+                    UU.IgnitionStart(env, cfg.SpringConfigUrl, gridName, ClientMode, cfg.Logger != null, cbs.IgniteId,
+                        cfg.RedirectJavaConsoleOutput);
 
                     // 5. At this point start routine is finished. We expect STARTUP object to have all necessary data.
                     var node = _startup.Ignite;
@@ -549,6 +550,7 @@ namespace Apache.Ignite.Core
                     {
                         Assembly assembly = Assembly.LoadFrom(s);
 
+                        // ReSharper disable once ConditionIsAlwaysTrueOrFalse
                         if (assembly != null)
                             continue;
                     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
index fd067b9..fd9fb79 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteManager.cs
@@ -75,7 +75,11 @@ namespace Apache.Ignite.Core.Impl
 
                 // 2. Create unmanaged pointer.
                 var jvm = CreateJvm(cfg);
-                jvm.EnableJavaConsoleWriter();
+
+                if (cfg.RedirectJavaConsoleOutput)
+                {
+                    jvm.EnableJavaConsoleWriter();
+                }
 
                 var cbs = new UnmanagedCallbacks(log, jvm);
                 jvm.RegisterCallbacks(cbs);

http://git-wip-us.apache.org/repos/asf/ignite/blob/af6b9337/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
index 58586a9..e355793 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedUtils.cs
@@ -30,7 +30,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         #region NATIVE METHODS: PROCESSOR
 
         internal static void IgnitionStart(Env env, string cfgPath, string gridName,
-            bool clientMode, bool userLogger, long igniteId)
+            bool clientMode, bool userLogger, long igniteId, bool redirectConsole)
         {
             using (var mem = IgniteManager.Memory.Allocate().GetStream())
             using (var cfgPath0 = env.NewStringUtf(cfgPath))
@@ -38,10 +38,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
             {
                 mem.WriteBool(clientMode);
                 mem.WriteBool(userLogger);
-
-                // Additional data.
-                mem.WriteBool(false);
-                mem.WriteBool(false);
+                mem.WriteBool(redirectConsole);
 
                 long* args = stackalloc long[5];
                 args[0] = cfgPath == null ? 0 : cfgPath0.Target.ToInt64();


[29/47] ignite git commit: IGNITE-5846 Add support of distributed matrices for OLS regression. This closes #3030.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedBlockOLSMultipleLinearRegressionTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedBlockOLSMultipleLinearRegressionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedBlockOLSMultipleLinearRegressionTest.java
new file mode 100644
index 0000000..e3c2979
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedBlockOLSMultipleLinearRegressionTest.java
@@ -0,0 +1,926 @@
+/*
+ * 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.ml.regressions;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.TestUtils;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
+import org.apache.ignite.ml.math.exceptions.NullArgumentException;
+import org.apache.ignite.ml.math.exceptions.SingularMatrixException;
+import org.apache.ignite.ml.math.impls.matrix.SparseBlockDistributedMatrix;
+import org.apache.ignite.ml.math.impls.vector.SparseBlockDistributedVector;
+import org.apache.ignite.ml.math.util.MatrixUtil;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for {@link OLSMultipleLinearRegression}.
+ */
+
+@GridCommonTest(group = "Distributed Models")
+public class DistributedBlockOLSMultipleLinearRegressionTest extends GridCommonAbstractTest {
+    /** */
+    private double[] y;
+
+    /** */
+    private double[][] x;
+
+    private AbstractMultipleLinearRegression regression;
+
+    /** Number of nodes in grid */
+    private static final int NODE_COUNT = 3;
+
+    private static final double PRECISION = 1E-12;
+
+    /** Grid instance. */
+    private Ignite ignite;
+
+    public DistributedBlockOLSMultipleLinearRegressionTest() {
+
+        super(false);
+
+
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        for (int i = 1; i <= NODE_COUNT; i++)
+            startGrid(i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override protected void beforeTest() throws Exception {
+        ignite = grid(NODE_COUNT);
+
+        ignite.configuration().setPeerClassLoadingEnabled(true);
+
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+
+        y = new double[]{11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
+        x = new double[6][];
+        x[0] = new double[]{0, 0, 0, 0, 0};
+        x[1] = new double[]{2.0, 0, 0, 0, 0};
+        x[2] = new double[]{0, 3.0, 0, 0, 0};
+        x[3] = new double[]{0, 0, 4.0, 0, 0};
+        x[4] = new double[]{0, 0, 0, 5.0, 0};
+        x[5] = new double[]{0, 0, 0, 0, 6.0};
+
+        regression = createRegression();
+    }
+
+    /** */
+    protected OLSMultipleLinearRegression createRegression() {
+        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
+        regression.newSampleData(new SparseBlockDistributedVector(y), new SparseBlockDistributedMatrix(x));
+        return regression;
+    }
+
+    /** */
+    @Test
+    public void testPerfectFit() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[] betaHat = regression.estimateRegressionParameters();
+        System.out.println("Beta hat is " + betaHat);
+        TestUtils.assertEquals(new double[]{11.0, 1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0, 5.0 / 6.0},
+                betaHat,
+                1e-13);
+        double[] residuals = regression.estimateResiduals();
+        TestUtils.assertEquals(new double[]{0d, 0d, 0d, 0d, 0d, 0d}, residuals,
+                1e-13);
+        Matrix errors = regression.estimateRegressionParametersVariance();
+        final double[] s = {1.0, -1.0 / 2.0, -1.0 / 3.0, -1.0 / 4.0, -1.0 / 5.0, -1.0 / 6.0};
+        Matrix refVar = new SparseBlockDistributedMatrix(s.length, s.length);
+        for (int i = 0; i < refVar.rowSize(); i++)
+            for (int j = 0; j < refVar.columnSize(); j++) {
+                if (i == 0) {
+                    refVar.setX(i, j, s[j]);
+                    continue;
+                }
+                double x = s[i] * s[j];
+                refVar.setX(i, j, (i == j) ? 2 * x : x);
+            }
+        Assert.assertEquals(0.0,
+                TestUtils.maximumAbsoluteRowSum(errors.minus(refVar)),
+                5.0e-16 * TestUtils.maximumAbsoluteRowSum(refVar));
+        Assert.assertEquals(1, ((OLSMultipleLinearRegression) regression).calculateRSquared(), 1E-12);
+    }
+
+    /**
+     * Test Longley dataset against certified values provided by NIST.
+     * Data Source: J. Longley (1967) "An Appraisal of Least Squares
+     * Programs for the Electronic Computer from the Point of View of the User"
+     * Journal of the American Statistical Association, vol. 62. September,
+     * pp. 819-841.
+     *
+     * Certified values (and data) are from NIST:
+     * http://www.itl.nist.gov/div898/strd/lls/data/LINKS/DATA/Longley.dat
+     */
+    @Test
+    public void testLongly() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        // Y values are first, then independent vars
+        // Each row is one observation
+        double[] design = new double[]{
+                60323, 83.0, 234289, 2356, 1590, 107608, 1947,
+                61122, 88.5, 259426, 2325, 1456, 108632, 1948,
+                60171, 88.2, 258054, 3682, 1616, 109773, 1949,
+                61187, 89.5, 284599, 3351, 1650, 110929, 1950,
+                63221, 96.2, 328975, 2099, 3099, 112075, 1951,
+                63639, 98.1, 346999, 1932, 3594, 113270, 1952,
+                64989, 99.0, 365385, 1870, 3547, 115094, 1953,
+                63761, 100.0, 363112, 3578, 3350, 116219, 1954,
+                66019, 101.2, 397469, 2904, 3048, 117388, 1955,
+                67857, 104.6, 419180, 2822, 2857, 118734, 1956,
+                68169, 108.4, 442769, 2936, 2798, 120445, 1957,
+                66513, 110.8, 444546, 4681, 2637, 121950, 1958,
+                68655, 112.6, 482704, 3813, 2552, 123366, 1959,
+                69564, 114.2, 502601, 3931, 2514, 125368, 1960,
+                69331, 115.7, 518173, 4806, 2572, 127852, 1961,
+                70551, 116.9, 554894, 4007, 2827, 130081, 1962
+        };
+
+        final int nobs = 16;
+        final int nvars = 6;
+
+        // Estimate the model
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(design, nobs, nvars, new SparseBlockDistributedMatrix());
+
+        // Check expected beta values from NIST
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        -3482258.63459582, 15.0618722713733,
+                        -0.358191792925910E-01, -2.02022980381683,
+                        -1.03322686717359, -0.511041056535807E-01,
+                        1829.15146461355}, 2E-6); //
+
+        // Check expected residuals from R
+        double[] residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[]{
+                        267.340029759711, -94.0139423988359, 46.28716775752924,
+                        -410.114621930906, 309.7145907602313, -249.3112153297231,
+                        -164.0489563956039, -13.18035686637081, 14.30477260005235,
+                        455.394094551857, -17.26892711483297, -39.0550425226967,
+                        -155.5499735953195, -85.6713080421283, 341.9315139607727,
+                        -206.7578251937366},
+                1E-7);
+
+        // Check standard errors from NIST
+        double[] errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[]{
+                890420.383607373,
+                84.9149257747669,
+                0.334910077722432E-01,
+                0.488399681651699,
+                0.214274163161675,
+                0.226073200069370,
+                455.478499142212}, errors, 1E-6);
+
+        // Check regression standard error against R
+        Assert.assertEquals(304.8540735619638, mdl.estimateRegressionStandardError(), 1E-8);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.995479004577296, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.992465007628826, mdl.calculateAdjustedRSquared(), 1E-12);
+
+        // TODO: IGNITE-5826, uncomment.
+        // checkVarianceConsistency(model);
+
+        // Estimate model without intercept
+        mdl.setNoIntercept(true);
+        mdl.newSampleData(design, nobs, nvars, new SparseBlockDistributedMatrix());
+
+        // Check expected beta values from R
+        betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        -52.99357013868291, 0.07107319907358,
+                        -0.42346585566399, -0.57256866841929,
+                        -0.41420358884978, 48.41786562001326}, 1E-8);
+
+        // Check standard errors from R
+        errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[]{
+                129.54486693117232, 0.03016640003786,
+                0.41773654056612, 0.27899087467676, 0.32128496193363,
+                17.68948737819961}, errors, 1E-11);
+
+        // Check expected residuals from R
+        residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[]{
+                        279.90274927293092, -130.32465380836874, 90.73228661967445, -401.31252201634948,
+                        -440.46768772620027, -543.54512853774793, 201.32111639536299, 215.90889365977932,
+                        73.09368242049943, 913.21694494481869, 424.82484953610174, -8.56475876776709,
+                        -361.32974610842876, 27.34560497213464, 151.28955976355002, -492.49937355336846},
+                1E-8);
+
+        // Check regression standard error against R
+        Assert.assertEquals(475.1655079819517, mdl.estimateRegressionStandardError(), 1E-10);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.9999670130706, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.999947220913, mdl.calculateAdjustedRSquared(), 1E-12);
+
+    }
+
+    /**
+     * Test R Swiss fertility dataset against R.
+     * Data Source: R datasets package
+     */
+    @Test
+    public void testSwissFertility() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[] design = new double[]{
+                80.2, 17.0, 15, 12, 9.96,
+                83.1, 45.1, 6, 9, 84.84,
+                92.5, 39.7, 5, 5, 93.40,
+                85.8, 36.5, 12, 7, 33.77,
+                76.9, 43.5, 17, 15, 5.16,
+                76.1, 35.3, 9, 7, 90.57,
+                83.8, 70.2, 16, 7, 92.85,
+                92.4, 67.8, 14, 8, 97.16,
+                82.4, 53.3, 12, 7, 97.67,
+                82.9, 45.2, 16, 13, 91.38,
+                87.1, 64.5, 14, 6, 98.61,
+                64.1, 62.0, 21, 12, 8.52,
+                66.9, 67.5, 14, 7, 2.27,
+                68.9, 60.7, 19, 12, 4.43,
+                61.7, 69.3, 22, 5, 2.82,
+                68.3, 72.6, 18, 2, 24.20,
+                71.7, 34.0, 17, 8, 3.30,
+                55.7, 19.4, 26, 28, 12.11,
+                54.3, 15.2, 31, 20, 2.15,
+                65.1, 73.0, 19, 9, 2.84,
+                65.5, 59.8, 22, 10, 5.23,
+                65.0, 55.1, 14, 3, 4.52,
+                56.6, 50.9, 22, 12, 15.14,
+                57.4, 54.1, 20, 6, 4.20,
+                72.5, 71.2, 12, 1, 2.40,
+                74.2, 58.1, 14, 8, 5.23,
+                72.0, 63.5, 6, 3, 2.56,
+                60.5, 60.8, 16, 10, 7.72,
+                58.3, 26.8, 25, 19, 18.46,
+                65.4, 49.5, 15, 8, 6.10,
+                75.5, 85.9, 3, 2, 99.71,
+                69.3, 84.9, 7, 6, 99.68,
+                77.3, 89.7, 5, 2, 100.00,
+                70.5, 78.2, 12, 6, 98.96,
+                79.4, 64.9, 7, 3, 98.22,
+                65.0, 75.9, 9, 9, 99.06,
+                92.2, 84.6, 3, 3, 99.46,
+                79.3, 63.1, 13, 13, 96.83,
+                70.4, 38.4, 26, 12, 5.62,
+                65.7, 7.7, 29, 11, 13.79,
+                72.7, 16.7, 22, 13, 11.22,
+                64.4, 17.6, 35, 32, 16.92,
+                77.6, 37.6, 15, 7, 4.97,
+                67.6, 18.7, 25, 7, 8.65,
+                35.0, 1.2, 37, 53, 42.34,
+                44.7, 46.6, 16, 29, 50.43,
+                42.8, 27.7, 22, 29, 58.33
+        };
+
+        final int nobs = 47;
+        final int nvars = 4;
+
+        // Estimate the model
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(design, nobs, nvars, new SparseBlockDistributedMatrix());
+
+        // Check expected beta values from R
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        91.05542390271397,
+                        -0.22064551045715,
+                        -0.26058239824328,
+                        -0.96161238456030,
+                        0.12441843147162}, 1E-12);
+
+        // Check expected residuals from R
+        double[] residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[]{
+                        7.1044267859730512, 1.6580347433531366,
+                        4.6944952770029644, 8.4548022690166160, 13.6547432343186212,
+                        -9.3586864458500774, 7.5822446330520386, 15.5568995563859289,
+                        0.8113090736598980, 7.1186762732484308, 7.4251378771228724,
+                        2.6761316873234109, 0.8351584810309354, 7.1769991119615177,
+                        -3.8746753206299553, -3.1337779476387251, -0.1412575244091504,
+                        1.1186809170469780, -6.3588097346816594, 3.4039270429434074,
+                        2.3374058329820175, -7.9272368576900503, -7.8361010968497959,
+                        -11.2597369269357070, 0.9445333697827101, 6.6544245101380328,
+                        -0.9146136301118665, -4.3152449403848570, -4.3536932047009183,
+                        -3.8907885169304661, -6.3027643926302188, -7.8308982189289091,
+                        -3.1792280015332750, -6.7167298771158226, -4.8469946718041754,
+                        -10.6335664353633685, 11.1031134362036958, 6.0084032641811733,
+                        5.4326230830188482, -7.2375578629692230, 2.1671550814448222,
+                        15.0147574652763112, 4.8625103516321015, -7.1597256413907706,
+                        -0.4515205619767598, -10.2916870903837587, -15.7812984571900063},
+                1E-12);
+
+        // Check standard errors from R
+        double[] errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[]{
+                6.94881329475087,
+                0.07360008972340,
+                0.27410957467466,
+                0.19454551679325,
+                0.03726654773803}, errors, 1E-10);
+
+        // Check regression standard error against R
+        Assert.assertEquals(7.73642194433223, mdl.estimateRegressionStandardError(), 1E-12);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.649789742860228, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.6164363850373927, mdl.calculateAdjustedRSquared(), 1E-12);
+
+        // TODO: IGNITE-5826, uncomment.
+        // checkVarianceConsistency(model);
+
+        // Estimate the model with no intercept
+        mdl = new OLSMultipleLinearRegression();
+        mdl.setNoIntercept(true);
+        mdl.newSampleData(design, nobs, nvars, new SparseBlockDistributedMatrix());
+
+        // Check expected beta values from R
+        betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        0.52191832900513,
+                        2.36588087917963,
+                        -0.94770353802795,
+                        0.30851985863609}, 1E-12);
+
+        // Check expected residuals from R
+        residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[]{
+                        44.138759883538249, 27.720705122356215, 35.873200836126799,
+                        34.574619581211977, 26.600168342080213, 15.074636243026923, -12.704904871199814,
+                        1.497443824078134, 2.691972687079431, 5.582798774291231, -4.422986561283165,
+                        -9.198581600334345, 4.481765170730647, 2.273520207553216, -22.649827853221336,
+                        -17.747900013943308, 20.298314638496436, 6.861405135329779, -8.684712790954924,
+                        -10.298639278062371, -9.896618896845819, 4.568568616351242, -15.313570491727944,
+                        -13.762961360873966, 7.156100301980509, 16.722282219843990, 26.716200609071898,
+                        -1.991466398777079, -2.523342564719335, 9.776486693095093, -5.297535127628603,
+                        -16.639070567471094, -10.302057295211819, -23.549487860816846, 1.506624392156384,
+                        -17.939174438345930, 13.105792202765040, -1.943329906928462, -1.516005841666695,
+                        -0.759066561832886, 20.793137744128977, -2.485236153005426, 27.588238710486976,
+                        2.658333257106881, -15.998337823623046, -5.550742066720694, -14.219077806826615},
+                1E-12);
+
+        // Check standard errors from R
+        errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[]{
+                0.10470063765677, 0.41684100584290,
+                0.43370143099691, 0.07694953606522}, errors, 1E-10);
+
+        // Check regression standard error against R
+        Assert.assertEquals(17.24710630547, mdl.estimateRegressionStandardError(), 1E-10);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.946350722085, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.9413600915813, mdl.calculateAdjustedRSquared(), 1E-12);
+    }
+
+    /**
+     * Test hat matrix computation
+     */
+    @Test
+    public void testHat() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        /*
+         * This example is from "The Hat Matrix in Regression and ANOVA",
+         * David C. Hoaglin and Roy E. Welsch,
+         * The American Statistician, Vol. 32, No. 1 (Feb., 1978), pp. 17-22.
+         *
+         */
+        double[] design = new double[]{
+                11.14, .499, 11.1,
+                12.74, .558, 8.9,
+                13.13, .604, 8.8,
+                11.51, .441, 8.9,
+                12.38, .550, 8.8,
+                12.60, .528, 9.9,
+                11.13, .418, 10.7,
+                11.7, .480, 10.5,
+                11.02, .406, 10.5,
+                11.41, .467, 10.7
+        };
+
+        int nobs = 10;
+        int nvars = 2;
+
+        // Estimate the model
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(design, nobs, nvars, new SparseBlockDistributedMatrix());
+
+        Matrix hat = mdl.calculateHat();
+
+        // Reference data is upper half of symmetric hat matrix
+        double[] refData = new double[]{
+                .418, -.002, .079, -.274, -.046, .181, .128, .222, .050, .242,
+                .242, .292, .136, .243, .128, -.041, .033, -.035, .004,
+                .417, -.019, .273, .187, -.126, .044, -.153, .004,
+                .604, .197, -.038, .168, -.022, .275, -.028,
+                .252, .111, -.030, .019, -.010, -.010,
+                .148, .042, .117, .012, .111,
+                .262, .145, .277, .174,
+                .154, .120, .168,
+                .315, .148,
+                .187
+        };
+
+        // Check against reference data and verify symmetry
+        int k = 0;
+        for (int i = 0; i < 10; i++) {
+            for (int j = i; j < 10; j++) {
+                Assert.assertEquals(refData[k], hat.getX(i, j), 10e-3);
+                Assert.assertEquals(hat.getX(i, j), hat.getX(j, i), 10e-12);
+                k++;
+            }
+        }
+
+        /*
+         * Verify that residuals computed using the hat matrix are close to
+         * what we get from direct computation, i.e. r = (I - H) y
+         */
+        double[] residuals = mdl.estimateResiduals();
+        Matrix id = MatrixUtil.identityLike(hat, 10);
+        double[] hatResiduals = id.minus(hat).times(mdl.getY()).getStorage().data();
+        TestUtils.assertEquals(residuals, hatResiduals, 10e-12);
+    }
+
+    /**
+     * test calculateYVariance
+     */
+    @Test
+    public void testYVariance() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        // assumes: y = new double[]{11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(new SparseBlockDistributedVector(y), new SparseBlockDistributedMatrix(x));
+        TestUtils.assertEquals(mdl.calculateYVariance(), 3.5, 0);
+    }
+
+    /**
+     * Verifies that setting X and Y separately has the same effect as newSample(X,Y).
+     */
+    @Test
+    public void testNewSample2() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] y = new double[]{1, 2, 3, 4};
+        double[][] x = new double[][]{
+                {19, 22, 33},
+                {20, 30, 40},
+                {25, 35, 45},
+                {27, 37, 47}
+        };
+        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
+        regression.newSampleData(new SparseBlockDistributedVector(y), new SparseBlockDistributedMatrix(x));
+        Matrix combinedX = regression.getX().copy();
+        Vector combinedY = regression.getY().copy();
+        regression.newXSampleData(new SparseBlockDistributedMatrix(x));
+        regression.newYSampleData(new SparseBlockDistributedVector(y));
+        for (int i = 0; i < combinedX.rowSize(); i++) {
+            for (int j = 0; j < combinedX.columnSize(); j++)
+                Assert.assertEquals(combinedX.get(i, j), regression.getX().get(i, j), PRECISION);
+
+        }
+        for (int i = 0; i < combinedY.size(); i++)
+            Assert.assertEquals(combinedY.get(i), regression.getY().get(i), PRECISION);
+
+
+        // No intercept
+        regression.setNoIntercept(true);
+        regression.newSampleData(new SparseBlockDistributedVector(y), new SparseBlockDistributedMatrix(x));
+        combinedX = regression.getX().copy();
+        combinedY = regression.getY().copy();
+        regression.newXSampleData(new SparseBlockDistributedMatrix(x));
+        regression.newYSampleData(new SparseBlockDistributedVector(y));
+
+        for (int i = 0; i < combinedX.rowSize(); i++) {
+            for (int j = 0; j < combinedX.columnSize(); j++)
+                Assert.assertEquals(combinedX.get(i, j), regression.getX().get(i, j), PRECISION);
+
+        }
+        for (int i = 0; i < combinedY.size(); i++)
+            Assert.assertEquals(combinedY.get(i), regression.getY().get(i), PRECISION);
+
+    }
+
+    /** */
+    @Test(expected = NullArgumentException.class)
+    public void testNewSampleDataYNull() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            createRegression().newSampleData(null, new SparseBlockDistributedMatrix(new double[][]{{1}}));
+            fail("NullArgumentException");
+        } catch (NullArgumentException e) {
+            return;
+        }
+        fail("NullArgumentException");
+    }
+
+    /** */
+    public void testNewSampleDataXNull() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            createRegression().newSampleData(new SparseBlockDistributedVector(new double[]{1}), null);
+            fail("NullArgumentException");
+        } catch (NullArgumentException e) {
+            return;
+        }
+        fail("NullArgumentException");
+
+
+    }
+
+    /**
+     * This is a test based on the Wampler1 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler1.shtml
+     */
+    @Test
+    public void testWampler1() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[]{
+                1, 0,
+                6, 1,
+                63, 2,
+                364, 3,
+                1365, 4,
+                3906, 5,
+                9331, 6,
+                19608, 7,
+                37449, 8,
+                66430, 9,
+                111111, 10,
+                177156, 11,
+                271453, 12,
+                402234, 13,
+                579195, 14,
+                813616, 15,
+                1118481, 16,
+                1508598, 17,
+                2000719, 18,
+                2613660, 19,
+                3368421, 20};
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseBlockDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        1.0,
+                        1.0, 1.0,
+                        1.0, 1.0,
+                        1.0}, 1E-8);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+                new double[]{
+                        0.0,
+                        0.0, 0.0,
+                        0.0, 0.0,
+                        0.0}, 1E-8);
+
+        TestUtils.assertEquals(1.0, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(0, mdl.estimateErrorVariance(), 1.0e-7);
+        TestUtils.assertEquals(0.00, mdl.calculateResidualSumOfSquares(), 1.0e-6);
+    }
+
+    /**
+     * This is a test based on the Wampler2 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler2.shtml
+     */
+    @Test
+    public void testWampler2() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[]{
+                1.00000, 0,
+                1.11111, 1,
+                1.24992, 2,
+                1.42753, 3,
+                1.65984, 4,
+                1.96875, 5,
+                2.38336, 6,
+                2.94117, 7,
+                3.68928, 8,
+                4.68559, 9,
+                6.00000, 10,
+                7.71561, 11,
+                9.92992, 12,
+                12.75603, 13,
+                16.32384, 14,
+                20.78125, 15,
+                26.29536, 16,
+                33.05367, 17,
+                41.26528, 18,
+                51.16209, 19,
+                63.00000, 20};
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseBlockDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        1.0,
+                        1.0e-1,
+                        1.0e-2,
+                        1.0e-3, 1.0e-4,
+                        1.0e-5}, 1E-8);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+                new double[]{
+                        0.0,
+                        0.0, 0.0,
+                        0.0, 0.0,
+                        0.0}, 1E-8);
+        TestUtils.assertEquals(1.0, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(0, mdl.estimateErrorVariance(), 1.0e-7);
+        TestUtils.assertEquals(0.00, mdl.calculateResidualSumOfSquares(), 1.0e-6);
+    }
+
+    /**
+     * This is a test based on the Wampler3 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler3.shtml
+     */
+    @Test
+    public void testWampler3() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[]{
+                760, 0,
+                -2042, 1,
+                2111, 2,
+                -1684, 3,
+                3888, 4,
+                1858, 5,
+                11379, 6,
+                17560, 7,
+                39287, 8,
+                64382, 9,
+                113159, 10,
+                175108, 11,
+                273291, 12,
+                400186, 13,
+                581243, 14,
+                811568, 15,
+                1121004, 16,
+                1506550, 17,
+                2002767, 18,
+                2611612, 19,
+                3369180, 20};
+
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseBlockDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        1.0,
+                        1.0,
+                        1.0,
+                        1.0,
+                        1.0,
+                        1.0}, 1E-8);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+                new double[]{
+                        2152.32624678170,
+                        2363.55173469681, 779.343524331583,
+                        101.475507550350, 5.64566512170752,
+                        0.112324854679312}, 1E-8); //
+
+        TestUtils.assertEquals(.999995559025820, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(5570284.53333333, mdl.estimateErrorVariance(), 1.0e-6);
+        TestUtils.assertEquals(83554268.0000000, mdl.calculateResidualSumOfSquares(), 1.0e-5);
+    }
+
+    /**
+     * This is a test based on the Wampler4 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler4.shtml
+     */
+    @Test
+    public void testWampler4() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[]{
+                75901, 0,
+                -204794, 1,
+                204863, 2,
+                -204436, 3,
+                253665, 4,
+                -200894, 5,
+                214131, 6,
+                -185192, 7,
+                221249, 8,
+                -138370, 9,
+                315911, 10,
+                -27644, 11,
+                455253, 12,
+                197434, 13,
+                783995, 14,
+                608816, 15,
+                1370781, 16,
+                1303798, 17,
+                2205519, 18,
+                2408860, 19,
+                3444321, 20};
+
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseBlockDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+                new double[]{
+                        1.0,
+                        1.0,
+                        1.0,
+                        1.0,
+                        1.0,
+                        1.0}, 1E-6);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+                new double[]{
+                        215232.624678170,
+                        236355.173469681, 77934.3524331583,
+                        10147.5507550350, 564.566512170752,
+                        11.2324854679312}, 1E-8);
+
+        TestUtils.assertEquals(.957478440825662, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(55702845333.3333, mdl.estimateErrorVariance(), 1.0e-4);
+        TestUtils.assertEquals(835542680000.000, mdl.calculateResidualSumOfSquares(), 1.0e-3);
+    }
+
+    /**
+     * Anything requiring beta calculation should advertise SME.
+     */
+    public void testSingularCalculateBeta() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression(1e-15);
+        mdl.newSampleData(new double[]{1, 2, 3, 1, 2, 3, 1, 2, 3}, 3, 2, new SparseBlockDistributedMatrix());
+
+        try {
+            mdl.calculateBeta();
+            fail("SingularMatrixException");
+        } catch (SingularMatrixException e) {
+            return;
+        }
+        fail("SingularMatrixException");
+
+    }
+
+    /** */
+    public void testNoDataNPECalculateBeta() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        try {
+            mdl.calculateBeta();
+            fail("java.lang.NullPointerException");
+        } catch (NullPointerException e) {
+            return;
+        }
+        fail("java.lang.NullPointerException");
+
+    }
+
+    /** */
+    public void testNoDataNPECalculateHat() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        try {
+            mdl.calculateHat();
+            fail("java.lang.NullPointerException");
+        } catch (NullPointerException e) {
+            return;
+        }
+        fail("java.lang.NullPointerException");
+    }
+
+    /** */
+    public void testNoDataNPESSTO() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        try {
+            mdl.calculateTotalSumOfSquares();
+            fail("java.lang.NullPointerException");
+        } catch (NullPointerException e) {
+            return;
+        }
+        fail("java.lang.NullPointerException");
+
+
+    }
+
+    /** */
+    public void testMathIllegalArgumentException() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+
+        try {
+            mdl.validateSampleData(new SparseBlockDistributedMatrix(1, 2), new SparseBlockDistributedVector(1));
+            fail("MathIllegalArgumentException");
+        } catch (MathIllegalArgumentException e) {
+            return;
+        }
+        fail("MathIllegalArgumentException");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedOLSMultipleLinearRegressionTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedOLSMultipleLinearRegressionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedOLSMultipleLinearRegressionTest.java
new file mode 100644
index 0000000..764340c
--- /dev/null
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/DistributedOLSMultipleLinearRegressionTest.java
@@ -0,0 +1,934 @@
+/*
+ * 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.ml.regressions;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.util.IgniteUtils;
+import org.apache.ignite.ml.TestUtils;
+import org.apache.ignite.ml.math.Matrix;
+import org.apache.ignite.ml.math.Vector;
+import org.apache.ignite.ml.math.exceptions.MathIllegalArgumentException;
+import org.apache.ignite.ml.math.exceptions.NullArgumentException;
+import org.apache.ignite.ml.math.exceptions.SingularMatrixException;
+import org.apache.ignite.ml.math.impls.matrix.SparseDistributedMatrix;
+import org.apache.ignite.ml.math.impls.vector.SparseDistributedVector;
+import org.apache.ignite.ml.math.util.MatrixUtil;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.apache.ignite.testframework.junits.common.GridCommonTest;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for {@link OLSMultipleLinearRegression}.
+ */
+
+@GridCommonTest(group = "Distributed Models")
+public class DistributedOLSMultipleLinearRegressionTest extends GridCommonAbstractTest {
+    /** */
+    private double[] y;
+
+    /** */
+    private double[][] x;
+
+    private AbstractMultipleLinearRegression regression;
+
+    /** Number of nodes in grid */
+    private static final int NODE_COUNT = 3;
+
+    private static final double PRECISION = 1E-12;
+
+    /** Grid instance. */
+    private Ignite ignite;
+
+    public DistributedOLSMultipleLinearRegressionTest(){
+
+        super(false);
+
+
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        for (int i = 1; i <= NODE_COUNT; i++)
+            startGrid(i);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override protected void beforeTest() throws Exception {
+        ignite = grid(NODE_COUNT);
+
+        ignite.configuration().setPeerClassLoadingEnabled(true);
+
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+
+        y = new double[] {11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
+        x = new double[6][];
+        x[0] = new double[] {0, 0, 0, 0, 0};
+        x[1] = new double[] {2.0, 0, 0, 0, 0};
+        x[2] = new double[] {0, 3.0, 0, 0, 0};
+        x[3] = new double[] {0, 0, 4.0, 0, 0};
+        x[4] = new double[] {0, 0, 0, 5.0, 0};
+        x[5] = new double[] {0, 0, 0, 0, 6.0};
+
+        regression = createRegression();
+    }
+
+    /** */
+    protected OLSMultipleLinearRegression createRegression() {
+        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
+        regression.newSampleData(new SparseDistributedVector(y), new SparseDistributedMatrix(x));
+        return regression;
+    }
+
+    /** */
+    @Test
+    public void testPerfectFit() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[] betaHat = regression.estimateRegressionParameters();
+        System.out.println("Beta hat is " + betaHat);
+        TestUtils.assertEquals(new double[] {11.0, 1.0 / 2.0, 2.0 / 3.0, 3.0 / 4.0, 4.0 / 5.0, 5.0 / 6.0},
+            betaHat,
+            1e-13);
+        double[] residuals = regression.estimateResiduals();
+        TestUtils.assertEquals(new double[] {0d, 0d, 0d, 0d, 0d, 0d}, residuals,
+            1e-13);
+        Matrix errors = regression.estimateRegressionParametersVariance();
+        final double[] s = {1.0, -1.0 / 2.0, -1.0 / 3.0, -1.0 / 4.0, -1.0 / 5.0, -1.0 / 6.0};
+        Matrix refVar = new SparseDistributedMatrix(s.length, s.length);
+        for (int i = 0; i < refVar.rowSize(); i++)
+            for (int j = 0; j < refVar.columnSize(); j++) {
+                if (i == 0) {
+                    refVar.setX(i, j, s[j]);
+                    continue;
+                }
+                double x = s[i] * s[j];
+                refVar.setX(i, j, (i == j) ? 2 * x : x);
+            }
+        Assert.assertEquals(0.0,
+            TestUtils.maximumAbsoluteRowSum(errors.minus(refVar)),
+            5.0e-16 * TestUtils.maximumAbsoluteRowSum(refVar));
+        Assert.assertEquals(1, ((OLSMultipleLinearRegression)regression).calculateRSquared(), 1E-12);
+    }
+
+    /**
+     * Test Longley dataset against certified values provided by NIST.
+     * Data Source: J. Longley (1967) "An Appraisal of Least Squares
+     * Programs for the Electronic Computer from the Point of View of the User"
+     * Journal of the American Statistical Association, vol. 62. September,
+     * pp. 819-841.
+     *
+     * Certified values (and data) are from NIST:
+     * http://www.itl.nist.gov/div898/strd/lls/data/LINKS/DATA/Longley.dat
+     */
+    @Test
+    public void testLongly() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        // Y values are first, then independent vars
+        // Each row is one observation
+        double[] design = new double[] {
+            60323, 83.0, 234289, 2356, 1590, 107608, 1947,
+            61122, 88.5, 259426, 2325, 1456, 108632, 1948,
+            60171, 88.2, 258054, 3682, 1616, 109773, 1949,
+            61187, 89.5, 284599, 3351, 1650, 110929, 1950,
+            63221, 96.2, 328975, 2099, 3099, 112075, 1951,
+            63639, 98.1, 346999, 1932, 3594, 113270, 1952,
+            64989, 99.0, 365385, 1870, 3547, 115094, 1953,
+            63761, 100.0, 363112, 3578, 3350, 116219, 1954,
+            66019, 101.2, 397469, 2904, 3048, 117388, 1955,
+            67857, 104.6, 419180, 2822, 2857, 118734, 1956,
+            68169, 108.4, 442769, 2936, 2798, 120445, 1957,
+            66513, 110.8, 444546, 4681, 2637, 121950, 1958,
+            68655, 112.6, 482704, 3813, 2552, 123366, 1959,
+            69564, 114.2, 502601, 3931, 2514, 125368, 1960,
+            69331, 115.7, 518173, 4806, 2572, 127852, 1961,
+            70551, 116.9, 554894, 4007, 2827, 130081, 1962
+        };
+
+        final int nobs = 16;
+        final int nvars = 6;
+
+        // Estimate the model
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(design, nobs, nvars, new SparseDistributedMatrix());
+
+        // Check expected beta values from NIST
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                -3482258.63459582, 15.0618722713733,
+                -0.358191792925910E-01, -2.02022980381683,
+                -1.03322686717359, -0.511041056535807E-01,
+                1829.15146461355}, 2E-6); //
+
+        // Check expected residuals from R
+        double[] residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[] {
+                267.340029759711, -94.0139423988359, 46.28716775752924,
+                -410.114621930906, 309.7145907602313, -249.3112153297231,
+                -164.0489563956039, -13.18035686637081, 14.30477260005235,
+                455.394094551857, -17.26892711483297, -39.0550425226967,
+                -155.5499735953195, -85.6713080421283, 341.9315139607727,
+                -206.7578251937366},
+            1E-7);
+
+        // Check standard errors from NIST
+        double[] errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[] {
+            890420.383607373,
+            84.9149257747669,
+            0.334910077722432E-01,
+            0.488399681651699,
+            0.214274163161675,
+            0.226073200069370,
+            455.478499142212}, errors, 1E-6);
+
+        // Check regression standard error against R
+        Assert.assertEquals(304.8540735619638, mdl.estimateRegressionStandardError(), 1E-8);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.995479004577296, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.992465007628826, mdl.calculateAdjustedRSquared(), 1E-12);
+
+        // TODO: IGNITE-5826, uncomment.
+        // checkVarianceConsistency(model);
+
+        // Estimate model without intercept
+        mdl.setNoIntercept(true);
+        mdl.newSampleData(design, nobs, nvars, new SparseDistributedMatrix());
+
+        // Check expected beta values from R
+        betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                -52.99357013868291, 0.07107319907358,
+                -0.42346585566399, -0.57256866841929,
+                -0.41420358884978, 48.41786562001326}, 1E-8);
+
+        // Check standard errors from R
+        errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[] {
+            129.54486693117232, 0.03016640003786,
+            0.41773654056612, 0.27899087467676, 0.32128496193363,
+            17.68948737819961}, errors, 1E-11);
+
+        // Check expected residuals from R
+        residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[] {
+                279.90274927293092, -130.32465380836874, 90.73228661967445, -401.31252201634948,
+                -440.46768772620027, -543.54512853774793, 201.32111639536299, 215.90889365977932,
+                73.09368242049943, 913.21694494481869, 424.82484953610174, -8.56475876776709,
+                -361.32974610842876, 27.34560497213464, 151.28955976355002, -492.49937355336846},
+            1E-8);
+
+        // Check regression standard error against R
+        Assert.assertEquals(475.1655079819517, mdl.estimateRegressionStandardError(), 1E-10);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.9999670130706, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.999947220913, mdl.calculateAdjustedRSquared(), 1E-12);
+
+    }
+
+    /**
+     * Test R Swiss fertility dataset against R.
+     * Data Source: R datasets package
+     */
+    @Test
+    public void testSwissFertility() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        double[] design = new double[] {
+            80.2, 17.0, 15, 12, 9.96,
+            83.1, 45.1, 6, 9, 84.84,
+            92.5, 39.7, 5, 5, 93.40,
+            85.8, 36.5, 12, 7, 33.77,
+            76.9, 43.5, 17, 15, 5.16,
+            76.1, 35.3, 9, 7, 90.57,
+            83.8, 70.2, 16, 7, 92.85,
+            92.4, 67.8, 14, 8, 97.16,
+            82.4, 53.3, 12, 7, 97.67,
+            82.9, 45.2, 16, 13, 91.38,
+            87.1, 64.5, 14, 6, 98.61,
+            64.1, 62.0, 21, 12, 8.52,
+            66.9, 67.5, 14, 7, 2.27,
+            68.9, 60.7, 19, 12, 4.43,
+            61.7, 69.3, 22, 5, 2.82,
+            68.3, 72.6, 18, 2, 24.20,
+            71.7, 34.0, 17, 8, 3.30,
+            55.7, 19.4, 26, 28, 12.11,
+            54.3, 15.2, 31, 20, 2.15,
+            65.1, 73.0, 19, 9, 2.84,
+            65.5, 59.8, 22, 10, 5.23,
+            65.0, 55.1, 14, 3, 4.52,
+            56.6, 50.9, 22, 12, 15.14,
+            57.4, 54.1, 20, 6, 4.20,
+            72.5, 71.2, 12, 1, 2.40,
+            74.2, 58.1, 14, 8, 5.23,
+            72.0, 63.5, 6, 3, 2.56,
+            60.5, 60.8, 16, 10, 7.72,
+            58.3, 26.8, 25, 19, 18.46,
+            65.4, 49.5, 15, 8, 6.10,
+            75.5, 85.9, 3, 2, 99.71,
+            69.3, 84.9, 7, 6, 99.68,
+            77.3, 89.7, 5, 2, 100.00,
+            70.5, 78.2, 12, 6, 98.96,
+            79.4, 64.9, 7, 3, 98.22,
+            65.0, 75.9, 9, 9, 99.06,
+            92.2, 84.6, 3, 3, 99.46,
+            79.3, 63.1, 13, 13, 96.83,
+            70.4, 38.4, 26, 12, 5.62,
+            65.7, 7.7, 29, 11, 13.79,
+            72.7, 16.7, 22, 13, 11.22,
+            64.4, 17.6, 35, 32, 16.92,
+            77.6, 37.6, 15, 7, 4.97,
+            67.6, 18.7, 25, 7, 8.65,
+            35.0, 1.2, 37, 53, 42.34,
+            44.7, 46.6, 16, 29, 50.43,
+            42.8, 27.7, 22, 29, 58.33
+        };
+
+        final int nobs = 47;
+        final int nvars = 4;
+
+        // Estimate the model
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(design, nobs, nvars, new SparseDistributedMatrix());
+
+        // Check expected beta values from R
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                91.05542390271397,
+                -0.22064551045715,
+                -0.26058239824328,
+                -0.96161238456030,
+                0.12441843147162}, 1E-12);
+
+        // Check expected residuals from R
+        double[] residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[] {
+                7.1044267859730512, 1.6580347433531366,
+                4.6944952770029644, 8.4548022690166160, 13.6547432343186212,
+                -9.3586864458500774, 7.5822446330520386, 15.5568995563859289,
+                0.8113090736598980, 7.1186762732484308, 7.4251378771228724,
+                2.6761316873234109, 0.8351584810309354, 7.1769991119615177,
+                -3.8746753206299553, -3.1337779476387251, -0.1412575244091504,
+                1.1186809170469780, -6.3588097346816594, 3.4039270429434074,
+                2.3374058329820175, -7.9272368576900503, -7.8361010968497959,
+                -11.2597369269357070, 0.9445333697827101, 6.6544245101380328,
+                -0.9146136301118665, -4.3152449403848570, -4.3536932047009183,
+                -3.8907885169304661, -6.3027643926302188, -7.8308982189289091,
+                -3.1792280015332750, -6.7167298771158226, -4.8469946718041754,
+                -10.6335664353633685, 11.1031134362036958, 6.0084032641811733,
+                5.4326230830188482, -7.2375578629692230, 2.1671550814448222,
+                15.0147574652763112, 4.8625103516321015, -7.1597256413907706,
+                -0.4515205619767598, -10.2916870903837587, -15.7812984571900063},
+            1E-12);
+
+        // Check standard errors from R
+        double[] errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[] {
+            6.94881329475087,
+            0.07360008972340,
+            0.27410957467466,
+            0.19454551679325,
+            0.03726654773803}, errors, 1E-10);
+
+        // Check regression standard error against R
+        Assert.assertEquals(7.73642194433223, mdl.estimateRegressionStandardError(), 1E-12);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.649789742860228, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.6164363850373927, mdl.calculateAdjustedRSquared(), 1E-12);
+
+        // TODO: IGNITE-5826, uncomment.
+        // checkVarianceConsistency(model);
+
+        // Estimate the model with no intercept
+        mdl = new OLSMultipleLinearRegression();
+        mdl.setNoIntercept(true);
+        mdl.newSampleData(design, nobs, nvars, new SparseDistributedMatrix());
+
+        // Check expected beta values from R
+        betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                0.52191832900513,
+                2.36588087917963,
+                -0.94770353802795,
+                0.30851985863609}, 1E-12);
+
+        // Check expected residuals from R
+        residuals = mdl.estimateResiduals();
+        TestUtils.assertEquals(residuals, new double[] {
+                44.138759883538249, 27.720705122356215, 35.873200836126799,
+                34.574619581211977, 26.600168342080213, 15.074636243026923, -12.704904871199814,
+                1.497443824078134, 2.691972687079431, 5.582798774291231, -4.422986561283165,
+                -9.198581600334345, 4.481765170730647, 2.273520207553216, -22.649827853221336,
+                -17.747900013943308, 20.298314638496436, 6.861405135329779, -8.684712790954924,
+                -10.298639278062371, -9.896618896845819, 4.568568616351242, -15.313570491727944,
+                -13.762961360873966, 7.156100301980509, 16.722282219843990, 26.716200609071898,
+                -1.991466398777079, -2.523342564719335, 9.776486693095093, -5.297535127628603,
+                -16.639070567471094, -10.302057295211819, -23.549487860816846, 1.506624392156384,
+                -17.939174438345930, 13.105792202765040, -1.943329906928462, -1.516005841666695,
+                -0.759066561832886, 20.793137744128977, -2.485236153005426, 27.588238710486976,
+                2.658333257106881, -15.998337823623046, -5.550742066720694, -14.219077806826615},
+            1E-12);
+
+        // Check standard errors from R
+        errors = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(new double[] {
+            0.10470063765677, 0.41684100584290,
+            0.43370143099691, 0.07694953606522}, errors, 1E-10);
+
+        // Check regression standard error against R
+        Assert.assertEquals(17.24710630547, mdl.estimateRegressionStandardError(), 1E-10);
+
+        // Check R-Square statistics against R
+        Assert.assertEquals(0.946350722085, mdl.calculateRSquared(), 1E-12);
+        Assert.assertEquals(0.9413600915813, mdl.calculateAdjustedRSquared(), 1E-12);
+    }
+
+    /**
+     * Test hat matrix computation
+     */
+    @Test
+    public void testHat() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        /*
+         * This example is from "The Hat Matrix in Regression and ANOVA",
+         * David C. Hoaglin and Roy E. Welsch,
+         * The American Statistician, Vol. 32, No. 1 (Feb., 1978), pp. 17-22.
+         *
+         */
+        double[] design = new double[] {
+            11.14, .499, 11.1,
+            12.74, .558, 8.9,
+            13.13, .604, 8.8,
+            11.51, .441, 8.9,
+            12.38, .550, 8.8,
+            12.60, .528, 9.9,
+            11.13, .418, 10.7,
+            11.7, .480, 10.5,
+            11.02, .406, 10.5,
+            11.41, .467, 10.7
+        };
+
+        int nobs = 10;
+        int nvars = 2;
+
+        // Estimate the model
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(design, nobs, nvars, new SparseDistributedMatrix());
+
+        Matrix hat = mdl.calculateHat();
+
+        // Reference data is upper half of symmetric hat matrix
+        double[] refData = new double[] {
+            .418, -.002, .079, -.274, -.046, .181, .128, .222, .050, .242,
+            .242, .292, .136, .243, .128, -.041, .033, -.035, .004,
+            .417, -.019, .273, .187, -.126, .044, -.153, .004,
+            .604, .197, -.038, .168, -.022, .275, -.028,
+            .252, .111, -.030, .019, -.010, -.010,
+            .148, .042, .117, .012, .111,
+            .262, .145, .277, .174,
+            .154, .120, .168,
+            .315, .148,
+            .187
+        };
+
+        // Check against reference data and verify symmetry
+        int k = 0;
+        for (int i = 0; i < 10; i++) {
+            for (int j = i; j < 10; j++) {
+                Assert.assertEquals(refData[k], hat.getX(i, j), 10e-3);
+                Assert.assertEquals(hat.getX(i, j), hat.getX(j, i), 10e-12);
+                k++;
+            }
+        }
+
+        /*
+         * Verify that residuals computed using the hat matrix are close to
+         * what we get from direct computation, i.e. r = (I - H) y
+         */
+        double[] residuals = mdl.estimateResiduals();
+        Matrix id = MatrixUtil.identityLike(hat, 10);
+        double[] hatResiduals = id.minus(hat).times(mdl.getY()).getStorage().data();
+        TestUtils.assertEquals(residuals, hatResiduals, 10e-12);
+    }
+
+    /**
+     * test calculateYVariance
+     */
+    @Test
+    public void testYVariance() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        // assumes: y = new double[]{11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        mdl.newSampleData(new SparseDistributedVector(y), new SparseDistributedMatrix(x));
+        TestUtils.assertEquals(mdl.calculateYVariance(), 3.5, 0);
+    }
+
+    /**
+     * Verifies that setting X and Y separately has the same effect as newSample(X,Y).
+     */
+    @Test
+    public void testNewSample2() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] y = new double[] {1, 2, 3, 4};
+        double[][] x = new double[][] {
+            {19, 22, 33},
+            {20, 30, 40},
+            {25, 35, 45},
+            {27, 37, 47}
+        };
+        OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
+        regression.newSampleData(new SparseDistributedVector(y), new SparseDistributedMatrix(x));
+        Matrix combinedX = regression.getX().copy();
+        Vector combinedY = regression.getY().copy();
+        regression.newXSampleData(new SparseDistributedMatrix(x));
+        regression.newYSampleData(new SparseDistributedVector(y));
+        for (int i = 0; i < combinedX.rowSize(); i++) {
+            for (int j = 0; j < combinedX.columnSize(); j++)
+                Assert.assertEquals(combinedX.get(i,j), regression.getX().get(i,j), PRECISION);
+
+        }
+        for (int i = 0; i < combinedY.size(); i++)
+            Assert.assertEquals(combinedY.get(i), regression.getY().get(i), PRECISION);
+
+
+
+        // No intercept
+        regression.setNoIntercept(true);
+        regression.newSampleData(new SparseDistributedVector(y), new SparseDistributedMatrix(x));
+        combinedX = regression.getX().copy();
+        combinedY = regression.getY().copy();
+        regression.newXSampleData(new SparseDistributedMatrix(x));
+        regression.newYSampleData(new SparseDistributedVector(y));
+
+        for (int i = 0; i < combinedX.rowSize(); i++) {
+            for (int j = 0; j < combinedX.columnSize(); j++)
+                Assert.assertEquals(combinedX.get(i,j), regression.getX().get(i,j), PRECISION);
+
+        }
+        for (int i = 0; i < combinedY.size(); i++)
+            Assert.assertEquals(combinedY.get(i), regression.getY().get(i), PRECISION);
+
+    }
+
+    /** */
+    @Test(expected = NullArgumentException.class)
+    public void testNewSampleDataYNull() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            createRegression().newSampleData(null, new SparseDistributedMatrix(new double[][] {{1}}));
+            fail("NullArgumentException");
+        }
+        catch (NullArgumentException e) {
+            return;
+        }
+        fail("NullArgumentException");
+    }
+
+    /** */
+    public void testNewSampleDataXNull() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+
+        try {
+            createRegression().newSampleData(new SparseDistributedVector(new double[] {1}), null);
+            fail("NullArgumentException");
+        }
+        catch (NullArgumentException e) {
+            return;
+        }
+        fail("NullArgumentException");
+
+
+    }
+
+    /**
+     * This is a test based on the Wampler1 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler1.shtml
+     */
+    @Test
+    public void testWampler1() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[] {
+            1, 0,
+            6, 1,
+            63, 2,
+            364, 3,
+            1365, 4,
+            3906, 5,
+            9331, 6,
+            19608, 7,
+            37449, 8,
+            66430, 9,
+            111111, 10,
+            177156, 11,
+            271453, 12,
+            402234, 13,
+            579195, 14,
+            813616, 15,
+            1118481, 16,
+            1508598, 17,
+            2000719, 18,
+            2613660, 19,
+            3368421, 20};
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                1.0,
+                1.0, 1.0,
+                1.0, 1.0,
+                1.0}, 1E-8);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+            new double[] {
+                0.0,
+                0.0, 0.0,
+                0.0, 0.0,
+                0.0}, 1E-8);
+
+        TestUtils.assertEquals(1.0, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(0, mdl.estimateErrorVariance(), 1.0e-7);
+        TestUtils.assertEquals(0.00, mdl.calculateResidualSumOfSquares(), 1.0e-6);
+    }
+
+    /**
+     * This is a test based on the Wampler2 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler2.shtml
+     */
+    @Test
+    public void testWampler2() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[] {
+            1.00000, 0,
+            1.11111, 1,
+            1.24992, 2,
+            1.42753, 3,
+            1.65984, 4,
+            1.96875, 5,
+            2.38336, 6,
+            2.94117, 7,
+            3.68928, 8,
+            4.68559, 9,
+            6.00000, 10,
+            7.71561, 11,
+            9.92992, 12,
+            12.75603, 13,
+            16.32384, 14,
+            20.78125, 15,
+            26.29536, 16,
+            33.05367, 17,
+            41.26528, 18,
+            51.16209, 19,
+            63.00000, 20};
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                1.0,
+                1.0e-1,
+                1.0e-2,
+                1.0e-3, 1.0e-4,
+                1.0e-5}, 1E-8);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+            new double[] {
+                0.0,
+                0.0, 0.0,
+                0.0, 0.0,
+                0.0}, 1E-8);
+        TestUtils.assertEquals(1.0, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(0, mdl.estimateErrorVariance(), 1.0e-7);
+        TestUtils.assertEquals(0.00, mdl.calculateResidualSumOfSquares(), 1.0e-6);
+    }
+
+    /**
+     * This is a test based on the Wampler3 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler3.shtml
+     */
+    @Test
+    public void testWampler3() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[] {
+            760, 0,
+            -2042, 1,
+            2111, 2,
+            -1684, 3,
+            3888, 4,
+            1858, 5,
+            11379, 6,
+            17560, 7,
+            39287, 8,
+            64382, 9,
+            113159, 10,
+            175108, 11,
+            273291, 12,
+            400186, 13,
+            581243, 14,
+            811568, 15,
+            1121004, 16,
+            1506550, 17,
+            2002767, 18,
+            2611612, 19,
+            3369180, 20};
+
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0}, 1E-8);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+            new double[] {
+                2152.32624678170,
+                2363.55173469681, 779.343524331583,
+                101.475507550350, 5.64566512170752,
+                0.112324854679312}, 1E-8); //
+
+        TestUtils.assertEquals(.999995559025820, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(5570284.53333333, mdl.estimateErrorVariance(), 1.0e-6);
+        TestUtils.assertEquals(83554268.0000000, mdl.calculateResidualSumOfSquares(), 1.0e-5);
+    }
+
+    /**
+     * This is a test based on the Wampler4 data set
+     * http://www.itl.nist.gov/div898/strd/lls/data/Wampler4.shtml
+     */
+    @Test
+    public void testWampler4() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        double[] data = new double[] {
+            75901, 0,
+            -204794, 1,
+            204863, 2,
+            -204436, 3,
+            253665, 4,
+            -200894, 5,
+            214131, 6,
+            -185192, 7,
+            221249, 8,
+            -138370, 9,
+            315911, 10,
+            -27644, 11,
+            455253, 12,
+            197434, 13,
+            783995, 14,
+            608816, 15,
+            1370781, 16,
+            1303798, 17,
+            2205519, 18,
+            2408860, 19,
+            3444321, 20};
+
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+        final int nvars = 5;
+        final int nobs = 21;
+        double[] tmp = new double[(nvars + 1) * nobs];
+        int off = 0;
+        int off2 = 0;
+        for (int i = 0; i < nobs; i++) {
+            tmp[off2] = data[off];
+            tmp[off2 + 1] = data[off + 1];
+            tmp[off2 + 2] = tmp[off2 + 1] * tmp[off2 + 1];
+            tmp[off2 + 3] = tmp[off2 + 1] * tmp[off2 + 2];
+            tmp[off2 + 4] = tmp[off2 + 1] * tmp[off2 + 3];
+            tmp[off2 + 5] = tmp[off2 + 1] * tmp[off2 + 4];
+            off2 += (nvars + 1);
+            off += 2;
+        }
+        mdl.newSampleData(tmp, nobs, nvars, new SparseDistributedMatrix());
+        double[] betaHat = mdl.estimateRegressionParameters();
+        TestUtils.assertEquals(betaHat,
+            new double[] {
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0,
+                1.0}, 1E-6);
+
+        double[] se = mdl.estimateRegressionParametersStandardErrors();
+        TestUtils.assertEquals(se,
+            new double[] {
+                215232.624678170,
+                236355.173469681, 77934.3524331583,
+                10147.5507550350, 564.566512170752,
+                11.2324854679312}, 1E-8);
+
+        TestUtils.assertEquals(.957478440825662, mdl.calculateRSquared(), 1.0e-10);
+        TestUtils.assertEquals(55702845333.3333, mdl.estimateErrorVariance(), 1.0e-4);
+        TestUtils.assertEquals(835542680000.000, mdl.calculateResidualSumOfSquares(), 1.0e-3);
+    }
+
+    /**
+     * Anything requiring beta calculation should advertise SME.
+     */
+    public void testSingularCalculateBeta() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression(1e-15);
+        mdl.newSampleData(new double[] {1, 2, 3, 1, 2, 3, 1, 2, 3}, 3, 2, new SparseDistributedMatrix());
+
+        try {
+            mdl.calculateBeta();
+            fail("SingularMatrixException");
+        }
+        catch (SingularMatrixException e) {
+            return;
+        }
+        fail("SingularMatrixException");
+
+    }
+
+    /** */
+    public void testNoDataNPECalculateBeta() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        try {
+            mdl.calculateBeta();
+            fail("java.lang.NullPointerException");
+        }
+        catch (NullPointerException e) {
+            return;
+        }
+        fail("java.lang.NullPointerException");
+
+    }
+
+    /** */
+    public void testNoDataNPECalculateHat() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        try {
+            mdl.calculateHat();
+            fail("java.lang.NullPointerException");
+        }
+        catch (NullPointerException e) {
+            return;
+        }
+        fail("java.lang.NullPointerException");
+    }
+
+
+    public void testNoDataNPESSTO() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+        try {
+            mdl.calculateTotalSumOfSquares();
+            fail("java.lang.NullPointerException");
+        }
+        catch (NullPointerException e) {
+            return;
+        }
+        fail("java.lang.NullPointerException");
+
+
+    }
+
+    /** */
+    public void testMathIllegalArgumentException() {
+        IgniteUtils.setCurrentIgniteName(ignite.configuration().getIgniteInstanceName());
+        OLSMultipleLinearRegression mdl = new OLSMultipleLinearRegression();
+
+
+        try {
+            mdl.validateSampleData(new SparseDistributedMatrix(1, 2), new SparseDistributedVector(1));
+            fail("MathIllegalArgumentException");
+        }
+        catch (MathIllegalArgumentException e) {
+            return;
+        }
+        fail("MathIllegalArgumentException");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
index 4be7336..2774028 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/OLSMultipleLinearRegressionTest.java
@@ -418,6 +418,7 @@ public class OLSMultipleLinearRegressionTest extends AbstractMultipleLinearRegre
 
         Matrix hat = mdl.calculateHat();
 
+
         // Reference data is upper half of symmetric hat matrix
         double[] refData = new double[] {
             .418, -.002, .079, -.274, -.046, .181, .128, .222, .050, .242,

http://git-wip-us.apache.org/repos/asf/ignite/blob/b0a86018/modules/ml/src/test/java/org/apache/ignite/ml/regressions/RegressionsTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/RegressionsTestSuite.java b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/RegressionsTestSuite.java
index a54a4e3..2a0b111 100644
--- a/modules/ml/src/test/java/org/apache/ignite/ml/regressions/RegressionsTestSuite.java
+++ b/modules/ml/src/test/java/org/apache/ignite/ml/regressions/RegressionsTestSuite.java
@@ -25,7 +25,7 @@ import org.junit.runners.Suite;
  */
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
-    OLSMultipleLinearRegressionTest.class
+    OLSMultipleLinearRegressionTest.class, DistributedOLSMultipleLinearRegressionTest.class, DistributedBlockOLSMultipleLinearRegressionTest.class
 })
 public class RegressionsTestSuite {
     // No-op.


[17/47] ignite git commit: IGNITE-4394 Web Console: Select only server nodes for local queries on Queries screen.

Posted by sb...@apache.org.
IGNITE-4394 Web Console: Select only server nodes for local queries on Queries screen.


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

Branch: refs/heads/ignite-zk
Commit: 63b628da4863ec79ddca211958fb32abc07f9c7d
Parents: fa52789
Author: alexdel <ve...@yandex.ru>
Authored: Wed Nov 15 21:48:15 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Wed Nov 15 21:48:15 2017 +0700

----------------------------------------------------------------------
 modules/web-console/frontend/app/modules/sql/sql.controller.js | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/63b628da/modules/web-console/frontend/app/modules/sql/sql.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/frontend/app/modules/sql/sql.controller.js b/modules/web-console/frontend/app/modules/sql/sql.controller.js
index b4c8a6f..f5edb04 100644
--- a/modules/web-console/frontend/app/modules/sql/sql.controller.js
+++ b/modules/web-console/frontend/app/modules/sql/sql.controller.js
@@ -871,7 +871,8 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
                                 ip: _.head(node.attributes['org.apache.ignite.ips'].split(', ')),
                                 version: node.attributes['org.apache.ignite.build.ver'],
                                 gridName: node.attributes['org.apache.ignite.ignite.name'],
-                                os: `${node.attributes['os.name']} ${node.attributes['os.arch']} ${node.attributes['os.version']}`
+                                os: `${node.attributes['os.name']} ${node.attributes['os.arch']} ${node.attributes['os.version']}`,
+                                client: node.attributes['org.apache.ignite.cache.client']
                             });
                         });
 
@@ -1338,7 +1339,7 @@ export default ['$rootScope', '$scope', '$http', '$q', '$timeout', '$interval',
             if (_.isEmpty(name))
                 return Promise.resolve(null);
 
-            const nodes = cacheNodes(name);
+            const nodes = _.filter(cacheNodes(name), (node) => !node.client);
 
             if (local) {
                 return Nodes.selectNode(nodes, name)


[03/47] ignite git commit: IGNITE-6863 Visor CMD: Fixed check that cache available on node.

Posted by sb...@apache.org.
IGNITE-6863 Visor CMD: Fixed check that cache available on node.


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

Branch: refs/heads/ignite-zk
Commit: e489e372ee15812f861a43313e9fa18fbec05a39
Parents: 02ccc9f
Author: vsisko <vs...@gridgain.com>
Authored: Tue Nov 14 09:44:18 2017 +0700
Committer: Alexey Kuznetsov <ak...@apache.org>
Committed: Tue Nov 14 09:44:18 2017 +0700

----------------------------------------------------------------------
 .../cache/VisorCacheMetricsCollectorTask.java   |  5 ++-
 .../visor/node/VisorGridConfiguration.java      |  6 ++-
 .../commands/cache/VisorCacheCommandSpec.scala  | 44 +++++++++++++++-----
 3 files changed, 42 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e489e372/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCacheMetricsCollectorTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCacheMetricsCollectorTask.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCacheMetricsCollectorTask.java
index 8ce3c8c..ab1fa8c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCacheMetricsCollectorTask.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/cache/VisorCacheMetricsCollectorTask.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.List;
 import java.util.Map;
 import org.apache.ignite.compute.ComputeJobResult;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
 import org.apache.ignite.internal.processors.cache.GridCacheProcessor;
 import org.apache.ignite.internal.processors.cache.IgniteCacheProxy;
 import org.apache.ignite.internal.processors.task.GridInternal;
@@ -109,7 +110,9 @@ public class VisorCacheMetricsCollectorTask extends VisorMultiNodeTask<VisorCach
             boolean allCaches = cacheNames.isEmpty();
 
             for (IgniteCacheProxy ca : caches) {
-                if (ca.context().started()) {
+                GridCacheContext ctx = ca.context();
+
+                if (ctx.started() && (ctx.affinityNode() || ctx.isNear())) {
                     String cacheName = ca.getName();
 
                     VisorCacheMetrics cm = new VisorCacheMetrics(ignite, cacheName);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e489e372/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorGridConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorGridConfiguration.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorGridConfiguration.java
index 9e2370c..85849a5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorGridConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/node/VisorGridConfiguration.java
@@ -27,6 +27,7 @@ import java.util.Properties;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.configuration.BinaryConfiguration;
 import org.apache.ignite.configuration.ClientConnectorConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
 import org.apache.ignite.configuration.HadoopConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.internal.IgniteEx;
@@ -187,7 +188,10 @@ public class VisorGridConfiguration extends VisorDataTransferObject {
 
         srvcCfgs = VisorServiceConfiguration.list(c.getServiceConfiguration());
 
-        dataStorage = new VisorDataStorageConfiguration(c.getDataStorageConfiguration());
+        DataStorageConfiguration dsCfg = c.getDataStorageConfiguration();
+
+        if (dsCfg != null)
+            dataStorage = new VisorDataStorageConfiguration(dsCfg);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/e489e372/modules/visor-console/src/test/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommandSpec.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/test/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommandSpec.scala b/modules/visor-console/src/test/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommandSpec.scala
index 384aae0..d2c3711 100644
--- a/modules/visor-console/src/test/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommandSpec.scala
+++ b/modules/visor-console/src/test/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommandSpec.scala
@@ -17,25 +17,35 @@
 
 package org.apache.ignite.visor.commands.cache
 
+import java.lang.{Integer => JavaInt}
+import java.util.{Collections, List => JavaList}
+
 import org.apache.ignite.Ignition
 import org.apache.ignite.cache.CacheAtomicityMode._
 import org.apache.ignite.cache.CacheMode._
 import org.apache.ignite.cache.query.SqlQuery
 import org.apache.ignite.cache.query.annotations.QuerySqlField
 import org.apache.ignite.configuration._
+import org.apache.ignite.internal.visor.cache._
 import org.apache.ignite.spi.discovery.tcp._
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm._
-
-import java.lang.{Integer => JavaInt}
-import org.jetbrains.annotations._
-
+import org.apache.ignite.util.AttributeNodeFilter
 import org.apache.ignite.visor._
 import org.apache.ignite.visor.commands.cache.VisorCacheCommand._
+import org.apache.ignite.visor.visor.executeMulti
+import org.jetbrains.annotations._
+
+import scala.collection.JavaConversions._
 
 /**
  * Unit test for 'events' command.
  */
-class VisorCacheCommandSpec extends VisorRuntimeBaseSpec(1) {
+class VisorCacheCommandSpec extends VisorRuntimeBaseSpec(2) {
+    /** */
+    val CACHE_NAME = "replicated"
+
+    /** */
+    val FILTER_ATTRIBUTE_NAME = "NAME"
 
     /** IP finder. */
     val ipFinder = new TcpDiscoveryVmIpFinder(true)
@@ -47,9 +57,11 @@ class VisorCacheCommandSpec extends VisorRuntimeBaseSpec(1) {
     def cacheConfig(@NotNull name: String): CacheConfiguration[Object, Object] = {
         val cfg = new CacheConfiguration[Object, Object]
 
+        cfg.setName(name)
         cfg.setCacheMode(REPLICATED)
         cfg.setAtomicityMode(TRANSACTIONAL)
-        cfg.setName(name)
+
+        cfg.setNodeFilter(new AttributeNodeFilter(FILTER_ATTRIBUTE_NAME, "node-1"))
 
         val arr = Seq(classOf[JavaInt], classOf[Foo]).toArray
 
@@ -64,19 +76,18 @@ class VisorCacheCommandSpec extends VisorRuntimeBaseSpec(1) {
      * @param name Ignite instance name.
      * @return Grid configuration.
      */
-    override def config(name: String): IgniteConfiguration =
-    {
-        val cfg = new IgniteConfiguration
+    override def config(name: String): IgniteConfiguration = {
+        val cfg = super.config(name)
 
-        cfg.setIgniteInstanceName(name)
         cfg.setLocalHost("127.0.0.1")
-        cfg.setCacheConfiguration(cacheConfig("replicated"))
+        cfg.setCacheConfiguration(cacheConfig(CACHE_NAME))
 
         val discoSpi = new TcpDiscoverySpi()
 
         discoSpi.setIpFinder(ipFinder)
 
         cfg.setDiscoverySpi(discoSpi)
+        cfg.setUserAttributes(Collections.singletonMap(FILTER_ATTRIBUTE_NAME, name))
 
         cfg
     }
@@ -130,6 +141,17 @@ class VisorCacheCommandSpec extends VisorRuntimeBaseSpec(1) {
         it("should scan cache") {
             visor cache "-c=replicated -scan"
         }
+
+        it("should get metrics for nodes available by cache node filter") {
+            val caches: JavaList[String] = Collections.singletonList(CACHE_NAME)
+
+            val arg = new VisorCacheMetricsCollectorTaskArg(false, caches)
+
+            val metrics = executeMulti(classOf[VisorCacheMetricsCollectorTask], arg).toList
+
+            assert(metrics.size == 1)
+            assert(metrics.head.getNodes.size() == 1)
+        }
     }
 }
 


[26/47] ignite git commit: IGNITE-6947 Abandon remap after single map if future is done (fixes NPE)

Posted by sb...@apache.org.
IGNITE-6947 Abandon remap after single map if future is done (fixes NPE)


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

Branch: refs/heads/ignite-zk
Commit: 38f66c7f7735bab7c7ae581269f67a45246253ba
Parents: e3099cc4
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Fri Nov 17 15:48:12 2017 +0300
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Fri Nov 17 15:48:12 2017 +0300

----------------------------------------------------------------------
 .../near/GridNearOptimisticTxPrepareFuture.java       | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/38f66c7f/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 6d7a862..6cf076b 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
@@ -368,13 +368,6 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
 
         GridDistributedTxMapping mapping = map(write, topVer, null, topLocked, remap);
 
-        if (mapping.primary().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);
@@ -382,6 +375,13 @@ public class GridNearOptimisticTxPrepareFuture extends GridNearOptimisticTxPrepa
             return;
         }
 
+        if (mapping.primary().isLocal()) {
+            if (write.context().isNear())
+                tx.nearLocallyMapped(true);
+            else if (write.context().isColocated())
+                tx.colocatedLocallyMapped(true);
+        }
+
         if (keyLockFut != null)
             keyLockFut.onAllKeysAdded();