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 2016/07/20 09:06:46 UTC

[01/46] ignite git commit: GG-11294 ignite-schema-import-db shouldn't be uploaded on maven repository

Repository: ignite
Updated Branches:
  refs/heads/ignite-1232 6c5555801 -> 4cbcbab54


GG-11294 ignite-schema-import-db shouldn't be uploaded on maven repository


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

Branch: refs/heads/ignite-1232
Commit: b20e45c361cf6215bd374ab915173d18d1ee9822
Parents: b2fd2aa
Author: Anton Vinogradov <av...@apache.org>
Authored: Thu Jul 7 14:45:59 2016 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Thu Jul 7 14:45:59 2016 +0300

----------------------------------------------------------------------
 modules/schema-import-db/pom.xml | 12 ++++++++++++
 modules/schema-import/pom.xml    |  8 ++++++++
 2 files changed, 20 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/b20e45c3/modules/schema-import-db/pom.xml
----------------------------------------------------------------------
diff --git a/modules/schema-import-db/pom.xml b/modules/schema-import-db/pom.xml
index d3bcdec..b34281b 100644
--- a/modules/schema-import-db/pom.xml
+++ b/modules/schema-import-db/pom.xml
@@ -40,4 +40,16 @@
             <version>${project.version}</version>
         </dependency>
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>

http://git-wip-us.apache.org/repos/asf/ignite/blob/b20e45c3/modules/schema-import/pom.xml
----------------------------------------------------------------------
diff --git a/modules/schema-import/pom.xml b/modules/schema-import/pom.xml
index b1c8b1c..271e513 100644
--- a/modules/schema-import/pom.xml
+++ b/modules/schema-import/pom.xml
@@ -86,6 +86,14 @@
                     </archive>
                 </configuration>
             </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 


[40/46] ignite git commit: IGNITE-3470 - Support EXPIRED events in continuous queries

Posted by sb...@apache.org.
IGNITE-3470 - Support EXPIRED events in continuous queries


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

Branch: refs/heads/ignite-1232
Commit: 5ec99e8d987d7c966a55b8138aade6643decd5dd
Parents: 51add50
Author: Valentin Kulichenko <va...@gmail.com>
Authored: Tue Jul 19 16:01:32 2016 -0700
Committer: Valentin Kulichenko <va...@gmail.com>
Committed: Tue Jul 19 16:03:45 2016 -0700

----------------------------------------------------------------------
 .../ignite/cache/query/ContinuousQuery.java     | 47 +++++++++++++++-----
 .../processors/cache/IgniteCacheProxy.java      |  3 +-
 .../continuous/CacheContinuousQueryManager.java |  9 ++--
 ...ridCacheContinuousQueryAbstractSelfTest.java | 47 ++++++++++++++++++++
 4 files changed, 91 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5ec99e8d/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
index bbfe8cc..49d471e 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
@@ -21,6 +21,7 @@ import javax.cache.Cache;
 import javax.cache.configuration.Factory;
 import javax.cache.event.CacheEntryEventFilter;
 import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.event.EventType;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -142,6 +143,9 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
     /** Automatic unsubscription flag. */
     private boolean autoUnsubscribe = DFLT_AUTO_UNSUBSCRIBE;
 
+    /** Whether to notify about {@link EventType#EXPIRED} events. */
+    private boolean includeExpired;
+
     /**
      * Creates new continuous query.
      */
@@ -324,6 +328,38 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
         return this;
     }
 
+    /**
+     * Gets automatic unsubscription flag value.
+     *
+     * @return Automatic unsubscription flag.
+     */
+    public boolean isAutoUnsubscribe() {
+        return autoUnsubscribe;
+    }
+
+    /**
+     * Sets the flag value defining whether to notify about {@link EventType#EXPIRED} events.
+     * If {@code true}, then the remote listener will get notifications about entries
+     * expired in cache. Otherwise, only {@link EventType#CREATED}, {@link EventType#UPDATED}
+     * and {@link EventType#REMOVED} events will be fired in the remote listener.
+     * <p>
+     * This flag is {@code false} by default, so {@link EventType#EXPIRED} events are disabled.
+     *
+     * @param includeExpired Whether to notify about {@link EventType#EXPIRED} events.
+     */
+    public void setIncludeExpired(boolean includeExpired) {
+        this.includeExpired = includeExpired;
+    }
+
+    /**
+     * Gets the flag value defining whether to notify about {@link EventType#EXPIRED} events.
+     *
+     * @return Whether to notify about {@link EventType#EXPIRED} events.
+     */
+    public boolean isIncludeExpired() {
+        return includeExpired;
+    }
+
     /** {@inheritDoc} */
     @Override public ContinuousQuery<K, V> setPageSize(int pageSize) {
         return (ContinuousQuery<K, V>)super.setPageSize(pageSize);
@@ -333,13 +369,4 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
     @Override public ContinuousQuery<K, V> setLocal(boolean loc) {
         return (ContinuousQuery<K, V>)super.setLocal(loc);
     }
-
-    /**
-     * Gets automatic unsubscription flag value.
-     *
-     * @return Automatic unsubscription flag.
-     */
-    public boolean isAutoUnsubscribe() {
-        return autoUnsubscribe;
-    }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5ec99e8d/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
index fe4f79c..0d7bc6a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
@@ -616,7 +616,8 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
                 qry.getTimeInterval(),
                 qry.isAutoUnsubscribe(),
                 loc,
-                keepBinary);
+                keepBinary,
+                qry.isIncludeExpired());
 
             final QueryCursor<Cache.Entry<K, V>> cur =
                 qry.getInitialQuery() != null ? query(qry.getInitialQuery()) : null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/5ec99e8d/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
index 195f3ae..a8e5a6b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
@@ -421,7 +421,8 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
         long timeInterval,
         boolean autoUnsubscribe,
         boolean loc,
-        final boolean keepBinary) throws IgniteCheckedException
+        final boolean keepBinary,
+        final boolean includeExpired) throws IgniteCheckedException
     {
         IgniteClosure<Boolean, CacheContinuousQueryHandler> clsr;
 
@@ -438,7 +439,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                             rmtFilterFactory,
                             true,
                             false,
-                            true,
+                            !includeExpired,
                             false,
                             null);
                     else {
@@ -456,7 +457,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                             (CacheEntryEventSerializableFilter)fltr,
                             true,
                             false,
-                            true,
+                            !includeExpired,
                             false);
                     }
 
@@ -473,7 +474,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                         rmtFilter,
                         true,
                         false,
-                        true,
+                        !includeExpired,
                         false);
                 }
             };

http://git-wip-us.apache.org/repos/asf/ignite/blob/5ec99e8d/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
index f372e0d..d5dc557 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
@@ -34,6 +34,9 @@ import javax.cache.Cache;
 import javax.cache.configuration.Factory;
 import javax.cache.event.CacheEntryEvent;
 import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.event.EventType;
+import javax.cache.expiry.CreatedExpiryPolicy;
+import javax.cache.expiry.Duration;
 import javax.cache.integration.CacheWriterException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
@@ -1093,6 +1096,50 @@ public abstract class GridCacheContinuousQueryAbstractSelfTest extends GridCommo
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testExpired() throws Exception {
+        IgniteCache<Object, Object> cache = grid(0).cache(null).
+            withExpiryPolicy(new CreatedExpiryPolicy(new Duration(MILLISECONDS, 1000)));
+
+        final Map<Object, Object> map = new ConcurrentHashMap8<>();
+        final CountDownLatch latch = new CountDownLatch(2);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setIncludeExpired(true);
+
+        qry.setLocalListener(new CacheEntryUpdatedListener<Object, Object>() {
+            @Override public void onUpdated(Iterable<CacheEntryEvent<?, ?>> evts) {
+                for (CacheEntryEvent<?, ?> e : evts) {
+                    if (e.getEventType() == EventType.EXPIRED) {
+                        assertNull(e.getValue());
+
+                        map.put(e.getKey(), e.getOldValue());
+
+                        latch.countDown();
+                    }
+                }
+            }
+        });
+
+        try (QueryCursor<Cache.Entry<Object, Object>> ignored = cache.query(qry)) {
+            cache.put(1, 1);
+            cache.put(2, 2);
+
+            // Wait for expiration.
+            Thread.sleep(2000);
+
+            assert latch.await(LATCH_TIMEOUT, MILLISECONDS);
+
+            assertEquals(2, map.size());
+
+            assertEquals(1, (int)map.get(1));
+            assertEquals(2, (int)map.get(2));
+        }
+    }
+
+    /**
      *
      */
     private static class StoreFactory implements Factory<CacheStore> {


[32/46] ignite git commit: IGNITE-3416: CPP: Fixed string deserialization performance issue.

Posted by sb...@apache.org.
IGNITE-3416: CPP: Fixed string deserialization performance issue.


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

Branch: refs/heads/ignite-1232
Commit: 279de8f7c51dc93480bf64231321c451c7c11780
Parents: 590dffb
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Jul 19 15:54:27 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jul 19 15:54:27 2016 +0300

----------------------------------------------------------------------
 .../ignite/impl/binary/binary_id_resolver.h     | 10 ++++------
 .../ignite/impl/binary/binary_reader_impl.h     | 21 +++++++++++---------
 .../src/impl/binary/binary_reader_impl.cpp      | 14 +++++++++----
 .../src/impl/interop/interop_input_stream.cpp   | 14 +++++++------
 4 files changed, 34 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/279de8f7/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_id_resolver.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_id_resolver.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_id_resolver.h
index bbbf239..41ae628 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_id_resolver.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_id_resolver.h
@@ -88,12 +88,10 @@ namespace ignite
                 }
 
                 virtual int32_t GetFieldId(const int32_t typeId, const char* name) {
-                    if (!name)
-                    {
+                    if (name)
+                        return type.GetFieldId(name);
+                    else
                         IGNITE_ERROR_1(IgniteError::IGNITE_ERR_BINARY, "Field name cannot be NULL.");
-                    }
-
-                    return type.GetFieldId(name);
                 }
             private:
                 /** Actual type.  */
@@ -103,4 +101,4 @@ namespace ignite
     }
 }
 
-#endif //_IGNITE_IMPL_BINARY_BINARY_ID_RESOLVER
\ No newline at end of file
+#endif //_IGNITE_IMPL_BINARY_BINARY_ID_RESOLVER

http://git-wip-us.apache.org/repos/asf/ignite/blob/279de8f7/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
index 71b4e61..d9f1e1a 100644
--- a/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
+++ b/modules/platforms/cpp/binary/include/ignite/impl/binary/binary_reader_impl.h
@@ -1398,26 +1398,29 @@ namespace ignite
                 {
                     int32_t realLen = stream->ReadInt32();
 
-                    ignite::common::FixedSizeArray<char> arr(realLen + 1);
+                    std::string res;
 
-                    for (int32_t i = 0; i < realLen; i++)
-                        arr[i] = static_cast<char>(stream->ReadInt8());
+                    if (realLen > 0)
+                    {
+                        res.resize(realLen, 0);
 
-                    arr[realLen] = 0;
+                        stream->ReadInt8Array(reinterpret_cast<int8_t*>(&res[0]), realLen);
+                    }
 
-                    return std::string(arr.GetData());
+                    return res;
                 }
-
                 else if (typeId == IGNITE_HDR_NULL)
                     return std::string();
-                else {
+                else
+                {
                     int32_t pos = stream->Position() - 1;
 
-                    IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos, "expected", (int)IGNITE_TYPE_STRING, "actual", (int)typeId)
+                    IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_BINARY, "Invalid header", "position", pos,
+                        "expected", static_cast<int>(IGNITE_TYPE_STRING), "actual", static_cast<int>(typeId))
                 }
             }
         }
     }
 }
 
-#endif //_IGNITE_IMPL_BINARY_BINARY_READER
\ No newline at end of file
+#endif //_IGNITE_IMPL_BINARY_BINARY_READER

http://git-wip-us.apache.org/repos/asf/ignite/blob/279de8f7/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
index 75a110b..33205e4 100644
--- a/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
+++ b/modules/platforms/cpp/binary/src/impl/binary/binary_reader_impl.cpp
@@ -790,7 +790,9 @@ namespace ignite
                         {
                             int32_t currentFieldId = stream->ReadInt32(schemaPos);
 
-                            if (fieldId == currentFieldId)
+                            if (fieldId != currentFieldId)
+                                continue;
+                            else
                                 return static_cast<uint8_t>(stream->ReadInt8(schemaPos + 4)) + pos;
                         }
                         break;
@@ -802,7 +804,9 @@ namespace ignite
                         {
                             int32_t currentFieldId = stream->ReadInt32(schemaPos);
 
-                            if (fieldId == currentFieldId)
+                            if (fieldId != currentFieldId)
+                                continue;
+                            else
                                 return static_cast<uint16_t>(stream->ReadInt16(schemaPos + 4)) + pos;
                         }
                         break;
@@ -814,7 +818,9 @@ namespace ignite
                         {
                             int32_t currentFieldId = stream->ReadInt32(schemaPos);
 
-                            if (fieldId == currentFieldId)
+                            if (fieldId != currentFieldId)
+                                continue;
+                            else
                                 return stream->ReadInt32(schemaPos + 4) + pos;
                         }
                         break;
@@ -904,4 +910,4 @@ namespace ignite
             }
         }
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/279de8f7/modules/platforms/cpp/binary/src/impl/interop/interop_input_stream.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/binary/src/impl/interop/interop_input_stream.cpp b/modules/platforms/cpp/binary/src/impl/interop/interop_input_stream.cpp
index ce4f0ae..4bb4e07 100644
--- a/modules/platforms/cpp/binary/src/impl/interop/interop_input_stream.cpp
+++ b/modules/platforms/cpp/binary/src/impl/interop/interop_input_stream.cpp
@@ -35,7 +35,7 @@
  * Common macro to read an array.
  */
 #define IGNITE_INTEROP_IN_READ_ARRAY(len, shift) { \
-    CopyAndShift(reinterpret_cast<int8_t*>(res), 0, len << shift); \
+    CopyAndShift(reinterpret_cast<int8_t*>(res), 0, ((len) << (shift))); \
 }
 
 namespace ignite
@@ -196,12 +196,12 @@ namespace ignite
 
             void InteropInputStream::Position(int32_t pos)
             {
-                if (pos > len) {
+                if (pos <= len)
+                    this->pos = pos;
+                else {
                     IGNITE_ERROR_FORMATTED_3(IgniteError::IGNITE_ERR_MEMORY, "Requested input stream position is out of bounds",
                         "memPtr", mem->PointerLong(), "len", len, "pos", pos);
                 }
-
-                this->pos = pos;
             }
 
             void InteropInputStream::Synchronize()
@@ -212,7 +212,9 @@ namespace ignite
 
             void InteropInputStream::EnsureEnoughData(int32_t cnt) const
             {
-                if (len - pos < cnt) {
+                if (len - pos >= cnt)
+                    return;
+                else {
                     IGNITE_ERROR_FORMATTED_4(IgniteError::IGNITE_ERR_MEMORY, "Not enough data in the stream",
                         "memPtr", mem->PointerLong(), "len", len, "pos", pos, "requested", cnt);
                 }
@@ -227,7 +229,7 @@ namespace ignite
                 Shift(cnt);
             }
 
-            void InteropInputStream::Shift(int32_t cnt)
+            inline void InteropInputStream::Shift(int32_t cnt)
             {
                 pos += cnt;
             }


[27/46] ignite git commit: ignite-1232

Posted by sb...@apache.org.
ignite-1232


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

Branch: refs/heads/ignite-1232
Commit: 5579048b10ef9b720f8f2244ab981e6215e70628
Parents: d6846ff
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 19 11:20:29 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jul 19 11:20:29 2016 +0300

----------------------------------------------------------------------
 ...iteCacheDistributedJoinQueryConditionsTest.java | 16 ++++++++++++++++
 .../cache/IgniteCrossCachesJoinsQueryTest.java     | 17 ++++++++++++++++-
 .../query/IgniteSqlSchemaIndexingTest.java         |  3 ++-
 3 files changed, 34 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5579048b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
index 934e16b..af56c91 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.concurrent.atomic.AtomicInteger;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMemoryMode;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
 import org.apache.ignite.cache.affinity.Affinity;
@@ -39,6 +40,8 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
 import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
 import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
 
 /**
@@ -60,6 +63,9 @@ public class IgniteCacheDistributedJoinQueryConditionsTest extends GridCommonAbs
     /** */
     private int total;
 
+    /** */
+    private CacheMemoryMode memMode = ONHEAP_TIERED;
+
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
         IgniteConfiguration cfg = super.getConfiguration(gridName);
@@ -99,6 +105,15 @@ public class IgniteCacheDistributedJoinQueryConditionsTest extends GridCommonAbs
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testJoinQuery1Offheap() throws Exception {
+        memMode = OFFHEAP_TIERED;
+
+        testJoinQuery1();
+    }
+
+    /**
      * @param idx Use index flag.
      * @throws Exception If failed.
      */
@@ -567,6 +582,7 @@ public class IgniteCacheDistributedJoinQueryConditionsTest extends GridCommonAbs
         ccfg.setAtomicWriteOrderMode(PRIMARY);
         ccfg.setAtomicityMode(ATOMIC);
         ccfg.setBackups(0);
+        ccfg.setMemoryMode(memMode);
 
         return ccfg;
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/5579048b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
index 4633df7..0dd9281 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
@@ -35,6 +35,7 @@ import java.util.concurrent.Callable;
 import javax.cache.CacheException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMemoryMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.QueryEntity;
 import org.apache.ignite.cache.QueryIndex;
@@ -55,6 +56,8 @@ 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 static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
 import static org.apache.ignite.cache.CacheMode.PARTITIONED;
 import static org.apache.ignite.cache.CacheMode.REPLICATED;
 import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
@@ -97,6 +100,9 @@ public class IgniteCrossCachesJoinsQueryTest extends AbstractH2CompareQueryTest
     /** */
     private static Random rnd;
 
+    /** */
+    private CacheMemoryMode memMode = ONHEAP_TIERED;
+
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
         IgniteConfiguration cfg = super.getConfiguration(gridName);
@@ -334,6 +340,15 @@ public class IgniteCrossCachesJoinsQueryTest extends AbstractH2CompareQueryTest
     /**
      * @throws Exception If failed.
      */
+    public void testDistributedJoins1Offheap() throws Exception {
+        memMode = OFFHEAP_TIERED;
+
+        testDistributedJoins1();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testDistributedJoins2() throws Exception {
         distributedJoins = true;
 
@@ -727,7 +742,7 @@ public class IgniteCrossCachesJoinsQueryTest extends AbstractH2CompareQueryTest
         CacheConfiguration ccfg = new CacheConfiguration();
 
         ccfg.setName(cacheName);
-
+        ccfg.setMemoryMode(memMode);
         ccfg.setCacheMode(cacheMode);
 
         if (cacheMode == PARTITIONED)

http://git-wip-us.apache.org/repos/asf/ignite/blob/5579048b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
index 0cd8d13..88f1f1e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.query;
 
 import java.util.List;
 import java.util.concurrent.Callable;
+import javax.cache.CacheException;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
@@ -185,7 +186,7 @@ public class IgniteSqlSchemaIndexingTest extends GridCommonAbstractTest {
                 cache.query(qryWrong);
                 return null;
             }
-        }, IgniteException.class, "Failed to parse query");
+        }, CacheException.class, "Failed to parse query");
 
         SqlFieldsQuery qryCorrect = new SqlFieldsQuery("select f.\"id\", f.\"name\" " +
             "from \""+schemaName+"\".\"Fact\" f");


[04/46] ignite git commit: CacheKeepBinaryIterationSwapEnabledTest fix.

Posted by sb...@apache.org.
CacheKeepBinaryIterationSwapEnabledTest fix.


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

Branch: refs/heads/ignite-1232
Commit: e3c29d849bded5204685270505ff6d0c082cd028
Parents: d3bd6c1
Author: Anton Vinogradov <av...@apache.org>
Authored: Mon Jul 11 15:30:53 2016 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Mon Jul 11 15:32:57 2016 +0300

----------------------------------------------------------------------
 .../cache/CacheEvictableEntryImpl.java          | 11 ++++--
 .../CacheKeepBinaryIterationTest.java           | 36 ++++++++++----------
 2 files changed, 27 insertions(+), 20 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e3c29d84/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEvictableEntryImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEvictableEntryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEvictableEntryImpl.java
index b32362a..770daa1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEvictableEntryImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheEvictableEntryImpl.java
@@ -64,9 +64,16 @@ public class CacheEvictableEntryImpl<K, V> implements EvictableEntry<K, V> {
 
         try {
             assert ctx != null;
-            assert ctx.evicts() != null;
 
-            return ctx.evicts().evict(cached, null, false, null);
+            GridCacheEvictionManager mgr = ctx.evicts();
+
+            if (mgr == null) {
+                assert ctx.kernalContext().isStopping();
+
+                return false;
+            }
+
+            return mgr.evict(cached, null, false, null);
         }
         catch (IgniteCheckedException e) {
             U.error(ctx.grid().log(), "Failed to evict entry from cache: " + cached, e);

http://git-wip-us.apache.org/repos/asf/ignite/blob/e3c29d84/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationTest.java
index a775d21..605181f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheKeepBinaryIterationTest.java
@@ -29,11 +29,9 @@ import org.apache.ignite.cache.query.QueryCursor;
 import org.apache.ignite.cache.query.ScanQuery;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.util.tostring.GridToStringInclude;
 import org.apache.ignite.internal.util.typedef.internal.S;
-import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -221,11 +219,11 @@ public class CacheKeepBinaryIterationTest extends GridCommonAbstractTest {
     /**
      * @param ccfg Cache configuration.
      */
-    private void doTestScanQuery(CacheConfiguration<Object, Object> ccfg, boolean keepBinary,
-        boolean primitives) throws IgniteInterruptedCheckedException {
+    private void doTestScanQuery(final CacheConfiguration<Object, Object> ccfg, boolean keepBinary,
+        boolean primitives) throws Exception {
         IgniteCache<Object, Object> cache = grid(0).createCache(ccfg);
 
-        assertTrue(cache.size() == 0);
+        assertEquals(0, cache.size());
 
         try {
             for (int i = 0; i < KEYS; i++)
@@ -272,24 +270,25 @@ public class CacheKeepBinaryIterationTest extends GridCommonAbstractTest {
             }
         }
         finally {
-            cache.removeAll();
+            if (ccfg.getEvictionPolicy() != null) { // TODO: IGNITE-3462. Fixes evictionPolicy issues at cache destroy.
+                stopAllGrids();
 
-            if (ccfg.getEvictionPolicy() != null)
-                U.sleep(1000); // Fixes evictionPolicy issues at cache destroy.
-
-            grid(0).destroyCache(ccfg.getName());
+                startGridsMultiThreaded(getServerNodeCount());
+            }
+            else
+                grid(0).destroyCache(ccfg.getName());
         }
     }
 
     /**
      * @param ccfg Cache configuration.
      */
-    private void doTestLocalEntries(CacheConfiguration<Object, Object> ccfg,
+    private void doTestLocalEntries(final CacheConfiguration<Object, Object> ccfg,
         boolean keepBinary,
-        boolean primitives) throws IgniteInterruptedCheckedException {
+        boolean primitives) throws Exception {
         IgniteCache<Object, Object> cache = grid(0).createCache(ccfg);
 
-        assertTrue(cache.size() == 0);
+        assertEquals(0, cache.size());
 
         try {
             for (int i = 0; i < KEYS; i++)
@@ -341,12 +340,13 @@ public class CacheKeepBinaryIterationTest extends GridCommonAbstractTest {
             }
         }
         finally {
-            cache.removeAll();
+            if (ccfg.getEvictionPolicy() != null) { // TODO: IGNITE-3462. Fixes evictionPolicy issues at cache destroy.
+                stopAllGrids();
 
-            if (ccfg.getEvictionPolicy() != null)
-                U.sleep(1000); // Fixes evictionPolicy issues at cache destroy.
-
-            grid(0).destroyCache(ccfg.getName());
+                startGridsMultiThreaded(getServerNodeCount());
+            }
+            else
+                grid(0).destroyCache(ccfg.getName());
         }
     }
 


[18/46] ignite git commit: ignite-1088 Implemented store for multi jvm tests (fixed NPE) (cherry picked from commit d31a476)

Posted by sb...@apache.org.
ignite-1088 Implemented store for multi jvm tests (fixed NPE)
(cherry picked from commit d31a476)


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

Branch: refs/heads/ignite-1232
Commit: ade57eaf5b77f779642be424d8cdf858a327ce2d
Parents: 2f78346
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 5 07:43:51 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 15 16:21:21 2016 +0300

----------------------------------------------------------------------
 .../cache/GridCacheAbstractSelfTest.java          | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ade57eaf/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
index dcf5d98..d58e560 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
@@ -220,16 +220,18 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
     protected CacheConfiguration cacheConfiguration(String gridName) throws Exception {
         CacheConfiguration cfg = defaultCacheConfiguration();
 
-        Factory<? extends CacheStore<Object, Object>> storeFactory = storeStgy.getStoreFactory();
+        if (storeStgy != null) {
+            Factory<? extends CacheStore<Object, Object>> storeFactory = storeStgy.getStoreFactory();
 
-        CacheStore<?, ?> store = storeFactory.create();
+            CacheStore<?, ?> store = storeFactory.create();
 
-        if (store != null) {
-            cfg.setCacheStoreFactory(storeFactory);
-            cfg.setReadThrough(true);
-            cfg.setWriteThrough(true);
-            cfg.setLoadPreviousValue(true);
-            storeStgy.updateCacheConfiguration(cfg);
+            if (store != null) {
+                cfg.setCacheStoreFactory(storeFactory);
+                cfg.setReadThrough(true);
+                cfg.setWriteThrough(true);
+                cfg.setLoadPreviousValue(true);
+                storeStgy.updateCacheConfiguration(cfg);
+            }
         }
 
         cfg.setSwapEnabled(swapEnabled());


[21/46] ignite git commit: Added more info in assert message.

Posted by sb...@apache.org.
Added more info in assert message.


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

Branch: refs/heads/ignite-1232
Commit: 8d6273780bdb63397dfddaf7b7c1e65a8b717e8d
Parents: a648e88
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jul 15 16:40:31 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 15 16:40:31 2016 +0300

----------------------------------------------------------------------
 .../cache/distributed/dht/GridDhtPartitionTopologyImpl.java | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/8d627378/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
index 868e9db..c95817d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
@@ -255,7 +255,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
 
         try {
             assert exchId.topologyVersion().compareTo(topVer) > 0 : "Invalid topology version [topVer=" + topVer +
-                ", exchId=" + exchId + ']';
+                ", exchId=" + exchId +
+                ", fut=" + exchFut + ']';
 
             this.stopping = stopping;
 
@@ -337,11 +338,13 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
         assert topVer.equals(exchFut.topologyVersion()) :
             "Invalid topology [topVer=" + topVer +
                 ", cache=" + cctx.name() +
-                ", futVer=" + exchFut.topologyVersion() + ']';
+                ", futVer=" + exchFut.topologyVersion() +
+                ", fut=" + exchFut + ']';
         assert cctx.affinity().affinityTopologyVersion().equals(exchFut.topologyVersion()) :
             "Invalid affinity [topVer=" + cctx.affinity().affinityTopologyVersion() +
                 ", cache=" + cctx.name() +
-                ", futVer=" + exchFut.topologyVersion() + ']';
+                ", futVer=" + exchFut.topologyVersion() +
+                ", fut=" + exchFut + ']';
 
         List<List<ClusterNode>> aff = cctx.affinity().assignments(exchFut.topologyVersion());
 


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

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


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

Branch: refs/heads/ignite-1232
Commit: 4cbcbab5425713e6fcaba2a7a4fdbba606a9dffe
Parents: 5579048 c9a0b8c
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 20 12:04:02 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Jul 20 12:04:02 2016 +0300

----------------------------------------------------------------------
 assembly/LICENSE_FABRIC                         |    7 +-
 assembly/LICENSE_HADOOP                         |    7 +-
 examples/pom-standalone-lgpl.xml                |    6 +-
 examples/pom-standalone.xml                     |    6 +-
 examples/pom.xml                                |    6 +-
 examples/schema-import/pom-standalone.xml       |    6 +-
 examples/schema-import/pom.xml                  |    6 +-
 modules/cassandra/pom.xml                       |    2 +-
 modules/core/pom.xml                            |    6 +-
 .../org/apache/ignite/IgniteDataStreamer.java   |   52 +-
 .../IgniteDataStreamerTimeoutException.java     |   45 +
 .../ignite/cache/query/ContinuousQuery.java     |   47 +-
 .../ignite/internal/binary/BinaryContext.java   |    6 +-
 .../internal/binary/BinaryObjectImpl.java       |    8 +
 .../cache/CacheEvictableEntryImpl.java          |   11 +-
 .../processors/cache/GridCacheAdapter.java      |   38 +-
 .../processors/cache/GridCacheProcessor.java    |    2 +
 .../processors/cache/IgniteCacheProxy.java      |    3 +-
 .../dht/GridDhtPartitionTopologyImpl.java       |    9 +-
 .../continuous/CacheContinuousQueryManager.java |   13 +-
 .../datastreamer/DataStreamerImpl.java          |   71 +-
 .../PlatformAffinityFunctionTarget.java         |    8 +-
 .../cache/affinity/PlatformAffinityUtils.java   |    5 +
 .../PlatformDotNetConfigurationClosure.java     |    5 +
 .../handlers/cache/GridCacheCommandHandler.java |   84 +-
 .../service/GridServiceProcessor.java           |   70 +-
 .../ignite/internal/util/IgniteUtils.java       |   21 +
 .../ignite/scheduler/SchedulerFuture.java       |    5 +-
 .../binary/BinaryMarshallerSelfTest.java        |   41 +
 .../CacheKeepBinaryIterationTest.java           |   36 +-
 ...ridCacheContinuousQueryAbstractSelfTest.java |   47 +
 ...eContinuousQueryMultiNodesFilteringTest.java |  278 +++
 ...dCacheContinuousQueryNodesFilteringTest.java |  168 ++
 .../datastreamer/DataStreamerTimeoutTest.java   |  163 ++
 .../processors/igfs/IgfsIgniteMock.java         |  501 +++++
 .../internal/processors/igfs/IgfsMock.java      |  397 ++++
 .../GridCacheAtomicCommandHandlerSelfTest.java  |   39 +
 .../cache/GridCacheCommandHandlerSelfTest.java  |   19 +-
 ...rviceDeploymentExceptionPropagationTest.java |   80 +
 .../multijvm/IgniteCacheProcessProxy.java       |    1 -
 .../ignite/testsuites/IgniteCacheTestSuite.java |    2 +
 .../testsuites/IgniteRestHandlerTestSuite.java  |    2 +
 modules/flume/README.txt                        |    2 +-
 .../mapreduce/IgniteHadoopMapReducePlanner.java |   48 +-
 .../IgniteHadoopWeightedMapReducePlanner.java   |  846 +++++++++
 .../internal/processors/hadoop/HadoopUtils.java |   81 +
 .../planner/HadoopAbstractMapReducePlanner.java |  116 ++
 .../planner/HadoopMapReducePlanGroup.java       |  150 ++
 .../planner/HadoopMapReducePlanTopology.java    |   89 +
 .../hadoop/HadoopAbstractMapReduceTest.java     |   15 +
 .../HadoopDefaultMapReducePlannerSelfTest.java  |  451 +----
 .../processors/hadoop/HadoopPlannerMockJob.java |  168 ++
 .../HadoopWeightedMapReducePlannerTest.java     |  599 ++++++
 .../HadoopWeightedPlannerMapReduceTest.java     |   38 +
 .../testsuites/IgniteHadoopTestSuite.java       |    8 +-
 .../IgniteCacheQuerySelfTestSuite3.java         |    4 +
 modules/kafka/README.txt                        |    4 +-
 .../ignite/impl/binary/binary_id_resolver.h     |   10 +-
 .../ignite/impl/binary/binary_reader_impl.h     |   21 +-
 .../src/impl/binary/binary_reader_impl.cpp      |   14 +-
 .../src/impl/interop/interop_input_stream.cpp   |   14 +-
 .../platforms/cpp/jni/include/ignite/jni/java.h |    8 +-
 modules/platforms/cpp/jni/src/java.cpp          |   20 +-
 .../Apache.Ignite.Core.Tests.csproj             |    4 +
 .../Affinity/AffinityFunctionSpringTest.cs      |  104 +-
 .../Cache/CacheConfigurationTest.cs             |    1 +
 .../Config/Cache/Affinity/affinity-function.xml |    2 +-
 .../Cache/Affinity/affinity-function2.xml       |   49 +
 .../Apache.Ignite.Core.Tests/DeploymentTest.cs  |    2 +-
 .../Apache.Ignite.Core.Tests/TestRunner.cs      |    2 +-
 .../Apache.Ignite.Core.csproj                   |   18 +-
 .../Binary/UserSerializerProxy.cs               |   68 -
 .../Cache/Affinity/Fair/FairAffinityFunction.cs |    1 +
 .../Cache/Affinity/Fair/Package-Info.cs         |   26 +
 .../Cache/Affinity/Package-Info.cs              |   26 +
 .../Cache/Affinity/Rendezvous/Package-Info.cs   |   26 +
 .../Rendezvous/RendezvousAffinityFunction.cs    |    1 +
 .../Cache/Configuration/Package-Info.cs         |   26 +
 .../Cache/Eviction/Package-Info.cs              |   26 +
 .../Communication/Package-Info.cs               |   26 +
 .../Communication/Tcp/Package-Info.cs           |   26 +
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |    2 +-
 .../Impl/Binary/BinaryReaderExtensions.cs       |    2 +-
 .../Impl/Binary/UserSerializerProxy.cs          |   68 +
 .../Impl/Cache/Affinity/AffinityFunctionBase.cs |  140 ++
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |    2 +-
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        |   11 +-
 .../processors/schedule/ScheduleFutureImpl.java |    7 +-
 .../schedule/GridScheduleSelfTest.java          |   27 +-
 modules/schema-import-db/pom.xml                |   12 +
 modules/schema-import/pom.xml                   |    8 +
 .../ignite/visor/commands/VisorConsole.scala    |    5 +-
 .../commands/alert/VisorAlertCommand.scala      |    2 +-
 .../commands/cache/VisorCacheCommand.scala      |   40 +-
 .../commands/cache/VisorCacheStopCommand.scala  |    2 +-
 .../config/VisorConfigurationCommand.scala      |   23 +-
 .../commands/events/VisorEventsCommand.scala    |   29 +-
 .../visor/commands/gc/VisorGcCommand.scala      |   11 +-
 .../visor/commands/kill/VisorKillCommand.scala  |  184 +-
 .../visor/commands/node/VisorNodeCommand.scala  |   13 +-
 .../visor/commands/vvm/VisorVvmCommand.scala    |   11 +-
 .../scala/org/apache/ignite/visor/visor.scala   |   76 +-
 modules/web-console/DEVNOTES.txt                |   29 +-
 modules/web-console/src/main/js/.gitignore      |    2 -
 .../web-console/src/main/js/app/app.config.js   |   86 +
 modules/web-console/src/main/js/app/app.js      |  274 +++
 .../main/js/app/controllers/auth.controller.js  |   30 +
 .../js/app/controllers/notebooks.controller.js  |   69 +
 .../controllers/reset-password.controller.js    |   51 +
 .../js/app/directives/auto-focus.directive.js   |   26 +
 .../directives/centered/centered.directive.js   |    2 +-
 .../directives/copy-to-clipboard.directive.js   |   29 +
 .../information/information.directive.js        |    4 +-
 .../main/js/app/directives/match.directive.js   |   27 +
 .../app/directives/on-click-focus.directive.js  |   26 +
 .../directives/on-enter-focus-move.directive.js |   29 +
 .../js/app/directives/on-enter.directive.js     |   32 +
 .../js/app/directives/on-escape.directive.js    |   32 +
 .../ui-ace-docker/ui-ace-docker.directive.js    |    4 +-
 .../ui-ace-java/ui-ace-java.directive.js        |    4 +-
 .../ui-ace-pojos/ui-ace-pojos.directive.js      |    4 +-
 .../ui-ace-pom/ui-ace-pom.directive.js          |    4 +-
 .../ui-ace-xml/ui-ace-xml.directive.js          |    4 +-
 .../js/app/filters/domainsValidation.filter.js  |   33 +
 .../src/main/js/app/helpers/jade/mixins.jade    |   26 +-
 modules/web-console/src/main/js/app/index.js    |  241 ---
 .../src/main/js/app/modules/Demo/Demo.module.js |   15 +-
 .../src/main/js/app/modules/ace.module.js       |    4 +-
 .../main/js/app/modules/agent/agent.module.js   |   10 +-
 .../js/app/modules/branding/branding.module.js  |    1 -
 .../modules/branding/header-logo.directive.js   |    4 +-
 .../branding/powered-by-apache.directive.js     |    4 +-
 .../configuration/EventGroups.provider.js       |    2 +-
 .../configuration/generator/Pom.service.js      |    2 +-
 .../js/app/modules/dialog/dialog.factory.js     |    4 +-
 .../field/bs-select-placeholder.directive.js    |    7 +-
 .../modules/form/field/dropdown.directive.js    |    9 +-
 .../js/app/modules/form/field/dropdown.jade     |    4 +-
 .../main/js/app/modules/form/field/field.css    |    2 +-
 .../app/modules/form/field/field.directive.js   |    6 +-
 .../form/field/input/checkbox.directive.js      |    9 +-
 .../form/field/input/datalist.directive.js      |    9 +-
 .../app/modules/form/field/input/datalist.jade  |    2 +-
 .../form/field/input/number.directive.js        |    9 +-
 .../modules/form/field/input/text.directive.js  |   11 +-
 .../app/modules/form/group/group.directive.js   |    4 +-
 .../app/modules/form/group/table.directive.js   |    4 +-
 .../app/modules/form/panel/revert.directive.js  |    4 +-
 .../getting-started/GettingStarted.provider.js  |    2 +-
 .../js/app/modules/loading/loading.directive.js |   10 +-
 .../js/app/modules/loading/loading.service.js   |    2 +-
 .../caches/concurrency.directive.js             |    4 +-
 .../configuration/caches/general.directive.js   |    4 +-
 .../states/configuration/caches/general.jade    |    2 +-
 .../configuration/caches/memory.directive.js    |    4 +-
 .../configuration/caches/query.directive.js     |    4 +-
 .../configuration/caches/rebalance.directive.js |    4 +-
 .../caches/server-near-cache.directive.js       |    4 +-
 .../caches/statistics.directive.js              |    4 +-
 .../configuration/caches/store.directive.js     |    4 +-
 .../states/configuration/caches/store.jade      |    4 +-
 .../configuration/clusters/atomic.directive.js  |    4 +-
 .../clusters/attributes.directive.js            |    4 +-
 .../configuration/clusters/binary.directive.js  |    4 +-
 .../clusters/collision.directive.js             |    4 +-
 .../clusters/collision/custom.directive.js      |    4 +-
 .../clusters/collision/fifo-queue.directive.js  |    4 +-
 .../collision/job-stealing.directive.js         |    4 +-
 .../collision/priority-queue.directive.js       |    4 +-
 .../clusters/communication.directive.js         |    4 +-
 .../clusters/connector.directive.js             |    4 +-
 .../clusters/deployment.directive.js            |    4 +-
 .../clusters/discovery.directive.js             |    4 +-
 .../configuration/clusters/events.directive.js  |    4 +-
 .../clusters/failover.directive.js              |    4 +-
 .../configuration/clusters/general.directive.js |    4 +-
 .../general/discovery/cloud.directive.js        |    4 +-
 .../general/discovery/google.directive.js       |    4 +-
 .../general/discovery/jdbc.directive.js         |    4 +-
 .../general/discovery/multicast.directive.js    |    4 +-
 .../clusters/general/discovery/s3.directive.js  |    4 +-
 .../general/discovery/shared.directive.js       |    4 +-
 .../clusters/general/discovery/vm.directive.js  |    4 +-
 .../clusters/general/discovery/vm.jade          |    2 +-
 .../general/discovery/zookeeper.directive.js    |    4 +-
 .../bounded-exponential-backoff.directive.js    |    4 +-
 .../zookeeper/retrypolicy/custom.directive.js   |    4 +-
 .../exponential-backoff.directive.js            |    4 +-
 .../zookeeper/retrypolicy/forever.directive.js  |    4 +-
 .../zookeeper/retrypolicy/n-times.directive.js  |    4 +-
 .../zookeeper/retrypolicy/one-time.directive.js |    4 +-
 .../retrypolicy/until-elapsed.directive.js      |    4 +-
 .../configuration/clusters/igfs.directive.js    |    4 +-
 .../configuration/clusters/logger.directive.js  |    4 +-
 .../clusters/logger/custom.directive.js         |    4 +-
 .../clusters/logger/log4j.directive.js          |    4 +-
 .../clusters/logger/log4j2.directive.js         |    4 +-
 .../clusters/marshaller.directive.js            |    4 +-
 .../configuration/clusters/metrics.directive.js |    4 +-
 .../configuration/clusters/ssl.directive.js     |    4 +-
 .../configuration/clusters/swap.directive.js    |    4 +-
 .../configuration/clusters/thread.directive.js  |    4 +-
 .../configuration/clusters/time.directive.js    |    4 +-
 .../clusters/transactions.directive.js          |    4 +-
 .../configuration/domains/general.directive.js  |    4 +-
 .../configuration/domains/query.directive.js    |    4 +-
 .../states/configuration/domains/query.jade     |   14 +-
 .../configuration/domains/store.directive.js    |    4 +-
 .../states/configuration/domains/store.jade     |    8 +-
 .../states/configuration/igfs/dual.directive.js |    4 +-
 .../modules/states/configuration/igfs/dual.jade |    4 +-
 .../igfs/fragmentizer.directive.js              |    4 +-
 .../configuration/igfs/general.directive.js     |    4 +-
 .../states/configuration/igfs/ipc.directive.js  |    4 +-
 .../states/configuration/igfs/misc.directive.js |    4 +-
 .../modules/states/configuration/igfs/misc.jade |   12 +-
 .../configuration/igfs/secondary.directive.js   |    4 +-
 .../configuration/preview-panel.directive.js    |    4 +-
 .../configuration/summary/summary.controller.js |   17 +-
 .../main/js/app/modules/states/signin.state.js  |    3 +-
 .../main/js/app/modules/user/Auth.service.js    |   10 +-
 .../main/js/app/services/ChartColors.service.js |    2 +-
 .../src/main/js/app/services/Clone.service.js   |   64 +
 .../src/main/js/app/services/Confirm.service.js |   70 +
 .../js/app/services/ConfirmBatch.service.js     |   92 +
 .../js/app/services/CopyToClipboard.service.js  |   50 +
 .../main/js/app/services/Countries.service.js   |    2 +-
 .../src/main/js/app/services/Focus.service.js   |   33 +
 .../main/js/app/services/JavaTypes.service.js   |    6 +-
 .../main/js/app/services/LegacyTable.service.js |  205 +++
 .../main/js/app/services/LegacyUtils.service.js |  948 ++++++++++
 .../main/js/app/services/Messages.service.js    |   63 +
 .../js/app/services/ModelNormalizer.service.js  |   59 +
 .../app/services/UnsavedChangesGuard.service.js |   38 +
 .../src/main/js/app/services/cleanup.service.js |   46 -
 .../src/main/js/app/services/confirm.service.js |   70 -
 modules/web-console/src/main/js/app/vendor.js   |   54 +
 .../src/main/js/build/system.config.js          |  424 -----
 .../src/main/js/controllers/admin-controller.js |   33 +-
 .../main/js/controllers/caches-controller.js    |   97 +-
 .../main/js/controllers/clusters-controller.js  |  142 +-
 .../src/main/js/controllers/common-module.js    | 1741 ------------------
 .../main/js/controllers/domains-controller.js   |  295 ++-
 .../src/main/js/controllers/igfs-controller.js  |  126 +-
 .../main/js/controllers/profile-controller.js   |   27 +-
 .../src/main/js/controllers/sql-controller.js   |   75 +-
 .../src/main/js/generator/generator-java.js     |    7 +-
 .../src/main/js/generator/generator-xml.js      |    5 +-
 .../src/main/js/gulpfile.babel.js/paths.js      |   65 +-
 .../main/js/gulpfile.babel.js/tasks/build.js    |    2 +-
 .../main/js/gulpfile.babel.js/tasks/bundle.js   |   68 +-
 .../main/js/gulpfile.babel.js/tasks/clean.js    |    5 +-
 .../main/js/gulpfile.babel.js/tasks/connect.js  |   47 -
 .../src/main/js/gulpfile.babel.js/tasks/copy.js |   32 +-
 .../main/js/gulpfile.babel.js/tasks/eslint.js   |   46 -
 .../gulpfile.babel.js/tasks/ignite-modules.js   |    9 +-
 .../src/main/js/gulpfile.babel.js/tasks/sass.js |   25 -
 .../main/js/gulpfile.babel.js/tasks/watch.js    |   20 +-
 .../main/js/gulpfile.babel.js/webpack/common.js |  192 ++
 .../webpack/environments/development.js         |   64 +
 .../webpack/environments/production.js          |   45 +
 .../main/js/gulpfile.babel.js/webpack/index.js  |   32 +
 .../webpack/plugins/progress.js                 |   82 +
 modules/web-console/src/main/js/package.json    |  301 +--
 .../stylesheets/_font-awesome-custom.scss       |   27 +-
 .../src/main/js/public/stylesheets/style.scss   |   10 +-
 modules/web-console/src/main/js/serve/agent.js  |   89 +-
 .../web-console/src/main/js/serve/keys/test.crt |   13 -
 .../web-console/src/main/js/serve/keys/test.key |   18 -
 .../src/main/js/serve/routes/agent.js           |   30 +-
 .../js/views/configuration/domains-import.jade  |    2 +-
 .../main/js/views/configuration/domains.jade    |    8 +-
 .../main/js/views/configuration/summary.jade    |    2 +-
 .../src/main/js/views/includes/header.jade      |   19 +-
 .../web-console/src/main/js/views/index.jade    |   18 -
 .../web-console/src/main/js/views/reset.jade    |    4 +-
 .../src/main/js/views/settings/profile.jade     |   16 +-
 .../web-console/src/main/js/views/signin.jade   |   52 +-
 .../src/main/js/views/sql/notebook-new.jade     |    2 +-
 .../src/main/js/views/sql/paragraph-rate.jade   |    2 +-
 .../web-console/src/main/js/views/sql/sql.jade  |    6 +-
 .../main/js/views/templates/agent-download.jade |    2 +-
 .../src/main/js/views/templates/clone.jade      |    2 +-
 parent/pom.xml                                  |    9 +-
 284 files changed, 8984 insertions(+), 4824 deletions(-)
----------------------------------------------------------------------


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

http://git-wip-us.apache.org/repos/asf/ignite/blob/4cbcbab5/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------

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


[17/46] ignite git commit: ignite-1088 Implemented store for multi jvm tests (cherry picked from commit f91b699)

Posted by sb...@apache.org.
ignite-1088 Implemented store for multi jvm tests
(cherry picked from commit f91b699)


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

Branch: refs/heads/ignite-1232
Commit: 2f78346e0e3d6a1cb9483b66144175c826a1ff5f
Parents: 89fd76f
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jul 1 12:16:56 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 15 16:21:09 2016 +0300

----------------------------------------------------------------------
 .../cache/GridCacheAbstractFullApiSelfTest.java | 162 +++----
 .../cache/GridCacheAbstractMetricsSelfTest.java |   2 +-
 .../cache/GridCacheAbstractSelfTest.java        | 103 +---
 .../GridCacheInterceptorAbstractSelfTest.java   |   2 +-
 .../processors/cache/H2CacheStoreStrategy.java  | 468 +++++++++++++++++++
 .../IgniteCacheConfigVariationsFullApiTest.java | 122 +++--
 .../IgniteCacheReadThroughEvictionSelfTest.java |   2 +-
 .../processors/cache/MapCacheStoreStrategy.java | 145 ++++++
 .../cache/TestCacheStoreStrategy.java           |  96 ++++
 ...idCacheNearOnlyMultiNodeFullApiSelfTest.java |   2 +-
 ...edOffHeapTieredMultiNodeFullApiSelfTest.java |   2 +-
 .../configvariations/ConfigVariations.java      |   6 +-
 ...IgniteCacheConfigVariationsAbstractTest.java |  67 +--
 .../cache/IgniteCacheQueryIndexSelfTest.java    |   2 +-
 14 files changed, 882 insertions(+), 299 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
index 401afbf..5ab23a0 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
@@ -218,6 +218,8 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
+        initStoreStrategy();
+
         if (cacheStartType() == CacheStartMode.STATIC)
             super.beforeTestsStarted();
         else {
@@ -263,17 +265,12 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     }
 
     /**
-     * Checks that skipStore flag gets overriden inside a transaction.
-     *
-     * @throws Exception if failed.
+     * Checks that skipStore flag gets overridden inside a transaction.
      */
     public void testWriteThroughTx() {
-        if(isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         String key = "writeThroughKey";
 
-        map.remove(key);
+        storeStgy.removeFromStore(key);
 
         try (final Transaction transaction = grid(0).transactions().txStart()) {
             IgniteCache<String, Integer> cache = jcache(0);
@@ -290,27 +287,22 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             transaction.commit();
         }
 
-        assertEquals(2, map.get(key));
+        assertEquals(2, storeStgy.getFromStore(key));
     }
 
     /**
-     * Checks that skipStore flag gets overriden inside a transaction.
-     *
-     * @throws Exception if failed.
+     * Checks that skipStore flag gets overridden inside a transaction.
      */
     public void testNoReadThroughTx() {
-        if(isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         String key = "writeThroughKey";
 
         IgniteCache<String, Integer> cache = jcache(0);
 
-        resetStore();
+        storeStgy.resetStore();
 
         cache.put(key, 1);
 
-        putToStore(key, 2);
+        storeStgy.putToStore(key, 2);
 
         try (final Transaction transaction = grid(0).transactions().txStart()) {
             Integer old = cache.get(key);
@@ -324,7 +316,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             transaction.commit();
         }
 
-        assertEquals(0, reads.get());
+        assertEquals(0, storeStgy.getReads());
     }
 
     /** {@inheritDoc} */
@@ -560,9 +552,6 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
      * @throws Exception If failed.
      */
     public void testRemoveAllSkipStore() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         IgniteCache<String, Integer> jcache = jcache();
 
         jcache.putAll(F.asMap("1", 1, "2", 2, "3", 3));
@@ -2064,7 +2053,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         // Check db.
         if (!isMultiJvm()) {
-            putToStore("key3", 3);
+            storeStgy.putToStore("key3", 3);
 
             assertEquals((Integer)3, cache.getAndPutIfAbsent("key3", 4));
 
@@ -2136,7 +2125,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         // Check db.
         if (!isMultiJvm()) {
-            putToStore("key3", 3);
+            storeStgy.putToStore("key3", 3);
 
             cacheAsync.getAndPutIfAbsent("key3", 4);
 
@@ -2185,7 +2174,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         // Check db.
         if (!isMultiJvm()) {
-            putToStore("key3", 3);
+            storeStgy.putToStore("key3", 3);
 
             assertFalse(cache.putIfAbsent("key3", 4));
         }
@@ -2258,7 +2247,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         // Check db.
         if (!isMultiJvm()) {
-            putToStore("key3", 3);
+            storeStgy.putToStore("key3", 3);
 
             cacheAsync.putIfAbsent("key3", 4);
 
@@ -2362,7 +2351,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         assert cache.get("key") == 4;
 
         if (!isMultiJvm()) {
-            putToStore("key2", 5);
+            storeStgy.putToStore("key2", 5);
 
             info("key2 5 -> 6");
 
@@ -2421,7 +2410,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         assert cache.get("key") == 4;
 
         if (!isMultiJvm()) {
-            putToStore("key2", 5);
+            storeStgy.putToStore("key2", 5);
 
             assert cache.replace("key2", 6);
 
@@ -2497,7 +2486,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         assert cache.get("key") == 4;
 
         if (!isMultiJvm()) {
-            putToStore("key2", 5);
+            storeStgy.putToStore("key2", 5);
 
             cacheAsync.replace("key2", 5, 6);
 
@@ -2559,7 +2548,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         assert cache.get("key") == 4;
 
         if (!isMultiJvm()) {
-            putToStore("key2", 5);
+            storeStgy.putToStore("key2", 5);
 
             cacheAsync.replace("key2", 6);
 
@@ -2684,9 +2673,6 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
      * @throws Exception If failed.
      */
     public void testRemoveLoad() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         int cnt = 10;
 
         Set<String> keys = new HashSet<>();
@@ -2697,7 +2683,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         jcache().removeAll(keys);
 
         for (String key : keys)
-            putToStore(key, Integer.parseInt(key));
+            storeStgy.putToStore(key, Integer.parseInt(key));
 
         for (int g = 0; g < gridCount(); g++)
             grid(g).cache(null).localLoadCache(null);
@@ -3760,7 +3746,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         }
 
         // Avoid reloading from store.
-        map.remove(key);
+        storeStgy.removeFromStore(key);
 
         assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicateX() {
             @SuppressWarnings("unchecked")
@@ -4753,9 +4739,6 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
      * @throws Exception If failed.
      */
     public void testWithSkipStore() throws Exception {
-        if(isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         IgniteCache<String, Integer> cache = grid(0).cache(null);
 
         IgniteCache<String, Integer> cacheSkipStore = cache.withSkipStore();
@@ -4763,7 +4746,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         List<String> keys = primaryKeysForCache(cache, 10);
 
         for (int i = 0; i < keys.size(); ++i)
-            putToStore(keys.get(i), i);
+            storeStgy.putToStore(keys.get(i), i);
 
         assertFalse(cacheSkipStore.iterator().hasNext());
 
@@ -4801,7 +4784,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertEquals(i, map.get(key));
+            assertEquals(i, storeStgy.getFromStore(key));
         }
 
         for (int i = 0; i < keys.size(); ++i) {
@@ -4810,13 +4793,13 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             Integer val1 = -1;
 
             cacheSkipStore.put(key, val1);
-            assertEquals(i, map.get(key));
+            assertEquals(i, storeStgy.getFromStore(key));
             assertEquals(val1, cacheSkipStore.get(key));
 
             Integer val2 = -2;
 
             assertEquals(val1, cacheSkipStore.invoke(key, new SetValueProcessor(val2)));
-            assertEquals(i, map.get(key));
+            assertEquals(i, storeStgy.getFromStore(key));
             assertEquals(val2, cacheSkipStore.get(key));
         }
 
@@ -4825,7 +4808,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         for (String key : keys) {
@@ -4833,37 +4816,37 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
 
-            map.put(key, 0);
+            storeStgy.putToStore(key, 0);
 
             Integer val = -1;
 
             assertNull(cacheSkipStore.invoke(key, new SetValueProcessor(val)));
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
             assertEquals(val, cacheSkipStore.get(key));
 
             cache.remove(key);
 
-            map.put(key, 0);
+            storeStgy.putToStore(key, 0);
 
             assertTrue(cacheSkipStore.putIfAbsent(key, val));
             assertEquals(val, cacheSkipStore.get(key));
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             cache.remove(key);
 
-            map.put(key, 0);
+            storeStgy.putToStore(key, 0);
 
             assertNull(cacheSkipStore.getAndPut(key, val));
             assertEquals(val, cacheSkipStore.get(key));
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             cache.remove(key);
         }
 
         assertFalse(cacheSkipStore.iterator().hasNext());
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
         assertTrue(cache.size(ALL) == 0);
 
         // putAll/removeAll from multiple nodes.
@@ -4878,7 +4861,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : keys) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
         cache.putAll(data);
@@ -4886,7 +4869,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : keys) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.removeAll(data.keySet());
@@ -4894,7 +4877,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.putAll(data);
@@ -4902,7 +4885,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : keys) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.removeAll(data.keySet());
@@ -4910,7 +4893,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cache.removeAll(data.keySet());
@@ -4918,24 +4901,24 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
 
         // Miscellaneous checks.
 
         String newKey = "New key";
 
-        assertFalse(map.containsKey(newKey));
+        assertFalse(storeStgy.isInStore(newKey));
 
         cacheSkipStore.put(newKey, 1);
 
-        assertFalse(map.containsKey(newKey));
+        assertFalse(storeStgy.isInStore(newKey));
 
         cache.put(newKey, 1);
 
-        assertTrue(map.containsKey(newKey));
+        assertTrue(storeStgy.isInStore(newKey));
 
         Iterator<Cache.Entry<String, Integer>> it = cacheSkipStore.iterator();
 
@@ -4945,29 +4928,26 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         String rmvKey = entry.getKey();
 
-        assertTrue(map.containsKey(rmvKey));
+        assertTrue(storeStgy.isInStore(rmvKey));
 
         it.remove();
 
         assertNull(cacheSkipStore.get(rmvKey));
 
-        assertTrue(map.containsKey(rmvKey));
+        assertTrue(storeStgy.isInStore(rmvKey));
 
         assertTrue(cache.size(ALL) == 0);
         assertTrue(cacheSkipStore.size(ALL) == 0);
 
         cache.remove(rmvKey);
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testWithSkipStoreRemoveAll() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         if (atomicityMode() == TRANSACTIONAL || (atomicityMode() == ATOMIC && nearEnabled())) // TODO IGNITE-373.
             return;
 
@@ -4985,7 +4965,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : data.keySet()) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.removeAll();
@@ -4993,7 +4973,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : data.keySet()) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cache.removeAll();
@@ -5001,7 +4981,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key : data.keySet()) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
     }
 
@@ -5077,7 +5057,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             for (String key: keys) {
                 assertEquals(val, cacheSkipStore.get(key));
                 assertEquals(val, cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             tx.commit();
@@ -5086,10 +5066,10 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key: keys) {
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
-        assertEquals(0, map.size());
+        assertEquals(0, storeStgy.getStoreSize());
 
         // cacheSkipStore putAll(..)/removeAll(..) check.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
@@ -5103,10 +5083,10 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
-        map.putAll(data);
+        storeStgy.putAllToStore(data);
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             cacheSkipStore.removeAll(data.keySet());
@@ -5117,12 +5097,12 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key: keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
 
             cache.remove(key);
         }
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
 
         // cache putAll(..)/removeAll(..) check.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
@@ -5131,7 +5111,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             for (String key: keys) {
                 assertNotNull(cacheSkipStore.get(key));
                 assertNotNull(cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             cache.removeAll(data.keySet());
@@ -5139,13 +5119,13 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             for (String key: keys) {
                 assertNull(cacheSkipStore.get(key));
                 assertNull(cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             tx.commit();
         }
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
 
         // putAll(..) from both cacheSkipStore and cache.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
@@ -5166,7 +5146,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             for (String key: keys) {
                 assertNotNull(cacheSkipStore.get(key));
                 assertNotNull(cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             tx.commit();
@@ -5177,7 +5157,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
         for (int i = keys.size() / 2; i < keys.size(); i++) {
@@ -5185,7 +5165,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cache.removeAll(data.keySet());
@@ -5193,16 +5173,16 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         for (String key: keys) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
         // Check that read-through is disabled when cacheSkipStore is used.
         for (int i = 0; i < keys.size(); i++)
-            putToStore(keys.get(i), i);
+            storeStgy.putToStore(keys.get(i), i);
 
         assertTrue(cacheSkipStore.size(ALL) == 0);
         assertTrue(cache.size(ALL) == 0);
-        assertTrue(map.size() != 0);
+        assertTrue(storeStgy.getStoreSize() != 0);
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             assertTrue(cacheSkipStore.getAll(data.keySet()).size() == 0);
@@ -5225,7 +5205,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             for (String key : data.keySet()) {
-                map.put(key, 0);
+                storeStgy.putToStore(key, 0);
 
                 assertNull(cacheSkipStore.invoke(key, new SetValueProcessor(val)));
             }
@@ -5234,7 +5214,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         }
 
         for (String key : data.keySet()) {
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
@@ -5244,7 +5224,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             for (String key : data.keySet()) {
-                map.put(key, 0);
+                storeStgy.putToStore(key, 0);
 
                 assertTrue(cacheSkipStore.putIfAbsent(key, val));
             }
@@ -5253,7 +5233,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         }
 
         for (String key : data.keySet()) {
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
@@ -5263,7 +5243,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             for (String key : data.keySet()) {
-                map.put(key, 0);
+                storeStgy.putToStore(key, 0);
 
                 assertNull(cacheSkipStore.getAndPut(key, val));
             }
@@ -5272,7 +5252,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         }
 
         for (String key : data.keySet()) {
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
@@ -5292,7 +5272,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         throws Exception {
         assertTrue(cache.size(ALL) == 0);
         assertTrue(cacheSkipStore.size(ALL) == 0);
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractMetricsSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractMetricsSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractMetricsSelfTest.java
index 13bd081..5ad7e5c 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractMetricsSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractMetricsSelfTest.java
@@ -906,7 +906,7 @@ public abstract class GridCacheAbstractMetricsSelfTest extends GridCacheAbstract
         }
 
         // Avoid reloading from store.
-        map.remove(key);
+        storeStgy.removeFromStore(key);
 
         assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicateX() {
             @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
index b918f28..dcf5d98 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.internal.processors.cache;
 
-import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 import javax.cache.Cache;
 import javax.cache.configuration.Factory;
@@ -30,7 +29,6 @@ import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.cache.store.CacheStore;
-import org.apache.ignite.cache.store.CacheStoreAdapter;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
@@ -43,7 +41,6 @@ import org.apache.ignite.internal.util.typedef.P1;
 import org.apache.ignite.internal.util.typedef.R1;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiInClosure;
 import org.apache.ignite.lang.IgnitePredicate;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
@@ -52,7 +49,6 @@ import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.apache.ignite.transactions.Transaction;
 import org.jetbrains.annotations.Nullable;
-import org.jsr166.ConcurrentHashMap8;
 
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
@@ -66,21 +62,12 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
     /** Test timeout */
     private static final long TEST_TIMEOUT = 30 * 1000;
 
-    /** Store map. */
-    protected static final Map<Object, Object> map = new ConcurrentHashMap8<>();
-
-    /** Reads counter. */
-    protected static final AtomicInteger reads = new AtomicInteger();
-
-    /** Writes counter. */
-    protected static final AtomicInteger writes = new AtomicInteger();
-
-    /** Removes counter. */
-    protected static final AtomicInteger removes = new AtomicInteger();
-
     /** VM ip finder for TCP discovery. */
     protected static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
 
+    /** */
+    protected static TestCacheStoreStrategy storeStgy;
+
     /**
      * @return Grids count to start.
      */
@@ -97,6 +84,8 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
 
         assert cnt >= 1 : "At least one grid must be started";
 
+        initStoreStrategy();
+
         startGrids(cnt);
 
         awaitPartitionMapExchange();
@@ -106,7 +95,18 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
     @Override protected void afterTestsStopped() throws Exception {
         stopAllGrids();
 
-        map.clear();
+        if (storeStgy != null)
+            storeStgy.resetStore();
+    }
+
+    /**
+     * Initializes {@link #storeStgy} with respect to the nature of the test.
+     *
+     * @throws IgniteCheckedException If failed.
+     */
+    void initStoreStrategy() throws IgniteCheckedException {
+        if (storeStgy == null)
+            storeStgy = isMultiJvm() ? new H2CacheStoreStrategy() : new MapCacheStoreStrategy();
     }
 
     /** {@inheritDoc} */
@@ -188,28 +188,7 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
         assert jcache().unwrap(Ignite.class).transactions().tx() == null;
         assertEquals("Cache is not empty", 0, jcache().localSize(CachePeekMode.ALL));
 
-        resetStore();
-    }
-
-    /**
-     * Cleans up cache store.
-     */
-    protected void resetStore() {
-        map.clear();
-
-        reads.set(0);
-        writes.set(0);
-        removes.set(0);
-    }
-
-    /**
-     * Put entry to cache store.
-     *
-     * @param key Key.
-     * @param val Value.
-     */
-    protected void putToStore(Object key, Object val) {
-        map.put(key, val);
+        storeStgy.resetStore();
     }
 
     /** {@inheritDoc} */
@@ -241,13 +220,16 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
     protected CacheConfiguration cacheConfiguration(String gridName) throws Exception {
         CacheConfiguration cfg = defaultCacheConfiguration();
 
-        CacheStore<?, ?> store = cacheStore();
+        Factory<? extends CacheStore<Object, Object>> storeFactory = storeStgy.getStoreFactory();
+
+        CacheStore<?, ?> store = storeFactory.create();
 
         if (store != null) {
-            cfg.setCacheStoreFactory(new TestStoreFactory());
+            cfg.setCacheStoreFactory(storeFactory);
             cfg.setReadThrough(true);
             cfg.setWriteThrough(true);
             cfg.setLoadPreviousValue(true);
+            storeStgy.updateCacheConfiguration(cfg);
         }
 
         cfg.setSwapEnabled(swapEnabled());
@@ -303,37 +285,6 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * @return Write through storage emulator.
-     */
-    protected static CacheStore<?, ?> cacheStore() {
-        return new CacheStoreAdapter<Object, Object>() {
-            @Override public void loadCache(IgniteBiInClosure<Object, Object> clo,
-                Object... args) {
-                for (Map.Entry<Object, Object> e : map.entrySet())
-                    clo.apply(e.getKey(), e.getValue());
-            }
-
-            @Override public Object load(Object key) {
-                reads.incrementAndGet();
-
-                return map.get(key);
-            }
-
-            @Override public void write(javax.cache.Cache.Entry<? extends Object, ? extends Object> e) {
-                writes.incrementAndGet();
-
-                map.put(e.getKey(), e.getValue());
-            }
-
-            @Override public void delete(Object key) {
-                removes.incrementAndGet();
-
-                map.remove(key);
-            }
-        };
-    }
-
-    /**
      * @return {@code true} if swap should be enabled.
      */
     protected boolean swapEnabled() {
@@ -575,12 +526,4 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
         }
     }
 
-    /**
-     * Serializable factory.
-     */
-    protected static class TestStoreFactory implements Factory<CacheStore> {
-        @Override public CacheStore create() {
-            return cacheStore();
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheInterceptorAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheInterceptorAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheInterceptorAbstractSelfTest.java
index f50a3e0..68bfb6f 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheInterceptorAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheInterceptorAbstractSelfTest.java
@@ -1444,7 +1444,7 @@ public abstract class GridCacheInterceptorAbstractSelfTest extends GridCacheAbst
         interceptor.disabled = true;
 
         if (storeEnabled())
-            assertEquals("Unexpected store value", expVal, map.get(key));
+            assertEquals("Unexpected store value", expVal, storeStgy.getFromStore(key));
 
         try {
             for (int i = 0; i < gridCount(); i++)

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/H2CacheStoreStrategy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/H2CacheStoreStrategy.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/H2CacheStoreStrategy.java
new file mode 100644
index 0000000..ccb2994
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/H2CacheStoreStrategy.java
@@ -0,0 +1,468 @@
+/*
+ * 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.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.StringReader;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+import javax.cache.Cache;
+import javax.cache.configuration.Factory;
+import javax.cache.integration.CacheLoaderException;
+import javax.cache.integration.CacheWriterException;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.store.CacheStore;
+import org.apache.ignite.cache.store.CacheStoreAdapter;
+import org.apache.ignite.cache.store.CacheStoreSession;
+import org.apache.ignite.cache.store.CacheStoreSessionListener;
+import org.apache.ignite.cache.store.jdbc.CacheJdbcStoreSessionListener;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiInClosure;
+import org.apache.ignite.resources.CacheStoreSessionResource;
+import org.h2.jdbcx.JdbcConnectionPool;
+import org.h2.tools.RunScript;
+import org.h2.tools.Server;
+
+/**
+ * {@link TestCacheStoreStrategy} backed by H2 in-memory database.
+ */
+public class H2CacheStoreStrategy implements TestCacheStoreStrategy {
+    /** Pool to get {@link Connection}s from. */
+    private final JdbcConnectionPool dataSrc;
+
+    /** Script that creates CACHE table. */
+    private static final String CREATE_CACHE_TABLE =
+        "create table if not exists CACHE(k binary not null, v binary not null, PRIMARY KEY(k));";
+
+    /** Script that creates STATS table. */
+    private static final String CREATE_STATS_TABLES =
+        "create table if not exists READS(id bigint auto_increment);\n" +
+        "create table if not exists WRITES(id bigint auto_increment);\n" +
+        "create table if not exists REMOVES(id bigint auto_increment);";
+
+    /** Script that populates STATS table */
+    private static final String POPULATE_STATS_TABLE =
+        "delete from READS;\n" +
+        "delete from WRITES;\n" +
+        "delete from REMOVES;";
+
+
+    /**
+     * @throws IgniteCheckedException If failed.
+     */
+    public H2CacheStoreStrategy() throws IgniteCheckedException {
+        try {
+            Server.createTcpServer().start();
+            dataSrc = H2CacheStoreSessionListenerFactory.createDataSource();
+
+            try (Connection conn = connection()) {
+                RunScript.execute(conn, new StringReader(CREATE_CACHE_TABLE));
+                RunScript.execute(conn, new StringReader(CREATE_STATS_TABLES));
+                RunScript.execute(conn, new StringReader(POPULATE_STATS_TABLE));
+            }
+        }
+        catch (SQLException e) {
+            throw new IgniteCheckedException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getReads() {
+        return queryStats("reads");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getWrites() {
+        return queryStats("writes");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getRemoves() {
+        return queryStats("removes");
+    }
+
+    /**
+     * @param tbl Table name.
+     * @return Update statistics.
+     */
+    private int queryStats(String tbl) {
+        return querySingleInt("select count(*) from " + tbl, "Failed to query store stats [table=" + tbl + "]");
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getStoreSize() {
+        return querySingleInt("select count(*) from CACHE;", "Failed to query number of rows from CACHE table");
+    }
+
+    /** {@inheritDoc} */
+    @Override public void resetStore() {
+        try (Connection conn = connection()) {
+            RunScript.execute(conn, new StringReader("delete from CACHE;"));
+            RunScript.execute(conn, new StringReader(POPULATE_STATS_TABLE));
+        }
+        catch (SQLException e) {
+            throw new IgniteException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putToStore(Object key, Object val) {
+        Connection conn = null;
+        try {
+            conn = connection();
+            H2CacheStore.putToDb(conn, key, val);
+        }
+        catch (SQLException e) {
+            throw new IgniteException(e);
+        }
+        finally {
+            U.closeQuiet(conn);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putAllToStore(Map<?, ?> data) {
+        Connection conn = null;
+        PreparedStatement stmt = null;
+        try {
+            conn = connection();
+            stmt = conn.prepareStatement(H2CacheStore.MERGE);
+            for (Map.Entry<?, ?> e : data.entrySet()) {
+                stmt.setBinaryStream(1, new ByteArrayInputStream(H2CacheStore.serialize(e.getKey())));
+                stmt.setBinaryStream(2, new ByteArrayInputStream(H2CacheStore.serialize(e.getValue())));
+                stmt.addBatch();
+            }
+            stmt.executeBatch();
+        }
+        catch (SQLException e) {
+            throw new IgniteException(e);
+        }
+        finally {
+            U.closeQuiet(stmt);
+            U.closeQuiet(conn);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getFromStore(Object key) {
+        Connection conn = null;
+        try {
+            conn = connection();
+            return H2CacheStore.getFromDb(conn, key);
+        }
+        catch (SQLException e) {
+            throw new IgniteException(e);
+        }
+        finally {
+            U.closeQuiet(conn);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeFromStore(Object key) {
+        Connection conn = null;
+        try {
+            conn = connection();
+            H2CacheStore.removeFromDb(conn, key);
+        }
+        catch (SQLException e) {
+            throw new IgniteException(e);
+        }
+        finally {
+            U.closeQuiet(conn);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isInStore(Object key) {
+        return getFromStore(key) != null;
+    }
+
+    /**
+     * @return New {@link Connection} from {@link #dataSrc}
+     * @throws SQLException if failed
+     */
+    private Connection connection() throws SQLException {
+        return dataSrc.getConnection();
+    }
+
+    /**
+     * Retrieves single int value from {@link ResultSet} returned by given query.
+     *
+     * @param qry Query string (fully populated, with params).
+     * @param errorMsg Message for {@link IgniteException} to bear in case of failure.
+     * @return Requested value
+     */
+    private int querySingleInt(String qry, String errorMsg) {
+        Connection conn = null;
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try {
+            conn = connection();
+            stmt = conn.prepareStatement(qry);
+            rs = stmt.executeQuery();
+            if (rs.next())
+                return rs.getInt(1);
+            else
+                throw new IgniteException(errorMsg);
+        }
+        catch (SQLException e) {
+            throw new IgniteException(e);
+        }
+        finally {
+            U.closeQuiet(rs);
+            U.closeQuiet(stmt);
+            U.closeQuiet(conn);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCacheConfiguration(CacheConfiguration<Object, Object> cfg) {
+        cfg.setCacheStoreSessionListenerFactories(new H2CacheStoreSessionListenerFactory());
+    }
+
+    /** {@inheritDoc} */
+    @Override public Factory<? extends CacheStore<Object, Object>> getStoreFactory() {
+        return new H2StoreFactory();
+    }
+
+    /** Serializable H2 backed cache store factory. */
+    public static class H2StoreFactory implements Factory<CacheStore<Object, Object>> {
+        /** {@inheritDoc} */
+        @Override public CacheStore<Object, Object> create() {
+            return new H2CacheStore();
+        }
+    }
+
+    /** Serializable {@link Factory} producing H2 backed {@link CacheStoreSessionListener}s. */
+    public static class H2CacheStoreSessionListenerFactory implements Factory<CacheStoreSessionListener> {
+        /**
+         * @return Connection pool
+         */
+        static JdbcConnectionPool createDataSource() {
+            JdbcConnectionPool pool = JdbcConnectionPool.create("jdbc:h2:tcp://localhost/mem:TestDb;LOCK_MODE=0", "sa", "");
+            pool.setMaxConnections(100);
+            return pool;
+        }
+
+        /** {@inheritDoc} */
+        @Override public CacheStoreSessionListener create() {
+            CacheJdbcStoreSessionListener lsnr = new CacheJdbcStoreSessionListener();
+            lsnr.setDataSource(createDataSource());
+            return lsnr;
+        }
+    }
+
+    /** H2 backed {@link CacheStoreAdapter} implementations */
+    public static class H2CacheStore extends CacheStoreAdapter<Object, Object> {
+        /** Store session */
+        @CacheStoreSessionResource
+        private CacheStoreSession ses;
+
+        /** Template for an insert statement */
+        private static final String MERGE = "merge into CACHE(k, v) values(?, ?);";
+
+        /** {@inheritDoc} */
+        @Override public void loadCache(IgniteBiInClosure<Object, Object> clo, Object... args) {
+            Connection conn = ses.attachment();
+            assert conn != null;
+
+            Statement stmt = null;
+            ResultSet rs = null;
+            try {
+                stmt = conn.createStatement();
+                rs = stmt.executeQuery("select * from CACHE");
+                while (rs.next())
+                    clo.apply(deserialize(rs.getBytes(1)), deserialize(rs.getBytes(2)));
+            }
+            catch (SQLException e) {
+                throw new IgniteException(e);
+            }
+            finally {
+                U.closeQuiet(rs);
+                U.closeQuiet(stmt);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object load(Object key) throws CacheLoaderException {
+            try {
+                Connection conn = ses.attachment();
+                Object res = getFromDb(conn, key);
+                updateStats("reads");
+                return res;
+            }
+            catch (SQLException e) {
+                throw new CacheLoaderException("Failed to load object [key=" + key + ']', e);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void write(Cache.Entry<?, ?> entry) throws CacheWriterException {
+            try {
+                Connection conn = ses.attachment();
+                putToDb(conn, entry.getKey(), entry.getValue());
+                updateStats("writes");
+            }
+            catch (SQLException e) {
+                throw new CacheWriterException("Failed to write object [key=" + entry.getKey() + ", " +
+                    "val=" + entry.getValue() + ']', e);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public void delete(Object key) throws CacheWriterException {
+            try {
+                Connection conn = ses.attachment();
+                removeFromDb(conn, key);
+                updateStats("removes");
+            }
+            catch (SQLException e) {
+                throw new CacheWriterException("Failed to delete object [key=" + key + ']', e);
+            }
+        }
+
+        /**
+         * Selects from H2 and deserialize from bytes the value pointed by key.
+         *
+         * @param conn {@link Connection} to use.
+         * @param key Key to look for.
+         * @return Stored object or null if the key is missing from DB.
+         * @throws SQLException If failed.
+         */
+        static Object getFromDb(Connection conn, Object key) throws SQLException {
+            PreparedStatement stmt = null;
+            ResultSet rs = null;
+            try {
+                stmt = conn.prepareStatement("select v from CACHE where k = ?");
+                stmt.setBinaryStream(1, new ByteArrayInputStream(H2CacheStore.serialize(key)));
+                rs = stmt.executeQuery();
+                return rs.next() ? H2CacheStore.deserialize(rs.getBytes(1)) : null;
+            }
+            finally {
+                U.closeQuiet(rs);
+                U.closeQuiet(stmt);
+            }
+        }
+
+        /**
+         * Puts key-value pair to H2.
+         *
+         * @param conn {@link Connection} to use.
+         * @param key Key.
+         * @param val Value.
+         * @throws SQLException If failed.
+         */
+        static void putToDb(Connection conn, Object key, Object val) throws SQLException {
+            PreparedStatement stmt = null;
+            try {
+                stmt = conn.prepareStatement(H2CacheStore.MERGE);
+                stmt.setBinaryStream(1, new ByteArrayInputStream(H2CacheStore.serialize(key)));
+                stmt.setBinaryStream(2, new ByteArrayInputStream(H2CacheStore.serialize(val)));
+                stmt.executeUpdate();
+            }
+            finally {
+                U.closeQuiet(stmt);
+            }
+        }
+
+        /**
+         * Removes given key and its value from H2.
+         *
+         * @param conn {@link Connection} to invoke query upon.
+         * @param key Key to remove.
+         * @throws SQLException if failed.
+         */
+        static void removeFromDb(Connection conn, Object key) throws SQLException {
+            PreparedStatement stmt = null;
+            try {
+                stmt = conn.prepareStatement("delete from CACHE where k = ?");
+                stmt.setBinaryStream(1, new ByteArrayInputStream(H2CacheStore.serialize(key)));
+                stmt.executeUpdate();
+            }
+            finally {
+                U.closeQuiet(stmt);
+            }
+        }
+
+        /**
+         * Increments stored stats for given operation.
+         *
+         * @param tblName Table name
+         */
+        private void updateStats(String tblName) {
+            Connection conn = ses.attachment();
+            assert conn != null;
+            Statement stmt = null;
+            try {
+                stmt = conn.createStatement();
+                stmt.executeUpdate("insert into " + tblName + " default values");
+            }
+            catch (SQLException e) {
+                throw new IgniteException("Failed to update H2 store usage stats", e);
+            }
+            finally {
+                U.closeQuiet(stmt);
+            }
+        }
+
+        /**
+         * Turns given arbitrary object to byte array.
+         *
+         * @param obj Object to serialize
+         * @return Bytes representation of given object.
+         */
+        static byte[] serialize(Object obj) {
+            try (ByteArrayOutputStream b = new ByteArrayOutputStream()) {
+                try (ObjectOutputStream o = new ObjectOutputStream(b)) {
+                    o.writeObject(obj);
+                }
+                return b.toByteArray();
+            }
+            catch (Exception e) {
+                throw new IgniteException("Failed to serialize object to byte array [obj=" + obj, e);
+            }
+        }
+
+        /**
+         * Deserializes an object from its byte array representation.
+         *
+         * @param bytes Byte array representation of the object.
+         * @return Deserialized object.
+         */
+        public static Object deserialize(byte[] bytes) {
+            try (ByteArrayInputStream b = new ByteArrayInputStream(bytes)) {
+                try (ObjectInputStream o = new ObjectInputStream(b)) {
+                    return o.readObject();
+                }
+            }
+            catch (Exception e) {
+                throw new IgniteException("Failed to deserialize object from byte array", e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
index 5e8f162..7e6d015 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
@@ -351,9 +351,6 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
      * @throws Exception If failed.
      */
     public void testRemoveAllSkipStore() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         if (!storeEnabled())
             return;
 
@@ -2571,9 +2568,6 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
      * @throws Exception If failed.
      */
     public void testRemoveLoad() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         if (!storeEnabled())
             return;
 
@@ -3655,7 +3649,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         }
 
         // Avoid reloading from store.
-        map.remove(key);
+        storeStgy.removeFromStore(key);
 
         assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicateX() {
             @SuppressWarnings("unchecked")
@@ -4169,12 +4163,12 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         for (int i = 0; i < gridCount(); i++) {
             for (Cache.Entry entry : jcache(i))
-                map.put(entry.getKey(), entry.getValue());
+                storeStgy.putToStore(entry.getKey(), entry.getValue());
         }
 
-        assert map.size() == 2;
-        assert (Integer)map.get("key1") == 1;
-        assert (Integer)map.get("key2") == 2;
+        assert storeStgy.getStoreSize() == 2;
+        assert (Integer)storeStgy.getFromStore("key1") == 1;
+        assert (Integer)storeStgy.getFromStore("key2") == 2;
     }
 
     /**
@@ -4726,9 +4720,6 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
      * @throws Exception If failed.
      */
     public void testWithSkipStore() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         if (!storeEnabled())
             return;
 
@@ -4777,7 +4768,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertEquals(i, map.get(key));
+            assertEquals(i, storeStgy.getFromStore(key));
         }
 
         for (int i = 0; i < keys.size(); ++i) {
@@ -4786,13 +4777,13 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             Integer val1 = -1;
 
             cacheSkipStore.put(key, val1);
-            assertEquals(i, map.get(key));
+            assertEquals(i, storeStgy.getFromStore(key));
             assertEquals(val1, cacheSkipStore.get(key));
 
             Integer val2 = -2;
 
             assertEquals(val1, cacheSkipStore.invoke(key, new SetValueProcessor(val2)));
-            assertEquals(i, map.get(key));
+            assertEquals(i, storeStgy.getFromStore(key));
             assertEquals(val2, cacheSkipStore.get(key));
         }
 
@@ -4801,7 +4792,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         for (String key : keys) {
@@ -4809,37 +4800,37 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
 
-            map.put(key, 0);
+            storeStgy.putToStore(key, 0);
 
             Integer val = -1;
 
             assertNull(cacheSkipStore.invoke(key, new SetValueProcessor(val)));
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
             assertEquals(val, cacheSkipStore.get(key));
 
             cache.remove(key);
 
-            map.put(key, 0);
+            storeStgy.putToStore(key, 0);
 
             assertTrue(cacheSkipStore.putIfAbsent(key, val));
             assertEquals(val, cacheSkipStore.get(key));
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             cache.remove(key);
 
-            map.put(key, 0);
+            storeStgy.putToStore(key, 0);
 
             assertNull(cacheSkipStore.getAndPut(key, val));
             assertEquals(val, cacheSkipStore.get(key));
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             cache.remove(key);
         }
 
         assertFalse(cacheSkipStore.iterator().hasNext());
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
         assertTrue(cache.size(ALL) == 0);
 
         // putAll/removeAll from multiple nodes.
@@ -4854,7 +4845,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
         cache.putAll(data);
@@ -4862,7 +4853,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.removeAll(data.keySet());
@@ -4870,7 +4861,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.putAll(data);
@@ -4878,7 +4869,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.removeAll(data.keySet());
@@ -4886,7 +4877,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cache.removeAll(data.keySet());
@@ -4894,24 +4885,24 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
 
         // Miscellaneous checks.
 
         String newKey = "New key";
 
-        assertFalse(map.containsKey(newKey));
+        assertFalse(storeStgy.isInStore(newKey));
 
         cacheSkipStore.put(newKey, 1);
 
-        assertFalse(map.containsKey(newKey));
+        assertFalse(storeStgy.isInStore(newKey));
 
         cache.put(newKey, 1);
 
-        assertTrue(map.containsKey(newKey));
+        assertTrue(storeStgy.isInStore(newKey));
 
         Iterator<Cache.Entry<String, Integer>> it = cacheSkipStore.iterator();
 
@@ -4921,29 +4912,26 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         String rmvKey = entry.getKey();
 
-        assertTrue(map.containsKey(rmvKey));
+        assertTrue(storeStgy.isInStore(rmvKey));
 
         it.remove();
 
         assertNull(cacheSkipStore.get(rmvKey));
 
-        assertTrue(map.containsKey(rmvKey));
+        assertTrue(storeStgy.isInStore(rmvKey));
 
         assertTrue(cache.size(ALL) == 0);
         assertTrue(cacheSkipStore.size(ALL) == 0);
 
         cache.remove(rmvKey);
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
     }
 
     /**
      * @throws Exception If failed.
      */
     public void testWithSkipStoreRemoveAll() throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1088");
-
         if (atomicityMode() == TRANSACTIONAL || (atomicityMode() == ATOMIC && nearEnabled())) // TODO IGNITE-373.
             return;
 
@@ -4964,7 +4952,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : data.keySet()) {
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cacheSkipStore.removeAll();
@@ -4972,7 +4960,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : data.keySet()) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cache.removeAll();
@@ -4980,7 +4968,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : data.keySet()) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
     }
 
@@ -5054,7 +5042,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             for (String key : keys) {
                 assertEquals(val, cacheSkipStore.get(key));
                 assertEquals(val, cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             tx.commit();
@@ -5063,10 +5051,10 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
-        assertEquals(0, map.size());
+        assertEquals(0, storeStgy.getStoreSize());
 
         // cacheSkipStore putAll(..)/removeAll(..) check.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
@@ -5080,10 +5068,10 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
-        map.putAll(data);
+        storeStgy.putAllToStore(data);
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             cacheSkipStore.removeAll(data.keySet());
@@ -5094,12 +5082,12 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
 
             cache.remove(key);
         }
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
 
         // cache putAll(..)/removeAll(..) check.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
@@ -5108,7 +5096,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             for (String key : keys) {
                 assertNotNull(cacheSkipStore.get(key));
                 assertNotNull(cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             cache.removeAll(data.keySet());
@@ -5116,13 +5104,13 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             for (String key : keys) {
                 assertNull(cacheSkipStore.get(key));
                 assertNull(cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             tx.commit();
         }
 
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
 
         // putAll(..) from both cacheSkipStore and cache.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
@@ -5143,7 +5131,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             for (String key : keys) {
                 assertNotNull(cacheSkipStore.get(key));
                 assertNotNull(cache.get(key));
-                assertFalse(map.containsKey(key));
+                assertFalse(storeStgy.isInStore(key));
             }
 
             tx.commit();
@@ -5154,7 +5142,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
         for (int i = keys.size() / 2; i < keys.size(); i++) {
@@ -5162,7 +5150,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
             assertNotNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
-            assertTrue(map.containsKey(key));
+            assertTrue(storeStgy.isInStore(key));
         }
 
         cache.removeAll(data.keySet());
@@ -5170,7 +5158,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
-            assertFalse(map.containsKey(key));
+            assertFalse(storeStgy.isInStore(key));
         }
 
         // Check that read-through is disabled when cacheSkipStore is used.
@@ -5179,7 +5167,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         assertTrue(cacheSkipStore.size(ALL) == 0);
         assertTrue(cache.size(ALL) == 0);
-        assertTrue(map.size() != 0);
+        assertTrue(storeStgy.getStoreSize() != 0);
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             assertTrue(cacheSkipStore.getAll(data.keySet()).size() == 0);
@@ -5202,7 +5190,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             for (String key : data.keySet()) {
-                map.put(key, 0);
+                storeStgy.putToStore(key, 0);
 
                 assertNull(cacheSkipStore.invoke(key, new SetValueProcessor(val)));
             }
@@ -5211,7 +5199,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         }
 
         for (String key : data.keySet()) {
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
@@ -5221,7 +5209,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             for (String key : data.keySet()) {
-                map.put(key, 0);
+                storeStgy.putToStore(key, 0);
 
                 assertTrue(cacheSkipStore.putIfAbsent(key, val));
             }
@@ -5230,7 +5218,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         }
 
         for (String key : data.keySet()) {
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
@@ -5240,7 +5228,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             for (String key : data.keySet()) {
-                map.put(key, 0);
+                storeStgy.putToStore(key, 0);
 
                 assertNull(cacheSkipStore.getAndPut(key, val));
             }
@@ -5249,7 +5237,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         }
 
         for (String key : data.keySet()) {
-            assertEquals(0, map.get(key));
+            assertEquals(0, storeStgy.getFromStore(key));
 
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
@@ -5268,7 +5256,7 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         throws Exception {
         assertTrue(cache.size(ALL) == 0);
         assertTrue(cacheSkipStore.size(ALL) == 0);
-        assertTrue(map.size() == 0);
+        assertTrue(storeStgy.getStoreSize() == 0);
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheReadThroughEvictionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheReadThroughEvictionSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheReadThroughEvictionSelfTest.java
index 78afdc8..5da656d 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheReadThroughEvictionSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheReadThroughEvictionSelfTest.java
@@ -51,7 +51,7 @@ public class IgniteCacheReadThroughEvictionSelfTest extends IgniteCacheConfigVar
 
     /** {@inheritDoc} */
     @Override protected void afterTest() throws Exception {
-        resetStore();
+        storeStgy.resetStore();
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/MapCacheStoreStrategy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/MapCacheStoreStrategy.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/MapCacheStoreStrategy.java
new file mode 100644
index 0000000..800d781
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/MapCacheStoreStrategy.java
@@ -0,0 +1,145 @@
+/*
+ * 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.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.Cache;
+import javax.cache.configuration.Factory;
+import javax.cache.configuration.FactoryBuilder;
+import org.apache.ignite.cache.store.CacheStore;
+import org.apache.ignite.cache.store.CacheStoreAdapter;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.lang.IgniteBiInClosure;
+import org.jsr166.ConcurrentHashMap8;
+
+/**
+ * {@link TestCacheStoreStrategy} implemented as a wrapper around {@link #map}
+ */
+public class MapCacheStoreStrategy implements TestCacheStoreStrategy {
+    /** Removes counter. */
+    private final static AtomicInteger removes = new AtomicInteger();
+
+    /** Writes counter. */
+    private final static AtomicInteger writes = new AtomicInteger();
+
+    /** Reads counter. */
+    private final static AtomicInteger reads = new AtomicInteger();
+
+    /** Store map. */
+    private final static Map<Object, Object> map = new ConcurrentHashMap8<>();
+
+    /** {@inheritDoc} */
+    @Override public int getReads() {
+        return reads.get();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getWrites() {
+        return writes.get();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getRemoves() {
+        return removes.get();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int getStoreSize() {
+        return map.size();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void resetStore() {
+        map.clear();
+
+        reads.set(0);
+        writes.set(0);
+        removes.set(0);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putToStore(Object key, Object val) {
+        map.put(key, val);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void putAllToStore(Map<?, ?> data) {
+        map.putAll(data);
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object getFromStore(Object key) {
+        return map.get(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeFromStore(Object key) {
+        map.remove(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isInStore(Object key) {
+        return map.containsKey(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void updateCacheConfiguration(CacheConfiguration<Object, Object> cfg) {
+        // No-op.
+    }
+
+    /** {@inheritDoc} */
+    @Override public Factory<? extends CacheStore<Object, Object>> getStoreFactory() {
+        return FactoryBuilder.factoryOf(MapCacheStore.class);
+    }
+
+    /** Serializable {@link #map} backed cache store factory */
+    public static class MapStoreFactory implements Factory<CacheStore<Object, Object>> {
+        /** {@inheritDoc} */
+        @Override public CacheStore<Object, Object> create() {
+            return new MapCacheStore();
+        }
+    }
+
+    /** {@link CacheStore} backed by {@link #map} */
+    public static class MapCacheStore extends CacheStoreAdapter<Object, Object> {
+        /** {@inheritDoc} */
+        @Override public void loadCache(IgniteBiInClosure<Object, Object> clo, Object... args) {
+            for (Map.Entry<Object, Object> e : map.entrySet())
+                clo.apply(e.getKey(), e.getValue());
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object load(Object key) {
+            reads.incrementAndGet();
+            return map.get(key);
+        }
+
+        /** {@inheritDoc} */
+        @Override public void write(Cache.Entry<?, ?> e) {
+            writes.incrementAndGet();
+            map.put(e.getKey(), e.getValue());
+        }
+
+        /** {@inheritDoc} */
+        @Override public void delete(Object key) {
+            removes.incrementAndGet();
+            map.remove(key);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/TestCacheStoreStrategy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/TestCacheStoreStrategy.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/TestCacheStoreStrategy.java
new file mode 100644
index 0000000..9ee174a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/TestCacheStoreStrategy.java
@@ -0,0 +1,96 @@
+/*
+ * 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.Map;
+import javax.cache.configuration.Factory;
+import org.apache.ignite.cache.store.CacheStore;
+import org.apache.ignite.configuration.CacheConfiguration;
+
+/**
+ * Interface for cache store backend manipulation and stats routines.
+ */
+public interface TestCacheStoreStrategy {
+    /**
+     * @return Number of reads to store.
+     */
+    public int getReads();
+
+    /**
+     * @return Number of writes to store.
+     */
+    public int getWrites();
+
+    /**
+     * @return Number of removals from store.
+     */
+    public int getRemoves();
+
+    /**
+     * @return Total number of items in the store.
+     */
+    public int getStoreSize();
+
+    /**
+     * Clear store contents.
+     */
+    public void resetStore();
+
+    /**
+     * Put entry to cache store.
+     *
+     * @param key Key.
+     * @param val Value.
+     */
+    public void putToStore(Object key, Object val);
+
+    /**
+     * @param data Items to put to store.
+     */
+    public void putAllToStore(Map<?, ?> data);
+
+    /**
+     * @param key Key to look for.
+     * @return {@link Object} pointed to by given key or {@code null} if no object is present.
+     */
+    public Object getFromStore(Object key);
+
+    /**
+     * @param key to look for
+     */
+    public void removeFromStore(Object key);
+
+    /**
+     * @param key to look for.
+     * @return {@code True} if object pointed to by key is in store, false otherwise.
+     */
+    public boolean isInStore(Object key);
+
+    /**
+     * Called from {@link GridCacheAbstractSelfTest#cacheConfiguration(String)},
+     * this method allows implementations to tune cache config.
+     *
+     * @param cfg {@link CacheConfiguration} to tune.
+     */
+    public void updateCacheConfiguration(CacheConfiguration<Object, Object> cfg);
+
+    /**
+     * @return {@link Factory} for write-through storage emulator.
+     */
+    public Factory<? extends CacheStore<Object, Object>> getStoreFactory();
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
index eaab103..411e1bf 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
@@ -390,7 +390,7 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
         }
 
         // Avoid reloading from store.
-        map.remove(key);
+        storeStgy.removeFromStore(key);
 
         assertTrue(GridTestUtils.waitForCondition(new GridAbsPredicateX() {
             @SuppressWarnings("unchecked")

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOffHeapTieredMultiNodeFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOffHeapTieredMultiNodeFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOffHeapTieredMultiNodeFullApiSelfTest.java
index cbcc739..0386510 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOffHeapTieredMultiNodeFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedOffHeapTieredMultiNodeFullApiSelfTest.java
@@ -68,6 +68,6 @@ public class GridCachePartitionedOffHeapTieredMultiNodeFullApiSelfTest extends G
         assertEquals(5, primaryCache.localPeek(key, CachePeekMode.ONHEAP).intValue());
         assertNull(primaryCache.localPeek(key, CachePeekMode.OFFHEAP));
         assertEquals(5, cache.get(key).intValue());
-        assertEquals(5, map.get(key));
+        assertEquals(5, storeStgy.getFromStore(key));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
index 0be6d50..4666581 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/configvariations/ConfigVariations.java
@@ -44,9 +44,9 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.configuration.TopologyValidator;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.processors.cache.MapCacheStoreStrategy;
 import org.apache.ignite.marshaller.optimized.OptimizedMarshaller;
 import org.apache.ignite.spi.swapspace.inmemory.GridTestSwapSpaceSpi;
-import org.apache.ignite.testframework.junits.IgniteCacheConfigVariationsAbstractTest;
 
 import static org.apache.ignite.internal.util.lang.GridFunc.asArray;
 
@@ -63,7 +63,7 @@ public class ConfigVariations {
 
     /** */
     private static final ConfigParameter<Object> CACHE_STORE_PARAM = Parameters.complexParameter(
-        Parameters.parameter("setCacheStoreFactory", Parameters.factory(IgniteCacheConfigVariationsAbstractTest.TestStoreFactory.class)),
+        Parameters.parameter("setCacheStoreFactory", Parameters.factory(MapCacheStoreStrategy.MapStoreFactory.class)),
         Parameters.parameter("setReadThrough", true),
         Parameters.parameter("setWriteThrough", true),
         Parameters.parameter("setCacheStoreSessionListenerFactories", noopCacheStoreSessionListenerFactory())
@@ -71,7 +71,7 @@ public class ConfigVariations {
 
     /** */
     private static final ConfigParameter<Object> SIMPLE_CACHE_STORE_PARAM = Parameters.complexParameter(
-        Parameters.parameter("setCacheStoreFactory", Parameters.factory(IgniteCacheConfigVariationsAbstractTest.TestStoreFactory.class)),
+        Parameters.parameter("setCacheStoreFactory", Parameters.factory(MapCacheStoreStrategy.MapStoreFactory.class)),
         Parameters.parameter("setReadThrough", true),
         Parameters.parameter("setWriteThrough", true)
     );


[24/46] ignite git commit: ignite-3413 Use cache node filter for continuous query registration (cherry picked from commit 89d64e7)

Posted by sb...@apache.org.
ignite-3413 Use cache node filter for continuous query registration
(cherry picked from commit 89d64e7)


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

Branch: refs/heads/ignite-1232
Commit: 46f42723ac76c025863d7a9250de3eec1eca524a
Parents: e119529
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 13 12:41:18 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Mon Jul 18 16:40:37 2016 +0300

----------------------------------------------------------------------
 .../continuous/CacheContinuousQueryManager.java |   4 +-
 ...eContinuousQueryMultiNodesFilteringTest.java | 278 +++++++++++++++++++
 ...dCacheContinuousQueryNodesFilteringTest.java | 168 +++++++++++
 .../IgniteCacheQuerySelfTestSuite3.java         |   4 +
 4 files changed, 453 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/46f42723/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
index c966527..195f3ae 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
@@ -642,7 +642,9 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
         hnd.localCache(cctx.isLocal());
 
         IgnitePredicate<ClusterNode> pred = (loc || cctx.config().getCacheMode() == CacheMode.LOCAL) ?
-            F.nodeForNodeId(cctx.localNodeId()) : F.<ClusterNode>alwaysTrue();
+            F.nodeForNodeId(cctx.localNodeId()) : cctx.config().getNodeFilter();
+
+        assert pred != null : cctx.config();
 
         UUID id = cctx.kernalContext().continuous().startRoutine(
             hnd,

http://git-wip-us.apache.org/repos/asf/ignite/blob/46f42723/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryMultiNodesFilteringTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryMultiNodesFilteringTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryMultiNodesFilteringTest.java
new file mode 100644
index 0000000..7000446
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryMultiNodesFilteringTest.java
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.util.Collections;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.configuration.Factory;
+import javax.cache.configuration.MutableCacheEntryListenerConfiguration;
+import javax.cache.event.CacheEntryCreatedListener;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryEventFilter;
+import javax.cache.event.CacheEntryListener;
+import javax.cache.event.CacheEntryListenerException;
+import javax.cache.event.CacheEntryRemovedListener;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.resources.IgniteInstanceResource;
+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.jsr166.ConcurrentHashMap8;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+
+/** */
+@SuppressWarnings("unchecked")
+public class GridCacheContinuousQueryMultiNodesFilteringTest extends GridCommonAbstractTest {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final int SERVER_GRIDS_COUNT = 6;
+
+    /** Cache entry operations' counts. */
+    private static final ConcurrentMap<String, AtomicInteger> opCounts = new ConcurrentHashMap8<>();
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        super.afterTest();
+    }
+
+    /** */
+    public void testFiltersAndListeners() throws Exception {
+        for (int i = 1; i <= SERVER_GRIDS_COUNT; i++)
+            startGrid(i, false);
+
+        startGrid(SERVER_GRIDS_COUNT + 1, true);
+
+        for (int i = 1; i <= SERVER_GRIDS_COUNT + 1; i++) {
+            for (int j = 0; j < i; j++) {
+                jcache(i, "part" + i).put("k" + j, "v0");
+                jcache(i, "repl" + i).put("k" + j, "v0");
+
+                // Should trigger updates
+                jcache(i, "part" + i).put("k" + j, "v1");
+                jcache(i, "repl" + i).put("k" + j, "v1");
+
+                jcache(i, "part" + i).remove("k" + j);
+                jcache(i, "repl" + i).remove("k" + j);
+            }
+        }
+
+        for (int i = 1; i <= SERVER_GRIDS_COUNT + 1; i++) {
+            // For each i, we did 3 ops on 2 caches on i keys, hence expected number.
+            final int expTotal = i * 3 * 2;
+            final int i0 = i;
+
+            GridTestUtils.waitForCondition(new GridAbsPredicate() {
+                @Override public boolean apply() {
+                    return opCounts.get("qry"  + i0 + "_total").get() == expTotal;
+                }
+            }, 5000);
+
+            int partInserts = opCounts.get("part" + i + "_ins").get();
+            int replInserts = opCounts.get("repl" + i + "_ins").get();
+            int partUpdates = opCounts.get("part" + i + "_upd").get();
+            int replUpdates = opCounts.get("repl" + i + "_upd").get();
+            int partRemoves = opCounts.get("part" + i + "_rmv").get();
+            int replRemoves = opCounts.get("repl" + i + "_rmv").get();
+            int totalQryOps = opCounts.get("qry"  + i + "_total").get();
+
+            assertEquals(i, partInserts);
+            assertEquals(i, replInserts);
+
+            assertEquals(i, partUpdates);
+            assertEquals(i, replUpdates);
+
+            assertEquals(i, partRemoves);
+            assertEquals(i, replRemoves);
+
+            assertEquals(expTotal, totalQryOps);
+
+            assertEquals(totalQryOps, partInserts + replInserts + partUpdates + replUpdates + partRemoves + replRemoves);
+        }
+    }
+
+    /** */
+    private Ignite startGrid(final int idx, boolean isClientMode) throws Exception {
+        String gridName = getTestGridName(idx);
+
+        IgniteConfiguration cfg = optimize(getConfiguration(gridName)).setClientMode(isClientMode);
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+        cfg.setUserAttributes(Collections.singletonMap("idx", idx));
+
+        Ignite node = startGrid(gridName, cfg);
+
+        IgnitePredicate<ClusterNode> nodeFilter = new NodeFilter(idx);
+
+        String partCacheName = "part" + idx;
+
+        IgniteCache partCache = node.createCache(defaultCacheConfiguration().setName("part" + idx)
+            .setCacheMode(PARTITIONED).setBackups(1).setNodeFilter(nodeFilter));
+
+        opCounts.put(partCacheName + "_ins", new AtomicInteger());
+        opCounts.put(partCacheName + "_upd", new AtomicInteger());
+        opCounts.put(partCacheName + "_rmv", new AtomicInteger());
+
+        partCache.registerCacheEntryListener(new ListenerConfiguration(partCacheName, ListenerConfiguration.Op.INSERT));
+        partCache.registerCacheEntryListener(new ListenerConfiguration(partCacheName, ListenerConfiguration.Op.UPDATE));
+        partCache.registerCacheEntryListener(new ListenerConfiguration(partCacheName, ListenerConfiguration.Op.REMOVE));
+
+        String replCacheName = "repl" + idx;
+
+        IgniteCache replCache = node.createCache(defaultCacheConfiguration().setName("repl" + idx)
+            .setCacheMode(REPLICATED).setNodeFilter(nodeFilter));
+
+        opCounts.put(replCacheName + "_ins", new AtomicInteger());
+        opCounts.put(replCacheName + "_upd", new AtomicInteger());
+        opCounts.put(replCacheName + "_rmv", new AtomicInteger());
+
+        replCache.registerCacheEntryListener(new ListenerConfiguration(replCacheName, ListenerConfiguration.Op.INSERT));
+        replCache.registerCacheEntryListener(new ListenerConfiguration(replCacheName, ListenerConfiguration.Op.UPDATE));
+        replCache.registerCacheEntryListener(new ListenerConfiguration(replCacheName, ListenerConfiguration.Op.REMOVE));
+
+        opCounts.put("qry" + idx + "_total", new AtomicInteger());
+
+        ContinuousQuery qry = new ContinuousQuery();
+        qry.setRemoteFilterFactory(new EntryEventFilterFactory(idx));
+        qry.setLocalListener(new CacheEntryUpdatedListener() {
+            /** {@inheritDoc} */
+            @Override public void onUpdated(Iterable evts) {
+                opCounts.get("qry" + idx + "_total").incrementAndGet();
+            }
+        });
+
+        partCache.query(qry);
+        replCache.query(qry);
+
+        return node;
+    }
+
+    /** */
+    private final static class ListenerConfiguration extends MutableCacheEntryListenerConfiguration {
+        /** Operation. */
+        enum Op {
+            /** Insert. */
+            INSERT,
+
+            /** Update. */
+            UPDATE,
+
+            /** Remove. */
+            REMOVE
+        }
+
+        /** */
+        ListenerConfiguration(final String cacheName, final Op op) {
+            super(new Factory<CacheEntryListener>() {
+                /** {@inheritDoc} */
+                @Override public CacheEntryListener create() {
+                    switch (op) {
+                        case INSERT:
+                            return new CacheEntryCreatedListener() {
+                                /** {@inheritDoc} */
+                                @Override public void onCreated(Iterable iterable) {
+                                    for (Object evt : iterable)
+                                        opCounts.get(cacheName + "_ins").getAndIncrement();
+                                }
+                            };
+                        case UPDATE:
+                            return new CacheEntryUpdatedListener() {
+                                /** {@inheritDoc} */
+                                @Override public void onUpdated(Iterable iterable) {
+                                    for (Object evt : iterable)
+                                        opCounts.get(cacheName + "_upd").getAndIncrement();
+                                }
+                            };
+                        case REMOVE:
+                            return new CacheEntryRemovedListener() {
+                                /** {@inheritDoc} */
+                                @Override public void onRemoved(Iterable iterable) {
+                                    for (Object evt : iterable)
+                                        opCounts.get(cacheName + "_rmv").getAndIncrement();
+                                }
+                            };
+                        default:
+                            throw new IgniteException(new IllegalArgumentException());
+                    }
+                }
+            }, null, true, false);
+        }
+    }
+
+    /** */
+    private final static class EntryEventFilterFactory implements Factory<CacheEntryEventFilter> {
+        /** */
+        @IgniteInstanceResource
+        private Ignite ignite;
+
+        /** Grid index to determine whether node filter has been invoked. */
+        private final int idx;
+
+        /** */
+        private EntryEventFilterFactory(int idx) {
+            this.idx = idx;
+        }
+
+        /** {@inheritDoc} */
+        @Override public CacheEntryEventFilter create() {
+            return new CacheEntryEventFilter() {
+                /** {@inheritDoc} */
+                @Override public boolean evaluate(CacheEntryEvent evt) throws CacheEntryListenerException {
+                    int evtNodeIdx = (Integer)(ignite.cluster().localNode().attributes().get("idx"));
+
+                    assertTrue(evtNodeIdx % 2 == idx % 2);
+
+                    return true;
+                }
+            };
+        }
+    }
+
+    /** */
+    private final static class NodeFilter implements IgnitePredicate<ClusterNode> {
+        /** */
+        private final int idx;
+
+        /** */
+        private NodeFilter(int idx) {
+            this.idx = idx;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean apply(ClusterNode clusterNode) {
+            return ((Integer)clusterNode.attributes().get("idx") % 2) == idx % 2;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46f42723/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryNodesFilteringTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryNodesFilteringTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryNodesFilteringTest.java
new file mode 100644
index 0000000..dccde65
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryNodesFilteringTest.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.query.continuous;
+
+import java.io.Serializable;
+import java.util.Collections;
+import javax.cache.configuration.Factory;
+import javax.cache.event.CacheEntryEvent;
+import javax.cache.event.CacheEntryEventFilter;
+import javax.cache.event.CacheEntryUpdatedListener;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.query.ContinuousQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.lang.IgnitePredicate;
+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.GridStringLogger;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/** */
+@SuppressWarnings("unused")
+public class GridCacheContinuousQueryNodesFilteringTest extends GridCommonAbstractTest implements Serializable {
+    /** */
+    private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+    /** */
+    private static final String ENTRY_FILTER_CLS_NAME = "org.apache.ignite.tests.p2p.CacheDeploymentEntryEventFilter";
+
+    /**
+     * Tests that node not matched by filter really does not try to participate in the query.
+     *
+     * @throws Exception if failed.
+     */
+    @SuppressWarnings("EmptyTryBlock")
+    public void testNodeWithoutAttributeExclusion() throws Exception {
+        try (Ignite node1 = startNodeWithCache()) {
+            try (Ignite node2 = startGrid("node2", getConfiguration("node2", false, null))) {
+                assertEquals(2, node2.cluster().nodes().size());
+            }
+        }
+    }
+
+    /**
+     * Test that node matched by filter and having filter instantiation problems fails for sure.
+     *
+     * @throws Exception if failed.
+     */
+    public void testNodeWithAttributeFailure() throws Exception {
+        try (Ignite node1 = startNodeWithCache()) {
+            GridStringLogger log = new GridStringLogger();
+
+            try (Ignite node2 = startGrid("node2", getConfiguration("node2", true, log))) {
+                fail();
+            }
+            catch (IgniteException e) {
+                assertTrue(log.toString().contains("Class not found for continuous query remote filter " +
+                    "[name=org.apache.ignite.tests.p2p.CacheDeploymentEntryEventFilter]"));
+            }
+        }
+    }
+
+    /**
+     * Start first, attribute-bearing, node, create new cache and launch continuous query on it.
+     *
+     * @return Node.
+     * @throws Exception if failed.
+     */
+    private Ignite startNodeWithCache() throws Exception {
+        Ignite node1 = startGrid("node1", getConfiguration("node1", true, null));
+
+        CacheConfiguration<Integer, Integer> ccfg = new CacheConfiguration<>();
+        ccfg.setName("attrsTestCache");
+        ccfg.setNodeFilter(new IgnitePredicate<ClusterNode>() {
+            /** {@inheritDoc} */
+            @Override public boolean apply(ClusterNode node) {
+                return "data".equals(node.attribute("node-type"));
+            }
+        });
+
+        IgniteCache<Integer, Integer> cache = node1.createCache(ccfg);
+
+        ContinuousQuery<Integer, Integer> qry = new ContinuousQuery<>();
+
+        qry.setRemoteFilterFactory(new RemoteFilterFactory());
+        qry.setLocalListener(new CacheEntryUpdatedListener<Integer, Integer>() {
+            /** {@inheritDoc} */
+            @Override public void onUpdated(Iterable<CacheEntryEvent<? extends Integer, ? extends Integer>> evts) {
+                // No-op.
+            }
+        });
+
+        RemoteFilterFactory.clsLdr = getExternalClassLoader();
+
+        cache.query(qry);
+
+        // Switch class loader before starting the second node.
+        RemoteFilterFactory.clsLdr = getClass().getClassLoader();
+
+        return node1;
+    }
+
+    /**
+     * @param name Node name.
+     * @param setAttr Flag indicating whether node user attribute should be set.
+     * @param log Logger.
+     * @return Node configuration w/specified name.
+     * @throws Exception If failed.
+     */
+    private IgniteConfiguration getConfiguration(String name, boolean setAttr, GridStringLogger log) throws Exception {
+        IgniteConfiguration cfg = optimize(getConfiguration(name));
+
+        ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+        if (setAttr)
+            cfg.setUserAttributes(Collections.singletonMap("node-type", "data"));
+
+        cfg.setGridLogger(log);
+
+        return cfg;
+    }
+
+    /**
+     *
+     */
+    private static class RemoteFilterFactory implements Factory<CacheEntryEventFilter<Integer, Integer>> {
+        /** */
+        private static ClassLoader clsLdr;
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("unchecked")
+        @Override public CacheEntryEventFilter<Integer, Integer> create() {
+            try {
+                Class<?> filterCls = clsLdr.loadClass(ENTRY_FILTER_CLS_NAME);
+
+                assert CacheEntryEventFilter.class.isAssignableFrom(filterCls);
+
+                return ((Class<CacheEntryEventFilter>)filterCls).newInstance();
+            }
+            catch (ClassNotFoundException e) {
+                throw new IgniteException("Class not found for continuous query remote filter [name=" +
+                    e.getMessage() + "]");
+            }
+            catch (Exception e) { // We really don't expect anything else fancy here.
+                throw new AssertionError("Unexpected exception", e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/46f42723/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
index f7821a8..032dd3b 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite3.java
@@ -43,6 +43,8 @@ import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheCon
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryConcurrentTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryLocalAtomicSelfTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryLocalSelfTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryMultiNodesFilteringTest;
+import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryNodesFilteringTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryPartitionAtomicOneNodeTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryPartitionTxOneNodeTest;
 import org.apache.ignite.internal.processors.cache.query.continuous.GridCacheContinuousQueryPartitionedOnlySelfTest;
@@ -111,6 +113,8 @@ public class IgniteCacheQuerySelfTestSuite3 extends TestSuite {
         suite.addTestSuite(CacheContinuousQueryExecuteInPrimaryTest.class);
         suite.addTestSuite(CacheContinuousQueryLostPartitionTest.class);
         suite.addTestSuite(ContinuousQueryRemoteFilterMissingInClassPathSelfTest.class);
+        suite.addTestSuite(GridCacheContinuousQueryNodesFilteringTest.class);
+        suite.addTestSuite(GridCacheContinuousQueryMultiNodesFilteringTest.class);
         suite.addTestSuite(IgniteCacheContinuousQueryImmutableEntryTest.class);
         suite.addTestSuite(CacheKeepBinaryIterationTest.class);
         suite.addTestSuite(CacheKeepBinaryIterationStoreEnabledTest.class);


[20/46] ignite git commit: ignite-1089 Fixed tests for multi jvm mode. This closes #846. (cherry picked from commit bf57413)

Posted by sb...@apache.org.
ignite-1089 Fixed tests for multi jvm mode. This closes #846.
(cherry picked from commit bf57413)


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

Branch: refs/heads/ignite-1232
Commit: a648e88c14295bf2c45b8e200eb5a3137997e131
Parents: d2198a1
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jul 15 16:26:00 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 15 16:26:00 2016 +0300

----------------------------------------------------------------------
 .../testframework/junits/multijvm/IgniteCacheProcessProxy.java    | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/a648e88c/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
index adbf1ab..740b201 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
@@ -724,7 +724,6 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
      *
      */
     private static class PartitionSizeLongTask extends CacheTaskAdapter<Void, Void, Long> {
-
         /** Partition. */
         int partition;
 
@@ -742,7 +741,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param loc Local.
          */
         public PartitionSizeLongTask(String cacheName, boolean async, CachePeekMode[] peekModes, int partition, boolean loc) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.loc = loc;
             this.peekModes = peekModes;
             this.partition = partition;


[03/46] ignite git commit: IGNITE-3227 - Fixed compilation.

Posted by sb...@apache.org.
IGNITE-3227 - Fixed compilation.


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

Branch: refs/heads/ignite-1232
Commit: d3bd6c186959b9bc125b7ca5913c15ba9fe3bbd5
Parents: 0b11855
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Thu Jul 7 16:23:19 2016 -0700
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Thu Jul 7 16:23:19 2016 -0700

----------------------------------------------------------------------
 .../testframework/junits/multijvm/IgniteCacheProcessProxy.java     | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d3bd6c18/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
index 9cbbbd2..3be0423 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
@@ -735,7 +735,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param loc Local.
          */
         public PartitionSizeLongTask(String cacheName, boolean async, CachePeekMode[] peekModes, int partition, boolean loc) {
-            super(cacheName, async, null);
+            super(cacheName, async);
             this.loc = loc;
             this.peekModes = peekModes;
             this.partition = partition;


[19/46] ignite git commit: ignite-1089 Fixed tests for multi jvm mode. This closes #846. (cherry picked from commit bf57413)

Posted by sb...@apache.org.
ignite-1089 Fixed tests for multi jvm mode. This closes #846.
(cherry picked from commit bf57413)


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

Branch: refs/heads/ignite-1232
Commit: d2198a1df0e5c907434ec1a465eb118823723439
Parents: ade57ea
Author: sboikov <sb...@gridgain.com>
Authored: Mon Jul 4 21:08:24 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 15 16:21:37 2016 +0300

----------------------------------------------------------------------
 .../cache/GridCacheAbstractFullApiSelfTest.java | 160 ++++++++++--------
 .../IgniteCacheConfigVariationsFullApiTest.java | 157 +++++++++--------
 ...idCacheNearOnlyMultiNodeFullApiSelfTest.java | 168 ++++++++-----------
 .../junits/common/GridCommonAbstractTest.java   |  12 +-
 .../multijvm/IgniteCacheProcessProxy.java       | 109 ++++++------
 5 files changed, 317 insertions(+), 289 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d2198a1d/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
index 5ab23a0..32d46e2 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
@@ -69,6 +69,7 @@ import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
 import org.apache.ignite.internal.processors.resource.GridSpringResourceContext;
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
+import org.apache.ignite.internal.util.lang.IgnitePair;
 import org.apache.ignite.internal.util.typedef.CIX1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.PA;
@@ -3559,9 +3560,6 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
      * @throws Exception If failed.
      */
     private void checkTtl(boolean inTx, boolean oldEntry) throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1089");
-
         if (memoryMode() == OFFHEAP_TIERED)
             return;
 
@@ -3573,22 +3571,17 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         final String key = primaryKeysForCache(jcache(), 1).get(0);
 
-        GridCacheAdapter<String, Integer> internalCache = internalCache(fullCache());
-
-        if (internalCache.isNear())
-            internalCache = internalCache.context().near().dht();
-
-        GridCacheEntryEx entry;
+        IgnitePair<Long> entryTtl;
 
         if (oldEntry) {
             c.put(key, 1);
 
-            entry = internalCache.peekEx(key);
+            entryTtl = entryTtl(fullCache(), key);
 
-            assert entry != null;
-
-            assertEquals(0, entry.ttl());
-            assertEquals(0, entry.expireTime());
+            assertNotNull(entryTtl.get1());
+            assertNotNull(entryTtl.get2());
+            assertEquals((Long)0L, entryTtl.get1());
+            assertEquals((Long)0L, entryTtl.get2());
         }
 
         long startTime = System.currentTimeMillis();
@@ -3605,10 +3598,10 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             }
 
             if (oldEntry) {
-                entry = internalCache.peekEx(key);
+                entryTtl = entryTtl(fullCache(), key);
 
-                assertEquals(0, entry.ttl());
-                assertEquals(0, entry.expireTime());
+                assertEquals((Long)0L, entryTtl.get1());
+                assertEquals((Long)0L, entryTtl.get2());
             }
         }
 
@@ -3630,18 +3623,14 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
-
-                GridCacheEntryEx curEntry = cache.peekEx(key);
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                assertEquals(ttl, curEntry.ttl());
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long) curEntryTtl.get1());
+                assertTrue(curEntryTtl.get2() > startTime);
 
-                assert curEntry.expireTime() > startTime;
-
-                expireTimes[i] = curEntry.expireTime();
+                expireTimes[i] = curEntryTtl.get2();
             }
         }
 
@@ -3663,18 +3652,14 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
-
-                GridCacheEntryEx curEntry = cache.peekEx(key);
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                assertEquals(ttl, curEntry.ttl());
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long) curEntryTtl.get1());
+                assertTrue(curEntryTtl.get2() > startTime);
 
-                assert curEntry.expireTime() > startTime;
-
-                expireTimes[i] = curEntry.expireTime();
+                expireTimes[i] = curEntryTtl.get2();
             }
         }
 
@@ -3696,18 +3681,14 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                GridCacheEntryEx curEntry = cache.peekEx(key);
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long) curEntryTtl.get1());
+                assertTrue(curEntryTtl.get2() > startTime);
 
-                assertEquals(ttl, curEntry.ttl());
-
-                assert curEntry.expireTime() > startTime;
-
-                expireTimes[i] = curEntry.expireTime();
+                expireTimes[i] = curEntryTtl.get2();
             }
         }
 
@@ -3733,15 +3714,12 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                GridCacheEntryEx curEntry = cache.peekEx(key);
-
-                assertEquals(ttl, curEntry.ttl());
-                assertEquals(expireTimes[i], curEntry.expireTime());
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long)curEntryTtl.get1());
+                assertEquals(expireTimes[i], (long)curEntryTtl.get2());
             }
         }
 
@@ -3777,21 +3755,24 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             }
         }, Math.min(ttl * 10, getTestTimeout())));
 
-        if (internalCache.isLocal())
-            return;
+        IgniteCache fullCache = fullCache();
 
-        assert c.get(key) == null;
+        if (!isMultiJvmObject(fullCache)) {
+            GridCacheAdapter internalCache = internalCache(fullCache);
 
-        internalCache = internalCache(fullCache());
+            if (internalCache.isLocal())
+                return;
+        }
 
-        if (internalCache.isNear())
-            internalCache = internalCache.context().near().dht();
+        assert c.get(key) == null;
 
         // Ensure that old TTL and expire time are not longer "visible".
-        entry = internalCache.peekEx(key);
+        entryTtl = entryTtl(fullCache(), key);
 
-        assertEquals(0, entry.ttl());
-        assertEquals(0, entry.expireTime());
+        assertNotNull(entryTtl.get1());
+        assertNotNull(entryTtl.get2());
+        assertEquals(0, (long)entryTtl.get1());
+        assertEquals(0, (long)entryTtl.get2());
 
         // Ensure that next update will not pick old expire time.
 
@@ -3810,12 +3791,14 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         U.sleep(2000);
 
-        entry = internalCache.peekEx(key);
+        entryTtl = entryTtl(fullCache(), key);
 
         assertEquals((Integer)10, c.get(key));
 
-        assertEquals(0, entry.ttl());
-        assertEquals(0, entry.expireTime());
+        assertNotNull(entryTtl.get1());
+        assertNotNull(entryTtl.get2());
+        assertEquals(0, (long)entryTtl.get1());
+        assertEquals(0, (long)entryTtl.get2());
     }
 
     /**
@@ -4319,6 +4302,15 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     }
 
     /**
+     * @param cache Cache.
+     * @param key Entry key.
+     * @return Pair [ttl, expireTime]; both values null if entry not found
+     */
+    protected IgnitePair<Long> entryTtl(IgniteCache cache, String key) {
+        return executeOnLocalOrRemoteJvm(cache, new EntryTtlTask(key, true));
+    }
+
+    /**
      * @throws Exception If failed.
      */
     public void testIterator() throws Exception {
@@ -5613,6 +5605,40 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     /**
      *
      */
+    public static class EntryTtlTask implements TestCacheCallable<String, Integer, IgnitePair<Long>> {
+        /** Entry key. */
+        private final String key;
+
+        /** Check cache for nearness, use DHT cache if it is near. */
+        private final boolean useDhtForNearCache;
+
+        /**
+         * @param key Entry key.
+         * @param useDhtForNearCache Check cache for nearness, use DHT cache if it is near.
+         */
+        public EntryTtlTask(String key, boolean useDhtForNearCache) {
+            this.key = key;
+            this.useDhtForNearCache = useDhtForNearCache;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgnitePair<Long> call(Ignite ignite, IgniteCache<String, Integer> cache) throws Exception {
+            GridCacheAdapter<?, ?> internalCache = internalCache0(cache);
+
+            if (useDhtForNearCache && internalCache.context().isNear())
+                internalCache = internalCache.context().near().dht();
+
+            GridCacheEntryEx entry = internalCache.peekEx(key);
+
+            return entry != null ?
+                new IgnitePair<>(entry.ttl(), entry.expireTime()) :
+                new IgnitePair<Long>(null, null);
+        }
+    }
+
+    /**
+     *
+     */
     private static class CheckIteratorTask extends TestIgniteIdxCallable<Void> {
         /**
          * @param idx Index.

http://git-wip-us.apache.org/repos/asf/ignite/blob/d2198a1d/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
index 7e6d015..2ca09c8 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheConfigVariationsFullApiTest.java
@@ -71,6 +71,7 @@ import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
+import org.apache.ignite.internal.util.lang.IgnitePair;
 import org.apache.ignite.internal.util.typedef.CIX1;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.PA;
@@ -3462,9 +3463,6 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
      * @throws Exception If failed.
      */
     private void checkTtl(boolean inTx, boolean oldEntry) throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1089");
-
         if (memoryMode() == OFFHEAP_TIERED)
             return;
 
@@ -3476,22 +3474,14 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         final String key = primaryKeysForCache(1).get(0);
 
-        GridCacheAdapter<String, Integer> internalCache = internalCache(serverNodeCache());
-
-        if (internalCache.isNear())
-            internalCache = internalCache.context().near().dht();
-
-        GridCacheEntryEx entry;
+        IgnitePair<Long> entryTtl;
 
         if (oldEntry) {
             c.put(key, 1);
 
-            entry = internalCache.peekEx(key);
-
-            assert entry != null;
-
-            assertEquals(0, entry.ttl());
-            assertEquals(0, entry.expireTime());
+            entryTtl = entryTtl(serverNodeCache(), key);
+            assertEquals((Long)0L, entryTtl.get1());
+            assertEquals((Long)0L, entryTtl.get2());
         }
 
         long startTime = System.currentTimeMillis();
@@ -3508,10 +3498,12 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             }
 
             if (oldEntry) {
-                entry = internalCache.peekEx(key);
+                entryTtl = entryTtl(serverNodeCache(), key);
 
-                assertEquals(0, entry.ttl());
-                assertEquals(0, entry.expireTime());
+                assertNotNull(entryTtl.get1());
+                assertNotNull(entryTtl.get2());
+                assertEquals((Long)0L, entryTtl.get1());
+                assertEquals((Long)0L, entryTtl.get2());
             }
         }
 
@@ -3533,18 +3525,13 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(cacheName()).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<Object, Object> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                GridCacheEntryEx curEntry = cache.peekEx(key);
-
-                assertEquals(ttl, curEntry.ttl());
-
-                assert curEntry.expireTime() > startTime;
-
-                expireTimes[i] = curEntry.expireTime();
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long)curEntryTtl.get1());
+                assertTrue(curEntryTtl.get2() > startTime);
+                expireTimes[i] = curEntryTtl.get2();
             }
         }
 
@@ -3566,18 +3553,13 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(cacheName()).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<Object, Object> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
-
-                GridCacheEntryEx curEntry = cache.peekEx(key);
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                assertEquals(ttl, curEntry.ttl());
-
-                assert curEntry.expireTime() > startTime;
-
-                expireTimes[i] = curEntry.expireTime();
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long)curEntryTtl.get1());
+                assertTrue(curEntryTtl.get2() > startTime);
+                expireTimes[i] = curEntryTtl.get2();
             }
         }
 
@@ -3599,18 +3581,13 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(cacheName()).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<Object, Object> cache = internalCache(jcache(i));
-
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
-
-                GridCacheEntryEx curEntry = cache.peekEx(key);
-
-                assertEquals(ttl, curEntry.ttl());
-
-                assert curEntry.expireTime() > startTime;
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                expireTimes[i] = curEntry.expireTime();
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long)curEntryTtl.get1());
+                assertTrue(curEntryTtl.get2() > startTime);
+                expireTimes[i] = curEntryTtl.get2();
             }
         }
 
@@ -3636,15 +3613,12 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         for (int i = 0; i < gridCount(); i++) {
             if (grid(i).affinity(cacheName()).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter cache = internalCache(jcache(i));
+                IgnitePair<Long> curEntryTtl = entryTtl(jcache(i), key);
 
-                if (cache.context().isNear())
-                    cache = cache.context().near().dht();
-
-                GridCacheEntryEx curEntry = cache.peekEx(key);
-
-                assertEquals(ttl, curEntry.ttl());
-                assertEquals(expireTimes[i], curEntry.expireTime());
+                assertNotNull(curEntryTtl.get1());
+                assertNotNull(curEntryTtl.get2());
+                assertEquals(ttl, (long)curEntryTtl.get1());
+                assertEquals(expireTimes[i], (long)curEntryTtl.get2());
             }
         }
 
@@ -3680,21 +3654,24 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
             }
         }, Math.min(ttl * 10, getTestTimeout())));
 
-        if (internalCache.isLocal())
-            return;
+        IgniteCache srvNodeCache = serverNodeCache();
 
-        assert c.get(key) == null;
+        if (!isMultiJvmObject(srvNodeCache)) {
+            GridCacheAdapter internalCache = internalCache(srvNodeCache);
 
-        internalCache = internalCache(serverNodeCache());
+            if (internalCache.isLocal())
+                return;
+        }
 
-        if (internalCache.isNear())
-            internalCache = internalCache.context().near().dht();
+        assert c.get(key) == null;
 
         // Ensure that old TTL and expire time are not longer "visible".
-        entry = internalCache.peekEx(key);
+        entryTtl = entryTtl(srvNodeCache, key);
 
-        assertEquals(0, entry.ttl());
-        assertEquals(0, entry.expireTime());
+        assertNotNull(entryTtl.get1());
+        assertNotNull(entryTtl.get2());
+        assertEquals(0, (long)entryTtl.get1());
+        assertEquals(0, (long)entryTtl.get2());
 
         // Ensure that next update will not pick old expire time.
 
@@ -3713,12 +3690,14 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
 
         U.sleep(2000);
 
-        entry = internalCache.peekEx(key);
+        entryTtl = entryTtl(srvNodeCache, key);
 
         assertEquals((Integer)10, c.get(key));
 
-        assertEquals(0, entry.ttl());
-        assertEquals(0, entry.expireTime());
+        assertNotNull(entryTtl.get1());
+        assertNotNull(entryTtl.get2());
+        assertEquals(0, (long)entryTtl.get1());
+        assertEquals(0, (long)entryTtl.get2());
     }
 
     /**
@@ -4300,6 +4279,15 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
     }
 
     /**
+     * @param cache Cache.
+     * @param key Entry key.
+     * @return Pair [ttl, expireTime]; both values null if entry not found
+     */
+    protected IgnitePair<Long> entryTtl(IgniteCache cache, String key) {
+        return executeOnLocalOrRemoteJvm(cache, new EntryTtlTask(key));
+    }
+
+    /**
      * @throws Exception If failed.
      */
     public void testIterator() throws Exception {
@@ -5643,6 +5631,33 @@ public class IgniteCacheConfigVariationsFullApiTest extends IgniteCacheConfigVar
         }
     }
 
+    /** */
+    private static class EntryTtlTask implements TestCacheCallable<String, Integer, IgnitePair<Long>> {
+        /** */
+        private final String key;
+
+        /**
+         * @param key Key.
+         */
+        private EntryTtlTask(String key) {
+            this.key = key;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgnitePair<Long> call(Ignite ignite, IgniteCache<String, Integer> cache) throws Exception {
+            GridCacheAdapter<?, ?> internalCache = internalCache0(cache);
+
+            if (internalCache.context().isNear())
+                internalCache = internalCache.context().near().dht();
+
+            GridCacheEntryEx entry = internalCache.peekEx(key);
+
+            return entry != null ?
+                new IgnitePair<>(entry.ttl(), entry.expireTime()) :
+                new IgnitePair<Long>(null, null);
+        }
+    }
+
     /**
      *
      */

http://git-wip-us.apache.org/repos/asf/ignite/blob/d2198a1d/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
index 411e1bf..5fab800 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCacheNearOnlyMultiNodeFullApiSelfTest.java
@@ -39,10 +39,10 @@ import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.events.Event;
-import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryEx;
 import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException;
 import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
+import org.apache.ignite.internal.util.lang.IgnitePair;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.internal.util.typedef.P1;
 import org.apache.ignite.internal.util.typedef.internal.U;
@@ -211,6 +211,10 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
      * @throws Exception If failed.
      */
     public void testReaderTtlTx() throws Exception {
+        // IgniteProcessProxy#transactions is not implemented.
+        if (isMultiJvm())
+            return;
+
         checkReaderTtl(true);
     }
 
@@ -222,13 +226,19 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
     }
 
     /**
+     * @param cache Cache.
+     * @param key Entry key.
+     * @return Pair [ttl, expireTime] for near cache entry; both values null if entry not found
+     */
+    protected IgnitePair<Long> nearEntryTtl(IgniteCache cache, String key) {
+        return executeOnLocalOrRemoteJvm(cache, new EntryTtlTask(key, false));
+    }
+
+    /**
      * @param inTx If {@code true} starts explicit transaction.
      * @throws Exception If failed.
      */
     private void checkReaderTtl(boolean inTx) throws Exception {
-        if (isMultiJvm())
-            fail("https://issues.apache.org/jira/browse/IGNITE-1089");
-
         int ttl = 1000;
 
         final ExpiryPolicy expiry = new TouchedExpiryPolicy(new Duration(TimeUnit.MILLISECONDS, ttl));
@@ -242,17 +252,14 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
         info("Finished first put.");
 
         {
-            GridCacheAdapter<String, Integer> dht = internalCache(fullCache());
-
-            if (dht.context().isNear())
-                dht = dht.context().near().dht();
+            IgnitePair<Long> entryTtl = entryTtl(fullCache(), key);
 
-            GridCacheEntryEx entry = dht.peekEx(key);
+            assertEquals((Integer)1, c.get(key));
 
-            assert entry != null;
-
-            assertEquals(0, entry.ttl());
-            assertEquals(0, entry.expireTime());
+            assertNotNull(entryTtl.get1());
+            assertNotNull(entryTtl.get2());
+            assertEquals(0, (long)entryTtl.get1());
+            assertEquals(0, (long)entryTtl.get2());
         }
 
         long startTime = System.currentTimeMillis();
@@ -278,30 +285,19 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
         for (int i = 0; i < gridCount(); i++) {
             info("Checking grid: " + grid(i).localNode().id());
 
-            GridCacheEntryEx entry = null;
-
-            if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> dht = internalCache(jcache(i));
+            IgnitePair<Long> entryTtl = null;
 
-                if (dht.context().isNear())
-                    dht = dht.context().near().dht();
+            if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key))
+                entryTtl = entryTtl(jcache(i), key);
+            else if (i == nearIdx)
+                entryTtl = nearEntryTtl(jcache(i), key);
 
-                entry = dht.peekEx(key);
-
-                assert entry != null;
-            }
-            else if (i == nearIdx) {
-                GridCacheAdapter<String, Integer> near = internalCache(jcache(i));
-
-                entry = near.peekEx(key);
-
-                assert entry != null;
-            }
-
-            if (entry != null) {
-                assertEquals(ttl, entry.ttl());
-                assert entry.expireTime() > startTime;
-                expireTimes[i] = entry.expireTime();
+            if (entryTtl != null) {
+                assertNotNull(entryTtl.get1());
+                assertNotNull(entryTtl.get2());
+                assertEquals(ttl, (long)entryTtl.get1());
+                assertTrue(entryTtl.get2() > startTime);
+                expireTimes[i] = entryTtl.get2();
             }
         }
 
@@ -322,30 +318,19 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
         }
 
         for (int i = 0; i < gridCount(); i++) {
-            GridCacheEntryEx entry = null;
-
-            if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> dht = internalCache(jcache(i));
-
-                if (dht.context().isNear())
-                    dht = dht.context().near().dht();
-
-                entry = dht.peekEx(key);
-
-                assert entry != null;
-            }
-            else if (i == nearIdx) {
-                GridCacheAdapter<String, Integer> near = internalCache(jcache(i));
-
-                entry = near.peekEx(key);
-
-                assert entry != null;
-            }
-
-            if (entry != null) {
-                assertEquals(ttl, entry.ttl());
-                assert entry.expireTime() > expireTimes[i];
-                expireTimes[i] = entry.expireTime();
+            IgnitePair<Long> entryTtl = null;
+
+            if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key))
+                entryTtl = entryTtl(jcache(i), key);
+            else if (i == nearIdx)
+                entryTtl = nearEntryTtl(jcache(i), key);
+
+            if (entryTtl != null) {
+                assertNotNull(entryTtl.get1());
+                assertNotNull(entryTtl.get2());
+                assertEquals(ttl, (long)entryTtl.get1());
+                assertTrue(entryTtl.get2() > startTime);
+                expireTimes[i] = entryTtl.get2();
             }
         }
 
@@ -363,29 +348,18 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
         }
 
         for (int i = 0; i < gridCount(); i++) {
-            GridCacheEntryEx entry = null;
-
-            if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key)) {
-                GridCacheAdapter<String, Integer> dht = internalCache(jcache(i));
-
-                if (dht.context().isNear())
-                    dht = dht.context().near().dht();
-
-                entry = dht.peekEx(key);
-
-                assert entry != null;
-            }
-            else if (i == nearIdx) {
-                GridCacheAdapter<String, Integer> near = internalCache(jcache(i));
-
-                entry = near.peekEx(key);
-
-                assert entry != null;
-            }
-
-            if (entry != null) {
-                assertEquals(ttl, entry.ttl());
-                assertEquals(expireTimes[i], entry.expireTime());
+            IgnitePair<Long> entryTtl = null;
+
+            if (grid(i).affinity(null).isPrimaryOrBackup(grid(i).localNode(), key))
+                entryTtl = entryTtl(jcache(i), key);
+            else if (i == nearIdx)
+                entryTtl = nearEntryTtl(jcache(i), key);
+
+            if (entryTtl != null) {
+                assertNotNull(entryTtl.get1());
+                assertNotNull(entryTtl.get2());
+                assertEquals(ttl, (long)entryTtl.get1());
+                assertEquals(expireTimes[i], (long)entryTtl.get2());
             }
         }
 
@@ -421,17 +395,12 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
 
         // Ensure that old TTL and expire time are not longer "visible".
         {
-            GridCacheAdapter<String, Integer> dht = internalCache(fullCache());
-
-            if (dht.context().isNear())
-                dht = dht.context().near().dht();
+            IgnitePair<Long> entryTtl = entryTtl(fullCache(), key);
 
-            GridCacheEntryEx entry = dht.peekEx(key);
-
-            assert entry != null;
-
-            assertEquals(0, entry.ttl());
-            assertEquals(0, entry.expireTime());
+            assertNotNull(entryTtl.get1());
+            assertNotNull(entryTtl.get2());
+            assertEquals(0, (long)entryTtl.get1());
+            assertEquals(0, (long)entryTtl.get2());
         }
 
         // Ensure that next update will not pick old expire time.
@@ -451,17 +420,12 @@ public class GridCacheNearOnlyMultiNodeFullApiSelfTest extends GridCachePartitio
         U.sleep(2000);
 
         {
-            GridCacheAdapter<String, Integer> dht = internalCache(fullCache());
-
-            if (dht.context().isNear())
-                dht = dht.context().near().dht();
-
-            GridCacheEntryEx entry = dht.peekEx(key);
-
-            assert entry != null;
+            IgnitePair<Long> entryTtl = entryTtl(fullCache(), key);
 
-            assertEquals(0, entry.ttl());
-            assertEquals(0, entry.expireTime());
+            assertNotNull(entryTtl.get1());
+            assertNotNull(entryTtl.get2());
+            assertEquals(0, (long)entryTtl.get1());
+            assertEquals(0, (long)entryTtl.get2());
         }
     }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/d2198a1d/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
index 5b03f8e..87509a4 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
@@ -161,15 +161,23 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
      * @param cache Cache.
      * @return Cache.
      */
-    protected <K, V> GridCacheAdapter<K, V> internalCache(IgniteCache<K, V> cache) {
+    protected static <K, V> GridCacheAdapter<K, V> internalCache0(IgniteCache<K, V> cache) {
         if (isMultiJvmObject(cache))
-            throw new UnsupportedOperationException("Oparetion can't be supported automatically for multi jvm " +
+            throw new UnsupportedOperationException("Operation can't be supported automatically for multi jvm " +
                 "(send closure instead).");
 
         return ((IgniteKernal)cache.unwrap(Ignite.class)).internalCache(cache.getName());
     }
 
     /**
+     * @param cache Cache.
+     * @return Cache.
+     */
+    protected <K, V> GridCacheAdapter<K, V> internalCache(IgniteCache<K, V> cache) {
+        return internalCache0(cache);
+    }
+
+    /**
      * @return Cache.
      */
     protected <K, V> IgniteCache<K, V> jcache() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/d2198a1d/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
index 3be0423..adbf1ab 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
@@ -65,6 +65,9 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
     /** With async. */
     private final boolean isAsync;
 
+    /** Expiry policy. */
+    private final ExpiryPolicy expiryPlc;
+
     /** Ignite proxy. */
     private final transient IgniteProcessProxy igniteProxy;
 
@@ -73,24 +76,26 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
      * @param proxy Ignite Process Proxy.
      */
     public IgniteCacheProcessProxy(String name, IgniteProcessProxy proxy) {
-        this(name, false, proxy);
+        this(name, false, null, proxy);
     }
 
     /**
      * @param name Name.
      * @param async Async flag.
+     * @param plc Expiry policy.
      * @param proxy Ignite Process Proxy.
      */
-    public IgniteCacheProcessProxy(String name, boolean async, IgniteProcessProxy proxy) {
+    private IgniteCacheProcessProxy(String name, boolean async, ExpiryPolicy plc, IgniteProcessProxy proxy) {
         cacheName = name;
         isAsync = async;
+        expiryPlc = plc;
         igniteProxy = proxy;
         compute = proxy.remoteCompute();
     }
 
     /** {@inheritDoc} */
     @Override public IgniteCache<K, V> withAsync() {
-        return new IgniteCacheProcessProxy<>(cacheName, true, igniteProxy);
+        return new IgniteCacheProcessProxy<>(cacheName, true, null, igniteProxy);
     }
 
     /** {@inheritDoc} */
@@ -116,7 +121,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
 
     /** {@inheritDoc} */
     @Override public IgniteCache<K, V> withExpiryPolicy(ExpiryPolicy plc) {
-        throw new UnsupportedOperationException("Method should be supported.");
+        return new IgniteCacheProcessProxy<>(cacheName, isAsync, plc, igniteProxy);
     }
 
     /** {@inheritDoc} */
@@ -271,7 +276,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
 
     /** {@inheritDoc} */
     @Override public void put(K key, V val) {
-        compute.call(new PutTask<>(cacheName, isAsync, key, val));
+        compute.call(new PutTask<>(cacheName, isAsync, expiryPlc, key, val));
     }
 
     /** {@inheritDoc} */
@@ -449,6 +454,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
         throw new UnsupportedOperationException("Method should be supported.");
     }
 
+    /** {@inheritDoc} */
     @Override public CacheMetrics localMetrics() {
         throw new UnsupportedOperationException("Method should be supported.");
     }
@@ -458,6 +464,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
         throw new UnsupportedOperationException("Method should be supported.");
     }
 
+    /** {@inheritDoc} */
     @Override public CacheMetricsMXBean localMxBean() {
         throw new UnsupportedOperationException("Method should be supported.");
     }
@@ -480,7 +487,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param clazz Clazz.
          */
         public GetConfigurationTask(String cacheName, boolean async, Class<C> clazz) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.clazz = clazz;
         }
 
@@ -507,7 +514,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param args Args.
          */
         public LocalLoadCacheTask(String cacheName, boolean async, IgniteBiPredicate<K, V> p, Object[] args) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.p = p;
             this.args = args;
         }
@@ -537,7 +544,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param val Value.
          */
         public GetAndPutIfAbsentTask(String cacheName, boolean async, K key, V val) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.val = val;
         }
@@ -565,7 +572,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param byCurrThread By current thread.
          */
         public IsLocalLockedTask(String cacheName, boolean async, K key, boolean byCurrThread) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.byCurrThread = byCurrThread;
         }
@@ -589,7 +596,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param peekModes Peek modes.
          */
         public LocalEntriesTask(String cacheName, boolean async, CachePeekMode[] peekModes) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.peekModes = peekModes;
         }
 
@@ -617,7 +624,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public LocalEvictTask(String cacheName, boolean async, Collection<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
         }
 
@@ -646,7 +653,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param peekModes Peek modes.
          */
         public LocalPeekTask(String cacheName, boolean async, K key, CachePeekMode[] peekModes) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.peekModes = peekModes;
         }
@@ -674,7 +681,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param loc Local.
          */
         public SizeTask(String cacheName, boolean async, CachePeekMode[] peekModes, boolean loc) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.loc = loc;
             this.peekModes = peekModes;
         }
@@ -702,7 +709,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param loc Local.
          */
         public SizeLongTask(String cacheName, boolean async, CachePeekMode[] peekModes, boolean loc) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.loc = loc;
             this.peekModes = peekModes;
         }
@@ -760,7 +767,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param key Key.
          */
         public GetTask(String cacheName, boolean async, K key) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
         }
 
@@ -783,7 +790,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param key Key.
          */
         public GetEntryTask(String cacheName, boolean async, K key) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
         }
 
@@ -802,7 +809,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public RemoveAllTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -831,11 +838,12 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
         /**
          * @param cacheName Cache name.
          * @param async Async.
+         * @param expiryPlc Expiry policy.
          * @param key Key.
          * @param val Value.
          */
-        public PutTask(String cacheName, boolean async, K key, V val) {
-            super(cacheName, async);
+        public PutTask(String cacheName, boolean async, ExpiryPolicy expiryPlc, K key, V val) {
+            super(cacheName, async, expiryPlc);
             this.key = key;
             this.val = val;
         }
@@ -861,7 +869,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param key Key.
          */
         public ContainsKeyTask(String cacheName, boolean async, K key) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
         }
 
@@ -880,7 +888,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public ClearTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -900,7 +908,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public IteratorTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -931,7 +939,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param val Value.
          */
         public ReplaceTask(String cacheName, boolean async, K key, V val) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.val = val;
         }
@@ -951,7 +959,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public GetNameTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -973,7 +981,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param key Key.
          */
         public RemoveTask(String cacheName, boolean async, K key) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
         }
 
@@ -996,7 +1004,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param map Map.
          */
         public PutAllTask(String cacheName, boolean async, Map<? extends K, ? extends V> map) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.map = map;
         }
 
@@ -1021,7 +1029,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public RemoveAllKeysTask(String cacheName, boolean async, Set<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
         }
 
@@ -1046,7 +1054,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public GetAllTask(String cacheName, boolean async, Set<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
         }
 
@@ -1069,7 +1077,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public GetEntriesTask(String cacheName, boolean async, Set<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
         }
 
@@ -1092,7 +1100,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public GetAllOutTxTask(String cacheName, boolean async, Set<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
         }
 
@@ -1115,7 +1123,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public ContainsKeysTask(String cacheName, boolean async, Set<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
         }
 
@@ -1142,7 +1150,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param val Value.
          */
         public GetAndPutTask(String cacheName, boolean async, K key, V val) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.val = val;
         }
@@ -1170,7 +1178,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param val Value.
          */
         public PutIfAbsentTask(String cacheName, boolean async, K key, V val) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.val = val;
         }
@@ -1198,7 +1206,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param oldVal Old value.
          */
         public RemoveIfExistsTask(String cacheName, boolean async, K key, V oldVal) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.oldVal = oldVal;
         }
@@ -1222,7 +1230,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param key Key.
          */
         public GetAndRemoveTask(String cacheName, boolean async, K key) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
         }
 
@@ -1253,7 +1261,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param newVal New value.
          */
         public ReplaceIfExistsTask(String cacheName, boolean async, K key, V oldVal, V newVal) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.oldVal = oldVal;
             this.newVal = newVal;
@@ -1282,7 +1290,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param val Value.
          */
         public GetAndReplaceTask(String cacheName, boolean async, K key, V val) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.val = val;
         }
@@ -1309,7 +1317,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param key Key.
          */
         public ClearKeyTask(String cacheName, boolean async, boolean loc, K key) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.key = key;
             this.loc = loc;
         }
@@ -1341,7 +1349,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param keys Keys.
          */
         public ClearAllKeys(String cacheName, boolean async, boolean loc, Set<? extends K> keys) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.keys = keys;
             this.loc = loc;
         }
@@ -1379,7 +1387,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          */
         public InvokeTask(String cacheName, boolean async, K key, EntryProcessor<K, V, R> processor,
             Object[] args) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.args = args;
             this.key = key;
             this.processor = processor;
@@ -1413,7 +1421,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          */
         public InvokeAllTask(String cacheName, boolean async, Set<? extends K> keys,
             EntryProcessor<K, V, T> processor, Object[] args) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.args = args;
             this.keys = keys;
             this.processor = processor;
@@ -1434,7 +1442,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public CloseTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -1454,7 +1462,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public DestroyTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -1474,7 +1482,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param async Async.
          */
         public IsClosedTask(String cacheName, boolean async) {
-            super(cacheName, async);
+            super(cacheName, async, null);
         }
 
         /** {@inheritDoc} */
@@ -1496,7 +1504,7 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
          * @param clazz Clazz.
          */
         public UnwrapTask(String cacheName, boolean async, Class<R> clazz) {
-            super(cacheName, async);
+            super(cacheName, async, null);
             this.clazz = clazz;
         }
 
@@ -1520,21 +1528,28 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
         /** Async. */
         protected final boolean async;
 
+        /** Expiry policy. */
+        protected final ExpiryPolicy expiryPlc;
+
         /**
          * @param cacheName Cache name.
          * @param async Async.
+         * @param expiryPlc Optional expiry policy.
          */
-        public CacheTaskAdapter(String cacheName, boolean async) {
+        public CacheTaskAdapter(String cacheName, boolean async, ExpiryPolicy expiryPlc) {
             this.async = async;
             this.cacheName = cacheName;
+            this.expiryPlc = expiryPlc;
         }
 
         /**
-         * Returns cache instance.
+         * @return Cache instance.
          */
         protected IgniteCache<K, V> cache() {
             IgniteCache<K, V> cache = ignite.cache(cacheName);
 
+            cache = expiryPlc != null ? cache.withExpiryPolicy(expiryPlc) : cache;
+
             return async ? cache.withAsync() : cache;
         }
     }


[22/46] ignite git commit: IGNITE-3455: Entry placed on C++ side is not found on Java side (cherry picked from commit 84e83c9)

Posted by sb...@apache.org.
IGNITE-3455: Entry placed on C++ side is not found on Java side
(cherry picked from commit 84e83c9)


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

Branch: refs/heads/ignite-1232
Commit: 4f97444c1e6ac29648dd96bc93f878e1d2c3e784
Parents: 8d62737
Author: Denis Magda <dm...@gridgain.com>
Authored: Mon Jul 18 15:21:46 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Mon Jul 18 15:23:45 2016 +0300

----------------------------------------------------------------------
 .../ignite/internal/binary/BinaryContext.java   |  6 ++-
 .../binary/BinaryMarshallerSelfTest.java        | 41 ++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4f97444c/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
index 27e9440..d78c126 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryContext.java
@@ -1127,13 +1127,17 @@ public class BinaryContext {
                 mapper,
                 serializer,
                 true,
-                false
+                true
             );
 
             fieldsMeta = desc.fieldsMeta();
             schemas = desc.schema() != null ? Collections.singleton(desc.schema()) : null;
 
             descByCls.put(cls, desc);
+
+            // Registering in order to support the interoperability between Java, C++ and .Net.
+            // https://issues.apache.org/jira/browse/IGNITE-3455
+            predefinedTypes.put(id, desc);
         }
 
         metaHnd.addMeta(id, new BinaryMetadata(id, typeName, fieldsMeta, affKeyFieldName, schemas, isEnum).wrap(this));

http://git-wip-us.apache.org/repos/asf/ignite/blob/4f97444c/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
index 065081a..1285db7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
@@ -1791,6 +1791,47 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
     /**
      * @throws Exception If failed.
      */
+    public void testCustomTypeRegistration() throws Exception {
+        BinaryTypeConfiguration customType = new BinaryTypeConfiguration(Value.class.getName());
+
+        BinaryMarshaller marsh = binaryMarshaller(Arrays.asList(customType));
+
+        BinaryContext ctx = binaryContext(marsh);
+
+        int typeId = ctx.typeId(Value.class.getName());
+
+        BinaryClassDescriptor descriptor = ctx.descriptorForTypeId(true, typeId, null, false);
+
+        assertEquals(Value.class, descriptor.describedClass());
+        assertEquals(true, descriptor.registered());
+        assertEquals(true, descriptor.userType());
+
+        // Custom explicit types must be registered in 'predefinedTypes' in order not to break the interoperability.
+        Field field = ctx.getClass().getDeclaredField("predefinedTypes");
+
+        field.setAccessible(true);
+
+        Map<Integer, BinaryClassDescriptor> map = (Map<Integer, BinaryClassDescriptor>)field.get(ctx);
+
+        assertTrue(map.size() > 0);
+
+        assertNotNull(map.get(typeId));
+
+        // Custom explicit types must NOT be registered in 'predefinedTypeNames'.
+        field = ctx.getClass().getDeclaredField("predefinedTypeNames");
+
+        field.setAccessible(true);
+
+        Map<String, Integer> map2 = (Map<String, Integer>)field.get(ctx);
+
+        assertTrue(map2.size() > 0);
+
+        assertNull(map2.get(ctx.userTypeName(Value.class.getName())));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testFieldIdMapping() throws Exception {
         BinaryTypeConfiguration customType1 = new BinaryTypeConfiguration(Value.class.getName());
 


[30/46] ignite git commit: .NET: Move internal UserSerializerProxy to the appropriate namespace

Posted by sb...@apache.org.
.NET: Move internal UserSerializerProxy to the appropriate namespace


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

Branch: refs/heads/ignite-1232
Commit: 96f25aefd0e04f8f95383b5c2c6bcb3afc7e9757
Parents: 6cba20f
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Jul 19 14:00:31 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Jul 19 14:00:31 2016 +0300

----------------------------------------------------------------------
 .../Apache.Ignite.Core.csproj                   |  2 +-
 .../Binary/UserSerializerProxy.cs               | 68 --------------------
 .../Impl/Binary/UserSerializerProxy.cs          | 68 ++++++++++++++++++++
 3 files changed, 69 insertions(+), 69 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/96f25aef/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 57f89a6..fac94a8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -89,7 +89,6 @@
     <Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
     <Compile Include="Impl\Binary\IBinarySerializerInternal.cs" />
     <Compile Include="Binary\Package-Info.cs" />
-    <Compile Include="Binary\UserSerializerProxy.cs" />
     <Compile Include="Cache\Affinity\AffinityFunctionBase.cs" />
     <Compile Include="Cache\Affinity\AffinityKey.cs" />
     <Compile Include="Cache\Affinity\AffinityKeyMappedAttribute.cs" />
@@ -164,6 +163,7 @@
     <Compile Include="Impl\Binary\DateTimeSerializer.cs" />
     <Compile Include="Impl\Binary\SerializableSerializer.cs" />
     <Compile Include="Impl\Binary\BinaryWriterExtensions.cs" />
+    <Compile Include="Impl\Binary\UserSerializerProxy.cs" />
     <Compile Include="Impl\Cache\Affinity\AffinityFunctionSerializer.cs" />
     <Compile Include="Impl\Cache\Affinity\PlatformAffinityFunction.cs" />
     <Compile Include="Impl\Common\ObjectInfoHolder.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/96f25aef/modules/platforms/dotnet/Apache.Ignite.Core/Binary/UserSerializerProxy.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/UserSerializerProxy.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/UserSerializerProxy.cs
deleted file mode 100644
index 2cfc95e..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/UserSerializerProxy.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-\ufeff/*
- * 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.Binary
-{
-    using System;
-    using System.Diagnostics;
-    using System.Runtime.Serialization;
-    using Apache.Ignite.Core.Impl.Binary;
-
-    /// <summary>
-    /// User-defined serializer wrapper.
-    /// </summary>
-    internal class UserSerializerProxy : IBinarySerializerInternal
-    {
-        /** */
-        private readonly IBinarySerializer _serializer;
-
-        /// <summary>
-        /// Initializes a new instance of the <see cref="UserSerializerProxy"/> class.
-        /// </summary>
-        /// <param name="serializer">The serializer.</param>
-        public UserSerializerProxy(IBinarySerializer serializer)
-        {
-            Debug.Assert(serializer != null);
-
-            _serializer = serializer;
-        }
-
-        /** <inheritdoc /> */
-        public void WriteBinary<T>(T obj, BinaryWriter writer)
-        {
-            _serializer.WriteBinary(obj, writer);
-        }
-
-        /** <inheritdoc /> */
-        public T ReadBinary<T>(BinaryReader reader, Type type, int pos)
-        {
-            var obj = FormatterServices.GetUninitializedObject(type);
-
-            reader.AddHandle(pos, obj);
-
-            _serializer.ReadBinary(obj, reader);
-
-            return (T) obj;
-        }
-
-        /** <inheritdoc /> */
-        public bool SupportsHandles
-        {
-            get { return true; }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/ignite/blob/96f25aef/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
new file mode 100644
index 0000000..de25e32
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/UserSerializerProxy.cs
@@ -0,0 +1,68 @@
+/*
+ * 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.Diagnostics;
+    using System.Runtime.Serialization;
+    using Apache.Ignite.Core.Binary;
+
+    /// <summary>
+    /// User-defined serializer wrapper.
+    /// </summary>
+    internal class UserSerializerProxy : IBinarySerializerInternal
+    {
+        /** */
+        private readonly IBinarySerializer _serializer;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="UserSerializerProxy"/> class.
+        /// </summary>
+        /// <param name="serializer">The serializer.</param>
+        public UserSerializerProxy(IBinarySerializer serializer)
+        {
+            Debug.Assert(serializer != null);
+
+            _serializer = serializer;
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary<T>(T obj, BinaryWriter writer)
+        {
+            _serializer.WriteBinary(obj, writer);
+        }
+
+        /** <inheritdoc /> */
+        public T ReadBinary<T>(BinaryReader reader, Type type, int pos)
+        {
+            var obj = FormatterServices.GetUninitializedObject(type);
+
+            reader.AddHandle(pos, obj);
+
+            _serializer.ReadBinary(obj, reader);
+
+            return (T) obj;
+        }
+
+        /** <inheritdoc /> */
+        public bool SupportsHandles
+        {
+            get { return true; }
+        }
+    }
+}


[33/46] ignite git commit: IGNITE-3414: Hadoop: implemented new weight-based map-reduce planner.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopDefaultMapReducePlannerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopDefaultMapReducePlannerSelfTest.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopDefaultMapReducePlannerSelfTest.java
index ffa6f7d..a69b72a 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopDefaultMapReducePlannerSelfTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopDefaultMapReducePlannerSelfTest.java
@@ -17,47 +17,27 @@
 
 package org.apache.ignite.internal.processors.hadoop;
 
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteFileSystem;
-import org.apache.ignite.IgniteSpringBean;
 import org.apache.ignite.cluster.ClusterNode;
-import org.apache.ignite.configuration.FileSystemConfiguration;
 import org.apache.ignite.hadoop.mapreduce.IgniteHadoopMapReducePlanner;
 import org.apache.ignite.igfs.IgfsBlockLocation;
-import org.apache.ignite.igfs.IgfsFile;
-import org.apache.ignite.igfs.IgfsMetrics;
-import org.apache.ignite.igfs.IgfsOutputStream;
 import org.apache.ignite.igfs.IgfsPath;
-import org.apache.ignite.igfs.IgfsPathSummary;
-import org.apache.ignite.igfs.mapreduce.IgfsRecordResolver;
-import org.apache.ignite.igfs.mapreduce.IgfsTask;
-import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
-import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.IgniteEx;
-import org.apache.ignite.internal.cluster.IgniteClusterEx;
-import org.apache.ignite.internal.processors.cache.GridCacheUtilityKey;
-import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopAbstractMapReducePlanner;
 import org.apache.ignite.internal.processors.igfs.IgfsBlockLocationImpl;
-import org.apache.ignite.internal.processors.igfs.IgfsContext;
-import org.apache.ignite.internal.processors.igfs.IgfsEx;
-import org.apache.ignite.internal.processors.igfs.IgfsInputStreamAdapter;
-import org.apache.ignite.internal.processors.igfs.IgfsLocalMetrics;
-import org.apache.ignite.internal.processors.igfs.IgfsPaths;
-import org.apache.ignite.internal.processors.igfs.IgfsStatus;
+import org.apache.ignite.internal.processors.igfs.IgfsIgniteMock;
+import org.apache.ignite.internal.processors.igfs.IgfsMock;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.lang.IgniteFuture;
-import org.apache.ignite.lang.IgnitePredicate;
-import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.testframework.GridTestNode;
 import org.apache.ignite.testframework.GridTestUtils;
-import org.jetbrains.annotations.Nullable;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
 
 /**
  *
@@ -90,12 +70,12 @@ public class HadoopDefaultMapReducePlannerSelfTest extends HadoopAbstractSelfTes
     /** */
     private static final String INVALID_HOST_3 = "invalid_host3";
 
-    /** Mocked Grid. */
-    private static final MockIgnite GRID = new MockIgnite();
-
     /** Mocked IGFS. */
     private static final IgniteFileSystem IGFS = new MockIgfs();
 
+    /** Mocked Grid. */
+    private static final IgfsIgniteMock GRID = new IgfsIgniteMock(null, IGFS);
+
     /** Planner. */
     private static final HadoopMapReducePlanner PLANNER = new IgniteHadoopMapReducePlanner();
 
@@ -109,15 +89,15 @@ public class HadoopDefaultMapReducePlannerSelfTest extends HadoopAbstractSelfTes
     private static final ThreadLocal<HadoopMapReducePlan> PLAN = new ThreadLocal<>();
 
     /**
-     *
+     * Static initializer.
      */
     static {
-        GridTestUtils.setFieldValue(PLANNER, "ignite", GRID);
+        GridTestUtils.setFieldValue(PLANNER, HadoopAbstractMapReducePlanner.class, "ignite", GRID);
     }
 
     /** {@inheritDoc} */
     @Override protected void beforeTest() throws Exception {
-        GridTestUtils.setFieldValue(PLANNER, "log", log());
+        GridTestUtils.setFieldValue(PLANNER, HadoopAbstractMapReducePlanner.class, "log", log());
 
         BLOCK_MAP.clear();
         PROXY_MAP.clear();
@@ -445,7 +425,7 @@ public class HadoopDefaultMapReducePlannerSelfTest extends HadoopAbstractSelfTes
         top.add(node2);
         top.add(node3);
 
-        HadoopMapReducePlan plan = PLANNER.preparePlan(new MockJob(reducers, splitList), top, null);
+        HadoopMapReducePlan plan = PLANNER.preparePlan(new HadoopPlannerMockJob(splitList, reducers), top, null);
 
         PLAN.set(plan);
 
@@ -607,81 +587,17 @@ public class HadoopDefaultMapReducePlannerSelfTest extends HadoopAbstractSelfTes
     }
 
     /**
-     * Mocked job.
+     * Mocked IGFS.
      */
-    private static class MockJob implements HadoopJob {
-        /** Reducers count. */
-        private final int reducers;
-
-        /** */
-        private Collection<HadoopInputSplit> splitList;
-
+    private static class MockIgfs extends IgfsMock {
         /**
          * Constructor.
-         *
-         * @param reducers Reducers count.
-         * @param splitList Splits.
          */
-        private MockJob(int reducers, Collection<HadoopInputSplit> splitList) {
-            this.reducers = reducers;
-            this.splitList = splitList;
-        }
-
-        /** {@inheritDoc} */
-        @Override public HadoopJobId id() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public HadoopJobInfo info() {
-            return new HadoopDefaultJobInfo() {
-                @Override public int reducers() {
-                    return reducers;
-                }
-            };
+        public MockIgfs() {
+            super("igfs");
         }
 
         /** {@inheritDoc} */
-        @Override public Collection<HadoopInputSplit> input() throws IgniteCheckedException {
-            return splitList;
-        }
-
-        /** {@inheritDoc} */
-        @Override public HadoopTaskContext getTaskContext(HadoopTaskInfo info) throws IgniteCheckedException {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void initialize(boolean external, UUID nodeId) throws IgniteCheckedException {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public void dispose(boolean external) throws IgniteCheckedException {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public void prepareTaskEnvironment(HadoopTaskInfo info) throws IgniteCheckedException {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public void cleanupTaskEnvironment(HadoopTaskInfo info) throws IgniteCheckedException {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public void cleanupStagingDirectory() {
-            // No-op.
-        }
-    }
-
-    /**
-     * Mocked IGFS.
-     */
-    private static class MockIgfs implements IgfsEx {
-        /** {@inheritDoc} */
         @Override public boolean isProxy(URI path) {
             return PROXY_MAP.containsKey(path) && PROXY_MAP.get(path);
         }
@@ -692,331 +608,8 @@ public class HadoopDefaultMapReducePlannerSelfTest extends HadoopAbstractSelfTes
         }
 
         /** {@inheritDoc} */
-        @Override public Collection<IgfsBlockLocation> affinity(IgfsPath path, long start, long len,
-            long maxLen) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void stop(boolean cancel) {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsContext context() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsPaths proxyPaths() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsInputStreamAdapter open(IgfsPath path, int bufSize, int seqReadsBeforePrefetch) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsInputStreamAdapter open(IgfsPath path) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsInputStreamAdapter open(IgfsPath path, int bufSize) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsStatus globalSpace() throws IgniteCheckedException {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void globalSampling(@Nullable Boolean val) throws IgniteCheckedException {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public Boolean globalSampling() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsLocalMetrics localMetrics() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public long groupBlockSize() {
-            return 0;
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public String clientLogDirectory() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void clientLogDirectory(String logDir) {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean evictExclude(IgfsPath path, boolean primary) {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public String name() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public FileSystemConfiguration configuration() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
         @Override public boolean exists(IgfsPath path) {
             return true;
         }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public IgfsFile info(IgfsPath path) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsPathSummary summary(IgfsPath path) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public IgfsFile update(IgfsPath path, Map<String, String> props) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void rename(IgfsPath src, IgfsPath dest) {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean delete(IgfsPath path, boolean recursive) {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void mkdirs(IgfsPath path) {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public void mkdirs(IgfsPath path, @Nullable Map<String, String> props) {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public Collection<IgfsPath> listPaths(IgfsPath path) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public Collection<IgfsFile> listFiles(IgfsPath path) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public long usedSpaceSize() {
-            return 0;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsOutputStream create(IgfsPath path, boolean overwrite) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsOutputStream create(IgfsPath path, int bufSize, boolean overwrite, int replication,
-            long blockSize, @Nullable Map<String, String> props) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsOutputStream create(IgfsPath path, int bufSize, boolean overwrite,
-            @Nullable IgniteUuid affKey, int replication, long blockSize, @Nullable Map<String, String> props) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsOutputStream append(IgfsPath path, boolean create) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsOutputStream append(IgfsPath path, int bufSize, boolean create,
-            @Nullable Map<String, String> props) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void setTimes(IgfsPath path, long accessTime, long modificationTime) {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsMetrics metrics() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void resetMetrics() {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public long size(IgfsPath path) {
-            return 0;
-        }
-
-        /** {@inheritDoc} */
-        @Override public void format() {
-            // No-op.
-        }
-
-        /** {@inheritDoc} */
-        @Override public <T, R> R execute(IgfsTask<T, R> task, @Nullable IgfsRecordResolver rslvr,
-            Collection<IgfsPath> paths, @Nullable T arg) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public <T, R> R execute(IgfsTask<T, R> task, @Nullable IgfsRecordResolver rslvr,
-            Collection<IgfsPath> paths, boolean skipNonExistentFiles, long maxRangeLen, @Nullable T arg) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public <T, R> R execute(Class<? extends IgfsTask<T, R>> taskCls,
-            @Nullable IgfsRecordResolver rslvr, Collection<IgfsPath> paths, @Nullable T arg) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public <T, R> R execute(Class<? extends IgfsTask<T, R>> taskCls,
-            @Nullable IgfsRecordResolver rslvr, Collection<IgfsPath> paths, boolean skipNonExistentFiles,
-            long maxRangeLen, @Nullable T arg) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgniteUuid nextAffinityKey() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgniteFileSystem withAsync() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean isAsync() {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Override public <R> IgniteFuture<R> future() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgfsSecondaryFileSystem asSecondary() {
-            return null;
-        }
-    }
-
-    /**
-     * Mocked Grid.
-     */
-    @SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
-    private static class MockIgnite extends IgniteSpringBean implements IgniteEx {
-        /** {@inheritDoc} */
-        @Override public IgniteClusterEx cluster() {
-            return (IgniteClusterEx)super.cluster();
-        }
-
-        /** {@inheritDoc} */
-        @Override public IgniteFileSystem igfsx(String name) {
-            assert F.eq("igfs", name);
-
-            return IGFS;
-        }
-
-        /** {@inheritDoc} */
-        @Override public Hadoop hadoop() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public String name() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public <K extends GridCacheUtilityKey, V> IgniteInternalCache<K, V> utilityCache() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public <K, V> IgniteInternalCache<K, V> cachex(@Nullable String name) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public <K, V> IgniteInternalCache<K, V> cachex() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @SuppressWarnings("unchecked")
-        @Override public Collection<IgniteInternalCache<?, ?>> cachesx(@Nullable IgnitePredicate<? super IgniteInternalCache<?, ?>>... p) {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean eventUserRecordable(int type) {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean allEventsUserRecordable(int[] types) {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean isJmxRemoteEnabled() {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Override public boolean isRestartEnabled() {
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Override public ClusterNode localNode() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public String latestVersion() {
-            return null;
-        }
-
-        /** {@inheritDoc} */
-        @Override public GridKernalContext context() {
-            return null;
-        }
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
index b703896..5d1de38 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
@@ -17,13 +17,130 @@
 
 package org.apache.ignite.internal.processors.hadoop;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.UUID;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.io.IntWritable;
+import org.apache.hadoop.io.Text;
+import org.apache.hadoop.mapred.JobConf;
+import org.apache.hadoop.mapreduce.Job;
+import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
+import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheWriteSynchronizationMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.FileSystemConfiguration;
+import org.apache.ignite.configuration.HadoopConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.hadoop.fs.IgniteHadoopFileSystemCounterWriter;
+import org.apache.ignite.hadoop.fs.IgniteHadoopIgfsSecondaryFileSystem;
+import org.apache.ignite.igfs.IgfsGroupDataBlocksKeyMapper;
+import org.apache.ignite.igfs.IgfsIpcEndpointConfiguration;
+import org.apache.ignite.igfs.IgfsMode;
 import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.igfs.IgfsUserContext;
+import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.hadoop.counter.HadoopCounters;
+import org.apache.ignite.internal.processors.hadoop.counter.HadoopPerformanceCounter;
+import org.apache.ignite.internal.processors.hadoop.examples.HadoopWordCount1;
 import org.apache.ignite.internal.processors.hadoop.examples.HadoopWordCount2;
+import org.apache.ignite.internal.processors.igfs.IgfsEx;
+import org.apache.ignite.internal.processors.igfs.IgfsUtils;
+import org.apache.ignite.internal.util.lang.GridAbsPredicate;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.lang.IgniteOutClosure;
+import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
+import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.igfs.IgfsMode.PRIMARY;
+import static org.apache.ignite.internal.processors.hadoop.HadoopUtils.JOB_COUNTER_WRITER_PROPERTY;
+import static org.apache.ignite.internal.processors.hadoop.HadoopUtils.createJobInfo;
 
 /**
  * Test of whole cycle of map-reduce processing via Job tracker.
  */
-public class HadoopMapReduceTest extends HadoopAbstractMapReduceTest {
+public class HadoopMapReduceTest extends HadoopAbstractWordCountTest {
+    /** IGFS block size. */
+    protected static final int IGFS_BLOCK_SIZE = 512 * 1024;
+
+    /** Amount of blocks to prefetch. */
+    protected static final int PREFETCH_BLOCKS = 1;
+
+    /** Amount of sequential block reads before prefetch is triggered. */
+    protected static final int SEQ_READS_BEFORE_PREFETCH = 2;
+
+    /** Secondary file system URI. */
+    protected static final String SECONDARY_URI = "igfs://igfs-secondary:grid-secondary@127.0.0.1:11500/";
+
+    /** Secondary file system configuration path. */
+    protected static final String SECONDARY_CFG = "modules/core/src/test/config/hadoop/core-site-loopback-secondary.xml";
+
+    /** The user to run Hadoop job on behalf of. */
+    protected static final String USER = "vasya";
+
+    /** Secondary IGFS name. */
+    protected static final String SECONDARY_IGFS_NAME = "igfs-secondary";
+
+    /** The secondary Ignite node. */
+    protected Ignite igniteSecondary;
+
+    /** The secondary Fs. */
+    protected IgfsSecondaryFileSystem secondaryFs;
+
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return 3;
+    }
+
+    /**
+     * Gets owner of a IgfsEx path.
+     * @param p The path.
+     * @return The owner.
+     */
+    private static String getOwner(IgfsEx i, IgfsPath p) {
+        return i.info(p).property(IgfsUtils.PROP_USER_NAME);
+    }
+
+    /**
+     * Gets owner of a secondary Fs path.
+     * @param secFs The sec Fs.
+     * @param p The path.
+     * @return The owner.
+     */
+    private static String getOwnerSecondary(final IgfsSecondaryFileSystem secFs, final IgfsPath p) {
+        return IgfsUserContext.doAs(USER, new IgniteOutClosure<String>() {
+            @Override public String apply() {
+                return secFs.info(p).property(IgfsUtils.PROP_USER_NAME);
+            }
+        });
+    }
+
+    /**
+     * Checks owner of the path.
+     * @param p The path.
+     */
+    private void checkOwner(IgfsPath p) {
+        String ownerPrim = getOwner(igfs, p);
+        assertEquals(USER, ownerPrim);
+
+        String ownerSec = getOwnerSecondary(secondaryFs, p);
+        assertEquals(USER, ownerSec);
+    }
+
     /**
      * Tests whole job execution with all phases in all combination of new and old versions of API.
      * @throws Exception If fails.
@@ -35,32 +152,274 @@ public class HadoopMapReduceTest extends HadoopAbstractMapReduceTest {
 
         IgfsPath inFile = new IgfsPath(inDir, HadoopWordCount2.class.getSimpleName() + "-input");
 
+        final int red = 10_000;
+        final int blue = 20_000;
+        final int green = 15_000;
+        final int yellow = 7_000;
+
         generateTestFile(inFile.toString(), "red", red, "blue", blue, "green", green, "yellow", yellow );
 
-        for (boolean[] apiMode: getApiModes()) {
-            assert apiMode.length == 3;
+        for (int i = 0; i < 3; i++) {
+            igfs.delete(new IgfsPath(PATH_OUTPUT), true);
+
+            boolean useNewMapper = (i & 1) == 0;
+            boolean useNewCombiner = (i & 2) == 0;
+            boolean useNewReducer = (i & 4) == 0;
+
+            JobConf jobConf = new JobConf();
 
-            boolean useNewMapper = apiMode[0];
-            boolean useNewCombiner = apiMode[1];
-            boolean useNewReducer = apiMode[2];
+            jobConf.set(JOB_COUNTER_WRITER_PROPERTY, IgniteHadoopFileSystemCounterWriter.class.getName());
+            jobConf.setUser(USER);
+            jobConf.set(IgniteHadoopFileSystemCounterWriter.COUNTER_WRITER_DIR_PROPERTY, "/xxx/${USER}/zzz");
 
-            doTest(inFile, useNewMapper, useNewCombiner, useNewReducer);
+            //To split into about 40 items for v2
+            jobConf.setInt(FileInputFormat.SPLIT_MAXSIZE, 65000);
+
+            //For v1
+            jobConf.setInt("fs.local.block.size", 65000);
+
+            // File system coordinates.
+            setupFileSystems(jobConf);
+
+            HadoopWordCount1.setTasksClasses(jobConf, !useNewMapper, !useNewCombiner, !useNewReducer);
+
+            Job job = Job.getInstance(jobConf);
+
+            HadoopWordCount2.setTasksClasses(job, useNewMapper, useNewCombiner, useNewReducer, compressOutputSnappy());
+
+            job.setOutputKeyClass(Text.class);
+            job.setOutputValueClass(IntWritable.class);
+
+            FileInputFormat.setInputPaths(job, new Path(igfsScheme() + inFile.toString()));
+            FileOutputFormat.setOutputPath(job, new Path(igfsScheme() + PATH_OUTPUT));
+
+            job.setJarByClass(HadoopWordCount2.class);
+
+            HadoopJobId jobId = new HadoopJobId(UUID.randomUUID(), 1);
+
+            IgniteInternalFuture<?> fut = grid(0).hadoop().submit(jobId, createJobInfo(job.getConfiguration()));
+
+            fut.get();
+
+            checkJobStatistics(jobId);
+
+            final String outFile = PATH_OUTPUT + "/" + (useNewReducer ? "part-r-" : "part-") + "00000";
+
+            checkOwner(new IgfsPath(PATH_OUTPUT + "/" + "_SUCCESS"));
+
+            checkOwner(new IgfsPath(outFile));
+
+            String actual = readAndSortFile(outFile, job.getConfiguration());
+
+            assertEquals("Use new mapper: " + useNewMapper + ", new combiner: " + useNewCombiner + ", new reducer: " +
+                useNewReducer,
+                "blue\t" + blue + "\n" +
+                "green\t" + green + "\n" +
+                "red\t" + red + "\n" +
+                "yellow\t" + yellow + "\n",
+                actual
+            );
         }
     }
 
     /**
-     * Gets API mode combinations to be tested.
-     * Each boolean[] is { newMapper, newCombiner, newReducer } flag triplet.
+     * Gets if to compress output data with Snappy.
+     *
+     * @return If to compress output data with Snappy.
+     */
+    protected boolean compressOutputSnappy() {
+        return false;
+    }
+
+    /**
+     * Simple test job statistics.
      *
-     * @return Arrays of booleans indicating API combinations to test.
+     * @param jobId Job id.
+     * @throws IgniteCheckedException
      */
-    protected boolean[][] getApiModes() {
-        return new boolean[][] {
-            { false, false, false },
-            { false, false, true },
-            { false, true,  false },
-            { true,  false, false },
-            { true,  true,  true },
-        };
+    private void checkJobStatistics(HadoopJobId jobId) throws IgniteCheckedException, IOException {
+        HadoopCounters cntrs = grid(0).hadoop().counters(jobId);
+
+        HadoopPerformanceCounter perfCntr = HadoopPerformanceCounter.getCounter(cntrs, null);
+
+        Map<String, SortedMap<Integer,Long>> tasks = new TreeMap<>();
+
+        Map<String, Integer> phaseOrders = new HashMap<>();
+        phaseOrders.put("submit", 0);
+        phaseOrders.put("prepare", 1);
+        phaseOrders.put("start", 2);
+        phaseOrders.put("Cstart", 3);
+        phaseOrders.put("finish", 4);
+
+        String prevTaskId = null;
+
+        long apiEvtCnt = 0;
+
+        for (T2<String, Long> evt : perfCntr.evts()) {
+            //We expect string pattern: COMBINE 1 run 7fa86a14-5a08-40e3-a7cb-98109b52a706
+            String[] parsedEvt = evt.get1().split(" ");
+
+            String taskId;
+            String taskPhase;
+
+            if ("JOB".equals(parsedEvt[0])) {
+                taskId = parsedEvt[0];
+                taskPhase = parsedEvt[1];
+            }
+            else {
+                taskId = ("COMBINE".equals(parsedEvt[0]) ? "MAP" : parsedEvt[0].substring(0, 3)) + parsedEvt[1];
+                taskPhase = ("COMBINE".equals(parsedEvt[0]) ? "C" : "") + parsedEvt[2];
+            }
+
+            if (!taskId.equals(prevTaskId))
+                tasks.put(taskId, new TreeMap<Integer,Long>());
+
+            Integer pos = phaseOrders.get(taskPhase);
+
+            assertNotNull("Invalid phase " + taskPhase, pos);
+
+            tasks.get(taskId).put(pos, evt.get2());
+
+            prevTaskId = taskId;
+
+            apiEvtCnt++;
+        }
+
+        for (Map.Entry<String ,SortedMap<Integer,Long>> task : tasks.entrySet()) {
+            Map<Integer, Long> order = task.getValue();
+
+            long prev = 0;
+
+            for (Map.Entry<Integer, Long> phase : order.entrySet()) {
+                assertTrue("Phase order of " + task.getKey() + " is invalid", phase.getValue() >= prev);
+
+                prev = phase.getValue();
+            }
+        }
+
+        final IgfsPath statPath = new IgfsPath("/xxx/" + USER + "/zzz/" + jobId + "/performance");
+
+        assert GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                return igfs.exists(statPath);
+            }
+        }, 20_000);
+
+        final long apiEvtCnt0 = apiEvtCnt;
+
+        boolean res = GridTestUtils.waitForCondition(new GridAbsPredicate() {
+            @Override public boolean apply() {
+                try {
+                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(igfs.open(statPath)))) {
+                        return apiEvtCnt0 == HadoopTestUtils.simpleCheckJobStatFile(reader);
+                    }
+                }
+                catch (IOException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        }, 10000);
+
+        if (!res) {
+            BufferedReader reader = new BufferedReader(new InputStreamReader(igfs.open(statPath)));
+
+            assert false : "Invalid API events count [exp=" + apiEvtCnt0 +
+                ", actual=" + HadoopTestUtils.simpleCheckJobStatFile(reader) + ']';
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTest() throws Exception {
+        igniteSecondary = startGridWithIgfs("grid-secondary", SECONDARY_IGFS_NAME, PRIMARY, null, SECONDARY_REST_CFG);
+
+        super.beforeTest();
+    }
+
+    /**
+     * Start grid with IGFS.
+     *
+     * @param gridName Grid name.
+     * @param igfsName IGFS name
+     * @param mode IGFS mode.
+     * @param secondaryFs Secondary file system (optional).
+     * @param restCfg Rest configuration string (optional).
+     * @return Started grid instance.
+     * @throws Exception If failed.
+     */
+    protected Ignite startGridWithIgfs(String gridName, String igfsName, IgfsMode mode,
+        @Nullable IgfsSecondaryFileSystem secondaryFs, @Nullable IgfsIpcEndpointConfiguration restCfg) throws Exception {
+        FileSystemConfiguration igfsCfg = new FileSystemConfiguration();
+
+        igfsCfg.setDataCacheName("dataCache");
+        igfsCfg.setMetaCacheName("metaCache");
+        igfsCfg.setName(igfsName);
+        igfsCfg.setBlockSize(IGFS_BLOCK_SIZE);
+        igfsCfg.setDefaultMode(mode);
+        igfsCfg.setIpcEndpointConfiguration(restCfg);
+        igfsCfg.setSecondaryFileSystem(secondaryFs);
+        igfsCfg.setPrefetchBlocks(PREFETCH_BLOCKS);
+        igfsCfg.setSequentialReadsBeforePrefetch(SEQ_READS_BEFORE_PREFETCH);
+
+        CacheConfiguration dataCacheCfg = defaultCacheConfiguration();
+
+        dataCacheCfg.setName("dataCache");
+        dataCacheCfg.setCacheMode(PARTITIONED);
+        dataCacheCfg.setNearConfiguration(null);
+        dataCacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+        dataCacheCfg.setAffinityMapper(new IgfsGroupDataBlocksKeyMapper(2));
+        dataCacheCfg.setBackups(0);
+        dataCacheCfg.setAtomicityMode(TRANSACTIONAL);
+        dataCacheCfg.setOffHeapMaxMemory(0);
+
+        CacheConfiguration metaCacheCfg = defaultCacheConfiguration();
+
+        metaCacheCfg.setName("metaCache");
+        metaCacheCfg.setCacheMode(REPLICATED);
+        metaCacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
+        metaCacheCfg.setAtomicityMode(TRANSACTIONAL);
+
+        IgniteConfiguration cfg = new IgniteConfiguration();
+
+        cfg.setGridName(gridName);
+
+        TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
+
+        discoSpi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
+
+        cfg.setDiscoverySpi(discoSpi);
+        cfg.setCacheConfiguration(dataCacheCfg, metaCacheCfg);
+        cfg.setFileSystemConfiguration(igfsCfg);
+
+        cfg.setLocalHost("127.0.0.1");
+        cfg.setConnectorConfiguration(null);
+
+        HadoopConfiguration hadoopCfg = createHadoopConfiguration();
+
+        if (hadoopCfg != null)
+            cfg.setHadoopConfiguration(hadoopCfg);
+
+        return G.start(cfg);
+    }
+
+    /**
+     * Creates custom Hadoop configuration.
+     *
+     * @return The Hadoop configuration.
+     */
+    protected HadoopConfiguration createHadoopConfiguration() {
+        return null;
+    }
+
+    /**
+     * @return IGFS configuration.
+     */
+    @Override public FileSystemConfiguration igfsConfiguration() throws Exception {
+        FileSystemConfiguration fsCfg = super.igfsConfiguration();
+
+        secondaryFs = new IgniteHadoopIgfsSecondaryFileSystem(SECONDARY_URI, SECONDARY_CFG);
+
+        fsCfg.setSecondaryFileSystem(secondaryFs);
+
+        return fsCfg;
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopPlannerMockJob.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopPlannerMockJob.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopPlannerMockJob.java
new file mode 100644
index 0000000..88d0f80
--- /dev/null
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopPlannerMockJob.java
@@ -0,0 +1,168 @@
+/*
+ * 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.hadoop;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteLogger;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.UUID;
+
+/**
+ * Mock job for planner tests.
+ */
+public class HadoopPlannerMockJob implements HadoopJob {
+    /** Input splits. */
+    private final Collection<HadoopInputSplit> splits;
+
+    /** Reducers count. */
+    private final int reducers;
+
+    /**
+     * Constructor.
+     *
+     * @param splits Input splits.
+     * @param reducers Reducers.
+     */
+    public HadoopPlannerMockJob(Collection<HadoopInputSplit> splits, int reducers) {
+        this.splits = splits;
+        this.reducers = reducers;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<HadoopInputSplit> input() throws IgniteCheckedException {
+        return splits;
+    }
+
+    /** {@inheritDoc} */
+    @Override public HadoopJobInfo info() {
+        return new JobInfo(reducers);
+    }
+
+    /** {@inheritDoc} */
+    @Override public HadoopJobId id() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public HadoopTaskContext getTaskContext(HadoopTaskInfo info) throws IgniteCheckedException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void initialize(boolean external, UUID nodeId) throws IgniteCheckedException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void dispose(boolean external) throws IgniteCheckedException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void prepareTaskEnvironment(HadoopTaskInfo info) throws IgniteCheckedException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void cleanupTaskEnvironment(HadoopTaskInfo info) throws IgniteCheckedException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void cleanupStagingDirectory() {
+        throwUnsupported();
+    }
+
+    /**
+     * Throw {@link UnsupportedOperationException}.
+     */
+    private static void throwUnsupported() {
+        throw new UnsupportedOperationException("Should not be called!");
+    }
+
+    /**
+     * Mocked job info.
+     */
+    private static class JobInfo implements HadoopJobInfo {
+        /** Reducers. */
+        private final int reducers;
+
+        /**
+         * Constructor.
+         *
+         * @param reducers Reducers.
+         */
+        public JobInfo(int reducers) {
+            this.reducers = reducers;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int reducers() {
+            return reducers;
+        }
+
+        /** {@inheritDoc} */
+        @Nullable @Override public String property(String name) {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasCombiner() {
+            throwUnsupported();
+
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean hasReducer() {
+            throwUnsupported();
+
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public HadoopJob createJob(Class<? extends HadoopJob> jobCls, HadoopJobId jobId, IgniteLogger log,
+            @Nullable String[] libNames) throws IgniteCheckedException {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String jobName() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String user() {
+            throwUnsupported();
+
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedMapReducePlannerTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedMapReducePlannerTest.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedMapReducePlannerTest.java
new file mode 100644
index 0000000..4e7cc50
--- /dev/null
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedMapReducePlannerTest.java
@@ -0,0 +1,599 @@
+/*
+ * 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.hadoop;
+
+import org.apache.ignite.cluster.ClusterMetrics;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.hadoop.mapreduce.IgniteHadoopWeightedMapReducePlanner;
+import org.apache.ignite.igfs.IgfsBlockLocation;
+import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.internal.IgniteNodeAttributes;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopAbstractMapReducePlanner;
+import org.apache.ignite.internal.processors.igfs.IgfsIgniteMock;
+import org.apache.ignite.internal.processors.igfs.IgfsMock;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgniteProductVersion;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.UUID;
+
+/**
+ * Tests for weighted map-reduce planned.
+ */
+public class HadoopWeightedMapReducePlannerTest extends GridCommonAbstractTest {
+    /** ID 1. */
+    private static final UUID ID_1 = new UUID(0, 1);
+
+    /** ID 2. */
+    private static final UUID ID_2 = new UUID(0, 2);
+
+    /** ID 3. */
+    private static final UUID ID_3 = new UUID(0, 3);
+
+    /** MAC 1. */
+    private static final String MAC_1 = "mac1";
+
+    /** MAC 2. */
+    private static final String MAC_2 = "mac2";
+
+    /** MAC 3. */
+    private static final String MAC_3 = "mac3";
+
+    /** Host 1. */
+    private static final String HOST_1 = "host1";
+
+    /** Host 2. */
+    private static final String HOST_2 = "host2";
+
+    /** Host 3. */
+    private static final String HOST_3 = "host3";
+
+    /** Host 4. */
+    private static final String HOST_4 = "host4";
+
+    /** Host 5. */
+    private static final String HOST_5 = "host5";
+
+    /** Standard node 1. */
+    private static final MockNode NODE_1 = new MockNode(ID_1, MAC_1, HOST_1);
+
+    /** Standard node 2. */
+    private static final MockNode NODE_2 = new MockNode(ID_2, MAC_2, HOST_2);
+
+    /** Standard node 3. */
+    private static final MockNode NODE_3 = new MockNode(ID_3, MAC_3, HOST_3);
+
+    /** Standard nodes. */
+    private static final Collection<ClusterNode> NODES;
+
+    /**
+     * Static initializer.
+     */
+    static {
+        NODES = new ArrayList<>();
+
+        NODES.add(NODE_1);
+        NODES.add(NODE_2);
+        NODES.add(NODE_3);
+    }
+
+    /**
+     * Test one IGFS split being assigned to affinity node.
+     *
+     * @throws Exception If failed.
+     */
+    public void testOneIgfsSplitAffinity() throws Exception {
+        IgfsMock igfs = LocationsBuilder.create().add(0, NODE_1).add(50, NODE_2).add(100, NODE_3).buildIgfs();
+
+        List<HadoopInputSplit> splits = new ArrayList<>();
+
+        splits.add(new HadoopFileBlock(new String[] { HOST_1 }, URI.create("igfs://igfs@/file"), 0, 50));
+
+        final int expReducers = 4;
+
+        HadoopPlannerMockJob job = new HadoopPlannerMockJob(splits, expReducers);
+
+        IgniteHadoopWeightedMapReducePlanner planner = createPlanner(igfs);
+
+        HadoopMapReducePlan plan = planner.preparePlan(job, NODES, null);
+
+        assert plan.mappers() == 1;
+        assert plan.mapperNodeIds().size() == 1;
+        assert plan.mapperNodeIds().contains(ID_1);
+
+        checkPlanMappers(plan, splits, NODES, false/*only 1 split*/);
+        checkPlanReducers(plan, NODES, expReducers, false/* because of threshold behavior.*/);
+    }
+
+    /**
+     * Test one HDFS splits.
+     *
+     * @throws Exception If failed.
+     */
+    public void testHdfsSplitsAffinity() throws Exception {
+        IgfsMock igfs = LocationsBuilder.create().add(0, NODE_1).add(50, NODE_2).add(100, NODE_3).buildIgfs();
+
+        final List<HadoopInputSplit> splits = new ArrayList<>();
+
+        splits.add(new HadoopFileBlock(new String[] { HOST_1 }, URI.create("hfds://" + HOST_1 + "/x"), 0, 50));
+        splits.add(new HadoopFileBlock(new String[] { HOST_2 }, URI.create("hfds://" + HOST_2 + "/x"), 50, 100));
+        splits.add(new HadoopFileBlock(new String[] { HOST_3 }, URI.create("hfds://" + HOST_3 + "/x"), 100, 37));
+
+        // The following splits belong to hosts that are out of Ignite topology at all.
+        // This means that these splits should be assigned to any least loaded modes:
+        splits.add(new HadoopFileBlock(new String[] { HOST_4 }, URI.create("hfds://" + HOST_4 + "/x"), 138, 2));
+        splits.add(new HadoopFileBlock(new String[] { HOST_5 }, URI.create("hfds://" + HOST_5 + "/x"), 140, 3));
+
+        final int expReducers = 7;
+
+        HadoopPlannerMockJob job = new HadoopPlannerMockJob(splits, expReducers);
+
+        IgniteHadoopWeightedMapReducePlanner planner = createPlanner(igfs);
+
+        final HadoopMapReducePlan plan = planner.preparePlan(job, NODES, null);
+
+        checkPlanMappers(plan, splits, NODES, true);
+
+        checkPlanReducers(plan, NODES, expReducers, true);
+    }
+
+    /**
+     * Test HDFS splits with Replication == 3.
+     *
+     * @throws Exception If failed.
+     */
+    public void testHdfsSplitsReplication() throws Exception {
+        IgfsMock igfs = LocationsBuilder.create().add(0, NODE_1).add(50, NODE_2).add(100, NODE_3).buildIgfs();
+
+        final List<HadoopInputSplit> splits = new ArrayList<>();
+
+        splits.add(new HadoopFileBlock(new String[] { HOST_1, HOST_2, HOST_3 }, URI.create("hfds://" + HOST_1 + "/x"), 0, 50));
+        splits.add(new HadoopFileBlock(new String[] { HOST_2, HOST_3, HOST_4 }, URI.create("hfds://" + HOST_2 + "/x"), 50, 100));
+        splits.add(new HadoopFileBlock(new String[] { HOST_3, HOST_4, HOST_5 }, URI.create("hfds://" + HOST_3 + "/x"), 100, 37));
+        // The following splits belong to hosts that are out of Ignite topology at all.
+        // This means that these splits should be assigned to any least loaded modes:
+        splits.add(new HadoopFileBlock(new String[] { HOST_4, HOST_5, HOST_1 }, URI.create("hfds://" + HOST_4 + "/x"), 138, 2));
+        splits.add(new HadoopFileBlock(new String[] { HOST_5, HOST_1, HOST_2 }, URI.create("hfds://" + HOST_5 + "/x"), 140, 3));
+
+        final int expReducers = 8;
+
+        HadoopPlannerMockJob job = new HadoopPlannerMockJob(splits, expReducers);
+
+        IgniteHadoopWeightedMapReducePlanner planner = createPlanner(igfs);
+
+        final HadoopMapReducePlan plan = planner.preparePlan(job, NODES, null);
+
+        checkPlanMappers(plan, splits, NODES, true);
+
+        checkPlanReducers(plan, NODES, expReducers, true);
+    }
+
+    /**
+     * Get all IDs.
+     *
+     * @param nodes Nodes.
+     * @return IDs.
+     */
+    private static Set<UUID> allIds(Collection<ClusterNode> nodes) {
+        Set<UUID> allIds = new HashSet<>();
+
+        for (ClusterNode n : nodes)
+            allIds.add(n.id());
+
+        return allIds;
+    }
+
+    /**
+     * Check mappers for the plan.
+     *
+     * @param plan Plan.
+     * @param splits Splits.
+     * @param nodes Nodes.
+     * @param expectUniformity WHether uniformity is expected.
+     */
+    private static void checkPlanMappers(HadoopMapReducePlan plan, List<HadoopInputSplit> splits,
+        Collection<ClusterNode> nodes, boolean expectUniformity) {
+        // Number of mappers should correspomd to the number of input splits:
+        assertEquals(splits.size(), plan.mappers());
+
+        if (expectUniformity) {
+            // mappers are assigned to all available nodes:
+            assertEquals(nodes.size(), plan.mapperNodeIds().size());
+
+
+            assertEquals(allIds(nodes), plan.mapperNodeIds());
+        }
+
+        // Check all splits are covered by mappers:
+        Set<HadoopInputSplit> set = new HashSet<>();
+
+        for (UUID id: plan.mapperNodeIds()) {
+            Collection<HadoopInputSplit> sp = plan.mappers(id);
+
+            assert sp != null;
+
+            for (HadoopInputSplit s: sp)
+                assertTrue(set.add(s));
+        }
+
+        // must be of the same size & contain same elements:
+        assertEquals(set, new HashSet<>(splits));
+    }
+
+    /**
+     * Check plan reducers.
+     *
+     * @param plan Plan.
+     * @param nodes Nodes.
+     * @param expReducers Expected reducers.
+     * @param expectUniformity Expected uniformity.
+     */
+    private static void checkPlanReducers(HadoopMapReducePlan plan,
+        Collection<ClusterNode> nodes, int expReducers, boolean expectUniformity) {
+
+        assertEquals(expReducers, plan.reducers());
+
+        if (expectUniformity)
+            assertEquals(allIds(nodes), plan.reducerNodeIds());
+
+        int sum = 0;
+        int lenSum = 0;
+
+        for (UUID uuid: plan.reducerNodeIds()) {
+            int[] rr = plan.reducers(uuid);
+
+            assert rr != null;
+
+            lenSum += rr.length;
+
+            for (int i: rr)
+                sum += i;
+        }
+
+        assertEquals(expReducers, lenSum);
+
+        // Numbers in the arrays must be consequtive integers stating from 0,
+        // check that simply calculating their total sum:
+        assertEquals((lenSum * (lenSum - 1) / 2), sum);
+    }
+
+    /**
+     * Create planner for IGFS.
+     *
+     * @param igfs IGFS.
+     * @return Planner.
+     */
+    private static IgniteHadoopWeightedMapReducePlanner createPlanner(IgfsMock igfs) {
+        IgniteHadoopWeightedMapReducePlanner planner = new IgniteHadoopWeightedMapReducePlanner();
+
+        IgfsIgniteMock ignite = new IgfsIgniteMock(null, igfs);
+
+        GridTestUtils.setFieldValue(planner, HadoopAbstractMapReducePlanner.class, "ignite", ignite);
+
+        return planner;
+    }
+
+    /**
+     * Throw {@link UnsupportedOperationException}.
+     */
+    private static void throwUnsupported() {
+        throw new UnsupportedOperationException("Should not be called!");
+    }
+
+    /**
+     * Mocked node.
+     */
+    private static class MockNode implements ClusterNode {
+        /** ID. */
+        private final UUID id;
+
+        /** MAC addresses. */
+        private final String macs;
+
+        /** Addresses. */
+        private final List<String> addrs;
+
+        /**
+         * Constructor.
+         *
+         * @param id Node ID.
+         * @param macs MAC addresses.
+         * @param addrs Addresses.
+         */
+        public MockNode(UUID id, String macs, String... addrs) {
+            assert addrs != null;
+
+            this.id = id;
+            this.macs = macs;
+
+            this.addrs = Arrays.asList(addrs);
+        }
+
+        /** {@inheritDoc} */
+        @Override public UUID id() {
+            return id;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("unchecked")
+        @Nullable @Override public <T> T attribute(String name) {
+            if (F.eq(name, IgniteNodeAttributes.ATTR_MACS))
+                return (T)macs;
+
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<String> addresses() {
+            return addrs;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object consistentId() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public ClusterMetrics metrics() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Map<String, Object> attributes() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<String> hostNames() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public long order() {
+            throwUnsupported();
+
+            return 0;
+        }
+
+        /** {@inheritDoc} */
+        @Override public IgniteProductVersion version() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isLocal() {
+            throwUnsupported();
+
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isDaemon() {
+            throwUnsupported();
+
+            return false;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isClient() {
+            throwUnsupported();
+
+            return false;
+        }
+    }
+
+    /**
+     * Locations builder.
+     */
+    private static class LocationsBuilder {
+        /** Locations. */
+        private final TreeMap<Long, Collection<MockNode>> locs = new TreeMap<>();
+
+        /**
+         * Create new locations builder.
+         *
+         * @return Locations builder.
+         */
+        public static LocationsBuilder create() {
+            return new LocationsBuilder();
+        }
+
+        /**
+         * Add locations.
+         *
+         * @param start Start.
+         * @param nodes Nodes.
+         * @return This builder for chaining.
+         */
+        public LocationsBuilder add(long start, MockNode... nodes) {
+            locs.put(start, Arrays.asList(nodes));
+
+            return this;
+        }
+
+        /**
+         * Build locations.
+         *
+         * @return Locations.
+         */
+        public TreeMap<Long, Collection<MockNode>> build() {
+            return locs;
+        }
+
+        /**
+         * Build IGFS.
+         *
+         * @return IGFS.
+         */
+        public MockIgfs buildIgfs() {
+            return new MockIgfs(build());
+        }
+    }
+
+    /**
+     * Mocked IGFS.
+     */
+    private static class MockIgfs extends IgfsMock {
+        /** Block locations. */
+        private final TreeMap<Long, Collection<MockNode>> locs;
+
+        /**
+         * Constructor.
+         *
+         * @param locs Block locations.
+         */
+        public MockIgfs(TreeMap<Long, Collection<MockNode>> locs) {
+            super("igfs");
+
+            this.locs = locs;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<IgfsBlockLocation> affinity(IgfsPath path, long start, long len) {
+            Collection<IgfsBlockLocation> res = new ArrayList<>();
+
+            long cur = start;
+            long remaining = len;
+
+            long prevLocStart = -1;
+            Collection<MockNode> prevLocNodes = null;
+
+            for (Map.Entry<Long, Collection<MockNode>> locEntry : locs.entrySet()) {
+                long locStart = locEntry.getKey();
+                Collection<MockNode> locNodes = locEntry.getValue();
+
+                if (prevLocNodes != null) {
+                    if (cur < locStart) {
+                        // Add part from previous block.
+                        long prevLen = locStart - prevLocStart;
+
+                        res.add(new IgfsBlockLocationMock(cur, prevLen, prevLocNodes));
+
+                        cur = locStart;
+                        remaining -= prevLen;
+                    }
+                }
+
+                prevLocStart = locStart;
+                prevLocNodes = locNodes;
+
+                if (remaining == 0)
+                    break;
+            }
+
+            // Add remainder.
+            if (remaining != 0)
+                res.add(new IgfsBlockLocationMock(cur, remaining, prevLocNodes));
+
+            return res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean exists(IgfsPath path) {
+            return true;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean isProxy(URI path) {
+            return false;
+        }
+    }
+
+    /**
+     * Mocked block location.
+     */
+    private static class IgfsBlockLocationMock implements IgfsBlockLocation {
+        /** Start. */
+        private final long start;
+
+        /** Length. */
+        private final long len;
+
+        /** Node IDs. */
+        private final List<UUID> nodeIds;
+
+        /**
+         * Constructor.
+         *
+         * @param start Start.
+         * @param len Length.
+         * @param nodes Nodes.
+         */
+        public IgfsBlockLocationMock(long start, long len, Collection<MockNode> nodes) {
+            this.start = start;
+            this.len = len;
+
+            this.nodeIds = new ArrayList<>(nodes.size());
+
+            for (MockNode node : nodes)
+                nodeIds.add(node.id);
+        }
+
+        /** {@inheritDoc} */
+        @Override public long start() {
+            return start;
+        }
+
+        /** {@inheritDoc} */
+        @Override public long length() {
+            return len;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<UUID> nodeIds() {
+            return nodeIds;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<String> names() {
+            throwUnsupported();
+
+            return null;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<String> hosts() {
+            throwUnsupported();
+
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedPlannerMapReduceTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedPlannerMapReduceTest.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedPlannerMapReduceTest.java
new file mode 100644
index 0000000..e0403c2
--- /dev/null
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopWeightedPlannerMapReduceTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.hadoop;
+
+import org.apache.ignite.configuration.HadoopConfiguration;
+import org.apache.ignite.hadoop.mapreduce.IgniteHadoopWeightedMapReducePlanner;
+
+/**
+ * Tests whole map-red execution Weighted planner.
+ */
+public class HadoopWeightedPlannerMapReduceTest extends HadoopMapReduceTest {
+    /** {@inheritDoc} */
+    @Override protected HadoopConfiguration createHadoopConfiguration() {
+        HadoopConfiguration hadoopCfg = new HadoopConfiguration();
+
+        // Use weighted planner with default settings:
+        IgniteHadoopWeightedMapReducePlanner planner = new IgniteHadoopWeightedMapReducePlanner();
+
+        hadoopCfg.setMapReducePlanner(planner);
+
+        return hadoopCfg;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
index 7d877ab..6900425 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/testsuites/IgniteHadoopTestSuite.java
@@ -28,7 +28,6 @@ import org.apache.ignite.hadoop.cache.HadoopTxConfigCacheTest;
 import org.apache.ignite.hadoop.fs.KerberosHadoopFileSystemFactorySelfTest;
 import org.apache.ignite.hadoop.util.BasicUserNameMapperSelfTest;
 import org.apache.ignite.hadoop.util.ChainedUserNameMapperSelfTest;
-import org.apache.ignite.hadoop.util.KerberosUserNameMapper;
 import org.apache.ignite.hadoop.util.KerberosUserNameMapperSelfTest;
 import org.apache.ignite.igfs.Hadoop1OverIgfsDualAsyncTest;
 import org.apache.ignite.igfs.Hadoop1OverIgfsDualSyncTest;
@@ -72,6 +71,8 @@ import org.apache.ignite.internal.processors.hadoop.HadoopTasksV1Test;
 import org.apache.ignite.internal.processors.hadoop.HadoopTasksV2Test;
 import org.apache.ignite.internal.processors.hadoop.HadoopV2JobSelfTest;
 import org.apache.ignite.internal.processors.hadoop.HadoopValidationSelfTest;
+import org.apache.ignite.internal.processors.hadoop.HadoopWeightedMapReducePlannerTest;
+import org.apache.ignite.internal.processors.hadoop.HadoopWeightedPlannerMapReduceTest;
 import org.apache.ignite.internal.processors.hadoop.shuffle.collections.HadoopConcurrentHashMultimapSelftest;
 import org.apache.ignite.internal.processors.hadoop.shuffle.collections.HadoopHashMapSelfTest;
 import org.apache.ignite.internal.processors.hadoop.shuffle.collections.HadoopSkipListSelfTest;
@@ -110,6 +111,9 @@ public class IgniteHadoopTestSuite extends TestSuite {
 
         TestSuite suite = new TestSuite("Ignite Hadoop MR Test Suite");
 
+        suite.addTest(new TestSuite(ldr.loadClass(HadoopDefaultMapReducePlannerSelfTest.class.getName())));
+        suite.addTest(new TestSuite(ldr.loadClass(HadoopWeightedMapReducePlannerTest.class.getName())));
+
         suite.addTest(new TestSuite(ldr.loadClass(BasicUserNameMapperSelfTest.class.getName())));
         suite.addTest(new TestSuite(ldr.loadClass(KerberosUserNameMapperSelfTest.class.getName())));
         suite.addTest(new TestSuite(ldr.loadClass(ChainedUserNameMapperSelfTest.class.getName())));
@@ -156,7 +160,6 @@ public class IgniteHadoopTestSuite extends TestSuite {
 
         suite.addTest(new TestSuite(ldr.loadClass(HadoopValidationSelfTest.class.getName())));
 
-        suite.addTest(new TestSuite(ldr.loadClass(HadoopDefaultMapReducePlannerSelfTest.class.getName())));
         suite.addTest(new TestSuite(ldr.loadClass(HadoopJobTrackerSelfTest.class.getName())));
 
         suite.addTest(new TestSuite(ldr.loadClass(HadoopHashMapSelfTest.class.getName())));
@@ -176,6 +179,7 @@ public class IgniteHadoopTestSuite extends TestSuite {
         suite.addTest(new TestSuite(ldr.loadClass(HadoopTasksV2Test.class.getName())));
 
         suite.addTest(new TestSuite(ldr.loadClass(HadoopMapReduceTest.class.getName())));
+        suite.addTest(new TestSuite(ldr.loadClass(HadoopWeightedPlannerMapReduceTest.class.getName())));
         suite.addTest(new TestSuite(ldr.loadClass(HadoopNoHadoopMapReduceTest.class.getName())));
         suite.addTest(new TestSuite(ldr.loadClass(HadoopMapReduceErrorResilienceTest.class.getName())));
 


[13/46] ignite git commit: IGNITE-3440: Ignite Services: ServiceTopologyCallable is executed before system cache is started (cherry picked from commit 06b24a9)

Posted by sb...@apache.org.
IGNITE-3440: Ignite Services: ServiceTopologyCallable is executed before system cache is started
(cherry picked from commit 06b24a9)


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

Branch: refs/heads/ignite-1232
Commit: c7eed8859202b99cc64b7f6d6efe46acf71ad72a
Parents: cd1d618
Author: Denis Magda <dm...@gridgain.com>
Authored: Wed Jul 13 14:19:51 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Wed Jul 13 15:28:50 2016 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheProcessor.java    |  2 +
 .../service/GridServiceProcessor.java           | 70 +++++++++++++++++++-
 2 files changed, 71 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c7eed885/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
index 9451254..e104b87 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProcessor.java
@@ -821,6 +821,8 @@ public class GridCacheProcessor extends GridProcessorAdapter {
         if (!ctx.config().isDaemon())
             ctx.cacheObjects().onUtilityCacheStarted();
 
+        ctx.service().onUtilityCacheStarted();
+
         // Wait for caches in SYNC preload mode.
         for (DynamicCacheDescriptor desc : registeredCaches.values()) {
             CacheConfiguration cfg = desc.cacheConfiguration();

http://git-wip-us.apache.org/repos/asf/ignite/blob/c7eed885/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
index fd895ea..01b7302 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
@@ -38,8 +38,10 @@ import javax.cache.event.CacheEntryEvent;
 import javax.cache.event.CacheEntryUpdatedListener;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cluster.ClusterGroup;
 import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.compute.ComputeJobContext;
 import org.apache.ignite.configuration.DeploymentMode;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.events.DiscoveryEvent;
@@ -86,6 +88,8 @@ import org.apache.ignite.lang.IgniteProductVersion;
 import org.apache.ignite.lang.IgniteUuid;
 import org.apache.ignite.marshaller.Marshaller;
 import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.resources.JobContextResource;
+import org.apache.ignite.resources.LoggerResource;
 import org.apache.ignite.services.Service;
 import org.apache.ignite.services.ServiceConfiguration;
 import org.apache.ignite.services.ServiceDescriptor;
@@ -137,6 +141,9 @@ public class GridServiceProcessor extends GridProcessorAdapter {
     /** Deployment futures. */
     private final ConcurrentMap<String, GridFutureAdapter<?>> undepFuts = new ConcurrentHashMap8<>();
 
+    /** Pending compute job contexts that waiting for utility cache initialization. */
+    private final List<ComputeJobContext> pendingJobCtxs = new ArrayList<>(0);
+
     /** Deployment executor service. */
     private final ExecutorService depExe;
 
@@ -1325,6 +1332,23 @@ public class GridServiceProcessor extends GridProcessorAdapter {
     }
 
     /**
+     * Called right after utility cache is started and ready for the usage.
+     */
+    public void onUtilityCacheStarted() {
+        synchronized (pendingJobCtxs) {
+            if (pendingJobCtxs.size() == 0)
+                return;
+
+            Iterator<ComputeJobContext> iter = pendingJobCtxs.iterator();
+
+            while (iter.hasNext()) {
+                iter.next().callcc();
+                iter.remove();
+            }
+        }
+    }
+
+    /**
      * Service deployment listener.
      */
     @SuppressWarnings("unchecked")
@@ -1809,9 +1833,20 @@ public class GridServiceProcessor extends GridProcessorAdapter {
         private final String svcName;
 
         /** */
+        private boolean waitedCacheInit;
+
+        /** */
         @IgniteInstanceResource
         private IgniteEx ignite;
 
+        /** */
+        @JobContextResource
+        private ComputeJobContext jCtx;
+
+        /** */
+        @LoggerResource
+        private IgniteLogger log;
+
         /**
          * @param svcName Service name.
          */
@@ -1821,7 +1856,40 @@ public class GridServiceProcessor extends GridProcessorAdapter {
 
         /** {@inheritDoc} */
         @Override public Map<UUID, Integer> call() throws Exception {
-            return serviceTopology(ignite.context().cache().utilityCache(), svcName);
+            IgniteInternalCache<Object, Object> cache = ignite.context().cache().utilityCache();
+
+            if (cache == null) {
+                List<ComputeJobContext> pendingCtxs = ignite.context().service().pendingJobCtxs;
+
+                synchronized (pendingCtxs) {
+                    // Double check cache reference after lock acqusition.
+                    cache = ignite.context().cache().utilityCache();
+
+                    if (cache == null) {
+                        if (!waitedCacheInit) {
+                            log.debug("Utility cache hasn't been initialized yet. Waiting.");
+
+                            // waiting for a minute for cache initialization.
+                            jCtx.holdcc(60 * 1000);
+
+                            pendingCtxs.add(jCtx);
+
+                            waitedCacheInit = true;
+
+                            return null;
+                        }
+                        else {
+                            log.error("Failed to gather service topology. Utility " +
+                                "cache initialization is stuck.");
+
+                            throw new IgniteCheckedException("Failed to gather service topology. Utility " +
+                                "cache initialization is stuck.");
+                        }
+                    }
+                }
+            }
+
+            return serviceTopology(cache, svcName);
         }
     }
 


[16/46] ignite git commit: ignite-1088 Implemented store for multi jvm tests (cherry picked from commit f91b699)

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
index bcea603..403835a 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/IgniteCacheConfigVariationsAbstractTest.java
@@ -17,9 +17,7 @@
 
 package org.apache.ignite.testframework.junits;
 
-import java.util.Map;
 import javax.cache.Cache;
-import javax.cache.configuration.Factory;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -29,8 +27,6 @@ import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMemoryMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.cache.CachePeekMode;
-import org.apache.ignite.cache.store.CacheStore;
-import org.apache.ignite.cache.store.CacheStoreAdapter;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
@@ -38,15 +34,16 @@ import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.H2CacheStoreStrategy;
+import org.apache.ignite.internal.processors.cache.MapCacheStoreStrategy;
+import org.apache.ignite.internal.processors.cache.TestCacheStoreStrategy;
 import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
 import org.apache.ignite.internal.util.typedef.X;
 import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.lang.IgniteBiInClosure;
 import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.configvariations.CacheStartMode;
 import org.apache.ignite.transactions.Transaction;
 import org.jetbrains.annotations.Nullable;
-import org.jsr166.ConcurrentHashMap8;
 
 import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
 import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
@@ -62,8 +59,8 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
     /** Test timeout. */
     private static final long TEST_TIMEOUT = 30 * 1000;
 
-    /** Store map. */
-    protected static final Map<Object, Object> map = new ConcurrentHashMap8<>();
+    /** */
+    protected static TestCacheStoreStrategy storeStgy;
 
     /** {@inheritDoc} */
     @Override protected long getTestTimeout() {
@@ -72,6 +69,7 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
 
     /** {@inheritDoc} */
     @Override protected final void beforeTestsStarted() throws Exception {
+        initStoreStrategy();
         assert testsCfg != null;
         assert !testsCfg.withClients() || testsCfg.gridCount() >= 3;
 
@@ -135,6 +133,12 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
         }
     }
 
+    /** Initialize {@link #storeStgy} with respect to the nature of the test */
+    void initStoreStrategy() throws IgniteCheckedException {
+        if (storeStgy == null)
+            storeStgy = isMultiJvm() ? new H2CacheStoreStrategy() : new MapCacheStoreStrategy();
+    }
+
     /**
      * Starts caches dynamically.
      *
@@ -189,7 +193,7 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
             }
         }
 
-        map.clear();
+        storeStgy.resetStore();
 
         super.afterTestsStopped();
     }
@@ -313,7 +317,7 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
         if (cacheIsNotEmptyMsg == null)
             assertEquals("Cache is not empty", 0, jcache().localSize(CachePeekMode.ALL));
 
-        resetStore();
+        storeStgy.resetStore();
 
         // Restore cache if current cache has garbage.
         if (cacheIsNotEmptyMsg != null) {
@@ -351,13 +355,6 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
     }
 
     /**
-     * Cleans up cache store.
-     */
-    protected void resetStore() {
-        map.clear();
-    }
-
-    /**
      * Put entry to cache store.
      *
      * @param key Key.
@@ -367,7 +364,7 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
         if (!storeEnabled())
             throw new IllegalStateException("Failed to put to store because store is disabled.");
 
-        map.put(key, val);
+        storeStgy.putToStore(key, val);
     }
 
     /**
@@ -432,31 +429,6 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
     }
 
     /**
-     * @return Write through storage emulator.
-     */
-    public static CacheStore<?, ?> cacheStore() {
-        return new CacheStoreAdapter<Object, Object>() {
-            @Override public void loadCache(IgniteBiInClosure<Object, Object> clo,
-                Object... args) {
-                for (Map.Entry<Object, Object> e : map.entrySet())
-                    clo.apply(e.getKey(), e.getValue());
-            }
-
-            @Override public Object load(Object key) {
-                return map.get(key);
-            }
-
-            @Override public void write(Cache.Entry<? extends Object, ? extends Object> e) {
-                map.put(e.getKey(), e.getValue());
-            }
-
-            @Override public void delete(Object key) {
-                map.remove(key);
-            }
-        };
-    }
-
-    /**
      * @return {@code true} if near cache should be enabled.
      */
     protected boolean nearEnabled() {
@@ -572,13 +544,4 @@ public abstract class IgniteCacheConfigVariationsAbstractTest extends IgniteConf
     protected static boolean containsKey(IgniteCache cache, Object key) throws Exception {
         return offheapTiered(cache) ? cache.localPeek(key, CachePeekMode.OFFHEAP) != null : cache.containsKey(key);
     }
-
-    /**
-     * Serializable factory.
-     */
-    public static class TestStoreFactory implements Factory<CacheStore> {
-        @Override public CacheStore create() {
-            return cacheStore();
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/2f78346e/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryIndexSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryIndexSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryIndexSelfTest.java
index d834eb3..73b665e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryIndexSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryIndexSelfTest.java
@@ -74,7 +74,7 @@ public class IgniteCacheQueryIndexSelfTest extends GridCacheAbstractSelfTest {
      */
     public void testWithStoreLoad() throws Exception {
         for (int i = 0; i < ENTRY_CNT; i++)
-            putToStore(i, new CacheValue(i));
+            storeStgy.putToStore(i, new CacheValue(i));
 
         IgniteCache<Integer, CacheValue> cache0 = grid(0).cache(null);
 


[14/46] ignite git commit: IgniteDataStreamer: fixed JavaDoc (cherry picked from commit 2537e0f)

Posted by sb...@apache.org.
IgniteDataStreamer: fixed JavaDoc
(cherry picked from commit 2537e0f)


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

Branch: refs/heads/ignite-1232
Commit: 2b5067b528bf6442450b0c16d0bfb1437ea41e1a
Parents: c7eed88
Author: Denis Magda <dm...@gridgain.com>
Authored: Fri Jul 15 09:35:41 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Fri Jul 15 09:37:20 2016 +0300

----------------------------------------------------------------------
 .../core/src/main/java/org/apache/ignite/IgniteDataStreamer.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/2b5067b5/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java b/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
index aa2e1fe..484fee9 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
@@ -211,7 +211,7 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * By default the timeout is disabled.
      *
      * @param timeout Timeout in milliseconds.
-     * @throws IllegalArgumentException If {@param timeout} is zero or less than {@code -1}.
+     * @throws IllegalArgumentException If timeout is zero or less than {@code -1}.
      */
     public void timeout(long timeout);
 
@@ -423,7 +423,7 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @param cancel {@code True} to cancel ongoing streaming operations.
      * @throws CacheException If failed to map key to node.
      * @throws IgniteInterruptedException If thread has been interrupted.
-     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded, only if {@param cancel} is {@code false}.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded, only if cancel is {@code false}.
      */
     public void close(boolean cancel) throws CacheException, IgniteInterruptedException,
         IgniteDataStreamerTimeoutException;


[29/46] ignite git commit: IGNITE-2527: IndexOutOfBoundsException in scheduler future. Reviewed and merged by Denis Magda (dmagda@gridgain.com).

Posted by sb...@apache.org.
IGNITE-2527: IndexOutOfBoundsException in scheduler future.
Reviewed and merged by Denis Magda (dmagda@gridgain.com).


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

Branch: refs/heads/ignite-1232
Commit: 6cba20f4e772d6a7e32cd899dfb7ff48f52f6c1f
Parents: 4a2a08b
Author: Milap Wadhwa <mi...@gmail.com>
Authored: Tue Jul 19 13:05:21 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Tue Jul 19 13:05:21 2016 +0300

----------------------------------------------------------------------
 .../ignite/scheduler/SchedulerFuture.java       |  5 ++--
 .../processors/schedule/ScheduleFutureImpl.java |  7 ++++-
 .../schedule/GridScheduleSelfTest.java          | 27 ++++++++++++++++++--
 3 files changed, 34 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/6cba20f4/modules/core/src/main/java/org/apache/ignite/scheduler/SchedulerFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/scheduler/SchedulerFuture.java b/modules/core/src/main/java/org/apache/ignite/scheduler/SchedulerFuture.java
index 4dcefc6..df4a3d1 100644
--- a/modules/core/src/main/java/org/apache/ignite/scheduler/SchedulerFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/scheduler/SchedulerFuture.java
@@ -94,7 +94,8 @@ public interface SchedulerFuture<R> extends IgniteFuture<R> {
      *
      * @param cnt Array length.
      * @param start Start timestamp.
-     * @return Array of the next execution times in milliseconds.
+     * @return Array of the next execution times in milliseconds or an empty array if there is no next execution time
+     *         scheduled.
      * @throws IgniteException Thrown in case of any errors.
      */
     public long[] nextExecutionTimes(int cnt, long start) throws IgniteException;
@@ -116,7 +117,7 @@ public interface SchedulerFuture<R> extends IgniteFuture<R> {
     /**
      * Gets next execution time of scheduled task.
      *
-     * @return Next execution time in milliseconds.
+     * @return Next execution time in milliseconds or {@code 0} if there is no next execution time.
      * @throws IgniteException Thrown in case of any errors.
      */
     public long nextExecutionTime() throws IgniteException;

http://git-wip-us.apache.org/repos/asf/ignite/blob/6cba20f4/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
----------------------------------------------------------------------
diff --git a/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java b/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
index 5a86019..ac23a79 100644
--- a/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
+++ b/modules/schedule/src/main/java/org/apache/ignite/internal/processors/schedule/ScheduleFutureImpl.java
@@ -60,6 +60,9 @@ class ScheduleFutureImpl<R> implements SchedulerFuture<R> {
     /** Empty time array. */
     private static final long[] EMPTY_TIMES = new long[] {};
 
+    /** No next execution time constant. **/
+    private static final long NO_NEXT_EXECUTION_TIME = 0;
+
     /** Identifier generated by cron scheduler. */
     private volatile String id;
 
@@ -450,7 +453,9 @@ class ScheduleFutureImpl<R> implements SchedulerFuture<R> {
 
     /** {@inheritDoc} */
     @Override public long nextExecutionTime() {
-        return nextExecutionTimes(1, U.currentTimeMillis())[0];
+        long[] execTimes = nextExecutionTimes(1, U.currentTimeMillis());
+
+        return execTimes == EMPTY_TIMES ? NO_NEXT_EXECUTION_TIME : execTimes[0];
     }
 
     /** {@inheritDoc} */

http://git-wip-us.apache.org/repos/asf/ignite/blob/6cba20f4/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java b/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
index dec2103..b2463b4 100644
--- a/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
+++ b/modules/schedule/src/test/java/org/apache/ignite/internal/processors/schedule/GridScheduleSelfTest.java
@@ -333,8 +333,30 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
     }
 
     /**
-     * Waits until method {@link org.apache.ignite.scheduler.SchedulerFuture#last()} returns not a null value. Tries to call specified number
-     * of attempts with 100ms interval between them.
+     * @throws Exception If failed.
+     */
+    public void testNoNextExecutionTime() throws Exception {
+        SchedulerFuture<Integer> future = grid(0).scheduler().scheduleLocal(() -> 1, "{55} 53 3/5 * * *");
+
+        try {
+            future.get();
+
+            fail("Accepted wrong cron expression");
+        }
+        catch (IgniteException e) {
+            assertTrue(e.getMessage().startsWith("Invalid cron expression in schedule pattern"));
+        }
+
+        assertTrue(future.isDone());
+
+        assertEquals(0, future.nextExecutionTime());
+
+        assertEquals(0, future.nextExecutionTimes(2, System.currentTimeMillis()).length);
+    }
+
+    /**
+     * Waits until method {@link org.apache.ignite.scheduler.SchedulerFuture#last()} returns not a null value. Tries to
+     * call specified number of attempts with 100ms interval between them.
      *
      * @param fut Schedule future to call method on.
      * @param attempts Max number of attempts to try.
@@ -383,6 +405,7 @@ public class GridScheduleSelfTest extends GridCommonAbstractTest {
             execCntr.incrementAndGet();
         }
     }
+
     /**
      * Test callable job.
      */


[05/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/eslint.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/eslint.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/eslint.js
deleted file mode 100644
index 2d60037..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/eslint.js
+++ /dev/null
@@ -1,46 +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.
- */
-
-import gulp from 'gulp';
-import cache from 'gulp-cached';
-import eslint from 'gulp-eslint';
-import sequence from 'gulp-sequence';
-
-const paths = [
-    './app/**/*.js',
-    './controllers/**/*.js',
-    './generator/**/*.js',
-    './ignite_modules_temp/**/*.js',
-    './gulpfile.babel.js/**/*.js',
-    './gulpfile.babel.js/*.js'
-];
-
-gulp.task('eslint:node', () =>
-	gulp.src('./serve/**/*.js')
-        .pipe(cache('eslint:node'))
-		.pipe(eslint({envs: ['node']}))
-		.pipe(eslint.format())
-);
-
-gulp.task('eslint:browser', () =>
-	gulp.src(paths)
-        .pipe(cache('eslint:browser'))
-		.pipe(eslint({envs: ['browser']}))
-		.pipe(eslint.format())
-);
-
-gulp.task('eslint', (cb) => sequence('eslint:browser', 'eslint:node', cb));

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/ignite-modules.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/ignite-modules.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/ignite-modules.js
index b1b1190..b97de7c 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/ignite-modules.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/ignite-modules.js
@@ -19,8 +19,7 @@ import gulp from 'gulp';
 import inject from 'gulp-inject';
 import clean from 'gulp-rimraf';
 import sequence from 'gulp-sequence';
-
-import { appModulePaths, igniteModulesTemp } from '../paths';
+import {appModulePaths, igniteModulesTemp} from '../paths';
 
 gulp.task('ignite:modules', (cb) => sequence('ignite:modules:copy', 'ignite:modules:inject', cb));
 
@@ -37,7 +36,7 @@ gulp.task('ignite:modules:inject', () =>
             transform: (filePath) => {
                 const igniteModuleName = filePath.replace(/.*ignite_modules_temp\/([^\/]+).*/mgi, '$1');
 
-                // return file contents as string
+                // Return file contents as string.
                 return `import './${igniteModuleName}/main';`;
             }
         }))
@@ -47,10 +46,10 @@ gulp.task('ignite:modules:inject', () =>
             transform: (filePath, file, i) => {
                 const igniteModuleName = filePath.replace(/.*ignite_modules_temp\/([^\/]+).*/mgi, '$1');
 
-                // return file contents as string
+                // Return file contents as string.
                 return (i ? ',' : '') + `'ignite-console.${igniteModuleName}'`;
             }
         }))
-        .pipe(clean({ force: true }))
+        .pipe(clean({force: true}))
         .pipe(gulp.dest(igniteModulesTemp))
 );

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/sass.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/sass.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/sass.js
deleted file mode 100644
index 13dc502..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/sass.js
+++ /dev/null
@@ -1,25 +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.
- */
-
-import gulp from 'gulp';
-import sass from 'gulp-sass';
-
-gulp.task('sass', () =>
-    gulp.src('./public/stylesheets/style.scss')
-        .pipe(sass({ outputStyle: 'nested' }).on('error', sass.logError))
-        .pipe(gulp.dest('./public/stylesheets'))
-);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/watch.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/watch.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/watch.js
index 8666999..c179f9c 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/watch.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/watch.js
@@ -18,22 +18,14 @@
 import gulp from 'gulp';
 import sequence from 'gulp-sequence';
 
-import { sassPaths, jadePaths, jadeModulePaths, resourcePaths, resourceModulePaths, appPaths, appModulePaths } from '../paths';
+import { jadePaths, jadeModulePaths, resourcePaths, resourceModulePaths, appModulePaths } from '../paths';
 
-gulp.task('watch:sass', (cb) => sequence('sass', 'bundle:ignite:app', cb));
-
-gulp.task('watch:ignite-modules', (cb) => sequence('clean:ignite-modules-temp', 'ignite:modules', ['eslint:browser', 'copy:ignite_modules:js', 'bundle:ignite:app'], cb));
-
-// Build + connect + watch task.
-gulp.task('watch', ['build', 'connect'], () => {
-    gulp.watch(sassPaths, ['watch:sass']);
+gulp.task('watch:ignite-modules', (cb) => sequence('clean:ignite-modules-temp', 'ignite:modules', cb));
 
+// Build + watch task.
+gulp.task('watch', ['build'], () => {
     gulp.watch(jadePaths.concat(jadeModulePaths), ['jade']);
-
-    gulp.watch(resourcePaths, ['copy:resource']);
-    gulp.watch(resourceModulePaths, ['copy:ignite_modules:resource']);
-
-    gulp.watch(appPaths, ['eslint:browser', 'copy:js', 'bundle:ignite:app']);
+    gulp.watch(resourcePaths, ['copy:resource:app']);
+    gulp.watch(resourceModulePaths, ['copy:resource:ignite_modules']);
     gulp.watch(appModulePaths, ['watch:ignite-modules']);
 });
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js
new file mode 100644
index 0000000..237f2e7
--- /dev/null
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/common.js
@@ -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.
+ */
+
+import path from 'path';
+import fs from 'fs';
+import webpack from 'webpack';
+import autoprefixer from 'autoprefixer-core';
+import jade from 'jade';
+import progressPlugin from './plugins/progress';
+import eslintFormatter from 'eslint-friendly-formatter';
+
+import ExtractTextPlugin from 'extract-text-webpack-plugin';
+import HtmlWebpackPlugin from 'html-webpack-plugin';
+
+import {srcDir, destDir, rootDir} from '../paths';
+
+const NODE_ENV = process.env.NODE_ENV || 'production';
+const development = NODE_ENV === 'development';
+const node_modules_path = path.resolve('node_modules');
+const cssLoader = 'css-loader?sourceMap!postcss-loader';
+const stylesLoader = cssLoader + '!sass-loader?outputStyle=expanded&sourceMap=true&sourceMapContents=true';
+
+let favicon;
+
+try {
+    fs.accessSync('build/ignite_modules/favicon.ico', fs.F_OK);
+
+    favicon = 'build/ignite_modules/favicon.ico';
+} catch (ignore) {
+    favicon = 'build/favicon.ico';
+}
+
+export default () => {
+    return {
+        node: {
+            fs: 'empty'
+        },
+
+        // Entry points.
+        entry: {
+            polyfill: 'babel-polyfill',
+            app: path.join(srcDir, 'app.js'),
+            vendor: path.join(srcDir, 'vendor.js')
+        },
+
+        // Output system.
+        output: {
+            path: destDir,
+            publicPath: './',
+            filename: '[name].js'
+        },
+
+        // Resolves modules.
+        resolve: {
+            extensions: [
+                '',
+                '.js'
+            ],
+            root: [rootDir],
+            modulesDirectories: [
+                node_modules_path,
+                './'
+            ]
+        },
+
+        // Modules resolvers.
+        /* global require */
+        module: {
+            noParse: [],
+            preLoaders: [
+                {
+                    test: /\.js$/,
+                    exclude: [node_modules_path],
+                    loader: 'eslint-loader'
+                }
+            ],
+            loaders: [
+                {
+                    test: /\.json$/,
+                    loader: 'json-loader'
+                },
+                {
+                    test: /\.jade$/,
+                    loaders: [
+                        `ngtemplate-loader?relativeTo=${rootDir}`,
+                        'html-loader?attrs[]=img:src&attrs[]=img:data-src',
+                        'jade-html-loader'
+                    ]
+                },
+                {
+                    test: /\.js$/,
+                    exclude: [node_modules_path],
+                    loaders: ['ng-annotate-loader']
+                },
+                {
+                    test: /\.js$/,
+                    exclude: [node_modules_path],
+                    loader: 'babel-loader',
+                    query: {
+                        cacheDirectory: true,
+                        plugins: ['transform-runtime',
+                            'add-module-exports'],
+                        presets: ['angular']
+
+                    }
+                },
+                {
+                    test: /\.css$/,
+                    loader: development ? `style-loader!${cssLoader}` : ExtractTextPlugin.extract('style-loader', cssLoader)
+                },
+                {
+                    test: /\.(scss|sass)$/,
+                    loader: development ? `style-loader!${stylesLoader}` : ExtractTextPlugin.extract('style-loader', stylesLoader)
+                },
+                {
+                    test: /\.(woff2|woff|ttf|eot|svg)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
+                    loaders: [
+                        'file-loader?name=assets/fonts/[name].[ext]'
+                    ]
+                },
+                {
+                    test: /\.(jpe?g|png|gif)$/i,
+                    loaders: ['file-loader?name=assets/images/[name]_[hash].[ext]']
+                },
+                {
+                    test: require.resolve('jquery'),
+                    loaders: [
+                        'expose-loader?$',
+                        'expose-loader?jQuery'
+                    ]
+                },
+                {
+                    test: require.resolve('nvd3'),
+                    loaders: [
+                        'expose-loader?nv'
+                    ]
+                }
+            ]
+        },
+
+        // Postcss configuration.
+        postcss: [autoprefixer({browsers: ['last 2 versions']})],
+
+        // ESLint loader configuration.
+        eslint: {
+            failOnWarning: false,
+            failOnError: false,
+            formatter: eslintFormatter
+        },
+
+        // Load plugins.
+        plugins: [
+            new webpack.ProvidePlugin({
+                $: 'jquery',
+                jQuery: 'jquery',
+                _: 'lodash',
+                nv: 'nvd3'
+            }),
+            new webpack.DefinePlugin({NODE_ENV: JSON.stringify(NODE_ENV)}),
+            // new webpack.NoErrorsPlugin(),
+            new webpack.optimize.DedupePlugin(),
+            new webpack.optimize.CommonsChunkPlugin({
+                name: 'common',
+                chunks: ['vendor', 'app']
+            }),
+            new webpack.optimize.AggressiveMergingPlugin({moveToParents: true}),
+            new ExtractTextPlugin('assets/css/[name]' + (development ? '' : '.[chunkhash]') + '.css', {allChunks: true}),
+            new HtmlWebpackPlugin({
+                filename: 'index.html',
+                templateContent: () => {
+                    return jade.renderFile(path.join(rootDir, 'views', 'index.jade'));
+                },
+                favicon
+            }),
+            progressPlugin
+        ]
+    };
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/development.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/development.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/development.js
new file mode 100644
index 0000000..aad4b37
--- /dev/null
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/development.js
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+import webpack from 'webpack';
+import {destDir, rootDir} from '../../paths';
+
+export default () => {
+    const plugins = [
+        new webpack.HotModuleReplacementPlugin()
+    ];
+
+    return {
+        context: rootDir,
+        debug: true,
+        devtool: 'source-map',
+        watch: true,
+        devServer: {
+            historyApiFallback: true,
+            publicPath: '/',
+            contentBase: destDir,
+            info: true,
+            hot: true,
+            inline: true,
+            proxy: {
+                '/socket.io': {
+                    target: 'http://localhost:3000',
+                    changeOrigin: true,
+                    ws: true
+                },
+                '/api/v1/*': {
+                    target: 'http://localhost:3000',
+                    changeOrigin: true,
+                    rewrite: (req) => {
+                        req.url = req.url.replace(/^\/api\/v1/, '');
+
+                        return req;
+                    }
+                }
+            },
+            watchOptions: {
+                aggregateTimeout: 1000,
+                poll: 1000
+            },
+            stats: {colors: true},
+            port: 9000
+        },
+        stats: {colors: true},
+        plugins
+    };
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js
new file mode 100644
index 0000000..db66720
--- /dev/null
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/environments/production.js
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+import webpack from 'webpack';
+
+import {destDir, rootDir} from '../../paths';
+
+export default () => {
+    const plugins = [
+        new webpack.optimize.UglifyJsPlugin({
+            path: destDir,
+            minimize: true,
+            warnings: false,
+            sourceMap: false,
+            mangle: true
+        })
+    ];
+
+    return {
+        context: rootDir,
+        bail: true, // Cancel build on error.
+        debug: false,
+        devtool: 'cheap-source-map',
+        output: {
+            publicPath: '/',
+            filename: '[name].[chunkhash].js',
+            path: destDir
+        },
+        plugins
+    };
+};

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js
new file mode 100644
index 0000000..6682f9c
--- /dev/null
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/index.js
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import _ from 'lodash';
+import commonConfig from './common';
+import devConfig from './environments/development';
+import prodConfig from './environments/production';
+
+const env = process.env.NODE_ENV || 'production';
+
+// Config by environments.
+const configs = {
+    production: prodConfig,
+    development: devConfig
+};
+
+// Load config file by environment
+export default _.merge(commonConfig(), configs[env]());

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js
new file mode 100644
index 0000000..5f753c7
--- /dev/null
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/webpack/plugins/progress.js
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+import ProgressPlugin from 'webpack/lib/ProgressPlugin';
+
+let chars = 0;
+let lastState = 0;
+let lastStateTime = 0;
+
+const outputStream = process.stdout;
+
+const _goToLineStart = (nextMessage) => {
+    let str = '';
+
+    for (; chars > nextMessage.length; chars--)
+        str += '\b \b';
+
+    chars = nextMessage.length;
+
+    for (let i = 0; i < chars; i++)
+        str += '\b';
+
+    if (str)
+        outputStream.write(str);
+};
+
+export default new ProgressPlugin((percentage, msg) => {
+    let state = msg;
+
+    if (percentage < 1) {
+        percentage = Math.floor(percentage * 100);
+
+        msg = percentage + '% ' + msg;
+
+        if (percentage < 100)
+            msg = ' ' + msg;
+
+        if (percentage < 10)
+            msg = ' ' + msg;
+    }
+
+    state = state.replace(/^\d+\/\d+\s+/, '');
+
+    if (percentage === 0) {
+        lastState = null;
+        lastStateTime = (new Date()).getTime();
+    }
+    else if (state !== lastState || percentage === 1) {
+        const now = (new Date()).getTime();
+
+        if (lastState) {
+            const stateMsg = (now - lastStateTime) + 'ms ' + lastState;
+
+            _goToLineStart(stateMsg);
+
+            outputStream.write(stateMsg + '\n');
+
+            chars = 0;
+        }
+
+        lastState = state;
+        lastStateTime = now;
+    }
+
+    _goToLineStart(msg);
+
+    outputStream.write(msg);
+});

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/package.json
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/package.json b/modules/web-console/src/main/js/package.json
index 776ebdc..b2c648d 100644
--- a/modules/web-console/src/main/js/package.json
+++ b/modules/web-console/src/main/js/package.json
@@ -4,8 +4,9 @@
   "description": "Interactive Web console for configuration, executing SQL queries and monitoring of Apache Ignite Cluster",
   "private": true,
   "scripts": {
-    "start": "jspm i && gulp build --debug && node serve",
-    "eslint": "node_modules/.bin/gulp eslint"
+    "dev": "cross-env NODE_ENV=development gulp watch",
+    "build": "cross-env NODE_ENV=production gulp build",
+    "eslint": "eslint --env node --format node_modules/eslint-friendly-formatter gulpfile.babel.js/ serve/ app/ controllers/ generator/ ignite_modules/ ignite_modules_temp/"
   },
   "author": "",
   "contributors": [
@@ -18,254 +19,110 @@
   "keywords": "grid",
   "homepage": "https://ignite.apache.org/",
   "engines": {
-    "node": ">=0.12.4"
+    "npm": "^3.x.x",
+    "node": "^4.x.x"
   },
+  "os": [
+    "darwin",
+    "linux",
+    "win32"
+  ],
   "dependencies": {
-    "async": "1.5.2",
+    "angular": "^1.5.5",
+    "angular-animate": "^1.5.5",
+    "angular-aria": "^1.5.5",
+    "angular-cookies": "^1.5.5",
+    "angular-drag-and-drop-lists": "^1.4.0",
+    "angular-gridster": "^0.13.3",
+    "angular-motion": "^0.4.4",
+    "angular-nvd3": "^1.0.7",
+    "angular-retina": "^0.3.13",
+    "angular-sanitize": "^1.5.5",
+    "angular-smart-table": "^2.1.8",
+    "angular-socket-io": "^0.7.0",
+    "angular-strap": "^2.3.8",
+    "angular-touch": "^1.5.5",
+    "angular-tree-control": "^0.2.26",
+    "angular-ui-grid": "^3.1.1",
+    "angular-ui-router": "^0.3.1",
     "body-parser": "^1.15.0",
     "bootstrap-sass": "^3.3.6",
+    "brace": "^0.8.0",
     "connect-mongo": "^1.1.0",
     "cookie-parser": "~1.4.0",
-    "debug": "~2.2.0",
-    "express": "~4.13.3",
+    "es6-promise": "^3.0.2",
+    "express": "^4.14.0",
     "express-session": "^1.12.0",
+    "file-saver": "^1.3.2",
     "fire-up": "^1.0.0",
-    "jade": "~1.11.0",
-    "jszip": "^2.6.0",
+    "font-awesome": "^4.6.3",
+    "glob": "^7.0.3",
+    "jquery": "^3.0.0",
+    "jszip": "^3.0.0",
     "lodash": "^4.8.2",
     "mongoose": "^4.4.11",
     "mongoose-deep-populate": "^3.0.0",
     "nconf": "^0.8.2",
     "nodemailer": "^2.3.0",
+    "nvd3": "^1.8.3",
     "passport": "^0.3.2",
     "passport-local": "^1.0.0",
     "passport-local-mongoose": "^4.0.0",
     "passport.socketio": "^3.6.1",
+    "query-command-supported": "^1.0.0",
     "require-dir": "^0.3.0",
     "socket.io": "^1.4.5",
+    "socket.io-client": "^1.4.6",
+    "ui-router-metatags": "^1.0.3",
     "ws": "^0.8.0"
   },
   "devDependencies": {
-    "babel-core": "^6.7.2",
-    "babel-eslint": "^6.0.2",
-    "babel-preset-es2015": "^6.6.0",
-    "babel-register": "^6.7.2",
-    "gulp": "^3.9.0",
-    "gulp-cached": "^1.1.0",
-    "gulp-connect": "^3.2.2",
-    "gulp-environments": "^0.1.1",
+    "assets-webpack-plugin": "^3.2.0",
+    "autoprefixer-core": "^6.0.1",
+    "babel-core": "^6.7.6",
+    "babel-eslint": "^6.0.4",
+    "babel-loader": "^6.2.4",
+    "babel-plugin-add-module-exports": "^0.2.1",
+    "babel-plugin-transform-runtime": "^6.7.5",
+    "babel-polyfill": "^6.7.4",
+    "babel-preset-angular": "^6.0.15",
+    "babel-runtime": "^6.6.1",
+    "bootstrap-loader": "^1.0.10",
+    "cross-env": "^1.0.7",
+    "css-loader": "^0.23.0",
+    "eslint": "^2.9.0",
+    "eslint-friendly-formatter": "^2.0.5",
+    "eslint-loader": "^1.0.0",
+    "expose-loader": "^0.7.1",
+    "extract-text-webpack-plugin": "^1.0.1",
+    "file-loader": "^0.9.0",
+    "gulp": "^3.9.1",
     "gulp-eslint": "^2.0.0",
-    "gulp-html-replace": "^1.5.5",
-    "gulp-ignore": "^2.0.1",
     "gulp-inject": "^4.0.0",
     "gulp-jade": "^1.1.0",
     "gulp-rimraf": "^0.2.0",
-    "gulp-sass": "^2.1.0",
     "gulp-sequence": "^0.4.1",
     "gulp-util": "^3.0.7",
-    "http-proxy-middleware": "^0.13.0",
-    "jspm": "^0.16.32",
-    "mocha": "~2.4.5",
+    "html-loader": "^0.4.3",
+    "html-webpack-plugin": "^2.21.0",
+    "imagemin-pngquant": "^5.0.0",
+    "jade": "^1.11.0",
+    "jade-html-loader": "0.0.3",
+    "json-loader": "^0.5.4",
+    "mocha": "~2.5.3",
     "morgan": "^1.7.0",
-    "should": "^8.3.0",
-    "supertest": "^1.1.0"
-  },
-  "jspm": {
-    "directories": {
-      "packages": "build/jspm_packages"
-    },
-    "configFile": "build/system.config.js",
-    "dependencies": {
-      "ace": "github:ajaxorg/ace-builds@1.2.3",
-      "angular": "github:angular/bower-angular@^1.5.0",
-      "angular-animate": "github:angular/bower-angular-animate@^1.5.0",
-      "angular-drag-and-drop-lists": "github:marceljuenemann/angular-drag-and-drop-lists@^1.3.0",
-      "angular-gridster": "github:ManifestWebDesign/angular-gridster@^0.13.5",
-      "angular-motion": "github:mgcrea/angular-motion@^0.4.3",
-      "angular-nvd3": "github:krispo/angular-nvd3@^1.0.4",
-      "angular-retina": "github:jrief/angular-retina@0.3.8",
-      "angular-sanitize": "github:angular/bower-angular-sanitize@^1.5.0",
-      "angular-smart-table": "github:lorenzofox3/Smart-Table@^2.1.4",
-      "angular-socket-io": "github:btford/angular-socket-io@^0.7.0",
-      "angular-strap": "github:mgcrea/angular-strap@2.3.8",
-      "angular-tree-control": "github:wix/angular-tree-control@^0.2.23",
-      "angular-ui-grid": "github:angular-ui/bower-ui-grid@^3.0.7",
-      "angular-ui-router": "github:angular-ui/ui-router@^0.2.15",
-      "angular-ui-router-metatags": "github:tinusn/ui-router-metatags@^1.0.3",
-      "blob": "github:eligrey/Blob.js@master",
-      "bootstrap-carousel": "github:twbs/bootstrap@^3.3.6",
-      "css": "github:systemjs/plugin-css@^0.1.20",
-      "file-saver": "github:eligrey/FileSaver.js@master",
-      "font-awesome": "npm:font-awesome@4.5.0",
-      "jade": "github:johnsoftek/plugin-jade@^0.6.0",
-      "jquery": "github:components/jquery@^2.1.4",
-      "json": "github:systemjs/plugin-json@^0.1.0",
-      "jszip": "github:Stuk/jszip@^2.5.0",
-      "lodash": "github:lodash/lodash@^4.2.6",
-      "pdfmake": "github:bpampuch/pdfmake@^0.1.20",
-      "query-command-supported": "github:zenorocha/document.queryCommandSupported@^1.0.0",
-      "socket.io-client": "github:socketio/socket.io-client@1.4.5",
-      "text": "github:systemjs/plugin-text@^0.0.7"
-    },
-    "devDependencies": {
-      "babel": "npm:babel-core@^5.8.24",
-      "babel-runtime": "npm:babel-runtime@^5.8.24",
-      "clean-css": "npm:clean-css@^3.4.8",
-      "core-js": "npm:core-js@^1.1.4"
-    },
-    "overrides": {
-      "github:angular/bower-angular@1.5.0": {
-        "format": "global",
-        "dependencies": {
-          "jquery": "github:components/jquery@^2.1.4"
-        },
-        "shim": {
-          "angular": {
-            "deps": [
-              "jquery"
-            ]
-          }
-        }
-      },
-      "github:btford/angular-socket-io@0.7.0": {
-        "dependencies": {
-          "socket.io-client": "github:socketio/socket.io-client@1.4.5"
-        }
-      },
-      "github:socketio/socket.io-client@1.4.5": {
-        "format": "global",
-        "main": "socket.io",
-        "shim": {
-          "socket.io": {
-            "exports": "io"
-          }
-        }
-      },
-      "github:Stuk/jszip@2.5.0": {
-        "format": "global",
-        "main": "./dist/jszip"
-      },
-      "github:bpampuch/pdfmake@0.1.20": {
-        "format": "global",
-        "main": "vfs_fonts",
-        "shim": {
-          "vfs_fonts": {
-            "deps": [
-              "./pdfmake"
-            ],
-            "exports": "pdfMake"
-          }
-        }
-      },
-      "github:zenorocha/document.queryCommandSupported@1.0.0": {
-        "format": "global"
-      },
-      "github:krispo/angular-nvd3@1.0.4": {
-        "main": "dist/angular-nvd3",
-        "dependencies": {
-          "nvd3": "npm:nvd3@1.8.1",
-          "d3": "npm:d3@3.5.14"
-        },
-        "shim": {
-          "dist/angular-nvd3": {
-            "deps": [
-              "d3",
-              "nvd3",
-              "nvd3/build/nv.d3.css!"
-            ]
-          }
-        }
-      },
-      "github:components/jquery@2.1.4": {
-        "format": "global"
-      },
-      "github:ajaxorg/ace-builds@1.2.3": {
-        "format": "global",
-        "main": "theme-chrome",
-        "shim": {
-          "theme-chrome": {
-            "exports": "ace",
-            "deps": [
-              "./ace",
-              "./mode-xml",
-              "./mode-java",
-              "./mode-sql",
-              "./ext-language_tools",
-              "./mode-dockerfile"
-            ]
-          },
-          "ace": {
-            "exports": "ace"
-          },
-          "mode-xml": {
-            "deps": [
-              "./ace"
-            ]
-          },
-          "mode-java": {
-            "deps": [
-              "./ace"
-            ]
-          },
-          "mode-sql": {
-            "deps": [
-              "./ace"
-            ]
-          },
-          "ext-language_tools": {
-            "deps": [
-              "./ace"
-            ]
-          },
-          "worker-xml": {
-            "deps": [
-              "./ace"
-            ]
-          },
-          "mode-dockerfile": {
-            "deps": [
-              "./ace"
-            ]
-          }
-        }
-      },
-      "github:angular-ui/bower-ui-grid@3.0.7": {
-        "dependencies": {
-          "pdfmake": "github:bpampuch/pdfmake@^0.1.20"
-        }
-      },
-      "github:mgcrea/angular-strap@2.3.8": {
-        "directories": {
-          "lib": "dist"
-        },
-        "main": "angular-strap.tpl",
-        "dependencies": {
-          "angular": "^1",
-          "angular-animate": "github:angular/bower-angular-animate@^1.5.0",
-          "angular-motion": "github:mgcrea/angular-motion@^0.4.3",
-          "angular-sanitize": "github:angular/bower-angular-sanitize@^1.5.0"
-        },
-        "shim": {
-          "angular-strap.tpl": {
-            "deps": [
-              "./angular-strap",
-              "angular"
-            ]
-          }
-        }
-      },
-      "github:eligrey/FileSaver.js@master": {
-        "format": "global",
-        "dependencies": {
-          "blob": "github:eligrey/Blob.js@master"
-        }
-      },
-      "github:eligrey/Blob.js@master": {
-        "format": "global"
-      },
-      "github:jrief/angular-retina@0.3.8": {
-        "main": "build/angular-retina.min"
-      }
-    }
+    "ng-annotate-loader": "0.1.0",
+    "ngtemplate-loader": "^1.3.1",
+    "node-sass": "^3.4.2",
+    "postcss-loader": "^0.9.1",
+    "resolve-url-loader": "^1.4.3",
+    "sass-loader": "^3.1.1",
+    "should": "^9.0.2",
+    "style-loader": "^0.13.1",
+    "supertest": "^1.1.0",
+    "url": "^0.11.0",
+    "url-loader": "^0.5.6",
+    "webpack": "^1.13.1",
+    "webpack-dev-server": "^1.14.1"
   }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/public/stylesheets/_font-awesome-custom.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/public/stylesheets/_font-awesome-custom.scss b/modules/web-console/src/main/js/public/stylesheets/_font-awesome-custom.scss
index 6ce9550..514acc2 100644
--- a/modules/web-console/src/main/js/public/stylesheets/_font-awesome-custom.scss
+++ b/modules/web-console/src/main/js/public/stylesheets/_font-awesome-custom.scss
@@ -15,17 +15,18 @@
  * limitations under the License.
  */
 
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/variables";
-$fa-font-path: "/jspm_packages/npm/font-awesome@4.5.0/fonts";
+@import '~font-awesome/scss/variables';
 
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/mixins";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/path";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/core";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/larger";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/fixed-width";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/list";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/bordered-pulled";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/animated";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/rotated-flipped";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/stacked";
-@import "../../build/jspm_packages/npm/font-awesome@4.5.0/scss/icons";
+$fa-font-path: 'https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/fonts';
+
+@import '~font-awesome/scss/mixins';
+@import '~font-awesome/scss/path';
+@import '~font-awesome/scss/core';
+@import '~font-awesome/scss/larger';
+@import '~font-awesome/scss/fixed-width';
+@import '~font-awesome/scss/list';
+@import '~font-awesome/scss/bordered-pulled';
+@import '~font-awesome/scss/animated';
+@import '~font-awesome/scss/rotated-flipped';
+@import '~font-awesome/scss/stacked';
+@import '~font-awesome/scss/icons';

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/public/stylesheets/style.scss b/modules/web-console/src/main/js/public/stylesheets/style.scss
index 2c047ac..9f35637 100644
--- a/modules/web-console/src/main/js/public/stylesheets/style.scss
+++ b/modules/web-console/src/main/js/public/stylesheets/style.scss
@@ -15,9 +15,8 @@
  * limitations under the License.
  */
 
-@import "font-awesome-custom";
-@import "bootstrap-custom";
-
+@import "./font-awesome-custom";
+@import "./bootstrap-custom";
 @import "./variables";
 
 @import "./../../app/directives/information/information.scss";
@@ -26,14 +25,14 @@
     font-family: 'Roboto Slab';
     font-style: normal;
     font-weight: 400;
-    src: local('Roboto Slab Regular'), local('RobotoSlab-Regular'), url(//fonts.gstatic.com/s/robotoslab/v6/y7lebkjgREBJK96VQi37ZiwlidHJgAgmTjOEEzwu1L8.ttf) format('truetype');
+    src: local('Roboto Slab Regular'), local('RobotoSlab-Regular'), url(https://fonts.gstatic.com/s/robotoslab/v6/y7lebkjgREBJK96VQi37ZiwlidHJgAgmTjOEEzwu1L8.ttf) format('truetype');
 }
 
 @font-face {
     font-family: 'Roboto Slab';
     font-style: normal;
     font-weight: 700;
-    src: local('Roboto Slab Bold'), local('RobotoSlab-Bold'), url(//fonts.gstatic.com/s/robotoslab/v6/dazS1PrQQuCxC3iOAJFEJTdGNerWpg2Hn6A-BxWgZ_I.ttf) format('truetype');
+    src: local('Roboto Slab Bold'), local('RobotoSlab-Bold'), url(https://fonts.gstatic.com/s/robotoslab/v6/dazS1PrQQuCxC3iOAJFEJTdGNerWpg2Hn6A-BxWgZ_I.ttf) format('truetype');
 }
 
 hr {
@@ -1927,6 +1926,7 @@ treecontrol.tree-classic {
 
     .ui-grid-cell .ui-grid-cell-contents {
         text-align: center;
+        white-space: pre;
 
         > i.fa {
             cursor: default;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/serve/agent.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/agent.js b/modules/web-console/src/main/js/serve/agent.js
index 77da925..a529e94 100644
--- a/modules/web-console/src/main/js/serve/agent.js
+++ b/modules/web-console/src/main/js/serve/agent.js
@@ -481,56 +481,57 @@ module.exports.factory = function(_, ws, fs, path, JSZip, socketio, settings, mo
 
             const jarFilter = (file) => path.extname(file) === '.jar';
 
-            for (const archive of agentArchives) {
-                const filePath = path.join(settings.agent.dists, archive);
-
-                const zip = new JSZip(fs.readFileSync(filePath));
-
-                const jarPath = _.find(_.keys(zip.files), jarFilter);
-
-                const jar = new JSZip(zip.files[jarPath].asNodeBuffer());
-
-                const manifest = jar.files['META-INF/MANIFEST.MF']
-                    .asText()
-                    .trim()
-                    .split(/\s*\n+\s*/)
-                    .map((line, r) => {
-                        r = line.split(/\s*:\s*/);
-
-                        this[r[0]] = r[1];
-
-                        return this;
-                    }, {})[0];
+            const agentsPromises = _.map(agentArchives, (fileName) => {
+                const filePath = path.join(settings.agent.dists, fileName);
+
+                return JSZip.loadAsync(fs.readFileSync(filePath))
+                    .then((zip) => {
+                        const jarPath = _.find(_.keys(zip.files), jarFilter);
+
+                        return JSZip.loadAsync(zip.files[jarPath].async('nodebuffer'))
+                            .then((jar) => jar.files['META-INF/MANIFEST.MF'].async('string'))
+                            .then((lines) => lines.trim()
+                                .split(/\s*\n+\s*/)
+                                .map((line, r) => {
+                                    r = line.split(/\s*:\s*/);
+
+                                    this[r[0]] = r[1];
+
+                                    return this;
+                                }, {})[0])
+                            .then((manifest) => {
+                                const ver = manifest['Implementation-Version'];
+                                const buildTime = manifest['Build-Time'];
+
+                                if (ver && buildTime)
+                                    return { fileName, filePath, ver, buildTime };
+                            });
+                    });
+            });
 
-                const ver = manifest['Implementation-Version'];
+            Promise.all(agentsPromises)
+                .then((agents) => {
+                    this.supportedAgents = _.keyBy(_.remove(agents, null), 'ver');
 
-                if (ver) {
-                    this.supportedAgents[ver] = {
-                        fileName: archive,
-                        filePath,
-                        buildTime: manifest['Build-Time']
-                    };
-                }
-            }
+                    const latest = _.head(Object.keys(this.supportedAgents).sort((a, b) => {
+                        const aParts = a.split('.');
+                        const bParts = b.split('.');
 
-            const latest = _.head(Object.keys(this.supportedAgents).sort((a, b) => {
-                const aParts = a.split('.');
-                const bParts = b.split('.');
+                        for (let i = 0; i < aParts.length; ++i) {
+                            if (bParts.length === i)
+                                return 1;
 
-                for (let i = 0; i < aParts.length; ++i) {
-                    if (bParts.length === i)
-                        return 1;
+                            if (aParts[i] === aParts[i])
+                                continue;
 
-                    if (aParts[i] === aParts[i])
-                        continue;
+                            return aParts[i] > bParts[i] ? 1 : -1;
+                        }
+                    }));
 
-                    return aParts[i] > bParts[i] ? 1 : -1;
-                }
-            }));
-
-            // Latest version of agent distribution.
-            if (latest)
-                this.supportedAgents.latest = this.supportedAgents[latest];
+                    // Latest version of agent distribution.
+                    if (latest)
+                        this.supportedAgents.latest = this.supportedAgents[latest];
+                });
         }
 
         attachLegacy(server) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/serve/keys/test.crt
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/keys/test.crt b/modules/web-console/src/main/js/serve/keys/test.crt
deleted file mode 100644
index 50c6d5c..0000000
--- a/modules/web-console/src/main/js/serve/keys/test.crt
+++ /dev/null
@@ -1,13 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIB6zCCAVQCCQDcAphbU6UcLjANBgkqhkiG9w0BAQsFADA6MRIwEAYDVQQDDAls
-b2NhbGhvc3QxJDAiBgkqhkiG9w0BCQEWFXNldmRva2ltb3ZAYXBhY2hlLm9yZzAe
-Fw0xNTA3MTQxMzAyNTNaFw0xODA2MjMxMzAyNTNaMDoxEjAQBgNVBAMMCWxvY2Fs
-aG9zdDEkMCIGCSqGSIb3DQEJARYVc2V2ZG9raW1vdkBhcGFjaGUub3JnMIGfMA0G
-CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDP/zpJrdHqCj6lPpeFF6LQtzKef6UiyBBo
-rbuOtCCgW8KMJJciluBWk2126qLt9smBN4jBpSNU3pq0r9gBMUTd/LSe7aY4D5ED
-Pjp7XsypNVKeHaHbFi7KhfHy0LYxsWiNPmmHJv4dtYOp+pGK25rkXNfyJxxjgxN6
-wo34+MnZIQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAFk9XEjcdyihws+fVmdGGUFo
-bVxI9YGH6agiNbU3WNF4B4VRzcPPW8z2mEo7eF9kgYmq/YzH4T8tgi/qkL/u8eZV
-Wmi9bg6RThLN6/hj3wVoOFKykbDQ05FFdhIJXN5UOjPmxYM97EKqg6J0W2HAb8SG
-+UekPnmAo/2HTKsLykH8
------END CERTIFICATE-----

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/serve/keys/test.key
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/keys/test.key b/modules/web-console/src/main/js/serve/keys/test.key
deleted file mode 100644
index 1b395c0..0000000
--- a/modules/web-console/src/main/js/serve/keys/test.key
+++ /dev/null
@@ -1,18 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,6798185330CE2EE2
-
-sOwkmD8rvjx11l09V26dJhLhl+SyPIhyeZ3TqHXrYCATKoXlzidT+uPu1jVYtrwr
-nBLA6TrIDYRrBNlEsqGZ0cSvWTIczzVW1xZKHEJo5q2vUT/W8u/Q1QQtS3P3GeKF
-dEzx496rpZqwwVw59GNbuIwyYoVvQf3iEXzfhplGmLPELYIplDFOLgNuXQyXSGx6
-rwKsCxXMLsDyrA6DCz0Odf08p2HvWk/s5Ne3DFcQlqRNtIrBVGD2O0/Fp8ZZ2I4E
-Yn2OIIWJff3HanOjLOWKdN8YAn5UleNmlEUdIHeS5qaQ68mabOxLkSef9qglV+sd
-FHTtUq0cG6t6nhxZBziexha6v1yl/xABAHHhNPOfak+HthWxRD4N9f1yFYAeTmkn
-4kwBWoSUe12XRf2pGNqhEUKN/KhDmWk85wI55i/Cu2XmNoiBFlS9BXrRYU8uVCJw
-KlxjKTDWl1opCyvxTDxJnMkt44ZT445LRePKVueGIIKSUIXNQypOE+C1I0CL0N2W
-Ts3m9nthquvLeMx92k7b8yW69BER5uac3SIlGCOJObQXsHgyk8wYiyd/zLKfjctG
-PXieaW81UKjp+GqWpvWPz3VqnKwoyUWeVOOTviurli6kYOrHuySTMqMb6hxJctw9
-grAQTT0UPiAKWcM7InLzZnRjco+v9QLLEokjVngXPba16K/CItFY16xuGlaFLW7Y
-XTc67AkL8b76HBZelMjmCsqjvSoULhuMFwTOvUMm/mSM8rMoi9asrJRLQHRMWCST
-/6RENPLzPlOMnNLBujpBbn8V3/aYzEZsHMI+6S3d27WYlTJIqpabSA==
------END RSA PRIVATE KEY-----

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/serve/routes/agent.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/serve/routes/agent.js b/modules/web-console/src/main/js/serve/routes/agent.js
index 020b692..48ec131 100644
--- a/modules/web-console/src/main/js/serve/routes/agent.js
+++ b/modules/web-console/src/main/js/serve/routes/agent.js
@@ -53,26 +53,26 @@ module.exports.factory = function(_, express, fs, JSZip, settings, agentMgr) {
                 if (errFs)
                     return res.download(agentPathZip, agentZip);
 
-                const zip = new JSZip(data);
-
-                const prop = [];
-
-                const host = req.hostname.match(/:/g) ? req.hostname.slice(0, req.hostname.indexOf(':')) : req.hostname;
+                // Set the archive name.
+                res.attachment(agentZip);
 
-                prop.push('tokens=' + req.user.token);
-                prop.push('server-uri=' + (settings.agent.SSLOptions ? 'https' : 'http') + '://' + host + ':' + settings.agent.port);
-                prop.push('#Uncomment following options if needed:');
-                prop.push('#node-uri=http://localhost:8080');
-                prop.push('#driver-folder=./jdbc-drivers');
+                JSZip.loadAsync(data)
+                    .then((zip) => {
+                        const prop = [];
 
-                zip.file(agentFld + '/default.properties', prop.join('\n'));
+                        const host = req.hostname.match(/:/g) ? req.hostname.slice(0, req.hostname.indexOf(':')) : req.hostname;
 
-                const buffer = zip.generate({type: 'nodebuffer', platform: 'UNIX'});
+                        prop.push('tokens=' + req.user.token);
+                        prop.push('server-uri=' + (settings.agent.SSLOptions ? 'https' : 'http') + '://' + host + ':' + settings.agent.port);
+                        prop.push('#Uncomment following options if needed:');
+                        prop.push('#node-uri=http://localhost:8080');
+                        prop.push('#driver-folder=./jdbc-drivers');
 
-                // Set the archive name.
-                res.attachment(agentZip);
+                        zip.file(agentFld + '/default.properties', prop.join('\n'));
 
-                res.send(buffer);
+                        zip.generateAsync({type: 'nodebuffer', platform: 'UNIX'})
+                            .then((buffer) => res.send(buffer));
+                    });
             });
         });
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/configuration/domains-import.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/domains-import.jade b/modules/web-console/src/main/js/views/configuration/domains-import.jade
index 23b9434..ccaeb27 100644
--- a/modules/web-console/src/main/js/views/configuration/domains-import.jade
+++ b/modules/web-console/src/main/js/views/configuration/domains-import.jade
@@ -83,7 +83,7 @@ mixin td-ellipses-lbl(w, lbl)
                             .col-xs-8.col-sm-10.col-md-10
                                 i.tipField.fa.fa-question-circle(bs-tooltip='' data-title='Password for connecting to database<br>Note, password would not be saved in preferences for security reasons')
                                 .input-tip
-                                    input.form-control(id='password' type='password' ng-model='selectedPreset.password' on-enter='importDomainNext()')
+                                    input.form-control(id='password' type='password' ng-model='selectedPreset.password' ignite-on-enter='importDomainNext()')
                         .settings-row
                             .checkbox
                                 label

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/configuration/domains.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/domains.jade b/modules/web-console/src/main/js/views/configuration/domains.jade
index 9975df9..7f3253e 100644
--- a/modules/web-console/src/main/js/views/configuration/domains.jade
+++ b/modules/web-console/src/main/js/views/configuration/domains.jade
@@ -30,14 +30,14 @@ include ../../app/helpers/jade/mixins.jade
                     thead
                         tr
                             th
-                                .col-sm-8
-                                    .col-sm-5
+                                .col-sm-9
+                                    .col-sm-6
                                         lable.labelHeader.labelFormField {{domainModelTitle()}}
-                                    .col-sm-7
+                                    .col-sm-6
                                         .pull-right.labelLogin.additional-filter(ng-if='(domains | domainsValidation:false:true).length > 0')
                                             a.labelFormField(ng-if='ui.showValid' ng-click='toggleValid()' bs-tooltip='' data-title='{{::ui.invalidKeyFieldsTooltip}}') Key fields should be configured: {{(displayedRows | domainsValidation:false:true).length}}&nbsp
                                             a.labelFormField(ng-if='!ui.showValid' ng-click='toggleValid()') Show all domain models: {{displayedRows.length}}&nbsp
-                                .col-sm-4
+                                .col-sm-3
                                     input.form-control.pull-right(type='text' st-search='valueType' placeholder='Filter domain models...')
                         tbody
                             tr

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/configuration/summary.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/configuration/summary.jade b/modules/web-console/src/main/js/views/configuration/summary.jade
index 830adc1..f367e67 100644
--- a/modules/web-console/src/main/js/views/configuration/summary.jade
+++ b/modules/web-console/src/main/js/views/configuration/summary.jade
@@ -88,7 +88,7 @@ mixin hard-link(ref, txt)
                                 .settings-row
                                     ignite-form-field.col-xs-8.col-sm-8.col-md-7(data-label='Near cache eviction policy')
                                         ignite-form-field-tooltip
-                                            | Cache expiration policy
+                                            | Near cache eviction policy
                                         ignite-form-field-dropdown(
                                             data-id='evictionPolicies'
                                             data-name='evictionPolicies'

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/includes/header.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/includes/header.jade b/modules/web-console/src/main/js/views/includes/header.jade
index 2b66d82..e224f64 100644
--- a/modules/web-console/src/main/js/views/includes/header.jade
+++ b/modules/web-console/src/main/js/views/includes/header.jade
@@ -23,16 +23,19 @@ header#header.header
                 ignite-header-logo
             td(ng-if='$root.user' style='padding-top: 20px')
                 ul.nav.navbar-nav(ignite-sidebar ignite-navbar)
-                    li(ng-class='{active: $state.includes("base.configuration")}')
-                        a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='sidebar.items' data-placement='bottom-right') Configuration
+                    li(ng-class='{active: $state.includes("base.configuration")}' bs-dropdown='sidebar.items' data-placement='bottom-right' data-trigger='hover focus' data-container='self' data-animation='' ng-click='$event.stopPropagation()')
+                        a.dropdown-toggle Configuration
                             span.caret
 
-                    li.sql-notebooks(ng-class='{active: $state.includes("base.sql")}' ng-controller='notebooks')
-                        a(ng-if='IgniteDemoMode' ui-sref='base.sql.demo') SQL
+                ul.nav.navbar-nav(ng-controller='notebooks')
+                    li.sql-notebooks(ng-if='IgniteDemoMode' ng-class='{active: $state.includes("base.sql")}')
+                        a(ui-sref='base.sql.demo') SQL
 
-                        a(ng-if='!IgniteDemoMode && !notebooks.length' ng-click='inputNotebookName()') SQL
+                    li.sql-notebooks(ng-if='!IgniteDemoMode && !notebooks.length' ng-class='{active: $state.includes("base.sql")}')
+                        a(ng-click='inputNotebookName()') SQL
 
-                        a.dropdown-toggle(ng-if='!IgniteDemoMode && notebooks.length' data-toggle='dropdown' bs-dropdown='notebookDropdown' data-placement='bottom-left') SQL
+                    li.sql-notebooks(ng-if='!IgniteDemoMode && notebooks.length' ng-class='{active: $state.includes("base.sql")}' bs-dropdown='notebookDropdown' data-placement='bottom-left' data-trigger='hover focus' data-container='self' data-animation='' ng-click='$event.stopPropagation()')
+                        a.dropdown-toggle SQL
                             span.caret
 
                     li(ui-sref-active='active'  ng-repeat='item in navbar.items')
@@ -43,6 +46,6 @@ header#header.header
                     button.btn.btn-info(ng-if='!IgniteDemoMode' ng-click='startDemo()') Start demo
 
                 ul.nav.navbar-nav.pull-right(ignite-userbar)
-                    li(ng-class='{active: $state.includes("settings")}')
-                        a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='userbar.items' data-placement='bottom-right') {{user.firstName}} {{user.lastName}}
+                    li(bs-dropdown='userbar.items' data-placement='bottom-right' data-trigger='hover focus' data-container='self' data-animation='' ng-class='{active: $state.includes("settings")}' ng-click='$event.stopPropagation()')
+                        a.dropdown-toggle {{user.firstName}} {{user.lastName}}
                             span.caret

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/index.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/index.jade b/modules/web-console/src/main/js/views/index.jade
index 8514533..707bfac 100644
--- a/modules/web-console/src/main/js/views/index.jade
+++ b/modules/web-console/src/main/js/views/index.jade
@@ -18,7 +18,6 @@ doctype html
 html(ng-app='ignite-console' id='app' ng-strict-di)
     head
         base(href='/')
-        link(rel='shortcut icon' href='favicon.ico')
 
         meta(http-equiv='content-type' content='text/html; charset=UTF8')
         meta(http-equiv='content-language' content='en')
@@ -30,11 +29,6 @@ html(ng-app='ignite-console' id='app' ng-strict-di)
         meta(name='keywords' content='{{$meta.keywords}}')
         meta(ng-repeat='(key, value) in $meta.properties' name='{{::key}}' content='{{::value}}')
 
-        // build:css
-        link(rel='stylesheet', href='/vendors.css')
-        link(rel='stylesheet', href='/app.css')
-        // endbuild
-
     body.theme-line.body-overlap.greedy
 
         .splash.splash-max-foreground(hide-on-state-change)
@@ -52,15 +46,3 @@ html(ng-app='ignite-console' id='app' ng-strict-di)
                 label {{IgniteDemoMode ? "Demo" : "Beta" }}
 
         .wrapper(ui-view='')
-
-
-        // build:js
-        script(src='jspm_packages/system.js')
-        script(src='system.config.js')
-        script(src='vendors.js')
-        script(src='app.js')
-        script System.import('app/index');
-        // endbuild
-
-        // ignite:plugins
-        // endignite
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/reset.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/reset.jade b/modules/web-console/src/main/js/views/reset.jade
index e5b8f12..9098105 100644
--- a/modules/web-console/src/main/js/views/reset.jade
+++ b/modules/web-console/src/main/js/views/reset.jade
@@ -37,11 +37,11 @@ header#header.header
                     .settings-row
                         label.col-sm-1.required Password:
                         .col-sm-3
-                            input#user_password.form-control(enter-focus-next='user_confirm' type='password' ng-model='reset_info.password' placeholder='New password' required)
+                            input#user_password.form-control(ignite-on-enter-focus-move='user_confirm' type='password' ng-model='reset_info.password' placeholder='New password' required)
                     .settings-row
                         label.col-sm-1.required Confirm:
                         .col-sm-3
-                            input#user_confirm.form-control(type='password' ng-model='reset_info.confirm' match='reset_info.password' placeholder='Confirm new password' required on-enter='resetForm.$valid && resetPassword(user_info)')
+                            input#user_confirm.form-control(type='password' ng-model='reset_info.confirm' ignite-match='reset_info.password' placeholder='Confirm new password' required ignite-on-enter='resetForm.$valid && resetPassword(user_info)')
                     .settings-row
                         button.btn.btn-primary(ng-disabled='resetForm.$invalid' ng-click='resetPassword(reset_info)') Reset Password
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/settings/profile.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/settings/profile.jade b/modules/web-console/src/main/js/views/settings/profile.jade
index 53991b3..bc4965a 100644
--- a/modules/web-console/src/main/js/views/settings/profile.jade
+++ b/modules/web-console/src/main/js/views/settings/profile.jade
@@ -28,23 +28,23 @@ mixin lbl(txt)
                     .details-row
                         +lbl('First name:')
                         .col-xs-5.col-sm-4
-                            input#profile-firstname.form-control(type='text' ng-model='user.firstName' placeholder='Input first name' required auto-focus)
+                            input#profile-firstname.form-control(ignite-on-enter-focus-move='profile-lastname' type='text' ng-model='user.firstName' placeholder='Input first name' required ignite-auto-focus)
                     .details-row
                         +lbl('Last name:')
                         .col-xs-5.col-sm-4
-                            input#profile-lastname.form-control(type='text' ng-model='user.lastName' placeholder='Input last name' required)
+                            input#profile-lastname.form-control(ignite-on-enter-focus-move='profile-email' type='text' ng-model='user.lastName' placeholder='Input last name' required)
                     .details-row
                         +lbl('Email:')
                         .col-xs-5.col-sm-4
-                            input#profile-email.form-control(type='email' ng-model='user.email' placeholder='Input email' required)
+                            input#profile-email.form-control(ignite-on-enter-focus-move='profile-company' type='email' ng-model='user.email' placeholder='Input email' required)
                     .details-row
                         +lbl('Company:')
                         .col-xs-5.col-sm-4
-                            input#profile-company.form-control(type='text' ng-model='user.company' placeholder='Input company name' required)
+                            input#profile-company.form-control(ignite-on-enter-focus-move='profile-country' type='text' ng-model='user.company' placeholder='Input company name' required)
                     .details-row
                         +lbl('Country:')
                         .col-xs-5.col-sm-4
-                            button#profile-country.select-toggle.form-control(bs-select bs-options='item.name as item.name for item in countries' type='text' ng-model='user.country' placeholder='Choose your country' required)
+                            button#profile-country.select-toggle.form-control(bs-select bs-options='item.name as item.name for item in countries' type='text' ng-model='user.country' placeholder='Choose your country' ng-required='true')
                     .details-row
                         .advanced-options
                             i.fa(
@@ -55,7 +55,7 @@ mixin lbl(txt)
                             +lbl('Security token:')
                             label {{user.token || 'No security token. Regenerate please.'}}
                             i.tipLabel.fa.fa-refresh(ng-click='generateToken()' bs-tooltip='' data-title='Generate random security token')
-                            i.tipLabel.fa.fa-clipboard(ng-click-copy='{{user.token}}' bs-tooltip='' data-title='Copy security token to clipboard')
+                            i.tipLabel.fa.fa-clipboard(ignite-copy-to-clipboard='{{user.token}}' bs-tooltip='' data-title='Copy security token to clipboard')
                             i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent')
                     .details-row
                         .advanced-options
@@ -67,10 +67,10 @@ mixin lbl(txt)
                             .details-row
                                 +lbl('New password:')
                                 .col-xs-5.col-sm-4
-                                    input.form-control(type='password' ng-model='user.password' placeholder='New password')
+                                    input#profile_password.form-control(ignite-on-enter-focus-move='profile_confirm' type='password' ng-model='user.password' placeholder='New password')
                             .details-row
                                 +lbl('Confirm:')
                                 .col-xs-5.col-sm-4
-                                    input.form-control(type='password' ng-model='user.confirm' match='user.password' placeholder='Confirm new password')
+                                    input#profile_confirm.form-control(type='password' ng-model='user.confirm' ignite-match='user.password' placeholder='Confirm new password')
                 .col-xs-12.col-sm-12.details-row
                     a.btn.btn-primary(ng-disabled='!profileCouldBeSaved()' ng-click='profileCouldBeSaved() && saveUser()' bs-tooltip='' data-title='{{saveBtnTipText()}}' data-placement='bottom' data-trigger='hover') Save

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/signin.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/signin.jade b/modules/web-console/src/main/js/views/signin.jade
index 73a07e7..a6c64a8 100644
--- a/modules/web-console/src/main/js/views/signin.jade
+++ b/modules/web-console/src/main/js/views/signin.jade
@@ -41,42 +41,42 @@ header#header.header
                             .settings-row
                                 p.col-xs-12.col-md-11(ng-show='action == "password/forgot"')
                                     | That's ok! Simply enter your email below and a reset password link will be sent to you via email. You can then follow that link and select a new password.
+                            .settings-row(ng-show='action == "signin"')
+                                +lblRequired('Email:')
+                                .col-xs-9.col-md-8
+                                    input#signin_email.form-control(ignite-on-enter-focus-move='user_password' type='email' ng-model='ui.email' placeholder='Input email' required)
+                            .settings-row(ng-show='action == "signup"')
+                                +lblRequired('Email:')
+                                .col-xs-9.col-md-8
+                                    input#signup_email.form-control(ignite-on-enter-focus-move='user_password' type='email' ng-model='ui.email' placeholder='Input email' required)
+                            .settings-row(ng-show='action != "password/forgot"')
+                                +lblRequired('Password:')
+                                .col-xs-9.col-md-8
+                                    input#user_password.form-control(ignite-on-enter-focus-move='user_confirm' type='password' ng-model='ui.password' placeholder='Password' ng-required='action != "password/forgot"' ignite-on-enter='action == "signin" && form.$valid && auth(action, ui)')
+                            .settings-row(ng-if='action == "signup"')
+                                +lblRequired('Confirm:')
+                                .col-xs-9.col-md-8
+                                    input#user_confirm.form-control(ignite-on-enter-focus-move='first_name' type='password' ng-model='ui_exclude.confirm' ignite-match='ui.password' placeholder='Confirm password' ng-required='action == "signup"')
                             .settings-row(ng-show='action == "signup"')
                                 +lblRequired('First Name:')
                                 .col-xs-9.col-md-8
-                                    input#first_name.form-control(enter-focus-next='last_name' type='text' ng-model='ui.firstName' placeholder='Input first name' ng-required='action=="signup"')
+                                    input#first_name.form-control(ignite-on-enter-focus-move='last_name' type='text' ng-model='ui.firstName' placeholder='Input first name' ng-required='action=="signup"')
                             .settings-row(ng-show='action == "signup"')
                                 +lblRequired('Last Name:')
                                 .col-xs-9.col-md-8
-                                    input#last_name.form-control(enter-focus-next='signup_email' type='text' ng-model='ui.lastName' placeholder='Input last name' ng-required='action=="signup"')
+                                    input#last_name.form-control(ignite-on-enter-focus-move='company' type='text' ng-model='ui.lastName' placeholder='Input last name' ng-required='action=="signup"')
                             .settings-row(ng-show='action == "password/forgot"')
                                 +lblRequired('Email:')
                                 .col-xs-9.col-md-8
-                                    input#forgot_email.form-control(on-enter='form.$valid && forgotPassword(ui)' type='email' ng-model='ui.email' placeholder='Input email' required)
-                            .settings-row(ng-show='action == "signin"')
-                                +lblRequired('Email:')
-                                .col-xs-9.col-md-8
-                                    input#signin_email.form-control(enter-focus-next='user_password' type='email' ng-model='ui.email' placeholder='Input email' required)
-                            .settings-row(ng-show='action == "signup"')
-                                +lblRequired('Email:')
-                                .col-xs-9.col-md-8
-                                    input#signup_email.form-control(enter-focus-next='company' type='email' ng-model='ui.email' placeholder='Input email' required)
+                                    input#forgot_email.form-control(ignite-on-enter='form.$valid && forgotPassword(ui)' type='email' ng-model='ui.email' placeholder='Input email' required)
                             .settings-row(ng-show='action == "signup"')
                                 +lblRequired('Company:')
                                 .col-xs-9.col-md-8
-                                    input#company.form-control(enter-focus-next='country' type='search' ng-model='ui.company' placeholder='Input company name' ng-required='action=="signup"')
+                                    input#company.form-control(ignite-on-enter-focus-move='country' type='text' ng-model='ui.company' placeholder='Input company name' ng-required='action=="signup"')
                             .settings-row(ng-show='action == "signup"')
                                 +lblRequired('Country:')
                                 .col-xs-9.col-md-8
-                                    button#country.select-toggle.form-control(bs-select bs-options='item.name as item.name for item in countries' enter-focus-next='user_password' type='search' ng-model='ui.country' placeholder='Choose your country' ng-required='action=="signup"')
-                            .settings-row(ng-show='action != "password/forgot"')
-                                +lblRequired('Password:')
-                                .col-xs-9.col-md-8
-                                    input#user_password.form-control(enter-focus-next='user_confirm' type='password' ng-model='ui.password' placeholder='Password' ng-required='action != "password/forgot"' on-enter='action == "signin" && form.$valid && auth(action, ui)')
-                            .settings-row(ng-if='action == "signup"')
-                                +lblRequired('Confirm:')
-                                .col-xs-9.col-md-8
-                                    input#user_confirm.form-control(type='password' ng-model='ui_exclude.confirm' match='ui.password' placeholder='Confirm password' ng-required='action == "signup"' on-enter='form.$valid && auth(action, ui)')
+                                    button#country.select-toggle.form-control(ignite-on-enter-focus-move='signup' bs-select bs-options='item.name as item.name for item in countries' type='text' ng-model='ui.country' placeholder='Choose your country' ng-required='action=="signup"')
                             .settings-row(ignite-terms)
                                 .col-md-offset-3(ng-if='action == "signup" && terms.termsState')
                                     label
@@ -84,17 +84,17 @@ header#header.header
                                         | I agree to the #[a(ui-sref='{{::terms.termsState}}' target='_blank') terms and conditions]
                         .col-xs-12.col-md-11
                             .login-footer(ng-show='action == "signup"')
-                                a.labelField(ng-click='action = "password/forgot"' on-click-focus='signin_email') Forgot password?
-                                a.labelLogin(ng-click='action = "signin"' on-click-focus='signin_email') Sign In
+                                a.labelField(ng-click='action = "password/forgot"' ignite-on-click-focus='signin_email') Forgot password?
+                                a.labelLogin(ng-click='action = "signin"' ignite-on-click-focus='signin_email') Sign In
                                 button#signup.btn.btn-primary(ng-click='auth(action, ui)' ng-disabled='form.$invalid') Sign Up
                         .col-xs-12.col-md-11
                             .login-footer(ng-show='action == "password/forgot"')
-                                a.labelField(ng-click='action = "signin"' on-click-focus='signin_email') Sign In
+                                a.labelField(ng-click='action = "signin"' ignite-on-click-focus='signin_email') Sign In
                                 button#forgot.btn.btn-primary(ng-click='forgotPassword(ui)' ng-disabled='form.$invalid') Send it to me
                         .col-xs-12.col-md-11
                             .login-footer(ng-show='action == "signin"')
-                                a.labelField(ng-click='action = "password/forgot"' on-click-focus='signin_email') Forgot password?
-                                a.labelLogin(ng-click='action = "signup"' on-click-focus='first_name') Sign Up
+                                a.labelField(ng-click='action = "password/forgot"' ignite-on-click-focus='signin_email') Forgot password?
+                                a.labelLogin(ng-click='action = "signup"' ignite-on-click-focus='first_name') Sign Up
                                 button#login.btn.btn-primary(ng-click='auth(action, ui)' ng-disabled='form.$invalid') Sign In
 
                     .col-xs-12.col-md-11.home-panel

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/sql/notebook-new.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/sql/notebook-new.jade b/modules/web-console/src/main/js/views/sql/notebook-new.jade
index 2a50137..51200e8 100644
--- a/modules/web-console/src/main/js/views/sql/notebook-new.jade
+++ b/modules/web-console/src/main/js/views/sql/notebook-new.jade
@@ -25,7 +25,7 @@
                     .col-sm-2
                         label.required.labelFormField Name:&nbsp;
                     .col-sm-10
-                        input.form-control(id='create-notebook' type='text' ng-model='name' required on-enter='ui.inputForm.$valid && createNewNotebook(name)' auto-focus)
+                        input.form-control(id='create-notebook' type='text' ng-model='name' required ignite-on-enter='ui.inputForm.$valid && createNewNotebook(name)' ignite-auto-focus)
             .modal-footer
                 button.btn.btn-default(id='copy-btn-cancel' ng-click='$hide()') Cancel
                 button.btn.btn-primary(id='copy-btn-confirm' ng-disabled='ui.inputForm.$invalid' ng-click='createNewNotebook(name)') Create

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/sql/paragraph-rate.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/sql/paragraph-rate.jade b/modules/web-console/src/main/js/views/sql/paragraph-rate.jade
index f6f105f..03c6497 100644
--- a/modules/web-console/src/main/js/views/sql/paragraph-rate.jade
+++ b/modules/web-console/src/main/js/views/sql/paragraph-rate.jade
@@ -22,7 +22,7 @@
         form(name='popoverForm' novalidate)
             .form-group(style='padding: 5px')
                 .col-sm-4
-                    input.form-control(id='paragraph-rate' ng-init='value = paragraph.rate.value' ng-model='value' type='number' min='1' required auto-focus)
+                    input.form-control(id='paragraph-rate' ng-init='value = paragraph.rate.value' ng-model='value' type='number' min='1' required ignite-auto-focus)
                 .col-sm-8(style='padding-left: 5px')
                     button.form-control.select-toggle(id='paragraph-unit' ng-init='unit = paragraph.rate.unit' ng-model='unit' required placeholder='Time unit' bs-select bs-options='item.value as item.label for item in timeUnit' data-container='false' tabindex='0')
             .form-actions(style='margin-top: 30px; padding: 5px')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/sql/sql.jade b/modules/web-console/src/main/js/views/sql/sql.jade
index be6d85e..a5e7fae 100644
--- a/modules/web-console/src/main/js/views/sql/sql.jade
+++ b/modules/web-console/src/main/js/views/sql/sql.jade
@@ -15,7 +15,7 @@
     limitations under the License.
 
 mixin btn-toolbar(btn, click, tip, focusId)
-    i.btn.btn-default.fa(class=btn ng-click=click bs-tooltip='' data-title=tip on-click-focus=focusId data-trigger='hover' data-placement='bottom')
+    i.btn.btn-default.fa(class=btn ng-click=click bs-tooltip='' data-title=tip ignite-on-click-focus=focusId data-trigger='hover' data-placement='bottom')
 
 mixin btn-toolbar-data(btn, kind, tip)
     i.btn.btn-default.fa(class=btn ng-click='setResult(paragraph, "#{kind}")' ng-class='{active: resultEq(paragraph, "#{kind}")}' bs-tooltip='' data-title=tip data-trigger='hover' data-placement='bottom')
@@ -52,7 +52,7 @@ mixin notebook-rename
         h1.col-sm-6(ng-show='notebook.edit')
             i.btn.fa.fa-floppy-o(ng-show='notebook.editName' ng-click='renameNotebook(notebook.editName)' bs-tooltip data-title='Save notebook name' data-trigger='hover')
             .input-tip
-                input.form-control(ng-model='notebook.editName' required on-enter='renameNotebook(notebook.editName)' on-escape='notebook.edit = false;')
+                input.form-control(ng-model='notebook.editName' required ignite-on-enter='renameNotebook(notebook.editName)' ignite-on-escape='notebook.edit = false;')
         h1.pull-right
             a.dropdown-toggle(data-toggle='dropdown' bs-dropdown='scrollParagraphs' data-placement='bottom-right') Scroll to query
                 span.caret
@@ -80,7 +80,7 @@ mixin paragraph-rename
         i.tipLabel.fa(style='float: left;' ng-class='paragraphExpanded(paragraph) ? "fa-chevron-circle-down" : "fa-chevron-circle-right"')
         i.tipLabel.fa.fa-floppy-o(style='float: right;' ng-show='paragraph.editName' ng-click='renameParagraph(paragraph, paragraph.editName); $event.stopPropagation();' bs-tooltip data-title='Save query name' data-trigger='hover')
         .input-tip
-            input.form-control(id='paragraph-name-{{paragraph.id}}' ng-model='paragraph.editName' required ng-click='$event.stopPropagation();' on-enter='renameParagraph(paragraph, paragraph.editName)' on-escape='paragraph.edit = false')
+            input.form-control(id='paragraph-name-{{paragraph.id}}' ng-model='paragraph.editName' required ng-click='$event.stopPropagation();' ignite-on-enter='renameParagraph(paragraph, paragraph.editName)' ignite-on-escape='paragraph.edit = false')
 
 mixin query-controls
     .sql-controls

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/templates/agent-download.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/templates/agent-download.jade b/modules/web-console/src/main/js/views/templates/agent-download.jade
index f17dac8..864694b 100644
--- a/modules/web-console/src/main/js/views/templates/agent-download.jade
+++ b/modules/web-console/src/main/js/views/templates/agent-download.jade
@@ -33,7 +33,7 @@
                     a(ng-click='agentLoad.showToken = ! agentLoad.showToken') {{agentLoad.showToken ? 'Hide security token...' : 'Show security token...'}}
                 .details-row(ng-show='agentLoad.showToken')
                     label.labelField Security token: {{user.token}}
-                    i.tipLabel.fa.fa-clipboard(ng-click-copy='{{user.token}}' bs-tooltip='' data-title='Copy security token to clipboard')
+                    i.tipLabel.fa.fa-clipboard(ignite-copy-to-clipboard='{{user.token}}' bs-tooltip='' data-title='Copy security token to clipboard')
                     i.tipLabel.fa.fa-question-circle(ng-if=lines bs-tooltip='' data-title='The security token is used for authorization of web agent')
             .agent-download(ng-if='hasAgents')
                 p Connection to Ignite Web Agent is established, but agent failed to connect to Ignite Node

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/views/templates/clone.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/views/templates/clone.jade b/modules/web-console/src/main/js/views/templates/clone.jade
index c94c534..25e99e7 100644
--- a/modules/web-console/src/main/js/views/templates/clone.jade
+++ b/modules/web-console/src/main/js/views/templates/clone.jade
@@ -25,7 +25,7 @@
                     .col-sm-2
                         label.required.labelFormField New name:&nbsp;
                     .col-sm-10
-                        input.form-control(id='copy-new-name' type='text' ng-model='newName' on-enter='form.$valid && ok(newName)' required auto-focus)
+                        input.form-control(id='copy-new-name' type='text' ng-model='newName' ignite-on-enter='form.$valid && ok(newName)' required ignite-auto-focus)
             .modal-footer
                 button.btn.btn-default(id='copy-btn-cancel' ng-click='$hide()') Cancel
                 button.btn.btn-primary(id='copy-btn-confirm' ng-disabled='ui.inputForm.$invalid' ng-click='ok(newName)') Confirm

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 9fbc78d..e4a6f84 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -874,13 +874,13 @@
                                         <exclude>**/*.ps1</exclude>
                                         <exclude>**/*.json</exclude>
                                         <!--web console-->
-                                        <exclude>**/src/main/js/*.babelrc</exclude>
-                                        <exclude>**/src/main/js/*.eslintrc</exclude>
-                                        <exclude>**/src/main/js/*.npmrc</exclude>
+                                        <exclude>**/src/main/js/.babelrc</exclude>
+                                        <exclude>**/src/main/js/.eslintrc</exclude>
                                         <exclude>**/src/main/js/build/**</exclude>
                                         <exclude>**/src/main/js/node_modules/**</exclude>
+                                        <exclude>**/src/main/js/ignite_modules/**</exclude>
+                                        <exclude>**/src/main/js/ignite_modules_temp/**</exclude>
                                         <exclude>**/src/main/js/serve/config/settings.json.sample</exclude>
-                                        <exclude>**/src/main/js/serve/keys/test.*</exclude>
                                     </excludes>
                                 </configuration>
                             </execution>


[37/46] ignite git commit: Fixes after merge.

Posted by sb...@apache.org.
Fixes after merge.


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

Branch: refs/heads/ignite-1232
Commit: 869db21602c22a5340206016b64369d9eb3e4efa
Parents: 84fddee
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Jul 19 17:09:19 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jul 19 17:09:19 2016 +0300

----------------------------------------------------------------------
 .../processors/cache/GridCacheAdapter.java      | 46 --------------------
 1 file changed, 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/869db216/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index 8bada9f..90669e0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -5709,52 +5709,6 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /**
-     * Internal callable for partition size calculation.
-     */
-    @GridInternal
-    private static class PartitionSizeLongJob extends TopologyVersionAwareJob {
-        /** */
-        private static final long serialVersionUID = 0L;
-
-        /** Partition. */
-        private final int partition;
-
-        /** Peek modes. */
-        private final CachePeekMode[] peekModes;
-
-        /**
-         * @param cacheName Cache name.
-         * @param topVer Affinity topology version.
-         * @param peekModes Cache peek modes.
-         * @param partition partition.
-         */
-        private PartitionSizeLongJob(String cacheName, AffinityTopologyVersion topVer, CachePeekMode[] peekModes, int partition) {
-            super(cacheName, topVer);
-
-            this.peekModes = peekModes;
-            this.partition = partition;
-        }
-
-        /** {@inheritDoc} */
-        @Nullable @Override public Object localExecute(@Nullable IgniteInternalCache cache) {
-            if (cache == null)
-                return 0;
-
-            try {
-                return cache.localSizeLong(partition, peekModes);
-            }
-            catch (IgniteCheckedException e) {
-                throw U.convertException(e);
-            }
-        }
-
-        /** {@inheritDoc} */
-        public String toString() {
-            return S.toString(PartitionSizeLongJob.class, this);
-        }
-    }
-
-    /**
      * Internal callable for global size calculation.
      */
     @GridInternal


[06/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/domains-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/domains-controller.js b/modules/web-console/src/main/js/controllers/domains-controller.js
index 467dc98..cfb539d 100644
--- a/modules/web-console/src/main/js/controllers/domains-controller.js
+++ b/modules/web-console/src/main/js/controllers/domains-controller.js
@@ -16,12 +16,10 @@
  */
 
 // Controller for Domain model screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('domainsController', [
-    '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', '$common', '$focus', '$confirm', '$confirmBatch', '$clone', '$loading', '$cleanup', '$unsavedChangesGuard', 'IgniteAgentMonitor', '$table',
-    function($root, $scope, $http, $state, $filter, $timeout, $modal, $common, $focus, $confirm, $confirmBatch, $clone, $loading, $cleanup, $unsavedChangesGuard, IgniteAgentMonitor, $table) {
-        $unsavedChangesGuard.install($scope);
+export default ['domainsController', [
+    '$rootScope', '$scope', '$http', '$state', '$filter', '$timeout', '$modal', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteConfirmBatch', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteAgentMonitor', 'IgniteLegacyTable',
+    function($root, $scope, $http, $state, $filter, $timeout, $modal, LegacyUtils, Messages, Focus, Confirm, ConfirmBatch, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, IgniteAgentMonitor, LegacyTable) {
+        UnsavedChangesGuard.install($scope);
 
         const emptyDomain = {empty: true};
 
@@ -32,7 +30,7 @@ consoleModule.controller('domainsController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyDomain;
 
-        $scope.ui = $common.formUI();
+        $scope.ui = LegacyUtils.formUI();
         $scope.ui.activePanels = [0, 1];
         $scope.ui.topPanels = [0, 1, 2];
 
@@ -68,14 +66,14 @@ consoleModule.controller('domainsController', [
             return !item.empty && (!item._id || _.find($scope.displayedRows, {_id: item._id}));
         };
 
-        $scope.getModel = $common.getModel;
-        $scope.javaBuiltInClasses = $common.javaBuiltInClasses;
-        $scope.compactJavaName = $common.compactJavaName;
-        $scope.widthIsSufficient = $common.widthIsSufficient;
-        $scope.saveBtnTipText = $common.saveBtnTipText;
+        $scope.getModel = LegacyUtils.getModel;
+        $scope.javaBuiltInClasses = LegacyUtils.javaBuiltInClasses;
+        $scope.compactJavaName = LegacyUtils.compactJavaName;
+        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
+        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
 
         $scope.tableSave = function(field, index, stopEdit) {
-            if ($table.tableEditing({model: 'table-index-fields'}, $table.tableEditedRowIndex())) {
+            if (LegacyTable.tableEditing({model: 'table-index-fields'}, LegacyTable.tableEditedRowIndex())) {
                 if ($scope.tableIndexItemSaveVisible(field, index))
                     return $scope.tableIndexItemSave(field, field.indexIdx, index, stopEdit);
             }
@@ -83,8 +81,8 @@ consoleModule.controller('domainsController', [
                 switch (field.type) {
                     case 'fields':
                     case 'aliases':
-                        if ($table.tablePairSaveVisible(field, index))
-                            return $table.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
+                        if (LegacyTable.tablePairSaveVisible(field, index))
+                            return LegacyTable.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
 
                         break;
 
@@ -108,37 +106,37 @@ consoleModule.controller('domainsController', [
         };
 
         $scope.tableReset = (trySave) => {
-            const field = $table.tableField();
+            const field = LegacyTable.tableField();
 
-            if (trySave && $common.isDefined(field) && !$scope.tableSave(field, $table.tableEditedRowIndex(), true))
+            if (trySave && LegacyUtils.isDefined(field) && !$scope.tableSave(field, LegacyTable.tableEditedRowIndex(), true))
                 return false;
 
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             return true;
         };
 
         $scope.tableNewItem = function(field) {
             if ($scope.tableReset(true))
-                $table.tableNewItem(field);
+                LegacyTable.tableNewItem(field);
         };
 
-        $scope.tableNewItemActive = $table.tableNewItemActive;
+        $scope.tableNewItemActive = LegacyTable.tableNewItemActive;
 
         $scope.tableStartEdit = function(item, field, index) {
             if ($scope.tableReset(true))
-                $table.tableStartEdit(item, field, index, $scope.tableSave);
+                LegacyTable.tableStartEdit(item, field, index, $scope.tableSave);
         };
 
-        $scope.tableEditing = $table.tableEditing;
+        $scope.tableEditing = LegacyTable.tableEditing;
 
         $scope.tableRemove = function(item, field, index) {
             if ($scope.tableReset(true))
-                $table.tableRemove(item, field, index);
+                LegacyTable.tableRemove(item, field, index);
         };
 
-        $scope.tablePairSave = $table.tablePairSave;
-        $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+        $scope.tablePairSave = LegacyTable.tablePairSave;
+        $scope.tablePairSaveVisible = LegacyTable.tablePairSaveVisible;
 
         $scope.queryFieldsTbl = {
             type: 'fields',
@@ -160,7 +158,7 @@ consoleModule.controller('domainsController', [
             save: $scope.tableSave
         };
 
-        $scope.queryMetadataVariants = $common.mkOptions(['Annotations', 'Configuration']);
+        $scope.queryMetadataVariants = LegacyUtils.mkOptions(['Annotations', 'Configuration']);
 
         const INFO_CONNECT_TO_DB = 'Configure connection to database';
         const INFO_SELECT_SCHEMAS = 'Select schemas to load tables from';
@@ -175,11 +173,11 @@ consoleModule.controller('domainsController', [
             'It may be a result of import tables from database without primary keys<br/>' +
             'Key field for such key types should be configured manually';
 
-        $scope.hidePopover = $common.hidePopover;
+        $scope.hidePopover = LegacyUtils.hidePopover;
 
-        const showPopoverMessage = $common.showPopoverMessage;
+        const showPopoverMessage = LegacyUtils.showPopoverMessage;
 
-        $scope.indexType = $common.mkOptions(['SORTED', 'FULLTEXT', 'GEOSPATIAL']);
+        $scope.indexType = LegacyUtils.mkOptions(['SORTED', 'FULLTEXT', 'GEOSPATIAL']);
 
         const _dbPresets = [
             {
@@ -269,8 +267,8 @@ consoleModule.controller('domainsController', [
 
                 localStorage.dbPresets = JSON.stringify(_dbPresets);
             }
-            catch (errMsg) {
-                $common.showError(errMsg);
+            catch (err) {
+                Messages.showError(err);
             }
         }
 
@@ -304,9 +302,9 @@ consoleModule.controller('domainsController', [
 
         $scope.ui.showValid = true;
 
-        $scope.supportedJdbcTypes = $common.mkOptions($common.SUPPORTED_JDBC_TYPES);
+        $scope.supportedJdbcTypes = LegacyUtils.mkOptions(LegacyUtils.SUPPORTED_JDBC_TYPES);
 
-        $scope.supportedJavaTypes = $common.mkOptions($common.javaBuiltInTypes);
+        $scope.supportedJavaTypes = LegacyUtils.mkOptions(LegacyUtils.javaBuiltInTypes);
 
         $scope.sortDirections = [
             {value: true, label: 'ASC'},
@@ -319,7 +317,7 @@ consoleModule.controller('domainsController', [
             const item = $scope.backupItem;
 
             if (item && item.keyType)
-                return $common.isJavaBuiltInClass(item.keyType);
+                return LegacyUtils.isJavaBuiltInClass(item.keyType);
 
             return false;
         };
@@ -331,7 +329,7 @@ consoleModule.controller('domainsController', [
         };
 
         $scope.selectSchema = function() {
-            if ($common.isDefined($scope.importDomain) && $common.isDefined($scope.importDomain.displayedSchemas))
+            if (LegacyUtils.isDefined($scope.importDomain) && LegacyUtils.isDefined($scope.importDomain.displayedSchemas))
                 $scope.importDomain.allSchemasSelected = $scope.importDomain.displayedSchemas.length > 0 && _.every($scope.importDomain.displayedSchemas, 'use', true);
         };
 
@@ -344,7 +342,7 @@ consoleModule.controller('domainsController', [
         };
 
         $scope.selectTable = function() {
-            if ($common.isDefined($scope.importDomain) && $common.isDefined($scope.importDomain.displayedTables))
+            if (LegacyUtils.isDefined($scope.importDomain) && LegacyUtils.isDefined($scope.importDomain.displayedTables))
                 $scope.importDomain.allTablesSelected = $scope.importDomain.displayedTables.length > 0 && _.every($scope.importDomain.displayedTables, 'use', true);
         };
 
@@ -378,9 +376,9 @@ consoleModule.controller('domainsController', [
          * Show import domain models modal.
          */
         $scope.showImportDomainModal = function() {
-            $table.tableReset();
+            LegacyTable.tableReset();
 
-            $common.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
+            LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
                 if ($scope.ui.inputForm.$dirty)
                     $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
 
@@ -412,7 +410,7 @@ consoleModule.controller('domainsController', [
                         }
 
                         // Get available JDBC drivers via agent.
-                        $loading.start('importDomainFromDb');
+                        Loading.start('importDomainFromDb');
 
                         $scope.jdbcDriverJars = [];
                         $scope.ui.selectedJdbcDriverJar = {};
@@ -436,12 +434,12 @@ consoleModule.controller('domainsController', [
 
                                     $scope.ui.selectedJdbcDriverJar = $scope.jdbcDriverJars[0].value;
 
-                                    $common.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
+                                    LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, function() {
                                         importDomainModal.$promise.then(() => {
                                             $scope.importDomain.action = 'connect';
                                             $scope.importDomain.tables = [];
 
-                                            $focus('jdbcUrl');
+                                            Focus.move('jdbcUrl');
                                         });
                                     });
                                 }
@@ -453,7 +451,7 @@ consoleModule.controller('domainsController', [
                             .finally(function() {
                                 $scope.importDomain.info = INFO_CONNECT_TO_DB;
 
-                                $loading.finish('importDomainFromDb');
+                                Loading.finish('importDomainFromDb');
                             });
                     });
             });
@@ -466,7 +464,7 @@ consoleModule.controller('domainsController', [
             IgniteAgentMonitor.awaitAgent()
                 .then(function() {
                     $scope.importDomain.loadingOptions = LOADING_SCHEMAS;
-                    $loading.start('importDomainFromDb');
+                    Loading.start('importDomainFromDb');
 
                     if ($root.IgniteDemoMode)
                         return IgniteAgentMonitor.schemas($scope.demoConnection);
@@ -489,12 +487,8 @@ consoleModule.controller('domainsController', [
 
                     $scope.importDomain.info = INFO_SELECT_SCHEMAS;
                 })
-                .catch(function(errMsg) {
-                    $common.showError(errMsg);
-                })
-                .finally(function() {
-                    $loading.finish('importDomainFromDb');
-                });
+                .catch(Messages.showError)
+                .finally(() => Loading.finish('importDomainFromDb'));
         }
 
         const DFLT_PARTITIONED_CACHE = {
@@ -594,7 +588,7 @@ consoleModule.controller('domainsController', [
             IgniteAgentMonitor.awaitAgent()
                 .then(function() {
                     $scope.importDomain.loadingOptions = LOADING_TABLES;
-                    $loading.start('importDomainFromDb');
+                    Loading.start('importDomainFromDb');
 
                     $scope.importDomain.allTablesSelected = false;
 
@@ -621,7 +615,7 @@ consoleModule.controller('domainsController', [
                         tbl.cacheOrTemplate = DFLT_PARTITIONED_CACHE.value;
                         tbl.label = tbl.schema + '.' + tbl.tbl;
                         tbl.edit = false;
-                        tbl.use = $common.isDefined(_.find(tbl.cols, function(col) {
+                        tbl.use = LegacyUtils.isDefined(_.find(tbl.cols, function(col) {
                             return col.key;
                         }));
                     });
@@ -630,12 +624,8 @@ consoleModule.controller('domainsController', [
                     $scope.importDomain.tables = tables;
                     $scope.importDomain.info = INFO_SELECT_TABLES;
                 })
-                .catch(function(errMsg) {
-                    $common.showError(errMsg);
-                })
-                .finally(function() {
-                    $loading.finish('importDomainFromDb');
-                });
+                .catch(Messages.showError)
+                .finally(() => Loading.finish('importDomainFromDb'));
         }
 
         $scope.applyDefaults = function() {
@@ -678,13 +668,13 @@ consoleModule.controller('domainsController', [
             $scope.importDomain.button = 'Save';
             $scope.importDomain.info = INFO_SELECT_OPTIONS;
 
-            $focus('domainPackageName');
+            Focus.move('domainPackageName');
         }
 
         function _saveBatch(batch) {
             if (batch && batch.length > 0) {
                 $scope.importDomain.loadingOptions = SAVING_DOMAINS;
-                $loading.start('importDomainFromDb');
+                Loading.start('importDomainFromDb');
 
                 $http.post('/api/v1/configuration/domains/save/batch', batch)
                     .success(function(savedBatch) {
@@ -717,17 +707,15 @@ consoleModule.controller('domainsController', [
 
                         $scope.selectItem(lastItem);
 
-                        $common.showInfo('Domain models imported from database.');
+                        Messages.showInfo('Domain models imported from database.');
 
                         $scope.ui.activePanels = [0, 1, 2];
 
                         $scope.ui.showValid = true;
                     })
-                    .error(function(errMsg) {
-                        $common.showError(errMsg);
-                    })
-                    .finally(function() {
-                        $loading.finish('importDomainFromDb');
+                    .error(Messages.showError)
+                    .finally(() => {
+                        Loading.finish('importDomainFromDb');
 
                         importDomainModal.hide();
                     });
@@ -737,10 +725,10 @@ consoleModule.controller('domainsController', [
         }
 
         function _saveDomainModel() {
-            if ($common.isEmptyString($scope.ui.packageName))
-                return $common.showPopoverMessage(null, null, 'domainPackageName', 'Package could not be empty');
+            if (LegacyUtils.isEmptyString($scope.ui.packageName))
+                return LegacyUtils.showPopoverMessage(null, null, 'domainPackageName', 'Package could not be empty');
 
-            if (!$common.isValidJavaClass('Package', $scope.ui.packageName, false, 'domainPackageName', true))
+            if (!LegacyUtils.isValidJavaClass('Package', $scope.ui.packageName, false, 'domainPackageName', true))
                 return false;
 
             const batch = [];
@@ -787,7 +775,7 @@ consoleModule.controller('domainsController', [
 
                     _.forEach(table.cols, function(col) {
                         const colName = col.name;
-                        const jdbcType = $common.findJdbcType(col.type);
+                        const jdbcType = LegacyUtils.findJdbcType(col.type);
                         const nullable = col.nullable;
 
                         qryFields.push(queryField(colName, jdbcType));
@@ -835,7 +823,7 @@ consoleModule.controller('domainsController', [
                         caches: []
                     };
 
-                    if ($common.isDefined(domainFound)) {
+                    if (LegacyUtils.isDefined(domainFound)) {
                         newDomain._id = domainFound._id;
                         newDomain.caches = domainFound.caches;
                         newDomain.confirm = true;
@@ -894,7 +882,11 @@ consoleModule.controller('domainsController', [
                         if (!newCache.cacheStoreFactory || newCache.cacheStoreFactory.kind !== 'CacheJdbcPojoStoreFactory') {
                             const dialect = $scope.importDomain.demo ? 'H2' : $scope.selectedPreset.db;
 
-                            newCache.cacheStoreFactory = {kind: 'CacheJdbcPojoStoreFactory', CacheJdbcPojoStoreFactory: {dataSourceBean: 'ds' + dialect, dialect}};
+                            newCache.cacheStoreFactory = {
+                                kind: 'CacheJdbcPojoStoreFactory',
+                                CacheJdbcPojoStoreFactory: {dataSourceBean: 'ds' + dialect, dialect},
+                                CacheJdbcBlobStoreFactory: { connectVia: 'DataSource' }
+                            };
                         }
 
                         if (!newCache.readThrough && !newCache.writeThrough) {
@@ -910,7 +902,7 @@ consoleModule.controller('domainsController', [
                         if (!_.includes(checkedCaches, cacheId)) {
                             const cache = _.find($scope.caches, {value: cacheId}).cache;
 
-                            const change = $common.autoCacheStoreConfiguration(cache, [newDomain]);
+                            const change = LegacyUtils.autoCacheStoreConfiguration(cache, [newDomain]);
 
                             if (change)
                                 newDomain.cacheStoreChanges = [{cacheId, change}];
@@ -941,9 +933,9 @@ consoleModule.controller('domainsController', [
 
             function checkOverwrite() {
                 if (itemsToConfirm.length > 0) {
-                    $confirmBatch.confirm(overwriteMessage, itemsToConfirm)
+                    ConfirmBatch.confirm(overwriteMessage, itemsToConfirm)
                         .then(() => _saveBatch(_.filter(batch, (item) => !item.skip)))
-                        .catch(() => $common.showError('Importing of domain models interrupted by user.'));
+                        .catch(() => Messages.showError('Importing of domain models interrupted by user.'));
                 }
                 else
                     _saveBatch(batch);
@@ -952,7 +944,7 @@ consoleModule.controller('domainsController', [
             if (containKey)
                 checkOverwrite();
             else {
-                $confirm.confirm('Some tables have no primary key.<br/>' +
+                Confirm.confirm('Some tables have no primary key.<br/>' +
                         'You will need to configure key type and key fields for such tables after import complete.')
                     .then(() => checkOverwrite());
             }
@@ -1067,7 +1059,7 @@ consoleModule.controller('domainsController', [
         $scope.importCommon = {};
 
         // When landing on the page, get domain models and show them.
-        $loading.start('loadingDomainModelsScreen');
+        Loading.start('loadingDomainModelsScreen');
 
         $http.post('/api/v1/configuration/domains/list')
             .success(function(data) {
@@ -1120,26 +1112,25 @@ consoleModule.controller('domainsController', [
                 }
 
                 $scope.$watch('ui.inputForm.$valid', function(valid) {
-                    if (valid && _.isEqual(__original_value, $cleanup($scope.backupItem)))
+                    if (valid && ModelNormalizer.isEqual(__original_value, $scope.backupItem))
                         $scope.ui.inputForm.$dirty = false;
                 });
 
                 $scope.$watch('backupItem', function(val) {
                     const form = $scope.ui.inputForm;
 
-                    if (form.$pristine || (form.$valid && _.isEqual(__original_value, $cleanup(val))))
+                    if (form.$pristine || (form.$valid && ModelNormalizer.isEqual(__original_value, val)))
                         form.$setPristine();
                     else
                         form.$setDirty();
                 }, true);
             })
-            .catch(function(errMsg) {
-                $common.showError(errMsg);
-            })
-            .finally(function() {
+            .catch(Messages.showError)
+            .finally(() => {
                 $scope.ui.ready = true;
                 $scope.ui.inputForm.$setPristine();
-                $loading.finish('loadingDomainModelsScreen');
+
+                Loading.finish('loadingDomainModelsScreen');
             });
 
         const clearFormDefaults = (ngFormCtrl) => {
@@ -1155,7 +1146,7 @@ consoleModule.controller('domainsController', [
             function selectItem() {
                 clearFormDefaults($scope.ui.inputForm);
 
-                $table.tableReset();
+                LegacyTable.tableReset();
 
                 $scope.selectedItem = item;
 
@@ -1178,27 +1169,27 @@ consoleModule.controller('domainsController', [
 
                 $scope.backupItem = angular.merge({}, blank, $scope.backupItem);
 
-                __original_value = $cleanup($scope.backupItem);
+                __original_value = ModelNormalizer.normalize($scope.backupItem);
 
-                if ($common.isDefined($scope.backupItem) && !$common.isDefined($scope.backupItem.queryMetadata))
+                if (LegacyUtils.isDefined($scope.backupItem) && !LegacyUtils.isDefined($scope.backupItem.queryMetadata))
                     $scope.backupItem.queryMetadata = 'Configuration';
 
-                if ($common.isDefined($scope.selectedItem) && !$common.isDefined($scope.selectedItem.queryMetadata))
+                if (LegacyUtils.isDefined($scope.selectedItem) && !LegacyUtils.isDefined($scope.selectedItem.queryMetadata))
                     $scope.selectedItem.queryMetadata = 'Configuration';
 
-                if ($common.getQueryVariable('new'))
+                if (LegacyUtils.getQueryVariable('new'))
                     $state.go('base.configuration.domains');
             }
 
-            $common.confirmUnsavedChanges($scope.ui.inputForm.$dirty, selectItem);
+            LegacyUtils.confirmUnsavedChanges($scope.ui.inputForm.$dirty, selectItem);
         };
 
         // Add new domain model.
         $scope.createItem = function(cacheId) {
             if ($scope.tableReset(true)) {
                 $timeout(() => {
-                    $common.ensureActivePanel($scope.ui, 'query');
-                    $common.ensureActivePanel($scope.ui, 'general', 'keyType');
+                    LegacyUtils.ensureActivePanel($scope.ui, 'query');
+                    LegacyUtils.ensureActivePanel($scope.ui, 'general', 'keyType');
                 });
 
                 $scope.selectItem(null, prepareNewItem(cacheId));
@@ -1206,7 +1197,7 @@ consoleModule.controller('domainsController', [
         };
 
         function checkQueryConfiguration(item) {
-            if (item.queryMetadata === 'Configuration' && $common.domainForQueryConfigured(item)) {
+            if (item.queryMetadata === 'Configuration' && LegacyUtils.domainForQueryConfigured(item)) {
                 if (_.isEmpty(item.fields))
                     return showPopoverMessage($scope.ui, 'query', 'queryFields', 'Query fields should not be empty');
 
@@ -1225,17 +1216,17 @@ consoleModule.controller('domainsController', [
         }
 
         function checkStoreConfiguration(item) {
-            if ($common.domainForStoreConfigured(item)) {
-                if ($common.isEmptyString(item.databaseSchema))
+            if (LegacyUtils.domainForStoreConfigured(item)) {
+                if (LegacyUtils.isEmptyString(item.databaseSchema))
                     return showPopoverMessage($scope.ui, 'store', 'databaseSchema', 'Database schema should not be empty');
 
-                if ($common.isEmptyString(item.databaseTable))
+                if (LegacyUtils.isEmptyString(item.databaseTable))
                     return showPopoverMessage($scope.ui, 'store', 'databaseTable', 'Database table should not be empty');
 
                 if (_.isEmpty(item.keyFields))
                     return showPopoverMessage($scope.ui, 'store', 'keyFields', 'Key fields are not specified');
 
-                if ($common.isJavaBuiltInClass(item.keyType) && item.keyFields.length !== 1)
+                if (LegacyUtils.isJavaBuiltInClass(item.keyType) && item.keyFields.length !== 1)
                     return showPopoverMessage($scope.ui, 'store', 'keyFields', 'Only one field should be specified in case when key type is a Java built-in type');
 
                 if (_.isEmpty(item.valueFields))
@@ -1247,7 +1238,7 @@ consoleModule.controller('domainsController', [
 
         // Check domain model logical consistency.
         function validate(item) {
-            if (!$common.checkFieldValidators($scope.ui))
+            if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
             if (!checkQueryConfiguration(item))
@@ -1256,7 +1247,7 @@ consoleModule.controller('domainsController', [
             if (!checkStoreConfiguration(item))
                 return false;
 
-            if (!$common.domainForStoreConfigured(item) && !$common.domainForQueryConfigured(item) && item.queryMetadata === 'Configuration')
+            if (!LegacyUtils.domainForStoreConfigured(item) && !LegacyUtils.domainForQueryConfigured(item) && item.queryMetadata === 'Configuration')
                 return showPopoverMessage($scope.ui, 'query', 'query-title', 'SQL query domain model should be configured');
 
             return true;
@@ -1272,8 +1263,8 @@ consoleModule.controller('domainsController', [
 
         // Save domain models into database.
         function save(item) {
-            const qry = $common.domainForQueryConfigured(item);
-            const str = $common.domainForStoreConfigured(item);
+            const qry = LegacyUtils.domainForQueryConfigured(item);
+            const str = LegacyUtils.domainForStoreConfigured(item);
 
             item.kind = 'query';
 
@@ -1306,13 +1297,11 @@ consoleModule.controller('domainsController', [
 
                     $scope.selectItem(savedMeta);
 
-                    $common.showInfo('Domain model "' + item.valueType + '" saved.');
+                    Messages.showInfo('Domain model "' + item.valueType + '" saved.');
 
                     _checkShowValidPresentation();
                 })
-                .error(function(errMsg) {
-                    $common.showError(errMsg);
-                });
+                .error(Messages.showError);
         }
 
         // Save domain model.
@@ -1325,7 +1314,7 @@ consoleModule.controller('domainsController', [
                 _.forEach(item.caches, function(cacheId) {
                     const cache = _.find($scope.caches, {value: cacheId}).cache;
 
-                    const change = $common.autoCacheStoreConfiguration(cache, [item]);
+                    const change = LegacyUtils.autoCacheStoreConfiguration(cache, [item]);
 
                     if (change)
                         item.cacheStoreChanges.push({cacheId, change});
@@ -1343,13 +1332,13 @@ consoleModule.controller('domainsController', [
         }
 
         function _newNameIsValidJavaClass(newName) {
-            return $common.isValidJavaClass('New name for value type', newName, false, 'copy-new-name');
+            return LegacyUtils.isValidJavaClass('New name for value type', newName, false, 'copy-new-name');
         }
 
         // Save domain model with new name.
         $scope.cloneItem = function() {
             if ($scope.tableReset(true) && validate($scope.backupItem)) {
-                $clone.confirm($scope.backupItem.valueType, _domainNames(), _newNameIsValidJavaClass).then(function(newName) {
+                Clone.confirm($scope.backupItem.valueType, _domainNames(), _newNameIsValidJavaClass).then(function(newName) {
                     const item = angular.copy($scope.backupItem);
 
                     delete item._id;
@@ -1362,17 +1351,17 @@ consoleModule.controller('domainsController', [
 
         // Remove domain model from db.
         $scope.removeItem = function() {
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             const selectedItem = $scope.selectedItem;
 
-            $confirm.confirm('Are you sure you want to remove domain model: "' + selectedItem.valueType + '"?')
+            Confirm.confirm('Are you sure you want to remove domain model: "' + selectedItem.valueType + '"?')
                 .then(function() {
                     const _id = selectedItem._id;
 
                     $http.post('/api/v1/configuration/domains/remove', {_id})
                         .success(function() {
-                            $common.showInfo('Domain model has been removed: ' + selectedItem.valueType);
+                            Messages.showInfo('Domain model has been removed: ' + selectedItem.valueType);
 
                             const domains = $scope.domains;
 
@@ -1395,21 +1384,19 @@ consoleModule.controller('domainsController', [
 
                             _checkShowValidPresentation();
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         // Remove all domain models from db.
         $scope.removeAllItems = function() {
-            $table.tableReset();
+            LegacyTable.tableReset();
 
-            $confirm.confirm('Are you sure you want to remove all domain models?')
+            Confirm.confirm('Are you sure you want to remove all domain models?')
                 .then(function() {
                     $http.post('/api/v1/configuration/domains/remove/all')
                         .success(function() {
-                            $common.showInfo('All domain models have been removed');
+                            Messages.showInfo('All domain models have been removed');
 
                             $scope.domains = [];
 
@@ -1419,9 +1406,7 @@ consoleModule.controller('domainsController', [
                             $scope.backupItem = emptyDomain;
                             $scope.ui.showValid = true;
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
@@ -1432,7 +1417,7 @@ consoleModule.controller('domainsController', [
 
             let idx = -1;
 
-            if ($common.isDefined($scope.selectedItem)) {
+            if (LegacyUtils.isDefined($scope.selectedItem)) {
                 idx = _.findIndex(validFilter($scope.domains, $scope.ui.showValid, true), function(domain) {
                     return domain._id === $scope.selectedItem._id;
                 });
@@ -1458,23 +1443,23 @@ consoleModule.controller('domainsController', [
         $scope.tablePairValid = function(item, field, index) {
             const pairField = pairFields[field.model];
 
-            const pairValue = $table.tablePairValue(field, index);
+            const pairValue = LegacyTable.tablePairValue(field, index);
 
             if (pairField) {
                 const model = item[field.model];
 
-                if ($common.isDefined(model)) {
+                if (LegacyUtils.isDefined(model)) {
                     const idx = _.findIndex(model, function(pair) {
                         return pair[pairField.searchCol] === pairValue[pairField.valueCol];
                     });
 
                     // Found duplicate by key.
                     if (idx >= 0 && idx !== index)
-                        return showPopoverMessage($scope.ui, 'query', $table.tableFieldId(index, pairField.idPrefix + pairField.id), 'Field with such ' + pairField.dupObjName + ' already exists!');
+                        return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Field with such ' + pairField.dupObjName + ' already exists!');
                 }
 
-                if (pairField.classValidation && !$common.isValidJavaClass(pairField.msg, pairValue.value, true, $table.tableFieldId(index, 'Value' + pairField.id), false, $scope.ui, 'query'))
-                    return $table.tableFocusInvalidField(index, 'Value' + pairField.id);
+                if (pairField.classValidation && !LegacyUtils.isValidJavaClass(pairField.msg, pairValue.value, true, LegacyTable.tableFieldId(index, 'Value' + pairField.id), false, $scope.ui, 'query'))
+                    return LegacyTable.tableFocusInvalidField(index, 'Value' + pairField.id);
             }
 
             return true;
@@ -1497,10 +1482,10 @@ consoleModule.controller('domainsController', [
         $scope.tableDbFieldSaveVisible = function(field, index) {
             const dbFieldValue = tableDbFieldValue(field, index);
 
-            return $common.isDefined(dbFieldValue.databaseFieldType) &&
-                $common.isDefined(dbFieldValue.javaFieldType) &&
-                !$common.isEmptyString(dbFieldValue.databaseFieldName) &&
-                !$common.isEmptyString(dbFieldValue.javaFieldName);
+            return LegacyUtils.isDefined(dbFieldValue.databaseFieldType) &&
+                LegacyUtils.isDefined(dbFieldValue.javaFieldType) &&
+                !LegacyUtils.isEmptyString(dbFieldValue.databaseFieldName) &&
+                !LegacyUtils.isEmptyString(dbFieldValue.javaFieldName);
         };
 
         const dbFieldTables = {
@@ -1518,17 +1503,17 @@ consoleModule.controller('domainsController', [
 
                 let model = item[field.model];
 
-                if (!$common.isValidJavaIdentifier(dbFieldTable.msg + ' java name', dbFieldValue.javaFieldName, $table.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id)))
+                if (!LegacyUtils.isValidJavaIdentifier(dbFieldTable.msg + ' java name', dbFieldValue.javaFieldName, LegacyTable.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id)))
                     return false;
 
-                if ($common.isDefined(model)) {
+                if (LegacyUtils.isDefined(model)) {
                     let idx = _.findIndex(model, function(dbMeta) {
                         return dbMeta.databaseFieldName === dbFieldValue.databaseFieldName;
                     });
 
                     // Found duplicate.
                     if (idx >= 0 && index !== idx)
-                        return showPopoverMessage($scope.ui, 'store', $table.tableFieldId(index, 'DatabaseFieldName' + dbFieldTable.id), 'Field with such database name already exists!');
+                        return showPopoverMessage($scope.ui, 'store', LegacyTable.tableFieldId(index, 'DatabaseFieldName' + dbFieldTable.id), 'Field with such database name already exists!');
 
                     idx = _.findIndex(model, function(dbMeta) {
                         return dbMeta.javaFieldName === dbFieldValue.javaFieldName;
@@ -1536,7 +1521,7 @@ consoleModule.controller('domainsController', [
 
                     // Found duplicate.
                     if (idx >= 0 && index !== idx)
-                        return showPopoverMessage($scope.ui, 'store', $table.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id), 'Field with such java name already exists!');
+                        return showPopoverMessage($scope.ui, 'store', LegacyTable.tableFieldId(index, 'JavaFieldName' + dbFieldTable.id), 'Field with such java name already exists!');
 
                     if (index < 0)
                         model.push(dbFieldValue);
@@ -1557,11 +1542,11 @@ consoleModule.controller('domainsController', [
 
                 if (!stopEdit) {
                     if (index < 0)
-                        $table.tableNewItem(field);
+                        LegacyTable.tableNewItem(field);
                     else if (index < model.length - 1)
-                        $table.tableStartEdit(item, field, index + 1);
+                        LegacyTable.tableStartEdit(item, field, index + 1);
                     else
-                        $table.tableNewItem(field);
+                        LegacyTable.tableNewItem(field);
                 }
 
                 return true;
@@ -1579,7 +1564,7 @@ consoleModule.controller('domainsController', [
         }
 
         $scope.tableIndexSaveVisible = function(field, index) {
-            return !$common.isEmptyString(tableIndexName(field, index)) && $common.isDefined(tableIndexType(field, index));
+            return !LegacyUtils.isEmptyString(tableIndexName(field, index)) && LegacyUtils.isDefined(tableIndexType(field, index));
         };
 
         $scope.tableIndexSave = function(field, curIdx, stopEdit) {
@@ -1590,17 +1575,17 @@ consoleModule.controller('domainsController', [
 
             const indexes = item.indexes;
 
-            if ($common.isDefined(indexes)) {
+            if (LegacyUtils.isDefined(indexes)) {
                 const idx = _.findIndex(indexes, function(index) {
                     return index.name === indexName;
                 });
 
                 // Found duplicate.
                 if (idx >= 0 && idx !== curIdx)
-                    return showPopoverMessage($scope.ui, 'query', $table.tableFieldId(curIdx, 'IndexName'), 'Index with such name already exists!');
+                    return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(curIdx, 'IndexName'), 'Index with such name already exists!');
             }
 
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             if (curIdx < 0) {
                 const newIndex = {name: indexName, indexType};
@@ -1635,8 +1620,8 @@ consoleModule.controller('domainsController', [
             if ($scope.tableReset(true)) {
                 const index = $scope.backupItem.indexes[indexIdx];
 
-                $table.tableState(field, -1, 'table-index-fields');
-                $table.tableFocusInvalidField(-1, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx);
+                LegacyTable.tableState(field, -1, 'table-index-fields');
+                LegacyTable.tableFocusInvalidField(-1, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx);
 
                 field.newFieldName = null;
                 field.newDirection = true;
@@ -1651,7 +1636,7 @@ consoleModule.controller('domainsController', [
                 const index = indexes[itemIndex];
 
                 if (index)
-                    return $table.tableNewItemActive({model: 'table-index-fields'}) && field.indexIdx === itemIndex;
+                    return LegacyTable.tableNewItemActive({model: 'table-index-fields'}) && field.indexIdx === itemIndex;
             }
 
             return false;
@@ -1664,7 +1649,7 @@ consoleModule.controller('domainsController', [
                 const index = indexes[itemIndex];
 
                 if (index)
-                    return $table.tableEditing({model: 'table-index-fields'}, curIdx) && field.indexIdx === itemIndex;
+                    return LegacyTable.tableEditing({model: 'table-index-fields'}, curIdx) && field.indexIdx === itemIndex;
             }
 
             return false;
@@ -1684,7 +1669,7 @@ consoleModule.controller('domainsController', [
             if ($scope.tableReset(true)) {
                 const index = $scope.backupItem.indexes[indexIdx];
 
-                $table.tableState(field, curIdx, 'table-index-fields');
+                LegacyTable.tableState(field, curIdx, 'table-index-fields');
 
                 const indexItem = index.fields[curIdx];
 
@@ -1692,12 +1677,12 @@ consoleModule.controller('domainsController', [
                 field.curDirection = indexItem.direction;
                 field.indexIdx = indexIdx;
 
-                $focus('curFieldName' + (index.indexType === 'SORTED' ? 'S' : '') + field.indexIdx + '-' + curIdx);
+                Focus.move('curFieldName' + (index.indexType === 'SORTED' ? 'S' : '') + field.indexIdx + '-' + curIdx);
             }
         };
 
         $scope.tableIndexItemSaveVisible = function(field, index) {
-            return !$common.isEmptyString(tableIndexItemValue(field, index).name);
+            return !LegacyUtils.isEmptyString(tableIndexItemValue(field, index).name);
         };
 
         $scope.tableIndexItemSave = function(field, indexIdx, curIdx, stopEdit) {
@@ -1707,15 +1692,15 @@ consoleModule.controller('domainsController', [
 
             const fields = index.fields;
 
-            if ($common.isDefined(fields)) {
+            if (LegacyUtils.isDefined(fields)) {
                 const idx = _.findIndex(fields, (fld) => fld.name === indexItemValue.name);
 
                 // Found duplicate.
                 if (idx >= 0 && idx !== curIdx)
-                    return showPopoverMessage($scope.ui, 'query', $table.tableFieldId(curIdx, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx + (curIdx >= 0 ? '-' : '')), 'Field with such name already exists in index!');
+                    return showPopoverMessage($scope.ui, 'query', LegacyTable.tableFieldId(curIdx, 'FieldName' + (index.indexType === 'SORTED' ? 'S' : '') + indexIdx + (curIdx >= 0 ? '-' : '')), 'Field with such name already exists in index!');
             }
 
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             field.indexIdx = -1;
 
@@ -1743,19 +1728,19 @@ consoleModule.controller('domainsController', [
         };
 
         $scope.tableRemoveIndexItem = function(index, curIdx) {
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             index.fields.splice(curIdx, 1);
         };
 
         $scope.resetAll = function() {
-            $table.tableReset();
+            LegacyTable.tableReset();
 
-            $confirm.confirm('Are you sure you want to undo all changes for current domain model?')
+            Confirm.confirm('Are you sure you want to undo all changes for current domain model?')
                 .then(function() {
                     $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
                     $scope.ui.inputForm.$setPristine();
                 });
         };
-    }]
-);
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/igfs-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/igfs-controller.js b/modules/web-console/src/main/js/controllers/igfs-controller.js
index c37d08f..5f5f0bb 100644
--- a/modules/web-console/src/main/js/controllers/igfs-controller.js
+++ b/modules/web-console/src/main/js/controllers/igfs-controller.js
@@ -16,12 +16,10 @@
  */
 
 // Controller for IGFS screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('igfsController', [
-    '$scope', '$http', '$state', '$filter', '$timeout', '$common', '$confirm', '$clone', '$loading', '$cleanup', '$unsavedChangesGuard', '$table',
-    function($scope, $http, $state, $filter, $timeout, $common, $confirm, $clone, $loading, $cleanup, $unsavedChangesGuard, $table) {
-        $unsavedChangesGuard.install($scope);
+export default ['igfsController', [
+    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'IgniteLegacyTable',
+    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, LegacyTable) {
+        UnsavedChangesGuard.install($scope);
 
         const emptyIgfs = {empty: true};
 
@@ -35,69 +33,68 @@ consoleModule.controller('igfsController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyIgfs;
 
-        $scope.ui = $common.formUI();
+        $scope.ui = LegacyUtils.formUI();
         $scope.ui.activePanels = [0];
         $scope.ui.topPanels = [0];
 
-        $scope.compactJavaName = $common.compactJavaName;
-        $scope.widthIsSufficient = $common.widthIsSufficient;
-        $scope.saveBtnTipText = $common.saveBtnTipText;
+        $scope.compactJavaName = LegacyUtils.compactJavaName;
+        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
+        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
 
-        const showPopoverMessage = $common.showPopoverMessage;
+        const showPopoverMessage = LegacyUtils.showPopoverMessage;
 
-        // TODO LEGACY start
         $scope.tableSave = function(field, index, stopEdit) {
-            if (field.type === 'pathModes' && $table.tablePairSaveVisible(field, index))
-                return $table.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
+            if (field.type === 'pathModes' && LegacyTable.tablePairSaveVisible(field, index))
+                return LegacyTable.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
 
             return true;
         };
 
         $scope.tableReset = (trySave) => {
-            const field = $table.tableField();
+            const field = LegacyTable.tableField();
 
-            if (trySave && $common.isDefined(field) && !$scope.tableSave(field, $table.tableEditedRowIndex(), true))
+            if (trySave && LegacyUtils.isDefined(field) && !$scope.tableSave(field, LegacyTable.tableEditedRowIndex(), true))
                 return false;
 
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             return true;
         };
 
         $scope.tableNewItem = function(field) {
             if ($scope.tableReset(true))
-                $table.tableNewItem(field);
+                LegacyTable.tableNewItem(field);
         };
 
-        $scope.tableNewItemActive = $table.tableNewItemActive;
+        $scope.tableNewItemActive = LegacyTable.tableNewItemActive;
 
         $scope.tableStartEdit = function(item, field, index) {
             if ($scope.tableReset(true))
-                $table.tableStartEdit(item, field, index, $scope.tableSave);
+                LegacyTable.tableStartEdit(item, field, index, $scope.tableSave);
         };
 
-        $scope.tableEditing = $table.tableEditing;
-        $scope.tablePairSave = $table.tablePairSave;
-        $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+        $scope.tableEditing = LegacyTable.tableEditing;
+        $scope.tablePairSave = LegacyTable.tablePairSave;
+        $scope.tablePairSaveVisible = LegacyTable.tablePairSaveVisible;
 
         $scope.tableRemove = function(item, field, index) {
             if ($scope.tableReset(true))
-                $table.tableRemove(item, field, index);
+                LegacyTable.tableRemove(item, field, index);
         };
 
         $scope.tablePairValid = function(item, field, index) {
-            const pairValue = $table.tablePairValue(field, index);
+            const pairValue = LegacyTable.tablePairValue(field, index);
 
             const model = item[field.model];
 
-            if ($common.isDefined(model)) {
+            if (LegacyUtils.isDefined(model)) {
                 const idx = _.findIndex(model, function(pair) {
                     return pair.path === pairValue.key;
                 });
 
                 // Found duplicate.
                 if (idx >= 0 && idx !== index)
-                    return showPopoverMessage($scope.ui, 'misc', $table.tableFieldId(index, 'KeyPathMode'), 'Such path already exists!');
+                    return showPopoverMessage($scope.ui, 'misc', LegacyTable.tableFieldId(index, 'KeyPathMode'), 'Such path already exists!');
             }
 
             return true;
@@ -113,8 +110,7 @@ consoleModule.controller('igfsController', [
             save: $scope.tableSave
         };
 
-        $scope.igfsModes = $common.mkOptions(['PRIMARY', 'PROXY', 'DUAL_SYNC', 'DUAL_ASYNC']);
-        // TODO LEGACY start - end
+        $scope.igfsModes = LegacyUtils.mkOptions(['PRIMARY', 'PROXY', 'DUAL_SYNC', 'DUAL_ASYNC']);
 
         $scope.contentVisible = function() {
             const item = $scope.backupItem;
@@ -125,7 +121,7 @@ consoleModule.controller('igfsController', [
         $scope.toggleExpanded = function() {
             $scope.ui.expanded = !$scope.ui.expanded;
 
-            $common.hidePopover();
+            LegacyUtils.hidePopover();
         };
 
         $scope.igfss = [];
@@ -136,7 +132,7 @@ consoleModule.controller('igfsController', [
                 $scope.selectItem($scope.igfss[0]);
         }
 
-        $loading.start('loadingIgfsScreen');
+        Loading.start('loadingIgfsScreen');
 
         // When landing on the page, get IGFSs and show them.
         $http.post('/api/v1/configuration/igfs/list')
@@ -184,31 +180,29 @@ consoleModule.controller('igfsController', [
                 }
 
                 $scope.$watch('ui.inputForm.$valid', function(valid) {
-                    if (valid && _.isEqual(__original_value, $cleanup($scope.backupItem)))
+                    if (valid && ModelNormalizer.isEqual(__original_value, $scope.backupItem))
                         $scope.ui.inputForm.$dirty = false;
                 });
 
                 $scope.$watch('backupItem', function(val) {
                     const form = $scope.ui.inputForm;
 
-                    if (form.$pristine || (form.$valid && _.isEqual(__original_value, $cleanup(val))))
+                    if (form.$pristine || (form.$valid && ModelNormalizer.isEqual(__original_value, val)))
                         form.$setPristine();
                     else
                         form.$setDirty();
                 }, true);
             })
-            .catch(function(errMsg) {
-                $common.showError(errMsg);
-            })
+            .catch(Messages.showError)
             .finally(function() {
                 $scope.ui.ready = true;
                 $scope.ui.inputForm.$setPristine();
-                $loading.finish('loadingIgfsScreen');
+                Loading.finish('loadingIgfsScreen');
             });
 
         $scope.selectItem = function(item, backup) {
             function selectItem() {
-                $table.tableReset(); // TODO LEGACY
+                LegacyTable.tableReset();
 
                 $scope.selectedItem = item;
 
@@ -231,13 +225,13 @@ consoleModule.controller('igfsController', [
 
                 $scope.backupItem = angular.merge({}, blank, $scope.backupItem);
 
-                __original_value = $cleanup($scope.backupItem);
+                __original_value = ModelNormalizer.normalize($scope.backupItem);
 
-                if ($common.getQueryVariable('new'))
+                if (LegacyUtils.getQueryVariable('new'))
                     $state.go('base.configuration.igfs');
             }
 
-            $common.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
+            LegacyUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
         };
 
         $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
@@ -256,8 +250,8 @@ consoleModule.controller('igfsController', [
 
         // Add new IGFS.
         $scope.createItem = function(linkId) {
-            if ($scope.tableReset(true)) { // TODO LEGACY
-                $timeout(() => $common.ensureActivePanel($scope.ui, 'general', 'igfsName'));
+            if ($scope.tableReset(true)) {
+                $timeout(() => LegacyUtils.ensureActivePanel($scope.ui, 'general', 'igfsName'));
 
                 $scope.selectItem(null, prepareNewItem(linkId));
             }
@@ -265,12 +259,12 @@ consoleModule.controller('igfsController', [
 
         // Check IGFS logical consistency.
         function validate(item) {
-            $common.hidePopover();
+            LegacyUtils.hidePopover();
 
-            if ($common.isEmptyString(item.name))
+            if (LegacyUtils.isEmptyString(item.name))
                 return showPopoverMessage($scope.ui, 'general', 'igfsName', 'IGFS name should not be empty!');
 
-            if (!$common.checkFieldValidators($scope.ui))
+            if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
             if (!item.secondaryFileSystemEnabled && (item.defaultMode === 'PROXY'))
@@ -305,16 +299,14 @@ consoleModule.controller('igfsController', [
 
                     $scope.selectItem(item);
 
-                    $common.showInfo('IGFS "' + item.name + '" saved.');
+                    Messages.showInfo('IGFS "' + item.name + '" saved.');
                 })
-                .error(function(errMsg) {
-                    $common.showError(errMsg);
-                });
+                .error(Messages.showError);
         }
 
         // Save IGFS.
         $scope.saveItem = function() {
-            if ($scope.tableReset(true)) { // TODO LEGACY
+            if ($scope.tableReset(true)) {
                 const item = $scope.backupItem;
 
                 if (validate(item))
@@ -330,8 +322,8 @@ consoleModule.controller('igfsController', [
 
         // Clone IGFS with new name.
         $scope.cloneItem = function() {
-            if ($scope.tableReset(true) && validate($scope.backupItem)) { // TODO LEGACY
-                $clone.confirm($scope.backupItem.name, _igfsNames()).then(function(newName) {
+            if ($scope.tableReset(true) && validate($scope.backupItem)) {
+                Clone.confirm($scope.backupItem.name, _igfsNames()).then(function(newName) {
                     const item = angular.copy($scope.backupItem);
 
                     delete item._id;
@@ -345,17 +337,17 @@ consoleModule.controller('igfsController', [
 
         // Remove IGFS from db.
         $scope.removeItem = function() {
-            $table.tableReset(); // TODO LEGACY
+            LegacyTable.tableReset();
 
             const selectedItem = $scope.selectedItem;
 
-            $confirm.confirm('Are you sure you want to remove IGFS: "' + selectedItem.name + '"?')
+            Confirm.confirm('Are you sure you want to remove IGFS: "' + selectedItem.name + '"?')
                 .then(function() {
                     const _id = selectedItem._id;
 
                     $http.post('/api/v1/configuration/igfs/remove', {_id})
                         .success(function() {
-                            $common.showInfo('IGFS has been removed: ' + selectedItem.name);
+                            Messages.showInfo('IGFS has been removed: ' + selectedItem.name);
 
                             const igfss = $scope.igfss;
 
@@ -374,40 +366,36 @@ consoleModule.controller('igfsController', [
                                 }
                             }
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         // Remove all IGFS from db.
         $scope.removeAllItems = function() {
-            $table.tableReset(); // TODO LEGACY
+            LegacyTable.tableReset();
 
-            $confirm.confirm('Are you sure you want to remove all IGFS?')
+            Confirm.confirm('Are you sure you want to remove all IGFS?')
                 .then(function() {
                     $http.post('/api/v1/configuration/igfs/remove/all')
                         .success(function() {
-                            $common.showInfo('All IGFS have been removed');
+                            Messages.showInfo('All IGFS have been removed');
 
                             $scope.igfss = [];
                             $scope.backupItem = emptyIgfs;
                             $scope.ui.inputForm.$setPristine();
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         $scope.resetAll = function() {
-            $table.tableReset(); // TODO LEGACY
+            LegacyTable.tableReset();
 
-            $confirm.confirm('Are you sure you want to undo all changes for current IGFS?')
+            Confirm.confirm('Are you sure you want to undo all changes for current IGFS?')
                 .then(function() {
                     $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
                     $scope.ui.inputForm.$setPristine();
                 });
         };
-    }]
-);
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/profile-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/profile-controller.js b/modules/web-console/src/main/js/controllers/profile-controller.js
index 39457af..6b8f541 100644
--- a/modules/web-console/src/main/js/controllers/profile-controller.js
+++ b/modules/web-console/src/main/js/controllers/profile-controller.js
@@ -16,18 +16,16 @@
  */
 
 // Controller for Profile screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('profileController', [
-    '$rootScope', '$scope', '$http', '$common', '$focus', '$confirm', 'IgniteCountries', 'User',
-    function($root, $scope, $http, $common, $focus, $confirm, Countries, User) {
+export default ['profileController', [
+    '$rootScope', '$scope', '$http', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteFocus', 'IgniteConfirm', 'IgniteCountries', 'User',
+    function($root, $scope, $http, LegacyUtils, Messages, Focus, Confirm, Countries, User) {
         $scope.user = angular.copy($root.user);
 
         $scope.countries = Countries.getAll();
 
         $scope.generateToken = () => {
-            $confirm.confirm('Are you sure you want to change security token?')
-                .then(() => $scope.user.token = $common.randomString(20));
+            Confirm.confirm('Are you sure you want to change security token?')
+                .then(() => $scope.user.token = LegacyUtils.randomString(20));
         };
 
         const _passwordValid = () => {
@@ -53,9 +51,10 @@ consoleModule.controller('profileController', [
         $scope.togglePassword = () => {
             $scope.expandedPassword = !$scope.expandedPassword;
 
-            if (!$scope.expandedPassword) {
+            if ($scope.expandedPassword)
+                Focus.move('profile_password');
+            else {
                 delete $scope.user.password;
-
                 delete $scope.user.confirm;
             }
         };
@@ -82,11 +81,11 @@ consoleModule.controller('profileController', [
                     if ($scope.expandedToken)
                         $scope.toggleToken();
 
-                    $common.showInfo('Profile saved.');
+                    Messages.showInfo('Profile saved.');
 
-                    $focus('profile-username');
+                    Focus.move('profile-username');
                 })
-                .catch((err) => $common.showError('Failed to save profile: ' + $common.errorMessage(err)));
+                .catch(({data}) => Messages.showError(Messages.errorMessage('Failed to save profile: ', data)));
         };
-    }]
-);
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/sql-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/sql-controller.js b/modules/web-console/src/main/js/controllers/sql-controller.js
index a8058ff..7a851c3 100644
--- a/modules/web-console/src/main/js/controllers/sql-controller.js
+++ b/modules/web-console/src/main/js/controllers/sql-controller.js
@@ -16,11 +16,9 @@
  */
 
 // Controller for SQL notebook screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('sqlController', [
-    '$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', '$loading', '$common', '$confirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'QueryNotebooks', 'uiGridConstants', 'uiGridExporterConstants',
-    function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, $loading, $common, $confirm, agentMonitor, IgniteChartColors, QueryNotebooks, uiGridConstants, uiGridExporterConstants) {
+export default ['sqlController', [
+    '$rootScope', '$scope', '$http', '$q', '$timeout', '$interval', '$animate', '$location', '$anchorScroll', '$state', '$modal', '$popover', 'IgniteLoading', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteAgentMonitor', 'IgniteChartColors', 'QueryNotebooks', 'uiGridConstants', 'uiGridExporterConstants',
+    function($root, $scope, $http, $q, $timeout, $interval, $animate, $location, $anchorScroll, $state, $modal, $popover, Loading, LegacyUtils, Messages, Confirm, agentMonitor, IgniteChartColors, QueryNotebooks, uiGridConstants, uiGridExporterConstants) {
         let stopTopology = null;
 
         const _tryStopRefresh = function(paragraph) {
@@ -48,7 +46,7 @@ consoleModule.controller('sqlController', [
 
         $scope.aggregateFxs = ['FIRST', 'LAST', 'MIN', 'MAX', 'SUM', 'AVG', 'COUNT'];
 
-        $scope.modes = $common.mkOptions(['PARTITIONED', 'REPLICATED', 'LOCAL']);
+        $scope.modes = LegacyUtils.mkOptions(['PARTITIONED', 'REPLICATED', 'LOCAL']);
 
         $scope.loadingText = $root.IgniteDemoMode ? 'Demo grid is starting. Please wait...' : 'Loading notebook screen...';
 
@@ -79,10 +77,6 @@ consoleModule.controller('sqlController', [
 
         $scope.maskCacheName = (cacheName) => _.isEmpty(cacheName) ? '<default>' : cacheName;
 
-        const _handleException = function(err) {
-            $common.showError(err);
-        };
-
         // Time line X axis descriptor.
         const TIME_LINE = {value: -1, type: 'java.sql.Date', label: 'TIME_LINE'};
 
@@ -690,7 +684,8 @@ consoleModule.controller('sqlController', [
                             displayName: col.fieldName,
                             headerTooltip: _fullColName(col),
                             field: col.field,
-                            minWidth: 50
+                            minWidth: 50,
+                            cellClass: 'cell-left'
                         };
                     });
 
@@ -772,7 +767,7 @@ consoleModule.controller('sqlController', [
                 });
 
         const _startTopologyRefresh = () => {
-            $loading.start('sqlLoading');
+            Loading.start('sqlLoading');
 
             agentMonitor.awaitAgent()
                 .then(_updateTopology)
@@ -780,7 +775,7 @@ consoleModule.controller('sqlController', [
                     if ($root.IgniteDemoMode)
                         _.forEach($scope.notebook.paragraphs, $scope.execute);
 
-                    $loading.finish('sqlLoading');
+                    Loading.finish('sqlLoading');
 
                     stopTopology = $interval(_updateTopology, 5000, 0, false);
                 });
@@ -826,7 +821,7 @@ consoleModule.controller('sqlController', [
             .catch(() => {
                 $scope.notebookLoadFailed = true;
 
-                $loading.finish('sqlLoading');
+                Loading.finish('sqlLoading');
             });
 
         $scope.renameNotebook = function(name) {
@@ -855,7 +850,7 @@ consoleModule.controller('sqlController', [
                     .catch((err) => {
                         $scope.notebook.name = prevName;
 
-                        _handleException(err);
+                        Messages.showError(err);
                     });
             }
             else
@@ -863,7 +858,7 @@ consoleModule.controller('sqlController', [
         };
 
         $scope.removeNotebook = function() {
-            $confirm.confirm('Are you sure you want to remove: "' + $scope.notebook.name + '"?')
+            Confirm.confirm('Are you sure you want to remove: "' + $scope.notebook.name + '"?')
                 .then(function() {
                     return QueryNotebooks.remove($scope.notebook);
                 })
@@ -873,7 +868,7 @@ consoleModule.controller('sqlController', [
                     else
                         $state.go('base.configuration.clusters');
                 })
-                .catch(_handleException);
+                .catch(Messages.showError);
         };
 
         $scope.renameParagraph = function(paragraph, newName) {
@@ -886,8 +881,8 @@ consoleModule.controller('sqlController', [
                 $scope.rebuildScrollParagraphs();
 
                 QueryNotebooks.save($scope.notebook)
-                    .then(function() { paragraph.edit = false; })
-                    .catch(_handleException);
+                    .then(() => paragraph.edit = false)
+                    .catch(Messages.showError);
             }
             else
                 paragraph.edit = false;
@@ -934,7 +929,7 @@ consoleModule.controller('sqlController', [
             if (!_.isEmpty(paragraph.charts)) {
                 const chart = paragraph.charts[0].api.getScope().chart;
 
-                if (!$common.isDefined(paragraph.chartsOptions))
+                if (!LegacyUtils.isDefined(paragraph.chartsOptions))
                     paragraph.chartsOptions = {barChart: {stacked: true}, areaChart: {style: 'stack'}};
 
                 switch (paragraph.result) {
@@ -972,7 +967,7 @@ consoleModule.controller('sqlController', [
         };
 
         $scope.removeParagraph = function(paragraph) {
-            $confirm.confirm('Are you sure you want to remove: "' + paragraph.name + '"?')
+            Confirm.confirm('Are you sure you want to remove: "' + paragraph.name + '"?')
                 .then(function() {
                     $scope.stopRefresh(paragraph);
 
@@ -992,7 +987,7 @@ consoleModule.controller('sqlController', [
                     $scope.rebuildScrollParagraphs();
 
                     QueryNotebooks.save($scope.notebook)
-                        .catch(_handleException);
+                        .catch(Messages.showError);
                 });
         };
 
@@ -1013,7 +1008,7 @@ consoleModule.controller('sqlController', [
         };
 
         const _notObjectType = function(cls) {
-            return $common.isJavaBuiltInClass(cls);
+            return LegacyUtils.isJavaBuiltInClass(cls);
         };
 
         function _retainColumns(allCols, curCols, acceptableType, xAxis, unwantedCols) {
@@ -1060,7 +1055,7 @@ consoleModule.controller('sqlController', [
 
                 _.forEach(colsByTypes, function(colsByType, typeName) {
                     _.forEach(colsByType, function(col, ix) {
-                        col.fieldName = (needType && !$common.isEmptyString(typeName) ? typeName + '.' : '') + fieldName + (ix > 0 ? ix : '');
+                        col.fieldName = (needType && !LegacyUtils.isEmptyString(typeName) ? typeName + '.' : '') + fieldName + (ix > 0 ? ix : '');
                     });
                 });
             });
@@ -1131,10 +1126,10 @@ consoleModule.controller('sqlController', [
 
                 paragraph.chartColumns = [];
 
-                if (!$common.isDefined(paragraph.chartKeyCols))
+                if (!LegacyUtils.isDefined(paragraph.chartKeyCols))
                     paragraph.chartKeyCols = [];
 
-                if (!$common.isDefined(paragraph.chartValCols))
+                if (!LegacyUtils.isDefined(paragraph.chartValCols))
                     paragraph.chartValCols = [];
 
                 if (res.fieldsMetadata.length <= 2) {
@@ -1247,7 +1242,7 @@ consoleModule.controller('sqlController', [
 
         $scope.execute = function(paragraph) {
             QueryNotebooks.save($scope.notebook)
-                .catch(_handleException);
+                .catch(Messages.showError);
 
             paragraph.prevQuery = paragraph.queryArgs ? paragraph.queryArgs.query : paragraph.query;
 
@@ -1279,7 +1274,7 @@ consoleModule.controller('sqlController', [
         };
 
         $scope.queryExecuted = function(paragraph) {
-            return $common.isDefined(paragraph.queryArgs);
+            return LegacyUtils.isDefined(paragraph.queryArgs);
         };
 
         const _cancelRefresh = function(paragraph) {
@@ -1296,7 +1291,7 @@ consoleModule.controller('sqlController', [
 
         $scope.explain = function(paragraph) {
             QueryNotebooks.save($scope.notebook)
-                .catch(_handleException);
+                .catch(Messages.showError);
 
             _cancelRefresh(paragraph);
 
@@ -1323,7 +1318,7 @@ consoleModule.controller('sqlController', [
 
         $scope.scan = function(paragraph) {
             QueryNotebooks.save($scope.notebook)
-                .catch(_handleException);
+                .catch(Messages.showError);
 
             _cancelRefresh(paragraph);
 
@@ -1440,7 +1435,7 @@ consoleModule.controller('sqlController', [
                 csvContent += cols.join(';') + '\n';
             });
 
-            $common.download('application/octet-stream;charset=utf-8', fileName, escape(csvContent));
+            LegacyUtils.download('application/octet-stream;charset=utf-8', fileName, escape(csvContent));
         };
 
         $scope.exportCsv = function(paragraph) {
@@ -1458,7 +1453,7 @@ consoleModule.controller('sqlController', [
 
             agentMonitor.queryGetAll(args.cacheName, args.query)
                 .then((res) => _export(paragraph.name + '-all.csv', paragraph.columnFilter, res.fieldsMetadata, res.items))
-                .catch((err) => $common.showError(err))
+                .catch(Messages.showError)
                 .finally(() => paragraph.ace.focus());
         };
 
@@ -1467,9 +1462,7 @@ consoleModule.controller('sqlController', [
         //        .success(function(item) {
         //            _export(paragraph.name + '-all.csv', item.meta, item.rows);
         //    })
-        //    .error(function(errMsg) {
-        //        $common.showError(errMsg);
-        //    });
+        //    .error(Messages.showError);
         // };
 
         $scope.rateAsString = function(paragraph) {
@@ -1544,7 +1537,7 @@ consoleModule.controller('sqlController', [
         };
 
         $scope.importMetadata = function() {
-            $loading.start('loadingCacheMetadata');
+            Loading.start('loadingCacheMetadata');
 
             $scope.metadata = [];
 
@@ -1566,12 +1559,12 @@ consoleModule.controller('sqlController', [
                         return cache;
                     }), 'name');
                 })
-                .catch(_handleException)
-                .finally(() => $loading.finish('loadingCacheMetadata'));
+                .catch(Messages.showError)
+                .finally(() => Loading.finish('loadingCacheMetadata'));
         };
 
         $scope.showResultQuery = function(paragraph) {
-            if ($common.isDefined(paragraph)) {
+            if (LegacyUtils.isDefined(paragraph)) {
                 const scope = $scope.$new();
 
                 if (_.isNil(paragraph.queryArgs.query)) {
@@ -1591,5 +1584,5 @@ consoleModule.controller('sqlController', [
                 $modal({scope, template: '/templates/message.html', placement: 'center', show: true});
             }
         };
-    }]
-);
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/generator/generator-java.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/generator/generator-java.js b/modules/web-console/src/main/js/generator/generator-java.js
index 2b6ac2f..d9425e0 100644
--- a/modules/web-console/src/main/js/generator/generator-java.js
+++ b/modules/web-console/src/main/js/generator/generator-java.js
@@ -1319,10 +1319,9 @@ $generatorJava.cacheGeneral = function(cache, varName, res) {
     $generatorJava.enumProperty(res, varName, cache, 'cacheMode', 'org.apache.ignite.cache.CacheMode');
     $generatorJava.enumProperty(res, varName, cache, 'atomicityMode', 'org.apache.ignite.cache.CacheAtomicityMode');
 
-    if (cache.cacheMode === 'PARTITIONED')
-        $generatorJava.property(res, varName, cache, 'backups');
+    if (cache.cacheMode === 'PARTITIONED' && $generatorJava.property(res, varName, cache, 'backups'))
+        $generatorJava.property(res, varName, cache, 'readFromBackup');
 
-    $generatorJava.property(res, varName, cache, 'readFromBackup');
     $generatorJava.property(res, varName, cache, 'copyOnRead');
 
     if (cache.cacheMode === 'PARTITIONED' && cache.atomicityMode === 'TRANSACTIONAL')
@@ -1806,6 +1805,8 @@ $generatorJava.domainModelQueryIndexes = function(res, domain) {
                 $generatorJava.property(res, 'index', index, 'name');
                 $generatorJava.enumProperty(res, 'index', index, 'indexType', 'org.apache.ignite.cache.QueryIndexType');
 
+                res.needEmptyLine = true;
+
                 if (fields && fields.length > 0) {
                     $generatorJava.declareVariable(res, 'indFlds', 'java.util.LinkedHashMap', 'java.util.LinkedHashMap', 'String', 'Boolean');
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/generator/generator-xml.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/generator/generator-xml.js b/modules/web-console/src/main/js/generator/generator-xml.js
index 4528f36..efc8df8 100644
--- a/modules/web-console/src/main/js/generator/generator-xml.js
+++ b/modules/web-console/src/main/js/generator/generator-xml.js
@@ -1062,10 +1062,9 @@ $generatorXml.cacheGeneral = function(cache, res) {
     $generatorXml.property(res, cache, 'cacheMode');
     $generatorXml.property(res, cache, 'atomicityMode');
 
-    if (cache.cacheMode === 'PARTITIONED')
-        $generatorXml.property(res, cache, 'backups');
+    if (cache.cacheMode === 'PARTITIONED' && $generatorXml.property(res, cache, 'backups'))
+        $generatorXml.property(res, cache, 'readFromBackup');
 
-    $generatorXml.property(res, cache, 'readFromBackup');
     $generatorXml.property(res, cache, 'copyOnRead');
 
     if (cache.cacheMode === 'PARTITIONED' && cache.atomicityMode === 'TRANSACTIONAL')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/paths.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/paths.js b/modules/web-console/src/main/js/gulpfile.babel.js/paths.js
index b865fcf..cca3643 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/paths.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/paths.js
@@ -17,85 +17,54 @@
 
 import path from 'path';
 
-const srcDir = './app';
-const destDir = './build';
+const rootDir = path.resolve('./');
+const srcDir = path.resolve('app');
+const destDir = path.resolve('build');
 
 const igniteModulesDir = process.env.IGNITE_MODULES ? path.normalize(process.env.IGNITE_MODULES) : './ignite_modules';
-const igniteModulesTemp = './ignite_modules_temp';
-
-const sassPaths = [
-    './public/stylesheets/*.scss'
-];
+const igniteModulesTemp = path.resolve('ignite_modules_temp');
 
 const jadePaths = [
-    '!./views/error.jade',
     './views/*.jade',
     './views/**/*.jade'
 ];
 
-const jadeModulePaths = [
-    igniteModulesDir + '/**/view/**/*.jade'
-];
-
 const resourcePaths = [
-    './controllers/**/*.json',
     './public/**/*.png',
     './public/*.ico'
 ];
 
-const resourceModulePaths = [
-    igniteModulesDir + '/**/controllers/models/*.json',
-    igniteModulesDir + '/**/images/*.png'
-];
-
-const jsPaths = [
-    './{app,controllers,generator}/*.js',
-    './{app,controllers,generator}/**/*.js'
-];
-
-const jsModulePaths = [
-    igniteModulesTemp + '/index.js',
-    igniteModulesTemp + '/**/main.js',
-    igniteModulesTemp + '/**/module.js',
-    igniteModulesTemp + '/**/app/modules/*.js',
-    igniteModulesTemp + '/**/app/modules/**/*.js',
-    igniteModulesTemp + '/**/app/modules/**/*.jade'
+const jadeModulePaths = [
+    igniteModulesDir + '/**/view/**/*.jade'
 ];
 
-const appPaths = [
-    './app/**/*.\u0441ss',
-    './app/**/*.jade',
-    './app/data/*.json'
-].concat(jsPaths);
-
 const appModulePaths = [
     igniteModulesDir + '/index.js',
     igniteModulesDir + '/**/main.js',
     igniteModulesDir + '/**/module.js',
-    igniteModulesDir + '/**/app/**/*.css',
-    igniteModulesDir + '/**/app/data/*.json',
     igniteModulesDir + '/**/app/modules/*.js',
     igniteModulesDir + '/**/app/modules/**/*.js',
-    igniteModulesDir + '/**/app/modules/**/*.jade'
+    igniteModulesDir + '/**/app/modules/**/*.jade',
+    igniteModulesDir + '/**/app/**/*.css',
+    igniteModulesDir + '/**/app/data/*.json'
+];
+
+const resourceModulePaths = [
+    igniteModulesDir + '/**/images/*.png',
+    igniteModulesDir + '/*.ico'
 ];
 
 export {
+    rootDir,
     srcDir,
     destDir,
     igniteModulesDir,
     igniteModulesTemp,
 
-    sassPaths,
-
     jadePaths,
-    jadeModulePaths,
-
     resourcePaths,
-    resourceModulePaths,
 
-    jsPaths,
-    jsModulePaths,
-
-    appPaths,
+    jadeModulePaths,
+    resourceModulePaths,
     appModulePaths
 };

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/build.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/build.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/build.js
index 69cd6cd..7d7401b 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/build.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/build.js
@@ -18,4 +18,4 @@
 import gulp from 'gulp';
 import sequence from 'gulp-sequence';
 
-gulp.task('build', (cb) => sequence(['clean', 'clean:ignite-modules-temp'], 'ignite:modules', ['copy', 'jade', 'sass'], 'bundle', cb));
+gulp.task('build', (cb) => sequence(['clean', 'clean:ignite-modules-temp'], 'ignite:modules', ['copy:resource', 'jade'], 'bundle', cb));

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/bundle.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/bundle.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/bundle.js
index 38ed8d8..d3e8dca 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/bundle.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/bundle.js
@@ -16,61 +16,17 @@
  */
 
 import gulp from 'gulp';
-import jspm from 'jspm';
-import util from 'gulp-util';
-import sequence from 'gulp-sequence';
-import htmlReplace from 'gulp-html-replace';
-
-import { srcDir, destDir, igniteModulesTemp } from '../paths';
-
-const options = {
-    minify: true
-};
-
-if (util.env.debug)
-    delete options.minify;
-
-if (util.env.debug || util.env.sourcemaps)
-    options.sourceMaps = true;
-
-gulp.task('bundle', ['eslint', 'bundle:ignite']);
-
-// Package all external dependencies and ignite-console.
-gulp.task('bundle:ignite', (cb) => {
-    if (util.env.debug)
-        return sequence('bundle:ignite:vendors', 'bundle:ignite:app', cb);
-
-    return sequence('bundle:ignite:app-min', 'bundle:ignite:app-min:replace', cb);
-});
-
-gulp.task('bundle:ignite:vendors', () => {
-    const exclude = [
-        `${srcDir}/**/*`,
-        `${srcDir}/**/*!jade`,
-        './controllers/**/*.js',
-        './generator/**/*.js',
-        './public/**/*!css',
-        `${igniteModulesTemp}/**/*`,
-        `${igniteModulesTemp}/**/*!jade`,
-        `${igniteModulesTemp}/**/*!css`
-    ].map((item) => `[${item}]`).join(' - ');
-
-    return jspm.bundle(`${srcDir}/index - ${exclude}`, `${destDir}/vendors.js`, options);
+import webpack from 'webpack';
+import webpackConfig from '../webpack';
+import WebpackDevServer from 'webpack-dev-server';
+
+gulp.task('bundle', (cb) => {
+    if (process.env.NODE_ENV === 'development') {
+        // Important! Call webpack and WebpackDevServer must be inline.
+        new WebpackDevServer(webpack(webpackConfig), webpackConfig.devServer)
+            .listen(webpackConfig.devServer.port, 'localhost', cb);
+    }
+    else
+        webpack(webpackConfig, cb);
 });
 
-gulp.task('bundle:ignite:app', () =>
-    jspm.bundle(`${srcDir}/index - ${destDir}/vendors`, `${destDir}/app.js`, options)
-);
-
-gulp.task('bundle:ignite:app-min', () =>
-    jspm.bundleSFX(`${srcDir}/index`, `${destDir}/app.min.js`, options)
-);
-
-gulp.task('bundle:ignite:app-min:replace', () =>
-    gulp.src('./build/index.html')
-        .pipe(htmlReplace({
-            css: 'app.min.css',
-            js: 'app.min.js'
-        }))
-        .pipe(gulp.dest('./build'))
-);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/clean.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/clean.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/clean.js
index 4c821e8..c9104b2 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/clean.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/clean.js
@@ -16,16 +16,13 @@
  */
 
 import gulp from 'gulp';
-import ignore from 'gulp-ignore';
 import clean from 'gulp-rimraf';
 
 import { destDir, igniteModulesTemp } from '../paths';
 
 // Clean build folder, remove files.
 gulp.task('clean', () =>
-    gulp.src(`${ destDir }/*`, {read: false})
-        .pipe(ignore('jspm_packages'))
-        .pipe(ignore('system.config.js'))
+    gulp.src(`${destDir}/*`, {read: false})
         .pipe(clean({ force: true }))
 );
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/connect.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/connect.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/connect.js
deleted file mode 100644
index 4bffe50..0000000
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/connect.js
+++ /dev/null
@@ -1,47 +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.
- */
-
-import gulp from 'gulp';
-import connect from 'gulp-connect';
-import proxy from 'http-proxy-middleware';
-
-import { destDir } from '../paths';
-
-// Task run static server to local development.
-gulp.task('connect', () => {
-    connect.server({
-        port: 8090,
-        root: [destDir],
-        middleware() {
-            return [
-                proxy('/socket.io', {
-                    target: 'http://localhost:3000',
-                    changeOrigin: true,
-                    ws: true
-                }),
-                proxy('/api/v1/', {
-                    target: 'http://localhost:3000',
-                    changeOrigin: true,
-                    pathRewrite: {
-                        '^/api/v1/': '/' // remove path
-                    }
-                })
-            ];
-        },
-        fallback: `${destDir}/index.html`
-    });
-});

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/gulpfile.babel.js/tasks/copy.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/copy.js b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/copy.js
index c97f11a..59373a8 100644
--- a/modules/web-console/src/main/js/gulpfile.babel.js/tasks/copy.js
+++ b/modules/web-console/src/main/js/gulpfile.babel.js/tasks/copy.js
@@ -16,42 +16,18 @@
  */
 
 import gulp from 'gulp';
-import util from 'gulp-util';
-import cache from 'gulp-cached';
 import sequence from 'gulp-sequence';
 
-import { destDir, jsPaths, jsModulePaths, resourcePaths, resourceModulePaths, igniteModulesTemp } from '../paths';
+import { destDir, resourcePaths, resourceModulePaths } from '../paths';
 
-gulp.task('copy', (cb) => {
-    const tasks = ['copy:resource', 'copy:ignite_modules:resource'];
+gulp.task('copy:resource', (cb) => sequence('copy:resource:app', 'copy:resource:ignite_modules', cb));
 
-    if (util.env.debug || util.env.sourcemaps) {
-        tasks.push('copy:js');
-
-        tasks.push('copy:ignite_modules:js');
-    }
-
-    return sequence(tasks, cb);
-});
-
-gulp.task('copy:js', () =>
-    gulp.src(jsPaths, {base: './'})
-        .pipe(cache('copy:js'))
-        .pipe(gulp.dest(destDir))
-);
-
-gulp.task('copy:ignite_modules:js', () =>
-    gulp.src(jsModulePaths)
-        .pipe(cache('copy:ignite_modules:js'))
-        .pipe(gulp.dest(`${destDir}/${igniteModulesTemp}`))
-);
-
-gulp.task('copy:resource', () =>
+gulp.task('copy:resource:app', () =>
     gulp.src(resourcePaths)
         .pipe(gulp.dest(destDir))
 );
 
-gulp.task('copy:ignite_modules:resource', () =>
+gulp.task('copy:resource:ignite_modules', () =>
     gulp.src(resourceModulePaths)
         .pipe(gulp.dest(`${destDir}/ignite_modules`))
 );


[45/46] ignite git commit: Merge branch 'gridgain-7.6.2'

Posted by sb...@apache.org.
Merge branch 'gridgain-7.6.2'


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

Branch: refs/heads/ignite-1232
Commit: c9a0b8cfe7597d736796511ded87781cf9a064a6
Parents: 5b0dbca 6b8020d
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Jul 20 11:56:35 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Jul 20 11:56:35 2016 +0300

----------------------------------------------------------------------
 .../PlatformDotNetConfigurationClosure.java     |  5 +++++
 modules/platforms/cpp/jni/src/java.cpp          | 20 ++++++++++----------
 .../Apache.Ignite.Core.Tests.csproj             |  1 +
 .../Config/Cache/Affinity/affinity-function.xml |  2 +-
 .../Apache.Ignite.Core.csproj                   |  3 +++
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        |  9 +++++----
 6 files changed, 25 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c9a0b8cf/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/dotnet/PlatformDotNetConfigurationClosure.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/c9a0b8cf/modules/platforms/cpp/jni/src/java.cpp
----------------------------------------------------------------------
diff --cc modules/platforms/cpp/jni/src/java.cpp
index 685afd3,56e042c..0af7ef4
--- a/modules/platforms/cpp/jni/src/java.cpp
+++ b/modules/platforms/cpp/jni/src/java.cpp
@@@ -370,9 -366,7 +370,9 @@@ namespace ignit
              JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_ASSIGN_PARTITIONS = JniMethod("affinityFunctionAssignPartitions", "(JJJJ)V", true);
              JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_REMOVE_NODE = JniMethod("affinityFunctionRemoveNode", "(JJJ)V", true);
              JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_DESTROY = JniMethod("affinityFunctionDestroy", "(JJ)V", true);
-             
+ 
 +            JniMethod M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE = JniMethod("consoleWrite", "(Ljava/lang/String;Z)V", true);
 +
              const char* C_PLATFORM_UTILS = "org/apache/ignite/internal/processors/platform/utils/PlatformUtils";
              JniMethod M_PLATFORM_UTILS_REALLOC = JniMethod("reallocate", "(JI)V", true);
              JniMethod M_PLATFORM_UTILS_ERR_DATA = JniMethod("errorData", "(Ljava/lang/Throwable;)[B", true);
@@@ -2508,35 -2488,6 +2508,35 @@@
                  }
              }
  
 +            void JniContext::SetConsoleHandler(ConsoleWriteHandler consoleHandler) {
 +                if (!consoleHandler)
 +                    throw std::invalid_argument("consoleHandler can not be null");
 +
 +                CONSOLE_LOCK.Enter();
-                     
++
 +                consoleWriteHandlers.push_back(consoleHandler);
 +
 +                CONSOLE_LOCK.Leave();
 +            }
 +
 +            int JniContext::RemoveConsoleHandler(ConsoleWriteHandler consoleHandler) {
 +                if (!consoleHandler)
 +                    throw std::invalid_argument("consoleHandler can not be null");
 +
 +                CONSOLE_LOCK.Enter();
 +
 +                int oldSize = static_cast<int>(consoleWriteHandlers.size());
-                     
-                 consoleWriteHandlers.erase(remove(consoleWriteHandlers.begin(), consoleWriteHandlers.end(), 
++
++                consoleWriteHandlers.erase(remove(consoleWriteHandlers.begin(), consoleWriteHandlers.end(),
 +                    consoleHandler), consoleWriteHandlers.end());
 +
 +                int removedCnt = oldSize - static_cast<int>(consoleWriteHandlers.size());
 +
 +                CONSOLE_LOCK.Leave();
 +
 +                return removedCnt;
 +            }
 +
              void JniContext::ThrowToJava(char* msg) {
                  JNIEnv* env = Attach();
  

http://git-wip-us.apache.org/repos/asf/ignite/blob/c9a0b8cf/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --cc modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 5c10612,f5eef65..9373f35
--- 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
@@@ -58,11 -56,9 +58,12 @@@
      <Compile Include="Binary\BinaryBuilderSelfTestFullFooter.cs" />
      <Compile Include="Binary\BinaryCompactFooterInteropTest.cs" />
      <Compile Include="Binary\BinarySelfTestFullFooter.cs" />
 -    <Compile Include="Cache\CacheAffinityFieldTest.cs" />
 +    <Compile Include="Binary\BinaryStringTest.cs" />
 +    <Compile Include="Cache\Affinity\AffinityFieldTest.cs" />
 +    <Compile Include="Cache\Affinity\AffinityFunctionSpringTest.cs" />
 +    <Compile Include="Cache\Affinity\AffinityFunctionTest.cs" />
      <Compile Include="Cache\CacheConfigurationTest.cs" />
+     <Compile Include="Cache\Affinity\AffinityFunctionSpringTest.cs" />
      <Compile Include="Cache\CacheDynamicStartTest.cs" />
      <Compile Include="Cache\CacheNearTest.cs" />
      <Compile Include="Cache\CacheTestAsyncWrapper.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/c9a0b8cf/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/ignite/blob/c9a0b8cf/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --cc modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index b0adf61,823f9f2..f6569b1
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@@ -166,16 -164,13 +166,19 @@@
      <Compile Include="Common\IgniteFutureCancelledException.cs" />
      <Compile Include="Common\IgniteGuid.cs" />
      <Compile Include="Common\Package-Info.cs" />
 +    <Compile Include="Impl\Binary\DateTimeSerializer.cs" />
 +    <Compile Include="Impl\Binary\SerializableSerializer.cs" />
      <Compile Include="Impl\Binary\BinaryWriterExtensions.cs" />
      <Compile Include="Impl\Cache\Affinity\AffinityFunctionBase.cs" />
 +    <Compile Include="Impl\Binary\UserSerializerProxy.cs" />
 +    <Compile Include="Impl\Cache\Affinity\AffinityFunctionSerializer.cs" />
 +    <Compile Include="Impl\Cache\Affinity\PlatformAffinityFunction.cs" />
 +    <Compile Include="Impl\Common\ObjectInfoHolder.cs" />
      <Compile Include="Impl\Common\Platform.cs" />
+     <Compile Include="Impl\Cache\Affinity\AffinityFunctionSerializer.cs" />
+     <Compile Include="Impl\Cache\Affinity\PlatformAffinityFunction.cs" />
      <Compile Include="Impl\Cache\Event\JavaCacheEntryEventFilter.cs" />
+     <Compile Include="Impl\Common\ObjectInfoHolder.cs" />
      <Compile Include="Impl\Common\PlatformJavaObjectFactoryProxy.cs" />
      <Compile Include="Compute\ComputeExecutionRejectedException.cs" />
      <Compile Include="Compute\ComputeJobAdapter.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/c9a0b8cf/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
----------------------------------------------------------------------
diff --cc modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
index 9719bba,b3489a2..ad8c8aa
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@@ -55,13 -56,6 +56,13 @@@ namespace Apache.Ignite.Core.Impl.Unman
          Justification = "This class instance usually lives as long as the app runs.")]
      internal unsafe class UnmanagedCallbacks
      {
 +        /** Console write delegate. */
 +        private static readonly ConsoleWriteDelegate ConsoleWriteDel = ConsoleWrite;
 +
 +        /** Console write pointer. */
-         private static readonly void* ConsoleWritePtr = 
++        private static readonly void* ConsoleWritePtr =
 +            Marshal.GetFunctionPointerForDelegate(ConsoleWriteDel).ToPointer();
 +
          /** Unmanaged context. */
          private volatile UnmanagedContext _ctx;
  
@@@ -940,12 -932,7 +941,12 @@@
          {
              SafeCall(() =>
              {
 -                var svc = _handleRegistry.Get<IService>(svcPtr, true);
 +                var svc = _handleRegistry.Get<IService>(svcPtr);
 +
 +                // Ignite does not guarantee that Cancel is called after Execute exits
 +                // So missing handle is a valid situation
 +                if (svc == null)
-                     return;   
++                    return;
  
                  using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
                  {


[11/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
Ignite Web Console speed up bundle rebuild and watch. Minor fixes.


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

Branch: refs/heads/ignite-1232
Commit: c38b3ba2fe7a8e63d45259bc78aa47145c2032fd
Parents: e3c29d8
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Jul 13 16:22:31 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Jul 13 16:22:31 2016 +0700

----------------------------------------------------------------------
 modules/web-console/DEVNOTES.txt                |   29 +-
 modules/web-console/src/main/js/.gitignore      |    2 -
 .../web-console/src/main/js/app/app.config.js   |   86 +
 modules/web-console/src/main/js/app/app.js      |  274 +++
 .../main/js/app/controllers/auth.controller.js  |   30 +
 .../js/app/controllers/notebooks.controller.js  |   69 +
 .../controllers/reset-password.controller.js    |   51 +
 .../js/app/directives/auto-focus.directive.js   |   26 +
 .../directives/centered/centered.directive.js   |    2 +-
 .../directives/copy-to-clipboard.directive.js   |   29 +
 .../information/information.directive.js        |    4 +-
 .../main/js/app/directives/match.directive.js   |   27 +
 .../app/directives/on-click-focus.directive.js  |   26 +
 .../directives/on-enter-focus-move.directive.js |   29 +
 .../js/app/directives/on-enter.directive.js     |   32 +
 .../js/app/directives/on-escape.directive.js    |   32 +
 .../ui-ace-docker/ui-ace-docker.directive.js    |    4 +-
 .../ui-ace-java/ui-ace-java.directive.js        |    4 +-
 .../ui-ace-pojos/ui-ace-pojos.directive.js      |    4 +-
 .../ui-ace-pom/ui-ace-pom.directive.js          |    4 +-
 .../ui-ace-xml/ui-ace-xml.directive.js          |    4 +-
 .../js/app/filters/domainsValidation.filter.js  |   33 +
 .../src/main/js/app/helpers/jade/mixins.jade    |   26 +-
 modules/web-console/src/main/js/app/index.js    |  241 ---
 .../src/main/js/app/modules/Demo/Demo.module.js |   15 +-
 .../src/main/js/app/modules/ace.module.js       |    4 +-
 .../main/js/app/modules/agent/agent.module.js   |   10 +-
 .../js/app/modules/branding/branding.module.js  |    1 -
 .../modules/branding/header-logo.directive.js   |    4 +-
 .../branding/powered-by-apache.directive.js     |    4 +-
 .../configuration/EventGroups.provider.js       |    2 +-
 .../configuration/generator/Pom.service.js      |    2 +-
 .../js/app/modules/dialog/dialog.factory.js     |    4 +-
 .../field/bs-select-placeholder.directive.js    |    7 +-
 .../modules/form/field/dropdown.directive.js    |    9 +-
 .../js/app/modules/form/field/dropdown.jade     |    4 +-
 .../main/js/app/modules/form/field/field.css    |    2 +-
 .../app/modules/form/field/field.directive.js   |    6 +-
 .../form/field/input/checkbox.directive.js      |    9 +-
 .../form/field/input/datalist.directive.js      |    9 +-
 .../app/modules/form/field/input/datalist.jade  |    2 +-
 .../form/field/input/number.directive.js        |    9 +-
 .../modules/form/field/input/text.directive.js  |   11 +-
 .../app/modules/form/group/group.directive.js   |    4 +-
 .../app/modules/form/group/table.directive.js   |    4 +-
 .../app/modules/form/panel/revert.directive.js  |    4 +-
 .../getting-started/GettingStarted.provider.js  |    2 +-
 .../js/app/modules/loading/loading.directive.js |   10 +-
 .../js/app/modules/loading/loading.service.js   |    2 +-
 .../caches/concurrency.directive.js             |    4 +-
 .../configuration/caches/general.directive.js   |    4 +-
 .../states/configuration/caches/general.jade    |    2 +-
 .../configuration/caches/memory.directive.js    |    4 +-
 .../configuration/caches/query.directive.js     |    4 +-
 .../configuration/caches/rebalance.directive.js |    4 +-
 .../caches/server-near-cache.directive.js       |    4 +-
 .../caches/statistics.directive.js              |    4 +-
 .../configuration/caches/store.directive.js     |    4 +-
 .../states/configuration/caches/store.jade      |    4 +-
 .../configuration/clusters/atomic.directive.js  |    4 +-
 .../clusters/attributes.directive.js            |    4 +-
 .../configuration/clusters/binary.directive.js  |    4 +-
 .../clusters/collision.directive.js             |    4 +-
 .../clusters/collision/custom.directive.js      |    4 +-
 .../clusters/collision/fifo-queue.directive.js  |    4 +-
 .../collision/job-stealing.directive.js         |    4 +-
 .../collision/priority-queue.directive.js       |    4 +-
 .../clusters/communication.directive.js         |    4 +-
 .../clusters/connector.directive.js             |    4 +-
 .../clusters/deployment.directive.js            |    4 +-
 .../clusters/discovery.directive.js             |    4 +-
 .../configuration/clusters/events.directive.js  |    4 +-
 .../clusters/failover.directive.js              |    4 +-
 .../configuration/clusters/general.directive.js |    4 +-
 .../general/discovery/cloud.directive.js        |    4 +-
 .../general/discovery/google.directive.js       |    4 +-
 .../general/discovery/jdbc.directive.js         |    4 +-
 .../general/discovery/multicast.directive.js    |    4 +-
 .../clusters/general/discovery/s3.directive.js  |    4 +-
 .../general/discovery/shared.directive.js       |    4 +-
 .../clusters/general/discovery/vm.directive.js  |    4 +-
 .../clusters/general/discovery/vm.jade          |    2 +-
 .../general/discovery/zookeeper.directive.js    |    4 +-
 .../bounded-exponential-backoff.directive.js    |    4 +-
 .../zookeeper/retrypolicy/custom.directive.js   |    4 +-
 .../exponential-backoff.directive.js            |    4 +-
 .../zookeeper/retrypolicy/forever.directive.js  |    4 +-
 .../zookeeper/retrypolicy/n-times.directive.js  |    4 +-
 .../zookeeper/retrypolicy/one-time.directive.js |    4 +-
 .../retrypolicy/until-elapsed.directive.js      |    4 +-
 .../configuration/clusters/igfs.directive.js    |    4 +-
 .../configuration/clusters/logger.directive.js  |    4 +-
 .../clusters/logger/custom.directive.js         |    4 +-
 .../clusters/logger/log4j.directive.js          |    4 +-
 .../clusters/logger/log4j2.directive.js         |    4 +-
 .../clusters/marshaller.directive.js            |    4 +-
 .../configuration/clusters/metrics.directive.js |    4 +-
 .../configuration/clusters/ssl.directive.js     |    4 +-
 .../configuration/clusters/swap.directive.js    |    4 +-
 .../configuration/clusters/thread.directive.js  |    4 +-
 .../configuration/clusters/time.directive.js    |    4 +-
 .../clusters/transactions.directive.js          |    4 +-
 .../configuration/domains/general.directive.js  |    4 +-
 .../configuration/domains/query.directive.js    |    4 +-
 .../states/configuration/domains/query.jade     |   14 +-
 .../configuration/domains/store.directive.js    |    4 +-
 .../states/configuration/domains/store.jade     |    8 +-
 .../states/configuration/igfs/dual.directive.js |    4 +-
 .../modules/states/configuration/igfs/dual.jade |    4 +-
 .../igfs/fragmentizer.directive.js              |    4 +-
 .../configuration/igfs/general.directive.js     |    4 +-
 .../states/configuration/igfs/ipc.directive.js  |    4 +-
 .../states/configuration/igfs/misc.directive.js |    4 +-
 .../modules/states/configuration/igfs/misc.jade |   12 +-
 .../configuration/igfs/secondary.directive.js   |    4 +-
 .../configuration/preview-panel.directive.js    |    4 +-
 .../configuration/summary/summary.controller.js |   17 +-
 .../main/js/app/modules/states/signin.state.js  |    3 +-
 .../main/js/app/modules/user/Auth.service.js    |   10 +-
 .../main/js/app/services/ChartColors.service.js |    2 +-
 .../src/main/js/app/services/Clone.service.js   |   64 +
 .../src/main/js/app/services/Confirm.service.js |   70 +
 .../js/app/services/ConfirmBatch.service.js     |   92 +
 .../js/app/services/CopyToClipboard.service.js  |   50 +
 .../main/js/app/services/Countries.service.js   |    2 +-
 .../src/main/js/app/services/Focus.service.js   |   33 +
 .../main/js/app/services/JavaTypes.service.js   |    6 +-
 .../main/js/app/services/LegacyTable.service.js |  205 +++
 .../main/js/app/services/LegacyUtils.service.js |  948 ++++++++++
 .../main/js/app/services/Messages.service.js    |   63 +
 .../js/app/services/ModelNormalizer.service.js  |   59 +
 .../app/services/UnsavedChangesGuard.service.js |   38 +
 .../src/main/js/app/services/cleanup.service.js |   46 -
 .../src/main/js/app/services/confirm.service.js |   70 -
 modules/web-console/src/main/js/app/vendor.js   |   54 +
 .../src/main/js/build/system.config.js          |  424 -----
 .../src/main/js/controllers/admin-controller.js |   33 +-
 .../main/js/controllers/caches-controller.js    |   97 +-
 .../main/js/controllers/clusters-controller.js  |  142 +-
 .../src/main/js/controllers/common-module.js    | 1741 ------------------
 .../main/js/controllers/domains-controller.js   |  295 ++-
 .../src/main/js/controllers/igfs-controller.js  |  126 +-
 .../main/js/controllers/profile-controller.js   |   27 +-
 .../src/main/js/controllers/sql-controller.js   |   75 +-
 .../src/main/js/generator/generator-java.js     |    7 +-
 .../src/main/js/generator/generator-xml.js      |    5 +-
 .../src/main/js/gulpfile.babel.js/paths.js      |   65 +-
 .../main/js/gulpfile.babel.js/tasks/build.js    |    2 +-
 .../main/js/gulpfile.babel.js/tasks/bundle.js   |   68 +-
 .../main/js/gulpfile.babel.js/tasks/clean.js    |    5 +-
 .../main/js/gulpfile.babel.js/tasks/connect.js  |   47 -
 .../src/main/js/gulpfile.babel.js/tasks/copy.js |   32 +-
 .../main/js/gulpfile.babel.js/tasks/eslint.js   |   46 -
 .../gulpfile.babel.js/tasks/ignite-modules.js   |    9 +-
 .../src/main/js/gulpfile.babel.js/tasks/sass.js |   25 -
 .../main/js/gulpfile.babel.js/tasks/watch.js    |   20 +-
 .../main/js/gulpfile.babel.js/webpack/common.js |  192 ++
 .../webpack/environments/development.js         |   64 +
 .../webpack/environments/production.js          |   45 +
 .../main/js/gulpfile.babel.js/webpack/index.js  |   32 +
 .../webpack/plugins/progress.js                 |   82 +
 modules/web-console/src/main/js/package.json    |  301 +--
 .../stylesheets/_font-awesome-custom.scss       |   27 +-
 .../src/main/js/public/stylesheets/style.scss   |   10 +-
 modules/web-console/src/main/js/serve/agent.js  |   89 +-
 .../web-console/src/main/js/serve/keys/test.crt |   13 -
 .../web-console/src/main/js/serve/keys/test.key |   18 -
 .../src/main/js/serve/routes/agent.js           |   30 +-
 .../js/views/configuration/domains-import.jade  |    2 +-
 .../main/js/views/configuration/domains.jade    |    8 +-
 .../main/js/views/configuration/summary.jade    |    2 +-
 .../src/main/js/views/includes/header.jade      |   19 +-
 .../web-console/src/main/js/views/index.jade    |   18 -
 .../web-console/src/main/js/views/reset.jade    |    4 +-
 .../src/main/js/views/settings/profile.jade     |   16 +-
 .../web-console/src/main/js/views/signin.jade   |   52 +-
 .../src/main/js/views/sql/notebook-new.jade     |    2 +-
 .../src/main/js/views/sql/paragraph-rate.jade   |    2 +-
 .../web-console/src/main/js/views/sql/sql.jade  |    6 +-
 .../main/js/views/templates/agent-download.jade |    2 +-
 .../src/main/js/views/templates/clone.jade      |    2 +-
 parent/pom.xml                                  |    8 +-
 182 files changed, 3754 insertions(+), 3909 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/DEVNOTES.txt
----------------------------------------------------------------------
diff --git a/modules/web-console/DEVNOTES.txt b/modules/web-console/DEVNOTES.txt
index 5a10a48..3732b78 100644
--- a/modules/web-console/DEVNOTES.txt
+++ b/modules/web-console/DEVNOTES.txt
@@ -3,25 +3,32 @@ Ignite Web Console Instructions
 
 How to deploy locally:
 
-1. Install locally MongoDB (version >=3.x) follow instructions from site http://docs.mongodb.org/manual/installation
+1. Install locally MongoDB (version >=3.x) follow instructions from site http://docs.mongodb.org/manual/installation.
 2. Install locally NodeJS (version >=4.x) using installer from site https://nodejs.org for your OS.
 3. Change directory '$IGNITE_HOME/modules/web-console/src/main/js'.
-4. Run "npm install" in terminal for download all dependencies.
-5. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
-6. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/src/main/js/serve/agent_dists' folder.
-
-Steps 1 - 6 should be executed once.
+4. Update npm to 3.x:
+  Linux:
+       npm install -g npm
+  Windows:
+       npm install -g npm-windows-upgrade
+       npm-windows-upgrade
+       See: https://github.com/felixrieseberg/npm-windows-upgrade
+  Check npm version: "npm --version".
+5. Run "npm install --no-optional" in terminal for download dependencies.
+6. Build ignite-web-agent module follow instructions from 'modules/web-agent/README.txt'.
+7. Copy ignite-web-agent-<version>.zip from target of ignite-web-agent module to 'modules/web-console/src/main/js/serve/agent_dists' folder.
+
+Steps 1 - 7 should be executed once.
 
 How to run console in development mode:
 
 1. Configure MongoDB to run as service or in terminal change dir to $MONGO_INSTALL_DIR/server/3.0/bin
   and start MongoDB by executing "mongod".
 
-2. In new terminal change directory to '$IGNITE_HOME/modules/web-console/src/main/js'
-  and start application by executing "npm start" (for first time) or "node serve" to start backend.
+2. In new terminal change directory to '$IGNITE_HOME/modules/web-console/src/main/js'.
+   If needed run "npm install --no-optional" (if dependencies changed) and run "node serve" to start backend.
 
 3. In new terminal change directory to '$IGNITE_HOME/modules/web-console/src/main/js'
-  and start virtual server and local changes watcher by executing "gulp watch --debug"
-  or "gulp connect" to start web server only.
+  and start webpack in development mode "npm run dev" .
 
-4. In browser open: http://localhost:8090
+4. In browser open: http://localhost:9000

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/.gitignore
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/.gitignore b/modules/web-console/src/main/js/.gitignore
index c966a99..a6af5e1 100644
--- a/modules/web-console/src/main/js/.gitignore
+++ b/modules/web-console/src/main/js/.gitignore
@@ -2,10 +2,8 @@
 *.log
 .npmrc
 build/*
-!build/system.config.js
 node_modules
 ignite_modules_temp/*
 public/stylesheets/*.css
 serve/config/*.json
 serve/agent_dists/*.zip
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/app.config.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/app.config.js b/modules/web-console/src/main/js/app/app.config.js
new file mode 100644
index 0000000..25c24b0
--- /dev/null
+++ b/modules/web-console/src/main/js/app/app.config.js
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import alertTemplateUrl from '../views/templates/alert.jade';
+
+const igniteConsoleCfg = angular.module('ignite-console.config', ['ngAnimate', 'mgcrea.ngStrap']);
+
+// Configure AngularJS animation: do not animate fa-spin.
+igniteConsoleCfg.config(['$animateProvider', ($animateProvider) => {
+    $animateProvider.classNameFilter(/^((?!(fa-spin)).)*$/);
+}]);
+
+// AngularStrap modal popup configuration.
+igniteConsoleCfg.config(['$modalProvider', ($modalProvider) => {
+    angular.extend($modalProvider.defaults, {
+        animation: 'am-fade-and-scale',
+        html: true
+    });
+}]);
+
+// AngularStrap popover configuration.
+igniteConsoleCfg.config(['$popoverProvider', ($popoverProvider) => {
+    angular.extend($popoverProvider.defaults, {
+        trigger: 'manual',
+        placement: 'right',
+        container: 'body',
+        templateUrl: '/templates/validation-error.html'
+    });
+}]);
+
+// AngularStrap tooltips configuration.
+igniteConsoleCfg.config(['$tooltipProvider', ($tooltipProvider) => {
+    angular.extend($tooltipProvider.defaults, {
+        container: 'body',
+        delay: 150,
+        placement: 'right',
+        html: 'true',
+        trigger: 'click hover'
+    });
+}]);
+
+// AngularStrap select (combobox) configuration.
+igniteConsoleCfg.config(['$selectProvider', ($selectProvider) => {
+    angular.extend($selectProvider.defaults, {
+        container: 'body',
+        maxLength: '5',
+        allText: 'Select All',
+        noneText: 'Clear All',
+        templateUrl: '/templates/select.html',
+        iconCheckmark: 'fa fa-check',
+        caretHtml: ''
+    });
+}]);
+
+// AngularStrap alerts configuration.
+igniteConsoleCfg.config(['$alertProvider', ($alertProvider) => {
+    angular.extend($alertProvider.defaults, {
+        container: 'body',
+        placement: 'top-right',
+        duration: '5',
+        templateUrl: alertTemplateUrl,
+        type: 'danger'
+    });
+}]);
+
+
+// AngularStrap dropdowns () configuration.
+igniteConsoleCfg.config(['$dropdownProvider', ($dropdownProvider) => {
+    angular.extend($dropdownProvider.defaults, {
+        templateUrl: 'templates/dropdown.html'
+    });
+}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/app.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/app.js b/modules/web-console/src/main/js/app/app.js
new file mode 100644
index 0000000..00ae3eb
--- /dev/null
+++ b/modules/web-console/src/main/js/app/app.js
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+import '../public/stylesheets/style.scss';
+
+import './app.config';
+
+import './decorator/select';
+import './decorator/tooltip';
+
+import './modules/form/form.module';
+import './modules/agent/agent.module.js';
+import './modules/query-notebooks/query-notebooks.module';
+import './modules/Demo/Demo.module.js';
+
+import './modules/states/signin.state';
+import './modules/states/logout.state';
+import './modules/states/password.state';
+import './modules/states/configuration.state';
+import './modules/states/sql.state';
+import './modules/states/profile.state';
+import './modules/states/admin.state';
+
+// ignite:modules
+import './modules/user/user.module';
+import './modules/branding/branding.module';
+import './modules/navbar/navbar.module';
+import './modules/configuration/configuration.module';
+import './modules/getting-started/GettingStarted.provider';
+import './modules/dialog/dialog.module';
+import './modules/Version/Version.provider';
+import './modules/ace.module';
+import './modules/socket.module';
+import './modules/loading/loading.module';
+// endignite
+
+// Directives.
+import igniteAutoFocus from './directives/auto-focus.directive.js';
+import igniteBsAffixUpdate from './directives/bs-affix-update.directive';
+import igniteCentered from './directives/centered/centered.directive.js';
+import igniteCopyToClipboard from './directives/copy-to-clipboard.directive.js';
+import igniteHideOnStateChange from './directives/hide-on-state-change/hide-on-state-change.directive';
+import igniteInformation from './directives/information/information.directive';
+import igniteMatch from './directives/match.directive.js';
+import igniteOnClickFocus from './directives/on-click-focus.directive.js';
+import igniteOnEnter from './directives/on-enter.directive.js';
+import igniteOnEnterFocusMove from './directives/on-enter-focus-move.directive.js';
+import igniteOnEscape from './directives/on-escape.directive.js';
+import igniteUiAceDocker from './directives/ui-ace-docker/ui-ace-docker.directive';
+import igniteUiAceJava from './directives/ui-ace-java/ui-ace-java.directive';
+import igniteUiAcePojos from './directives/ui-ace-pojos/ui-ace-pojos.directive';
+import igniteUiAcePom from './directives/ui-ace-pom/ui-ace-pom.directive';
+import igniteUiAceTabs from './directives/ui-ace-tabs.directive';
+import igniteUiAceXml from './directives/ui-ace-xml/ui-ace-xml.directive';
+
+// Services.
+import ChartColors from './services/ChartColors.service';
+import Clone from './services/Clone.service.js';
+import Confirm from './services/Confirm.service.js';
+import ConfirmBatch from './services/ConfirmBatch.service.js';
+import CopyToClipboard from './services/CopyToClipboard.service';
+import Countries from './services/Countries.service';
+import Focus from './services/Focus.service';
+import InetAddress from './services/InetAddress.service';
+import JavaTypes from './services/JavaTypes.service';
+import Messages from './services/Messages.service';
+import ModelNormalizer from './services/ModelNormalizer.service.js';
+import LegacyTable from './services/LegacyTable.service';
+import LegacyUtils from './services/LegacyUtils.service';
+import UnsavedChangesGuard from './services/UnsavedChangesGuard.service';
+
+// Providers.
+
+// Filters.
+import byName from './filters/byName.filter';
+import domainsValidation from './filters/domainsValidation.filter';
+import hasPojo from './filters/hasPojo.filter';
+
+// Generators
+import $generatorCommon from 'generator/generator-common';
+import $generatorJava from 'generator/generator-java';
+import $generatorOptional from 'generator/generator-optional';
+import $generatorProperties from 'generator/generator-properties';
+import $generatorReadme from 'generator/generator-readme';
+import $generatorXml from 'generator/generator-xml';
+
+window.$generatorCommon = $generatorCommon;
+window.$generatorJava = $generatorJava;
+window.$generatorOptional = $generatorOptional;
+window.$generatorProperties = $generatorProperties;
+window.$generatorReadme = $generatorReadme;
+window.$generatorXml = $generatorXml;
+
+// Controllers
+import admin from 'controllers/admin-controller';
+import caches from 'controllers/caches-controller';
+import clusters from 'controllers/clusters-controller';
+import domains from 'controllers/domains-controller';
+import igfs from 'controllers/igfs-controller';
+import profile from 'controllers/profile-controller';
+import sql from 'controllers/sql-controller';
+import auth from './controllers/auth.controller';
+import notebooks from './controllers/notebooks.controller';
+import resetPassword from './controllers/reset-password.controller';
+
+// Inject external modules.
+import 'ignite_modules_temp/index';
+
+import baseTemplate from '../views/base.jade';
+
+angular
+.module('ignite-console', [
+    // Optional AngularJS modules.
+    'ngAnimate',
+    'ngSanitize',
+    // Third party libs.
+    'ngRetina',
+    'btford.socket-io',
+    'mgcrea.ngStrap',
+    'ui.router',
+    'gridster',
+    'dndLists',
+    'nvd3',
+    'smart-table',
+    'treeControl',
+    'ui.grid',
+    'ui.grid.saveState',
+    'ui.grid.selection',
+    'ui.grid.resizeColumns',
+    'ui.grid.autoResize',
+    'ui.grid.exporter',
+    // Base modules.
+    'ignite-console.ace',
+    'ignite-console.Form',
+    'ignite-console.user',
+    'ignite-console.branding',
+    'ignite-console.socket',
+    'ignite-console.agent',
+    'ignite-console.query-notebooks',
+    'ignite-console.demo',
+    // States.
+    'ignite-console.states.login',
+    'ignite-console.states.logout',
+    'ignite-console.states.password',
+    'ignite-console.states.configuration',
+    'ignite-console.states.sql',
+    'ignite-console.states.profile',
+    'ignite-console.states.admin',
+    // Common modules.
+    'ignite-console.dialog',
+    'ignite-console.navbar',
+    'ignite-console.configuration',
+    'ignite-console.getting-started',
+    'ignite-console.version',
+    'ignite-console.loading',
+    // Ignite configuration module.
+    'ignite-console.config',
+    // Ignite modules.
+    'ignite-console.modules'
+])
+// Directives.
+.directive(...igniteAutoFocus)
+.directive(...igniteBsAffixUpdate)
+.directive(...igniteCentered)
+.directive(...igniteCopyToClipboard)
+.directive(...igniteHideOnStateChange)
+.directive(...igniteInformation)
+.directive(...igniteMatch)
+.directive(...igniteOnClickFocus)
+.directive(...igniteOnEnter)
+.directive(...igniteOnEnterFocusMove)
+.directive(...igniteOnEscape)
+.directive(...igniteUiAceDocker)
+.directive(...igniteUiAceJava)
+.directive(...igniteUiAcePojos)
+.directive(...igniteUiAcePom)
+.directive(...igniteUiAceTabs)
+.directive(...igniteUiAceXml)
+// Services.
+.service(...ChartColors)
+.service(...Clone)
+.service(...Confirm)
+.service(...ConfirmBatch)
+.service(...CopyToClipboard)
+.service(...Countries)
+.service(...Focus)
+.service(...InetAddress)
+.service(...JavaTypes)
+.service(...Messages)
+.service(...ModelNormalizer)
+.service(...LegacyTable)
+.service(...LegacyUtils)
+.service(...UnsavedChangesGuard)
+// Controllers.
+.controller(...admin)
+.controller(...auth)
+.controller(...notebooks)
+.controller(...resetPassword)
+.controller(...caches)
+.controller(...clusters)
+.controller(...domains)
+.controller(...igfs)
+.controller(...profile)
+.controller(...sql)
+// Filters.
+.filter(...hasPojo)
+.filter(...domainsValidation)
+.filter(...byName)
+.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', ($stateProvider, $locationProvider, $urlRouterProvider) => {
+    // Set up the states.
+    $stateProvider
+        .state('base', {
+            url: '',
+            abstract: true,
+            templateUrl: baseTemplate
+        })
+        .state('settings', {
+            url: '/settings',
+            abstract: true,
+            templateUrl: baseTemplate
+        });
+
+    $urlRouterProvider.otherwise('/');
+
+    $locationProvider.html5Mode(true);
+}])
+.run(['$rootScope', '$state', 'MetaTags', 'gettingStarted', ($root, $state, $meta, gettingStarted) => {
+    $root._ = _;
+    $root.$state = $state;
+    $root.$meta = $meta;
+    $root.gettingStarted = gettingStarted;
+}])
+.run(['$rootScope', 'Auth', 'User', 'IgniteAgentMonitor', ($root, Auth, User, agentMonitor) => {
+    if (Auth.authorized) {
+        User.read()
+            .then((user) => $root.$broadcast('user', user))
+            .then(() => Auth.authorized && agentMonitor.init());
+    }
+}])
+.run(['$rootScope', ($root) => {
+    $root.$on('$stateChangeStart', () => {
+        _.forEach(angular.element('.modal'), (m) => angular.element(m).scope().$hide());
+    });
+}])
+.run(['$rootScope', '$http', '$state', 'IgniteMessages', 'User',
+    ($root, $http, $state, Messages, User) => { // eslint-disable-line no-shadow
+        $root.revertIdentity = () => {
+            $http
+                .get('/api/v1/admin/revert/identity')
+                .then(User.read)
+                .then((user) => {
+                    $root.$broadcast('user', user);
+
+                    $state.go('settings.admin');
+                })
+                .catch(Messages.showError);
+        };
+    }
+]);
+

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/controllers/auth.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/controllers/auth.controller.js b/modules/web-console/src/main/js/app/controllers/auth.controller.js
new file mode 100644
index 0000000..21ffeb8
--- /dev/null
+++ b/modules/web-console/src/main/js/app/controllers/auth.controller.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+// Sign in controller.
+// TODO IGNITE-1936 Refactor this controller.
+export default ['auth', [
+    '$scope', 'IgniteFocus', 'IgniteCountries', 'Auth',
+    ($scope, Focus, Countries, Auth) => {
+        $scope.auth = Auth.auth;
+        $scope.forgotPassword = Auth.forgotPassword;
+        $scope.action = 'signin';
+        $scope.countries = Countries.getAll();
+
+        Focus.move('user_email');
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/controllers/notebooks.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/controllers/notebooks.controller.js b/modules/web-console/src/main/js/app/controllers/notebooks.controller.js
new file mode 100644
index 0000000..0440c46
--- /dev/null
+++ b/modules/web-console/src/main/js/app/controllers/notebooks.controller.js
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+// Controller that load notebooks in navigation bar .
+export default ['notebooks', [
+    '$rootScope', '$scope', '$modal', '$state', '$http', 'IgniteMessages',
+    ($root, $scope, $modal, $state, $http, Messages) => {
+        $root.notebooks = [];
+
+        // Pre-fetch modal dialogs.
+        const _notebookNewModal = $modal({scope: $scope, templateUrl: '/sql/notebook-new.html', show: false});
+
+        $root.rebuildDropdown = function() {
+            $scope.notebookDropdown = [
+                {text: 'Create new notebook', click: 'inputNotebookName()'},
+                {divider: true}
+            ];
+
+            _.forEach($root.notebooks, (notebook) => $scope.notebookDropdown.push({
+                text: notebook.name,
+                sref: 'base.sql.notebook({noteId:"' + notebook._id + '"})'
+            }));
+        };
+
+        $root.reloadNotebooks = function() {
+            // When landing on the page, get clusters and show them.
+            $http.post('/api/v1/notebooks/list')
+                .success((data) => {
+                    $root.notebooks = data;
+
+                    $root.rebuildDropdown();
+                })
+                .error(Messages.showError);
+        };
+
+        $root.inputNotebookName = () => {
+            _notebookNewModal.$promise.then(_notebookNewModal.show);
+        };
+
+        $root.createNewNotebook = (name) => {
+            $http.post('/api/v1/notebooks/new', {name})
+                .success((noteId) => {
+                    _notebookNewModal.hide();
+
+                    $root.reloadNotebooks();
+
+                    $state.go('base.sql.notebook', {noteId});
+                })
+                .error(Messages.showError);
+        };
+
+        $root.reloadNotebooks();
+
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/controllers/reset-password.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/controllers/reset-password.controller.js b/modules/web-console/src/main/js/app/controllers/reset-password.controller.js
new file mode 100644
index 0000000..f3cee81
--- /dev/null
+++ b/modules/web-console/src/main/js/app/controllers/reset-password.controller.js
@@ -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.
+ */
+
+// Controller for password reset.
+export default ['resetPassword', [
+    '$scope', '$modal', '$http', '$state', 'IgniteMessages', 'IgniteFocus',
+    ($scope, $modal, $http, $state, Messages, Focus) => {
+        if ($state.params.token) {
+            $http.post('/api/v1/password/validate/token', {token: $state.params.token})
+                .success((res) => {
+                    $scope.email = res.email;
+                    $scope.token = res.token;
+                    $scope.error = res.error;
+
+                    if ($scope.token && !$scope.error)
+                        Focus.move('user_password');
+                });
+        }
+
+        // Try to reset user password for provided token.
+        $scope.resetPassword = (reset_info) => {
+            $http.post('/api/v1/password/reset', reset_info)
+                .success(() => {
+                    Messages.showInfo('Password successfully changed');
+
+                    $state.go('base.configuration.clusters');
+                })
+                .error((err, state) => {
+                    Messages.showError(err);
+
+                    if (state === 503)
+                        $state.go('base.configuration.clusters');
+                });
+        };
+
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/auto-focus.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/auto-focus.directive.js b/modules/web-console/src/main/js/app/directives/auto-focus.directive.js
new file mode 100644
index 0000000..326fe1f
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/auto-focus.directive.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+// Directive to auto-focus specified element.
+export default ['igniteAutoFocus', ['$timeout', ($timeout) => {
+    return {
+        restrict: 'AC',
+        link(scope, element) {
+            $timeout(() => element[0].focus());
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/centered/centered.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/centered/centered.directive.js b/modules/web-console/src/main/js/app/directives/centered/centered.directive.js
index 719194c..4abd086 100644
--- a/modules/web-console/src/main/js/app/directives/centered/centered.directive.js
+++ b/modules/web-console/src/main/js/app/directives/centered/centered.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import './centered.css!';
+import './centered.css';
 
 export default ['centered', [() => {
     return {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js b/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js
new file mode 100644
index 0000000..ee2110e
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/copy-to-clipboard.directive.js
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+// Directive for copy to clipboard.
+export default ['igniteCopyToClipboard', ['IgniteCopyToClipboard', (CopyToClipboard) => {
+    return {
+        restrict: 'A',
+        link(scope, element, attrs) {
+            element.bind('click', () => CopyToClipboard.copy(attrs.igniteCopyToClipboard));
+
+            if (!document.queryCommandSupported('copy'))
+                element.hide();
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/information/information.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/information/information.directive.js b/modules/web-console/src/main/js/app/directives/information/information.directive.js
index 9250639..a9a2f8c 100644
--- a/modules/web-console/src/main/js/app/directives/information/information.directive.js
+++ b/modules/web-console/src/main/js/app/directives/information/information.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './information.jade!';
+import templateUrl from './information.jade';
 
 export default ['igniteInformation', [() => {
     return {
@@ -23,7 +23,7 @@ export default ['igniteInformation', [() => {
             title: '@'
         },
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true,
         transclude: true
     };

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/match.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/match.directive.js b/modules/web-console/src/main/js/app/directives/match.directive.js
new file mode 100644
index 0000000..3a45f6d
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/match.directive.js
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+// Directive to enable validation to match specified value.
+export default ['igniteMatch', ['$parse', ($parse) => {
+    return {
+        require: 'ngModel',
+        link(scope, elem, attrs, ctrl) {
+            scope.$watch(() => $parse(attrs.igniteMatch)(scope) === ctrl.$modelValue,
+                (currentValue) => ctrl.$setValidity('mismatch', currentValue));
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js b/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js
new file mode 100644
index 0000000..5c9ee88
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/on-click-focus.directive.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+// Directive to describe element that should be focused on click.
+export default ['igniteOnClickFocus', ['IgniteFocus', (Focus) => {
+    return function(scope, elem, attrs) {
+        elem.on('click', () => Focus.move(attrs.igniteOnClickFocus));
+
+        // Removes bound events in the element itself when the scope is destroyed
+        scope.$on('$destroy', () => elem.off('click'));
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js b/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js
new file mode 100644
index 0000000..2dd2884
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/on-enter-focus-move.directive.js
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+// Directive to move focus to specified element on ENTER key.
+export default ['igniteOnEnterFocusMove', ['IgniteFocus', (Focus) => {
+    return function(scope, elem, attrs) {
+        elem.on('keydown keypress', (event) => {
+            if (event.which === 13) {
+                event.preventDefault();
+
+                Focus.move(attrs.igniteOnEnterFocusMove);
+            }
+        });
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/on-enter.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-enter.directive.js b/modules/web-console/src/main/js/app/directives/on-enter.directive.js
new file mode 100644
index 0000000..459220e
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/on-enter.directive.js
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Directive to bind ENTER key press with some user action.
+export default ['igniteOnEnter', ['$timeout', ($timeout) => {
+    return function(scope, elem, attrs) {
+        elem.on('keydown keypress', (event) => {
+            if (event.which === 13) {
+                scope.$apply(() => $timeout(() => scope.$eval(attrs.igniteOnEnter)));
+
+                event.preventDefault();
+            }
+        });
+
+        // Removes bound events in the element itself when the scope is destroyed.
+        scope.$on('$destroy', () => elem.off('keydown keypress'));
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/on-escape.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/on-escape.directive.js b/modules/web-console/src/main/js/app/directives/on-escape.directive.js
new file mode 100644
index 0000000..aa1accd
--- /dev/null
+++ b/modules/web-console/src/main/js/app/directives/on-escape.directive.js
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Directive to bind ESC key press with some user action.
+export default ['igniteOnEscape', ['$timeout', ($timeout) => {
+    return function(scope, elem, attrs) {
+        elem.on('keydown keypress', (event) => {
+            if (event.which === 27) {
+                scope.$apply(() => $timeout(() => scope.$eval(attrs.igniteOnEscape)));
+
+                event.preventDefault();
+            }
+        });
+
+        // Removes bound events in the element itself when the scope is destroyed.
+        scope.$on('$destroy', () => elem.off('keydown keypress'));
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/ui-ace-docker/ui-ace-docker.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-docker/ui-ace-docker.directive.js b/modules/web-console/src/main/js/app/directives/ui-ace-docker/ui-ace-docker.directive.js
index 47a52df..08e4f76 100644
--- a/modules/web-console/src/main/js/app/directives/ui-ace-docker/ui-ace-docker.directive.js
+++ b/modules/web-console/src/main/js/app/directives/ui-ace-docker/ui-ace-docker.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './ui-ace-docker.jade!';
+import templateUrl from './ui-ace-docker.jade';
 import controller from './ui-ace-docker.controller';
 
 export default ['igniteUiAceDocker', [() => {
@@ -38,7 +38,7 @@ export default ['igniteUiAceDocker', [() => {
             data: '=ngModel'
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'ctrl',
         require: ['?^igniteUiAceTabs']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/ui-ace-java/ui-ace-java.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-java/ui-ace-java.directive.js b/modules/web-console/src/main/js/app/directives/ui-ace-java/ui-ace-java.directive.js
index cdce0fc..17d3a00 100644
--- a/modules/web-console/src/main/js/app/directives/ui-ace-java/ui-ace-java.directive.js
+++ b/modules/web-console/src/main/js/app/directives/ui-ace-java/ui-ace-java.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './ui-ace-java.jade!';
+import templateUrl from './ui-ace-java.jade';
 import controller from './ui-ace-java.controller';
 
 export default ['igniteUiAceJava', ['GeneratorJava', (generator) => {
@@ -125,7 +125,7 @@ export default ['igniteUiAceJava', ['GeneratorJava', (generator) => {
             data: '=?ngModel'
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'ctrl',
         require: ['igniteUiAceJava', '?^igniteUiAceTabs', '?^form', '?ngModel']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/ui-ace-pojos/ui-ace-pojos.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-pojos/ui-ace-pojos.directive.js b/modules/web-console/src/main/js/app/directives/ui-ace-pojos/ui-ace-pojos.directive.js
index 6222dc0..7c224b7 100644
--- a/modules/web-console/src/main/js/app/directives/ui-ace-pojos/ui-ace-pojos.directive.js
+++ b/modules/web-console/src/main/js/app/directives/ui-ace-pojos/ui-ace-pojos.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './ui-ace-pojos.jade!';
+import templateUrl from './ui-ace-pojos.jade';
 import controller from './ui-ace-pojos.controller';
 
 export default ['igniteUiAcePojos', [() => {
@@ -38,7 +38,7 @@ export default ['igniteUiAcePojos', [() => {
             pojos: '=ngModel'
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'ctrl',
         require: ['?^igniteUiAceTabs']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/ui-ace-pom/ui-ace-pom.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-pom/ui-ace-pom.directive.js b/modules/web-console/src/main/js/app/directives/ui-ace-pom/ui-ace-pom.directive.js
index 3d68ba9..2a7a878 100644
--- a/modules/web-console/src/main/js/app/directives/ui-ace-pom/ui-ace-pom.directive.js
+++ b/modules/web-console/src/main/js/app/directives/ui-ace-pom/ui-ace-pom.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './ui-ace-pom.jade!';
+import templateUrl from './ui-ace-pom.jade';
 import controller from './ui-ace-pom.controller';
 
 export default ['igniteUiAcePom', [() => {
@@ -33,7 +33,7 @@ export default ['igniteUiAcePom', [() => {
             cluster: '='
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'ctrl',
         require: ['?^igniteUiAceTabs']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js b/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js
index 1e913fb..3bae4de 100644
--- a/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js
+++ b/modules/web-console/src/main/js/app/directives/ui-ace-xml/ui-ace-xml.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './ui-ace-xml.jade!';
+import templateUrl from './ui-ace-xml.jade';
 import controller from './ui-ace-xml.controller';
 
 export default ['igniteUiAceXml', ['GeneratorXml', (generator) => {
@@ -125,7 +125,7 @@ export default ['igniteUiAceXml', ['GeneratorXml', (generator) => {
             data: '=?ngModel'
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'ctrl',
         require: ['igniteUiAceXml', '?^igniteUiAceTabs', '?^form', '?ngModel']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js b/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js
new file mode 100644
index 0000000..1a38392
--- /dev/null
+++ b/modules/web-console/src/main/js/app/filters/domainsValidation.filter.js
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// Filter domain models with key fields configuration.
+export default ['domainsValidation', ['IgniteLegacyUtils', (LegacyUtils) => (domains, valid, invalid) => {
+    if (valid && invalid)
+        return domains;
+
+    const out = [];
+
+    _.forEach(domains, function(domain) {
+        const _valid = !LegacyUtils.domainForStoreConfigured(domain) || LegacyUtils.isJavaBuiltInClass(domain.keyType) || !_.isEmpty(domain.keyFields);
+
+        if (valid && _valid || invalid && !_valid)
+            out.push(domain);
+    });
+
+    return out;
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/helpers/jade/mixins.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/helpers/jade/mixins.jade b/modules/web-console/src/main/js/app/helpers/jade/mixins.jade
index 2b8b282..08ebe87 100644
--- a/modules/web-console/src/main/js/app/helpers/jade/mixins.jade
+++ b/modules/web-console/src/main/js/app/helpers/jade/mixins.jade
@@ -42,7 +42,7 @@ mixin main-table(title, rows, focusId, click, rowTemplate, searchField)
                                 tbody
                                     tr(ng-repeat='row in displayedRows track by row._id' ignite-bs-affix-update)
                                         td
-                                            a(ng-class='{active: row._id == selectedItem._id}' on-click-focus=focusId ng-click=click) #{rowTemplate}
+                                            a(ng-class='{active: row._id == selectedItem._id}' ignite-on-click-focus=focusId ng-click=click) #{rowTemplate}
                         label.placeholder(ng-show='displayedRows.length == 0') No #{title} found
 
 //- Mixin with save, remove, clone and undo buttons.
@@ -359,8 +359,8 @@ mixin table-text-field(field, items, valid, save, placeholder, newItem)
         data-placeholder=placeholder
         data-ignite-unique=items
         data-ignite-form-field-input-autofocus='true'
-        on-enter=onEnter
-        on-escape=onEscape
+        ignite-on-enter=onEnter
+        ignite-on-escape=onEscape
         ng-blur=onBlur
     )
         block
@@ -389,8 +389,8 @@ mixin table-java-class-field(lbl, field, items, valid, save, newItem)
 
         data-placeholder='Enter fully qualified class name'
 
-        on-enter=onEnter
-        on-escape=onEscape
+        ignite-on-enter=onEnter
+        ignite-on-escape=onEscape
         ng-blur=onBlur
     )
         +error-feedback('form[ngModelName].$error.javaBuiltInClass', 'javaBuiltInClass', lbl + ' should not be the Java built-in class!')
@@ -419,8 +419,8 @@ mixin table-java-package-field(field, items, valid, save, newItem)
         data-java-package-name='true'
         data-ignite-unique=items
         data-ignite-form-field-input-autofocus='true'
-        on-enter=onEnter
-        on-escape=onEscape
+        ignite-on-enter=onEnter
+        ignite-on-escape=onEscape
         ng-blur=onBlur
     )
         block
@@ -445,8 +445,8 @@ mixin table-address-field(field, items, valid, save, newItem, portRange)
         data-ipaddress-with-port-range=portRange ? 'true' : null
         data-ignite-unique=items
         data-ignite-form-field-input-autofocus='true'
-        on-enter=onEnter
-        on-escape=onEscape
+        ignite-on-enter=onEnter
+        ignite-on-escape=onEscape
         ng-blur=onBlur
     )
         block
@@ -571,9 +571,9 @@ mixin table-pair-edit(tbl, prefix, keyPlaceholder, valPlaceholder, keyJavaBuiltI
         .fieldSep !{divider}
         .input-tip
             if keyJavaBuiltInTypes
-                input.form-control(id=keyFocusId enter-focus-next=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder bs-typeahead container='body' retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' on-escape='tableReset()')
+                input.form-control(id=keyFocusId ignite-on-enter-focus-move=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder bs-typeahead container='body' ignite-retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' ignite-on-escape='tableReset()')
             else
-                input.form-control(id=keyFocusId enter-focus-next=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder on-escape='tableReset()')
+                input.form-control(id=keyFocusId ignite-on-enter-focus-move=valFocusId type='text' ng-model=keyModel placeholder=keyPlaceholder ignite-on-escape='tableReset()')
     .col-xs-6.col-sm-6.col-md-6
         -var arg = keyModel + ', ' + valModel
         -var btnVisible = 'tablePairSaveVisible(' + tbl + ', ' + index + ')'
@@ -583,6 +583,6 @@ mixin table-pair-edit(tbl, prefix, keyPlaceholder, valPlaceholder, keyJavaBuiltI
         +btn-save(btnVisible, btnSave)
         .input-tip
             if valueJavaBuiltInTypes
-                input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder bs-typeahead container='body' retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' on-enter=btnVisibleAndSave on-escape='tableReset()')
+                input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder bs-typeahead container='body' ignite-retain-selection data-min-length='1' bs-options='javaClass for javaClass in javaBuiltInClasses' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')
             else
-                input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder on-enter=btnVisibleAndSave on-escape='tableReset()')
+                input.form-control(id=valFocusId type='text' ng-model=valModel placeholder=valPlaceholder ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/index.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/index.js b/modules/web-console/src/main/js/app/index.js
deleted file mode 100644
index 397d25f..0000000
--- a/modules/web-console/src/main/js/app/index.js
+++ /dev/null
@@ -1,241 +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.
- */
-
-import _ from 'lodash';
-import ace from 'ace';
-import angular from 'angular';
-import pdfMake from 'pdfmake';
-
-ace.config.set('basePath', '/jspm_packages/github/ajaxorg/ace-builds@1.2.3');
-
-window._ = _;
-window.require = ace.require; // TODO Should be removed after full refactoring to directives.
-window.pdfMake = pdfMake;
-
-import 'angular-animate';
-import 'angular-sanitize';
-import 'angular-strap';
-import 'angular-socket-io';
-import 'angular-retina';
-import 'angular-ui-router';
-import 'angular-ui-router-metatags';
-import 'angular-smart-table';
-import 'angular-ui-grid';
-import 'angular-drag-and-drop-lists';
-import 'angular-nvd3';
-import 'angular-tree-control';
-import 'angular-gridster';
-
-import 'bootstrap-carousel';
-import 'file-saver';
-import 'jszip';
-import 'query-command-supported';
-
-import 'public/stylesheets/style.css!';
-
-import 'angular-gridster/dist/angular-gridster.min.css!';
-import 'angular-tree-control/css/tree-control-attribute.css!';
-import 'angular-tree-control/css/tree-control.css!';
-import 'angular-ui-grid/ui-grid.css!';
-import 'angular-motion/dist/angular-motion.css!';
-
-import './decorator/select';
-import './decorator/tooltip';
-
-import './services/JavaTypes.service.js';
-import './modules/form/form.module';
-import './modules/agent/agent.module.js';
-import './modules/query-notebooks/query-notebooks.module';
-import './modules/Demo/Demo.module.js';
-
-import './modules/states/signin.state';
-import './modules/states/logout.state';
-import './modules/states/password.state';
-import './modules/states/configuration.state';
-import './modules/states/sql.state';
-import './modules/states/profile.state';
-import './modules/states/admin.state';
-
-// ignite:modules
-import './modules/user/user.module';
-import './modules/branding/branding.module';
-import './modules/navbar/navbar.module';
-import './modules/configuration/configuration.module';
-import './modules/getting-started/GettingStarted.provider';
-import './modules/dialog/dialog.module';
-import './modules/Version/Version.provider';
-import './modules/ace.module';
-import './modules/socket.module';
-import './modules/loading/loading.module';
-// endignite
-
-// Directives.
-import igniteHideOnStateChange from './directives/hide-on-state-change/hide-on-state-change.directive';
-import igniteInformation from './directives/information/information.directive';
-import igniteUiAceTabs from './directives/ui-ace-tabs.directive';
-import igniteUiAceXml from './directives/ui-ace-xml/ui-ace-xml.directive';
-import igniteUiAceJava from './directives/ui-ace-java/ui-ace-java.directive';
-import igniteUiAcePom from './directives/ui-ace-pom/ui-ace-pom.directive';
-import igniteUiAceDocker from './directives/ui-ace-docker/ui-ace-docker.directive';
-import igniteUiAcePojos from './directives/ui-ace-pojos/ui-ace-pojos.directive';
-import igniteBsAffixUpdate from './directives/bs-affix-update.directive';
-import ignite\u0421entered from './directives/centered/centered.directive.js';
-
-// Services.
-import cleanup from './services/cleanup.service';
-import confirm from './services/confirm.service';
-import IgniteInetAddress from './services/InetAddress.service';
-import IgniteCountries from './services/Countries.service';
-import IgniteChartColors from './services/ChartColors.service';
-import JavaTypes from './services/JavaTypes.service';
-
-// Providers.
-
-// Filters.
-import hasPojo from './filters/hasPojo.filter';
-import byName from './filters/byName.filter';
-
-// Generators
-import $generatorCommon from 'generator/generator-common';
-import $generatorJava from 'generator/generator-java';
-import $generatorOptional from 'generator/generator-optional';
-import $generatorProperties from 'generator/generator-properties';
-import $generatorReadme from 'generator/generator-readme';
-import $generatorXml from 'generator/generator-xml';
-
-window.$generatorCommon = $generatorCommon;
-window.$generatorJava = $generatorJava;
-window.$generatorOptional = $generatorOptional;
-window.$generatorProperties = $generatorProperties;
-window.$generatorReadme = $generatorReadme;
-window.$generatorXml = $generatorXml;
-
-// Add legacy logic;
-import consoleModule from 'controllers/common-module';
-window.consoleModule = consoleModule;
-
-import 'controllers/admin-controller';
-import 'controllers/caches-controller';
-import 'controllers/clusters-controller';
-import 'controllers/domains-controller';
-import 'controllers/igfs-controller';
-import 'controllers/profile-controller';
-import 'controllers/sql-controller';
-
-// Inject external modules.
-import 'ignite_modules_temp/index';
-
-angular
-.module('ignite-console', [
-    'ngRetina',
-    'btford.socket-io',
-    'ngAnimate',
-    'ngSanitize',
-    'mgcrea.ngStrap',
-    'ui.router',
-    'gridster',
-    // Base modules.
-    'ignite-console.ace',
-    'ignite-console.Form',
-    'ignite-console.user',
-    'ignite-console.branding',
-    'ignite-console.socket',
-    'ignite-console.agent',
-    'ignite-console.query-notebooks',
-    'ignite-console.demo',
-    // States.
-    'ignite-console.states.login',
-    'ignite-console.states.logout',
-    'ignite-console.states.password',
-    'ignite-console.states.configuration',
-    'ignite-console.states.sql',
-    'ignite-console.states.profile',
-    'ignite-console.states.admin',
-    // Common modules.
-    'ignite-console.dialog',
-    'ignite-console.navbar',
-    'ignite-console.configuration',
-    'ignite-console.getting-started',
-    'ignite-console.version',
-    'ignite-console.loading',
-    // Ignite legacy module.
-    'ignite-console.legacy',
-    // Ignite modules.
-    'ignite-console.modules'
-])
-// Directives.
-.directive(...igniteHideOnStateChange)
-.directive(...igniteInformation)
-.directive(...igniteUiAceTabs)
-.directive(...igniteUiAceXml)
-.directive(...igniteUiAceJava)
-.directive(...igniteUiAcePom)
-.directive(...igniteUiAceDocker)
-.directive(...igniteUiAcePojos)
-.directive(...igniteBsAffixUpdate)
-.directive(...ignite\u0421entered)
-// Services.
-.service(...cleanup)
-.service(...confirm)
-.service(...IgniteInetAddress)
-.service(...IgniteCountries)
-.service(...IgniteChartColors)
-.service(...JavaTypes)
-// Providers.
-// Filters.
-.filter(...hasPojo)
-.filter(...byName)
-.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', ($stateProvider, $locationProvider, $urlRouterProvider) => {
-    // Set up the states.
-    $stateProvider
-        .state('base', {
-            url: '',
-            abstract: true,
-            templateUrl: '/base.html'
-        })
-        .state('settings', {
-            url: '/settings',
-            abstract: true,
-            templateUrl: '/base.html'
-        });
-
-    $urlRouterProvider.otherwise('/');
-
-    $locationProvider.html5Mode(true);
-}])
-.config(['$animateProvider', ($animateProvider) => {
-    $animateProvider.classNameFilter(/^((?!(fa-spin)).)*$/);
-}])
-.run(['$rootScope', ($root) => {
-    $root._ = _;
-}])
-.run(['$rootScope', '$state', 'MetaTags', 'Auth', 'User', 'IgniteAgentMonitor', ($root, $state, $meta, Auth, User, agentMonitor) => {
-    $root.$state = $state;
-
-    $root.$meta = $meta;
-
-    if (Auth.authorized) {
-        User.read()
-            .then((user) => $root.$broadcast('user', user))
-            .then(() => Auth.authorized && agentMonitor.init());
-    }
-}])
-.run(['$rootScope', ($root) => {
-    $root.$on('$stateChangeStart', () => {
-        _.forEach(angular.element('.modal'), (m) => angular.element(m).scope().$hide());
-    });
-}]);

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js b/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js
index f08d84c..68aca9d 100644
--- a/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js
+++ b/modules/web-console/src/main/js/app/modules/Demo/Demo.module.js
@@ -17,7 +17,7 @@
 
 import angular from 'angular';
 
-import DEMO_INFO from 'app/data/demo-info.json!';
+import DEMO_INFO from 'app/data/demo-info.json';
 
 angular
 .module('ignite-console.demo', [
@@ -39,17 +39,16 @@ angular
         })
         .state('demo.reset', {
             url: '/demo/reset',
-            controller: ['$state', '$http', '$common', ($state, $http, $common) => {
+            controller: ['$state', '$http', 'IgniteMessages', ($state, $http, Messages) => {
                 $http.post('/api/v1/demo/reset')
                     .then(() => $state.go('base.configuration.clusters'))
-                    .catch((errMsg) => {
+                    .catch((err) => {
                         $state.go('base.configuration.clusters');
 
-                        $common.showError(errMsg);
+                        Messages.showError(err);
                     });
             }],
-            metaTags: {
-            }
+            metaTags: {}
         });
 }])
 .provider('Demo', ['$stateProvider', '$httpProvider', 'igniteSocketFactoryProvider', function($state, $http, socketFactory) {
@@ -82,14 +81,14 @@ angular
         }
     };
 }])
-.controller('demoController', ['$scope', '$state', '$window', '$confirm', ($scope, $state, $window, $confirm) => {
+.controller('demoController', ['$scope', '$state', '$window', 'IgniteConfirm', ($scope, $state, $window, Confirm) => {
     const _openTab = (stateName) => $window.open($state.href(stateName), '_blank');
 
     $scope.startDemo = () => {
         if (!$scope.user.demoCreated)
             return _openTab('demo.reset');
 
-        $confirm.confirm('Would you like to continue with previous demo session?', true, false)
+        Confirm.confirm('Would you like to continue with previous demo session?', true, false)
             .then((resume) => {
                 if (resume)
                     return _openTab('demo.resume');

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/ace.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/ace.module.js b/modules/web-console/src/main/js/app/modules/ace.module.js
index 2477965..4920a6f 100644
--- a/modules/web-console/src/main/js/app/modules/ace.module.js
+++ b/modules/web-console/src/main/js/app/modules/ace.module.js
@@ -44,13 +44,13 @@ angular
         const setOptions = (acee, session, opts) => {
             // Sets the ace worker path, if running from concatenated or minified source.
             if (angular.isDefined(opts.workerPath)) {
-                const config = window.ace.require('ace/config');
+                const config = window.ace.acequire('ace/config');
 
                 config.set('workerPath', opts.workerPath);
             }
 
             // Ace requires loading.
-            _.forEach(opts.require, (n) => window.ace.require(n));
+            _.forEach(opts.require, (n) => window.ace.acequire(n));
 
             // Boolean options.
             if (angular.isDefined(opts.showGutter))

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/agent/agent.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/agent/agent.module.js b/modules/web-console/src/main/js/app/modules/agent/agent.module.js
index 4e3f7ef..ca95166 100644
--- a/modules/web-console/src/main/js/app/modules/agent/agent.module.js
+++ b/modules/web-console/src/main/js/app/modules/agent/agent.module.js
@@ -19,7 +19,7 @@ import angular from 'angular';
 import io from 'socket.io-client'; // eslint-disable-line no-unused-vars
 
 class IgniteAgentMonitor {
-    constructor(socketFactory, $root, $q, $state, $modal, $common) {
+    constructor(socketFactory, $root, $q, $state, $modal, Messages) {
         this._scope = $root.$new();
 
         $root.$watch('user', () => {
@@ -45,7 +45,7 @@ class IgniteAgentMonitor {
          * Special dialog hide function.
          */
         this._downloadAgentModal.hide = () => {
-            $common.hideAlert();
+            Messages.hideAlert();
 
             _modalHide();
         };
@@ -87,7 +87,7 @@ class IgniteAgentMonitor {
 
         this._$q = $q;
 
-        this._$common = $common;
+        this.Messages = Messages;
     }
 
     /**
@@ -234,7 +234,7 @@ class IgniteAgentMonitor {
         if (this._scope.showModal) {
             this._downloadAgentModal.$promise.then(this._downloadAgentModal.show);
 
-            this._$common.showError(err);
+            this.Messages.showError(err);
         }
     }
 
@@ -314,7 +314,7 @@ class IgniteAgentMonitor {
     }
 }
 
-IgniteAgentMonitor.$inject = ['igniteSocketFactory', '$rootScope', '$q', '$state', '$modal', '$common'];
+IgniteAgentMonitor.$inject = ['igniteSocketFactory', '$rootScope', '$q', '$state', '$modal', 'IgniteMessages'];
 
 angular
     .module('ignite-console.agent', [

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/branding/branding.module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/branding/branding.module.js b/modules/web-console/src/main/js/app/modules/branding/branding.module.js
index bd28c68..cae7c91 100644
--- a/modules/web-console/src/main/js/app/modules/branding/branding.module.js
+++ b/modules/web-console/src/main/js/app/modules/branding/branding.module.js
@@ -43,4 +43,3 @@ angular
 .directive(...igniteTerms)
 .directive(...igniteFeatures)
 .directive(...igniteFooter);
-

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js b/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js
index 1bfbc45..423de9c 100644
--- a/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js
+++ b/modules/web-console/src/main/js/app/modules/branding/header-logo.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './header-logo.jade!';
+import templateUrl from './header-logo.jade';
 
 export default ['igniteHeaderLogo', ['IgniteBranding', (branding) => {
     function controller() {
@@ -26,7 +26,7 @@ export default ['igniteHeaderLogo', ['IgniteBranding', (branding) => {
 
     return {
         restrict: 'E',
-        template,
+        templateUrl,
         controller,
         controllerAs: 'logo',
         replace: true

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js b/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js
index 37f1dec..2f02446 100644
--- a/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js
+++ b/modules/web-console/src/main/js/app/modules/branding/powered-by-apache.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import templatePoweredByApache from './powered-by-apache.jade!';
+import templateUrl from './powered-by-apache.jade';
 
 export default ['ignitePoweredByApache', ['IgniteBranding', (branding) => {
     function controller() {
@@ -26,7 +26,7 @@ export default ['ignitePoweredByApache', ['IgniteBranding', (branding) => {
 
     return {
         restrict: 'E',
-        template: templatePoweredByApache,
+        templateUrl,
         controller,
         controllerAs: 'poweredBy',
         replace: true

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/configuration/EventGroups.provider.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/configuration/EventGroups.provider.js b/modules/web-console/src/main/js/app/modules/configuration/EventGroups.provider.js
index 2bbf11f..61f3188 100644
--- a/modules/web-console/src/main/js/app/modules/configuration/EventGroups.provider.js
+++ b/modules/web-console/src/main/js/app/modules/configuration/EventGroups.provider.js
@@ -16,7 +16,7 @@
  */
 
 // Events groups.
-import GROUPS from 'app/data/event-types.json!';
+import GROUPS from 'app/data/event-types.json';
 
 export default ['igniteEventGroups', function() {
     const groups = GROUPS;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/configuration/generator/Pom.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/configuration/generator/Pom.service.js b/modules/web-console/src/main/js/app/modules/configuration/generator/Pom.service.js
index 3508e59..674c16e 100644
--- a/modules/web-console/src/main/js/app/modules/configuration/generator/Pom.service.js
+++ b/modules/web-console/src/main/js/app/modules/configuration/generator/Pom.service.js
@@ -16,7 +16,7 @@
  */
 
 // Java built-in class names.
-import POM_DEPENDENCIES from 'app/data/pom-dependencies.json!';
+import POM_DEPENDENCIES from 'app/data/pom-dependencies.json';
 
 /**
  * Pom file generation entry point.

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/dialog/dialog.factory.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/dialog/dialog.factory.js b/modules/web-console/src/main/js/app/modules/dialog/dialog.factory.js
index 18a2174..e15891f 100644
--- a/modules/web-console/src/main/js/app/modules/dialog/dialog.factory.js
+++ b/modules/web-console/src/main/js/app/modules/dialog/dialog.factory.js
@@ -15,11 +15,11 @@
  * limitations under the License.
  */
 
-import template from './dialog.jade!';
+import templateUrl from './dialog.jade';
 
 export default ['IgniteDialog', ['$modal', ($modal) => {
     const defaults = {
-        template: template(),
+        templateUrl,
         placement: 'center',
         show: false
     };

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/bs-select-placeholder.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/bs-select-placeholder.directive.js b/modules/web-console/src/main/js/app/modules/form/field/bs-select-placeholder.directive.js
index 035fed4..83f438d 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/bs-select-placeholder.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/bs-select-placeholder.directive.js
@@ -28,12 +28,13 @@ export default ['bsSelect', [() => {
 
             const value = ngModel.$viewValue;
 
-            if (value && (!attrs.multiple || value.length))
-                $element.removeClass('placeholder');
-            else {
+            if (_.isNil(value) || (attrs.multiple && !value.length)) {
                 $element.html(attrs.placeholder);
+
                 $element.addClass('placeholder');
             }
+            else
+                $element.removeClass('placeholder');
         };
     };
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/dropdown.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/dropdown.directive.js b/modules/web-console/src/main/js/app/modules/form/field/dropdown.directive.js
index fe4d948..23c900a 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/dropdown.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/dropdown.directive.js
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-import template from './dropdown.jade!';
+import templateUrl from './dropdown.jade';
 
-export default ['igniteFormFieldDropdown', ['IgniteFormGUID', '$table', (guid, $table) => {
+export default ['igniteFormFieldDropdown', ['IgniteFormGUID', 'IgniteLegacyTable', (guid, LegacyTable) => {
     const controller = () => {};
 
     const link = (scope, $element, attrs, [form, label]) => {
@@ -48,9 +48,8 @@ export default ['igniteFormFieldDropdown', ['IgniteFormGUID', '$table', (guid, $
         scope.$watch(() => form.$pristine, setAsDefault);
         scope.$watch('value', setAsDefault);
 
-        // TODO LEGACY
         scope.tableReset = () => {
-            $table.tableSaveAndReset();
+            LegacyTable.tableSaveAndReset();
         };
     };
 
@@ -74,7 +73,7 @@ export default ['igniteFormFieldDropdown', ['IgniteFormGUID', '$table', (guid, $
             multiple: '='
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'dropdown',
         replace: true,

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/dropdown.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/dropdown.jade b/modules/web-console/src/main/js/app/modules/form/field/dropdown.jade
index 48b55d9..5b7cdf6 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/dropdown.jade
+++ b/modules/web-console/src/main/js/app/modules/form/field/dropdown.jade
@@ -30,7 +30,7 @@
 
         data-ng-required='required || false'
 
-        on-enter='{{ onEnter }}'
+        ignite-on-enter='{{ onEnter }}'
 
         tabindex='0'
 
@@ -51,7 +51,7 @@
 
         data-ng-required='required || false'
 
-        on-enter='{{ onEnter }}'
+        ignite-on-enter='{{ onEnter }}'
 
         tabindex='0'
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/field.css
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/field.css b/modules/web-console/src/main/js/app/modules/form/field/field.css
index 8dfe05e..3ea64f4 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/field.css
+++ b/modules/web-console/src/main/js/app/modules/form/field/field.css
@@ -16,7 +16,7 @@
  */
 
 .indexField {
-	float: left;
+    float: left;
     line-height: 28px;
     margin-right: 5px;
     color: #ec1c24;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/field.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/field.directive.js b/modules/web-console/src/main/js/app/modules/form/field/field.directive.js
index 0e3fe8d..630f74f 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/field.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/field.directive.js
@@ -15,8 +15,8 @@
  * limitations under the License.
  */
 
-import template from './field.jade!';
-import './field.css!';
+import templateUrl from './field.jade';
+import './field.css';
 
 export default ['igniteFormField', [() => {
     const controller = [function() {
@@ -34,7 +34,7 @@ export default ['igniteFormField', [() => {
             type: '@',
             name: '@'
         },
-        template,
+        templateUrl,
         controller,
         controllerAs: 'field',
         replace: true,


[26/46] ignite git commit: Merge remote-tracking branch 'remotes/origin/master' into ignite-1232

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


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

Branch: refs/heads/ignite-1232
Commit: d6846ffab680bc065a013f305317ac38ea4e3f4f
Parents: 6c55558 054b4eb
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 19 11:19:14 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jul 19 11:19:14 2016 +0300

----------------------------------------------------------------------
 .../store/jdbc/CacheAbstractJdbcStore.java      | 101 ++++------------
 .../cache/store/jdbc/CacheJdbcPojoStore.java    |   7 +-
 .../store/jdbc/CacheJdbcPojoStoreFactory.java   |  26 +++++
 .../store/jdbc/JdbcTypesDefaultTransformer.java | 117 +++++++++++++++++++
 .../cache/store/jdbc/JdbcTypesTransformer.java  |  39 +++++++
 5 files changed, 207 insertions(+), 83 deletions(-)
----------------------------------------------------------------------



[02/46] ignite git commit: IGNITE-3227 - Added method to get partition size

Posted by sb...@apache.org.
IGNITE-3227 - Added method to get partition size


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

Branch: refs/heads/ignite-1232
Commit: 0b118553cffa8bac970474df27086d2e7a82b4e9
Parents: b20e45c
Author: Alexey Goncharuk <al...@gmail.com>
Authored: Thu Jul 7 15:58:50 2016 -0700
Committer: Alexey Goncharuk <al...@gmail.com>
Committed: Thu Jul 7 16:00:04 2016 -0700

----------------------------------------------------------------------
 .../java/org/apache/ignite/IgniteCache.java     |  25 +
 .../processors/cache/GridCacheAdapter.java      | 215 ++++++++-
 .../processors/cache/GridCacheProxyImpl.java    |  36 ++
 .../processors/cache/IgniteCacheProxy.java      |  40 ++
 .../processors/cache/IgniteInternalCache.java   |  23 +
 .../cache/IgniteCacheAtomicPeekModesTest.java   |   2 +-
 .../cache/IgniteCachePeekModesAbstractTest.java | 463 ++++++++++++++++++-
 .../multijvm/IgniteCacheProcessProxy.java       |  46 +-
 8 files changed, 846 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
index 3a76dd3..40eedaf 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteCache.java
@@ -370,6 +370,20 @@ public interface IgniteCache<K, V> extends javax.cache.Cache<K, V>, IgniteAsyncS
     public long sizeLong(CachePeekMode... peekModes) throws CacheException;
 
     /**
+     * Gets the number of all entries cached in a partition as a long value. By default, if {@code peekModes} value
+     * isn't defined, only size of primary copies across all nodes will be returned. This behavior is identical to
+     * calling this method with {@link CachePeekMode#PRIMARY} peek mode.
+     * <p>
+     * NOTE: this operation is distributed and will query all participating nodes for their partition cache sizes.
+     *
+     * @param partition partition.
+     * @param peekModes Optional peek modes. If not provided, then total partition cache size is returned.
+     * @return Partion cache size across all nodes.
+     */
+    @IgniteAsyncSupported
+    public long sizeLong(int partition, CachePeekMode... peekModes) throws CacheException;
+
+    /**
      * Gets the number of all entries cached on this node. By default, if {@code peekModes} value isn't defined,
      * only size of primary copies will be returned. This behavior is identical to calling this method with
      * {@link CachePeekMode#PRIMARY} peek mode.
@@ -390,6 +404,17 @@ public interface IgniteCache<K, V> extends javax.cache.Cache<K, V>, IgniteAsyncS
     public long localSizeLong(CachePeekMode... peekModes);
 
     /**
+     * Gets the number of all entries cached on this node for the partition as a long value. By default, if {@code peekModes} value isn't
+     * defined, only size of primary copies will be returned. This behavior is identical to calling this method with
+     * {@link CachePeekMode#PRIMARY} peek mode.
+     *
+     * @param partition partition.
+     * @param peekModes Optional peek modes. If not provided, then total cache size is returned.
+     * @return Cache size on this node.
+     */
+    public long localSizeLong(int partition, CachePeekMode... peekModes);
+
+    /**
      * @param map Map containing keys and entry processors to be applied to values.
      * @param args Additional arguments to pass to the {@link EntryProcessor}.
      * @return The map of {@link EntryProcessorResult}s of the processing per key,

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index 26730aa..90669e0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -84,6 +84,7 @@ import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.processors.cache.affinity.GridCacheAffinityImpl;
 import org.apache.ignite.internal.processors.cache.distributed.IgniteExternalizableExpiryPolicy;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtCacheAdapter;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
 import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtInvalidPartitionException;
 import org.apache.ignite.internal.processors.cache.dr.GridCacheDrInfo;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
@@ -3841,6 +3842,14 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /** {@inheritDoc} */
+    @Override public long sizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException {
+        if (isLocal())
+            return localSizeLong(partition, peekModes);
+
+        return sizeLongAsync(partition, peekModes).get();
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteInternalFuture<Integer> sizeAsync(final CachePeekMode[] peekModes) {
         assert peekModes != null;
 
@@ -3883,6 +3892,36 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Long> sizeLongAsync(final int part, final CachePeekMode[] peekModes) {
+        assert peekModes != null;
+
+        final PeekModes modes = parsePeekModes(peekModes, true);
+
+        IgniteClusterEx cluster = ctx.grid().cluster();
+        final GridCacheAffinityManager aff = ctx.affinity();
+        final AffinityTopologyVersion topVer = aff.affinityTopologyVersion();
+
+        ClusterGroup grp = cluster.forDataNodes(name());
+
+        Collection<ClusterNode> nodes = grp.forPredicate(new IgnitePredicate<ClusterNode>() {
+            /** {@inheritDoc} */
+            @Override public boolean apply(ClusterNode clusterNode) {
+                return clusterNode.version().compareTo(PartitionSizeLongTask.SINCE_VER) >= 0 &&
+                    ((modes.primary && aff.primary(clusterNode, part, topVer)) ||
+                        (modes.backup && aff.backup(clusterNode, part, topVer)));
+            }
+        }).nodes();
+
+        if (nodes.isEmpty())
+            return new GridFinishedFuture<>(0L);
+
+        ctx.kernalContext().task().setThreadContext(TC_SUBGRID, nodes);
+
+        return ctx.kernalContext().task().execute(
+                new PartitionSizeLongTask(ctx.name(), ctx.affinity().affinityTopologyVersion(), peekModes, part), null);
+    }
+
+    /** {@inheritDoc} */
     @Override public int localSize(CachePeekMode[] peekModes) throws IgniteCheckedException {
         return (int)localSizeLong(peekModes);
     }
@@ -3936,6 +3975,50 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /** {@inheritDoc} */
+    @Override public long localSizeLong(int part, CachePeekMode[] peekModes) throws IgniteCheckedException {
+        PeekModes modes = parsePeekModes(peekModes, true);
+
+        long size = 0;
+
+        AffinityTopologyVersion topVer = ctx.affinity().affinityTopologyVersion();
+
+        // Swap and offheap are disabled for near cache.
+        GridCacheSwapManager swapMgr = ctx.isNear() ? ctx.near().dht().context().swap() : ctx.swap();
+
+        if (ctx.isLocal()){
+            modes.primary = true;
+            modes.backup = true;
+
+            if (modes.heap)
+                size += size();
+
+            if (modes.swap)
+                size += swapMgr.swapEntriesCount(0);
+
+            if (modes.offheap)
+                size += swapMgr.offheapEntriesCount(0);
+        }
+        else {
+            GridDhtLocalPartition dhtPart = ctx.topology().localPartition(part, topVer, false);
+
+            if (dhtPart != null) {
+                if (modes.primary && dhtPart.primary(topVer) || modes.backup && dhtPart.backup(topVer)) {
+                    if (modes.heap)
+                        size += dhtPart.publicSize();
+
+                    if (modes.swap)
+                        size += swapMgr.swapEntriesCount(part);
+
+                    if (modes.offheap)
+                        size += swapMgr.offheapEntriesCount(part);
+                }
+            }
+        }
+
+        return size;
+    }
+
+    /** {@inheritDoc} */
     @Override public int size() {
         return map.publicSize();
     }
@@ -5498,6 +5581,52 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /**
+     * Internal callable for partition size calculation.
+     */
+    @GridInternal
+    private static class PartitionSizeLongJob extends TopologyVersionAwareJob {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** Partition. */
+        private final int partition;
+
+        /** Peek modes. */
+        private final CachePeekMode[] peekModes;
+
+        /**
+         * @param cacheName Cache name.
+         * @param topVer Affinity topology version.
+         * @param peekModes Cache peek modes.
+         * @param partition partition.
+         */
+        private PartitionSizeLongJob(String cacheName, AffinityTopologyVersion topVer, CachePeekMode[] peekModes, int partition) {
+            super(cacheName, topVer);
+
+            this.peekModes = peekModes;
+            this.partition = partition;
+        }
+
+        /** {@inheritDoc} */
+        @Nullable @Override public Object localExecute(@Nullable IgniteInternalCache cache) {
+            if (cache == null)
+                return 0;
+
+            try {
+                return cache.localSizeLong(partition, peekModes);
+            }
+            catch (IgniteCheckedException e) {
+                throw U.convertException(e);
+            }
+        }
+
+        /** {@inheritDoc} */
+        public String toString() {
+            return S.toString(PartitionSizeLongJob.class, this);
+        }
+    }
+
+    /**
      * Internal callable for global size calculation.
      */
     @GridInternal
@@ -6470,7 +6599,7 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
          * @param topVer Affinity topology version.
          * @param peekModes Cache peek modes.
          */
-        public SizeLongTask(String cacheName, AffinityTopologyVersion topVer, CachePeekMode[] peekModes) {
+        private SizeLongTask(String cacheName, AffinityTopologyVersion topVer, CachePeekMode[] peekModes) {
             this.cacheName = cacheName;
             this.topVer = topVer;
             this.peekModes = peekModes;
@@ -6515,6 +6644,90 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
     }
 
     /**
+     * Partition Size Long task.
+     */
+    private static class PartitionSizeLongTask extends ComputeTaskAdapter<Object, Long> {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        private static final IgniteProductVersion SINCE_VER = IgniteProductVersion.fromString("1.5.30");
+
+        /** Partition */
+        private final int partition;
+
+        /** Cache name. */
+        private final String cacheName;
+
+        /** Affinity topology version. */
+        private final AffinityTopologyVersion topVer;
+
+        /** Peek modes. */
+        private final CachePeekMode[] peekModes;
+
+        /**
+         * @param cacheName Cache name.
+         * @param topVer Affinity topology version.
+         * @param peekModes Cache peek modes.
+         * @param partition partition.
+         */
+        private PartitionSizeLongTask(
+            String cacheName,
+            AffinityTopologyVersion topVer,
+            CachePeekMode[] peekModes,
+            int partition
+        ) {
+            this.cacheName = cacheName;
+            this.topVer = topVer;
+            this.peekModes = peekModes;
+            this.partition = partition;
+        }
+
+        /** {@inheritDoc} */
+        @Nullable @Override public Map<? extends ComputeJob, ClusterNode> map(
+            List<ClusterNode> subgrid,
+            @Nullable Object arg
+        ) throws IgniteException {
+            Map<ComputeJob, ClusterNode> jobs = new HashMap();
+
+            for (ClusterNode node : subgrid)
+                jobs.put(new PartitionSizeLongJob(cacheName, topVer, peekModes, partition), node);
+
+            return jobs;
+        }
+
+        /** {@inheritDoc} */
+        @Override public ComputeJobResultPolicy result(ComputeJobResult res, List<ComputeJobResult> rcvd) {
+            IgniteException e = res.getException();
+
+            if (e != null) {
+                if (e instanceof ClusterTopologyException)
+                    return ComputeJobResultPolicy.WAIT;
+
+                throw new IgniteException("Remote job threw exception.", e);
+            }
+
+            return ComputeJobResultPolicy.WAIT;
+        }
+
+        /** {@inheritDoc} */
+        @Nullable @Override public Long reduce(List<ComputeJobResult> results) throws IgniteException {
+            long size = 0;
+
+            for (ComputeJobResult res : results) {
+                if (res != null) {
+                    if (res.getException() == null)
+                        size += res.<Long>getData();
+                    else
+                        throw res.getException();
+                }
+            }
+
+            return size;
+        }
+    }
+
+    /**
      * Clear task.
      */
     private static class ClearTask<K> extends ComputeTaskAdapter<Object, Object> {

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
index a58c209..00898ec 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheProxyImpl.java
@@ -1472,6 +1472,18 @@ public class GridCacheProxyImpl<K, V> implements IgniteInternalCache<K, V>, Exte
     }
 
     /** {@inheritDoc} */
+    @Override public long sizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException {
+        CacheOperationContext prev = gate.enter(opCtx);
+
+        try {
+            return delegate.sizeLong(partition, peekModes);
+        }
+        finally {
+            gate.leave(prev);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public IgniteInternalFuture<Integer> sizeAsync(CachePeekMode[] peekModes) {
         CacheOperationContext prev = gate.enter(opCtx);
 
@@ -1496,6 +1508,18 @@ public class GridCacheProxyImpl<K, V> implements IgniteInternalCache<K, V>, Exte
     }
 
     /** {@inheritDoc} */
+    @Override public IgniteInternalFuture<Long> sizeLongAsync(int partition, CachePeekMode[] peekModes) {
+        CacheOperationContext prev = gate.enter(opCtx);
+
+        try {
+            return delegate.sizeLongAsync(partition, peekModes);
+        }
+        finally {
+            gate.leave(prev);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public int localSize(CachePeekMode[] peekModes) throws IgniteCheckedException {
         CacheOperationContext prev = gate.enter(opCtx);
 
@@ -1520,6 +1544,18 @@ public class GridCacheProxyImpl<K, V> implements IgniteInternalCache<K, V>, Exte
     }
 
     /** {@inheritDoc} */
+    @Override public long localSizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException {
+        CacheOperationContext prev = gate.enter(opCtx);
+
+        try {
+            return delegate.localSizeLong(partition, peekModes);
+        }
+        finally {
+            gate.leave(prev);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public int nearSize() {
         CacheOperationContext prev = gate.enter(opCtx);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
index 76cc77b..fe4f79c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
@@ -857,6 +857,29 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
     }
 
     /** {@inheritDoc} */
+    @Override public long sizeLong(int part, CachePeekMode... peekModes) throws CacheException {
+        GridCacheGateway<K, V> gate = this.gate;
+
+        CacheOperationContext prev = onEnter(gate, opCtx);
+
+        try {
+            if (isAsync()) {
+                setFuture(delegate.sizeLongAsync(part, peekModes));
+
+                return 0;
+            }
+            else
+                return delegate.sizeLong(part, peekModes);
+        }
+        catch (IgniteCheckedException e) {
+            throw cacheException(e);
+        }
+        finally {
+            onLeave(gate, prev);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public int localSize(CachePeekMode... peekModes) {
         GridCacheGateway<K, V> gate = this.gate;
 
@@ -891,6 +914,23 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
     }
 
     /** {@inheritDoc} */
+    @Override public long localSizeLong(int part, CachePeekMode... peekModes) {
+        GridCacheGateway<K, V> gate = this.gate;
+
+        CacheOperationContext prev = onEnter(gate, opCtx);
+
+        try {
+            return delegate.localSizeLong(part, peekModes);
+        }
+        catch (IgniteCheckedException e) {
+            throw cacheException(e);
+        }
+        finally {
+            onLeave(gate, prev);
+        }
+    }
+
+    /** {@inheritDoc} */
     @Override public V get(K key) {
         try {
             GridCacheGateway<K, V> gate = this.gate;

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteInternalCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteInternalCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteInternalCache.java
index 3dc3471..0ac98fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteInternalCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteInternalCache.java
@@ -1454,6 +1454,14 @@ public interface IgniteInternalCache<K, V> extends Iterable<Cache.Entry<K, V>> {
     public long localSizeLong(CachePeekMode[] peekModes) throws IgniteCheckedException;
 
     /**
+     * @param partition partition.
+     * @param peekModes Peek modes.
+     * @return Local cache size as a long value.
+     * @throws IgniteCheckedException If failed.
+     */
+    public long localSizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException;
+
+    /**
      * @param peekModes Peek modes.
      * @return Global cache size.
      * @throws IgniteCheckedException If failed.
@@ -1468,6 +1476,14 @@ public interface IgniteInternalCache<K, V> extends Iterable<Cache.Entry<K, V>> {
     public long sizeLong(CachePeekMode[] peekModes) throws IgniteCheckedException;
 
     /**
+     * @param partition partition
+     * @param peekModes Peek modes.
+     * @return Global cache size as a long value.
+     * @throws IgniteCheckedException If failed.
+     */
+    public long sizeLong(int partition, CachePeekMode[] peekModes) throws IgniteCheckedException;
+
+    /**
      * @param peekModes Peek modes.
      * @return Future.
      */
@@ -1480,6 +1496,13 @@ public interface IgniteInternalCache<K, V> extends Iterable<Cache.Entry<K, V>> {
     public IgniteInternalFuture<Long> sizeLongAsync(CachePeekMode[] peekModes);
 
     /**
+     * @param partition partiton
+     * @param peekModes Peek modes.
+     * @return Future.
+     */
+    public IgniteInternalFuture<Long> sizeLongAsync(int partition, CachePeekMode[] peekModes);
+
+    /**
      * Gets size of near cache key set. This method will return count of all entries in near
      * cache and has O(1) complexity on base cache projection.
      * <p>

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAtomicPeekModesTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAtomicPeekModesTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAtomicPeekModesTest.java
index 4270bab..8b7859a 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAtomicPeekModesTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAtomicPeekModesTest.java
@@ -48,4 +48,4 @@ public class IgniteCacheAtomicPeekModesTest extends IgniteCachePeekModesAbstract
     @Override protected CacheAtomicWriteOrderMode atomicWriteOrderMode() {
         return PRIMARY;
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePeekModesAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePeekModesAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePeekModesAbstractTest.java
index c27cccb..5dc059b 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePeekModesAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCachePeekModesAbstractTest.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import javax.cache.Cache;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.CacheMemoryMode;
 import org.apache.ignite.cache.CachePeekMode;
 import org.apache.ignite.cache.affinity.Affinity;
@@ -38,6 +39,7 @@ import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.NearCacheConfiguration;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
 import org.apache.ignite.internal.util.typedef.T2;
 import org.apache.ignite.spi.IgniteSpiCloseableIterator;
 import org.apache.ignite.spi.swapspace.SwapSpaceSpi;
@@ -501,6 +503,144 @@ public abstract class IgniteCachePeekModesAbstractTest extends IgniteCacheAbstra
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testLocalPartitionSize() throws Exception {
+        if (cacheMode() != LOCAL)
+            return;
+
+        awaitPartitionMapExchange();
+        checkEmpty();
+        int part = 0;
+        IgniteCache<Integer, String> cache0 = jcache(0);
+
+        IgniteCache<Integer, String> cacheAsync0 = cache0.withAsync();
+
+        for (int i = 0; i < HEAP_ENTRIES; i++) {
+            cache0.put(i, String.valueOf(i));
+
+            final long size = i + 1;
+
+            assertEquals(size, cache0.localSize());
+            assertEquals(size, cache0.localSizeLong(part, PRIMARY));
+            assertEquals(size, cache0.localSizeLong(part, BACKUP));
+            assertEquals(size, cache0.localSizeLong(part, NEAR));
+            assertEquals(size, cache0.localSizeLong(part, ALL));
+
+            assertEquals(size, cache0.size());
+            assertEquals(size, cache0.sizeLong(part, PRIMARY));
+            assertEquals(size, cache0.sizeLong(part, BACKUP));
+            assertEquals(size, cache0.sizeLong(part, NEAR));
+            assertEquals(size, cache0.sizeLong(part, ALL));
+
+            cacheAsync0.size();
+
+            assertEquals(size, (long) cacheAsync0.<Integer>future().get());
+
+            cacheAsync0.sizeLong(part, PRIMARY);
+
+            assertEquals(size, cacheAsync0.future().get());
+        }
+
+        for (int i = 0; i < HEAP_ENTRIES; i++) {
+            cache0.remove(i, String.valueOf(i));
+
+            final int size = HEAP_ENTRIES - i - 1;
+
+            assertEquals(size, cache0.localSize());
+            assertEquals(size, cache0.localSizeLong(part, PRIMARY));
+            assertEquals(size, cache0.localSizeLong(part, BACKUP));
+            assertEquals(size, cache0.localSizeLong(part, NEAR));
+            assertEquals(size, cache0.localSizeLong(part, ALL));
+
+            assertEquals(size, cache0.size());
+            assertEquals(size, cache0.sizeLong(part, PRIMARY));
+            assertEquals(size, cache0.sizeLong(part, BACKUP));
+            assertEquals(size, cache0.sizeLong(part, NEAR));
+            assertEquals(size, cache0.sizeLong(part, ALL));
+
+            cacheAsync0.size();
+
+            assertEquals(size, (long) cacheAsync0.<Integer>future().get());
+        }
+    }
+
+    /**
+     * @throws InterruptedException If failed.
+     */
+    public void testLocalPartitionSizeFlags() throws InterruptedException {
+        if (cacheMode() != LOCAL)
+            return;
+
+        awaitPartitionMapExchange();
+        checkEmpty();
+        int part = 0;
+        IgniteCache<Integer, String> cache0 = jcache(0);
+
+        Set<Integer> keys = new HashSet<>();
+
+        for (int i = 0; i < 200; i++) {
+            cache0.put(i, "test_val");
+
+            keys.add(i);
+        }
+
+        try {
+            int totalKeys = 200;
+
+            T2<Integer, Integer> swapKeys = swapKeysCount(0);
+
+            T2<Integer, Integer> offheapKeys = offheapKeysCount(0);
+
+            int totalSwap = swapKeys.get1() + swapKeys.get2();
+            int totalOffheap = offheapKeys.get1() + offheapKeys.get2();
+
+            log.info("Keys [total=" + totalKeys + ", offheap=" + offheapKeys + ", swap=" + swapKeys + ']');
+
+            assertTrue(totalSwap + totalOffheap < totalKeys);
+
+            assertEquals(totalKeys, cache0.localSize());
+            assertEquals(totalKeys, cache0.localSizeLong(part, ALL));
+
+            assertEquals(totalOffheap, cache0.localSizeLong(part, OFFHEAP));
+            assertEquals(totalSwap, cache0.localSizeLong(part, SWAP));
+            assertEquals(totalKeys - (totalSwap + totalOffheap), cache0.localSizeLong(part, ONHEAP));
+
+            assertEquals(totalOffheap, cache0.sizeLong(part, OFFHEAP));
+            assertEquals(totalSwap, cache0.sizeLong(part, SWAP));
+            assertEquals(totalKeys - (totalSwap + totalOffheap), cache0.sizeLong(part, ONHEAP));
+
+            assertEquals(totalOffheap, cache0.localSizeLong(part, OFFHEAP, PRIMARY));
+            assertEquals(totalSwap, cache0.localSizeLong(part, SWAP, PRIMARY));
+            assertEquals(totalKeys - (totalSwap + totalOffheap), cache0.localSizeLong(part, ONHEAP, PRIMARY));
+
+            assertEquals(totalOffheap, cache0.localSizeLong(part, OFFHEAP, BACKUP));
+            assertEquals(totalSwap, cache0.localSizeLong(part, SWAP, BACKUP));
+            assertEquals(totalKeys - (totalSwap + totalOffheap), cache0.localSizeLong(part, ONHEAP, BACKUP));
+        }
+        finally {
+            cache0.removeAll(keys);
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testNonLocalPartitionSize() throws Exception {
+        if (cacheMode() == LOCAL)
+            return;
+
+        awaitPartitionMapExchange(true, true);
+
+        checkEmpty();
+
+        for (int i = 0; i < gridCount(); i++) {
+            checkPartitionSizeAffinityFilter(i);
+            checkPartitionSizeStorageFilter(i);
+        }
+    }
+
+    /**
      * @param nodeIdx Node index.
      * @throws Exception If failed.
      */
@@ -627,6 +767,164 @@ public abstract class IgniteCachePeekModesAbstractTest extends IgniteCacheAbstra
     }
 
     /**
+     * @param nodeIdx Node index.
+     * @throws Exception If failed.
+     */
+    private void checkPartitionSizeAffinityFilter(int nodeIdx) throws Exception {
+        IgniteCache<Integer, String> cache0 = jcache(nodeIdx);
+
+        final int PUT_KEYS = 10;
+
+        int part = nodeIdx;
+
+        List<Integer> keys = null;
+
+        try {
+            if (cacheMode() == REPLICATED) {
+                keys = backupKeys(cache0, 10, 0);
+
+                for (Integer key : keys)
+                    cache0.put(key, String.valueOf(key));
+
+                int partSize = 0;
+
+                for (Integer key : keys){
+                    int keyPart = ignite(nodeIdx).affinity(null).partition(key);
+                    if (keyPart == part)
+                        partSize++;
+                }
+
+                assertEquals(PUT_KEYS, cache0.localSize(BACKUP));
+                assertEquals(PUT_KEYS, cache0.localSize(ALL));
+                assertEquals(partSize, cache0.localSizeLong(part, BACKUP));
+                assertEquals(partSize, cache0.localSizeLong(part, ALL));
+                assertEquals(0, cache0.localSizeLong(part, PRIMARY));
+                assertEquals(0, cache0.localSizeLong(part, NEAR));
+
+                for (int i = 0; i < gridCount(); i++) {
+                    IgniteCache<Integer, String> cache = jcache(i);
+                    assertEquals(0, cache.size(NEAR));
+                    assertEquals(partSize, cache.sizeLong(part, PRIMARY));
+                    assertEquals(partSize * (gridCount() - 1), cache.sizeLong(part, BACKUP));
+                    assertEquals(partSize * gridCount(), cache.sizeLong(part, PRIMARY, BACKUP));
+                    assertEquals(partSize * gridCount(), cache.sizeLong(part, ALL)); // Primary + backups.
+                }
+            }
+            else {
+                keys = nearKeys(cache0, PUT_KEYS, 0);
+
+                for (Integer key : keys)
+                    cache0.put(key, String.valueOf(key));
+
+                int partSize = 0;
+
+                for (Integer key :keys){
+                    int keyPart = ignite(nodeIdx).affinity(null).partition(key);
+                    if(keyPart == part)
+                        partSize++;
+                }
+
+                if (hasNearCache()) {
+                    assertEquals(0, cache0.localSize());
+                    assertEquals(0, cache0.localSizeLong(part, ALL));
+                    assertEquals(0, cache0.localSizeLong(part, NEAR));
+
+                    for (int i = 0; i < gridCount(); i++) {
+                        IgniteCache<Integer, String> cache = jcache(i);
+
+                        assertEquals(0, cache.sizeLong(part, NEAR));
+                        assertEquals(partSize, cache.sizeLong(part, BACKUP));
+                        assertEquals(partSize * 2, cache.sizeLong(part, PRIMARY, BACKUP));
+                        assertEquals(partSize * 2, cache.sizeLong(part, ALL)); // Primary + backups + near.
+                    }
+                }
+                else {
+                    assertEquals(0, cache0.localSize());
+                    //assertEquals(partitionSize, cache0.localSizeLong(partition, ALL));
+                    assertEquals(0, cache0.localSizeLong(part, NEAR));
+
+                    for (int i = 0; i < gridCount(); i++) {
+                        IgniteCache<Integer, String> cache = jcache(i);
+
+                        assertEquals(0, cache.size(NEAR));
+                        assertEquals(partSize, cache.sizeLong(part, BACKUP));
+                        assertEquals(partSize * 2, cache.sizeLong(part, PRIMARY, BACKUP));
+                        assertEquals(partSize * 2, cache.sizeLong(part, ALL)); // Primary + backups.
+                    }
+                }
+
+                assertEquals(0, cache0.localSize(BACKUP));
+                assertEquals(0, cache0.localSize(PRIMARY));
+            }
+
+            checkPrimarySize(PUT_KEYS);
+
+            Affinity<Integer> aff = ignite(0).affinity(null);
+
+            for (int i = 0; i < gridCount(); i++) {
+                if (i == nodeIdx)
+                    continue;
+
+                ClusterNode node = ignite(i).cluster().localNode();
+
+                int primary = 0;
+                int backups = 0;
+
+                for (Integer key : keys) {
+                    if (aff.isPrimary(node, key) && aff.partition(key) == part)
+                        primary++;
+                    else if (aff.isBackup(node, key) && aff.partition(key) == part)
+                        backups++;
+                }
+
+                IgniteCache<Integer, String> cache = jcache(i);
+
+                assertEquals(primary, cache.localSizeLong(part, PRIMARY));
+                assertEquals(backups, cache.localSizeLong(part, BACKUP));
+                assertEquals(primary + backups, cache.localSizeLong(part, PRIMARY, BACKUP));
+                assertEquals(primary + backups, cache.localSizeLong(part, BACKUP, PRIMARY));
+                assertEquals(primary + backups, cache.localSizeLong(part, ALL));
+            }
+
+            cache0.remove(keys.get(0));
+
+            keys.remove(0);
+
+            checkPrimarySize(PUT_KEYS - 1);
+
+            int primary = 0;
+            int backups = 0;
+
+            ClusterNode node = ignite(nodeIdx).cluster().localNode();
+
+            for (Integer key : keys) {
+                if (aff.isPrimary(node, key) && aff.partition(key) == part)
+                    primary++;
+                else if (aff.isBackup(node, key) && aff.partition(key) == part)
+                    backups++;
+            }
+
+            if (cacheMode() == REPLICATED) {
+                assertEquals(primary+backups, cache0.localSizeLong(part, ALL));
+                assertEquals(primary, cache0.localSizeLong(part, PRIMARY));
+                assertEquals(backups, cache0.localSizeLong(part, BACKUP));
+            }
+            else {
+                if (hasNearCache())
+                    assertEquals(0, cache0.localSizeLong(part, ALL));
+                else
+                    assertEquals(0, cache0.localSizeLong(part, ALL));
+            }
+        }
+        finally {
+            if (keys != null)
+                cache0.removeAll(new HashSet<>(keys));
+        }
+
+        checkEmpty();
+    }
+
+    /**
      * Checks size is zero.
      */
     private void checkEmpty() {
@@ -695,6 +993,31 @@ public abstract class IgniteCachePeekModesAbstractTest extends IgniteCacheAbstra
 
     /**
      * @param nodeIdx Node index.
+     * @param part Cache partition
+     * @return Tuple with number of primary and backup keys (one or both will be zero).
+     */
+    private T2<Integer, Integer> swapKeysCount(int nodeIdx, int part) throws IgniteCheckedException {
+        GridCacheContext ctx = ((IgniteEx)ignite(nodeIdx)).context().cache().internalCache().context();
+        // Swap and offheap are disabled for near cache.
+        GridCacheSwapManager swapMgr = ctx.isNear() ? ctx.near().dht().context().swap() : ctx.swap();
+        //First count entries...
+        int cnt = (int)swapMgr.swapEntriesCount(part);
+
+        GridCacheAffinityManager affinity = ctx.affinity();
+        AffinityTopologyVersion topVer = affinity.affinityTopologyVersion();
+
+        //And then find out whether they are primary or backup ones.
+        int primaryCnt = 0;
+        int backupCnt = 0;
+        if (affinity.primary(ctx.localNode(), part, topVer))
+            primaryCnt = cnt;
+        else if (affinity.backup(ctx.localNode(), part, topVer))
+            backupCnt = cnt;
+        return new T2<>(primaryCnt, backupCnt);
+    }
+
+    /**
+     * @param nodeIdx Node index.
      * @return Tuple with primary and backup keys.
      */
     private T2<List<Integer>, List<Integer>> offheapKeys(int nodeIdx) {
@@ -742,6 +1065,31 @@ public abstract class IgniteCachePeekModesAbstractTest extends IgniteCacheAbstra
 
     /**
      * @param nodeIdx Node index.
+     * @param part Cache partition.
+     * @return Tuple with number of primary and backup keys (one or both will be zero).
+     */
+    private T2<Integer, Integer> offheapKeysCount(int nodeIdx, int part) throws IgniteCheckedException {
+        GridCacheContext ctx = ((IgniteEx)ignite(nodeIdx)).context().cache().internalCache().context();
+        // Swap and offheap are disabled for near cache.
+        GridCacheSwapManager swapMgr = ctx.isNear() ? ctx.near().dht().context().swap() : ctx.swap();
+        //First count entries...
+        int cnt = (int)swapMgr.offheapEntriesCount(part);
+
+        GridCacheAffinityManager affinity = ctx.affinity();
+        AffinityTopologyVersion topVer = affinity.affinityTopologyVersion();
+
+        //And then find out whether they are primary or backup ones.
+        int primaryCnt = 0;
+        int backupCnt = 0;
+        if (affinity.primary(ctx.localNode(), part, topVer))
+            primaryCnt = cnt;
+        else if (affinity.backup(ctx.localNode(), part, topVer))
+            backupCnt = cnt;
+        return new T2<>(primaryCnt, backupCnt);
+    }
+
+    /**
+     * @param nodeIdx Node index.
      * @throws Exception If failed.
      */
     private void checkSizeStorageFilter(int nodeIdx) throws Exception {
@@ -862,6 +1210,119 @@ public abstract class IgniteCachePeekModesAbstractTest extends IgniteCacheAbstra
     }
 
     /**
+     * @param nodeIdx Node index.
+     * @throws Exception If failed.
+     */
+    private void checkPartitionSizeStorageFilter(int nodeIdx) throws Exception {
+        IgniteCache<Integer, String> cache0 = jcache(nodeIdx);
+
+        int part = nodeIdx;
+
+        List<Integer> primaryKeys = primaryKeys(cache0, 100, 10_000);
+        List<Integer> backupKeys = backupKeys(cache0, 100, 10_000);
+
+        try {
+            final String val = "test_value";
+
+            for (int i = 0; i < 100; i++) {
+                cache0.put(primaryKeys.get(i), val);
+                cache0.put(backupKeys.get(i), val);
+            }
+
+
+            int totalKeys = 200;
+
+            T2<Integer, Integer> swapKeys = swapKeysCount(nodeIdx, part);
+
+            T2<Integer, Integer> offheapKeys = offheapKeysCount(nodeIdx, part);
+
+            int totalSwap = swapKeys.get1() + swapKeys.get2();
+            int totalOffheap = offheapKeys.get1() + offheapKeys.get2();
+
+            log.info("Local keys [total=" + totalKeys + ", offheap=" + offheapKeys + ", swap=" + swapKeys + ']');
+
+            assertTrue(totalSwap + totalOffheap < totalKeys);
+
+            assertEquals(primaryKeys.size(), cache0.localSize());
+            assertEquals(totalKeys, cache0.localSize(ALL));
+            assertEquals(totalOffheap, cache0.localSizeLong(part, PRIMARY, BACKUP, NEAR, OFFHEAP));
+            assertEquals(totalSwap, cache0.localSizeLong(part, PRIMARY, BACKUP, NEAR, SWAP));
+            assertEquals((long)swapKeys.get1(), cache0.localSizeLong(part, SWAP, PRIMARY));
+            assertEquals((long)swapKeys.get2(), cache0.localSizeLong(part, SWAP, BACKUP));
+
+            assertEquals((long)offheapKeys.get1(), cache0.localSizeLong(part, OFFHEAP, PRIMARY));
+            assertEquals((long)offheapKeys.get2(), cache0.localSizeLong(part, OFFHEAP, BACKUP));
+
+            assertEquals(swapKeys.get1() + offheapKeys.get1(), cache0.localSizeLong(part, SWAP, OFFHEAP, PRIMARY));
+            assertEquals(swapKeys.get2() + offheapKeys.get2(), cache0.localSizeLong(part, SWAP, OFFHEAP, BACKUP));
+
+            assertEquals(totalSwap + totalOffheap, cache0.localSizeLong(part, PRIMARY, BACKUP, NEAR, SWAP, OFFHEAP));
+
+            int globalParitionSwapPrimary = 0;
+            int globalPartSwapBackup = 0;
+
+            int globalPartOffheapPrimary = 0;
+            int globalPartOffheapBackup = 0;
+
+            for (int i = 0; i < gridCount(); i++) {
+                T2<Integer, Integer> swap = swapKeysCount(i, part);
+
+                globalParitionSwapPrimary += swap.get1();
+                globalPartSwapBackup += swap.get2();
+
+                T2<Integer, Integer> offheap = offheapKeysCount(i, part);
+
+                globalPartOffheapPrimary += offheap.get1();
+                globalPartOffheapBackup += offheap.get2();
+            }
+
+            int backups;
+
+            if (cacheMode() == LOCAL)
+                backups = 0;
+            else if (cacheMode() == PARTITIONED)
+                backups = 1;
+            else // REPLICATED.
+                backups = gridCount() - 1;
+
+            int globalTotal = totalKeys + totalKeys * backups;
+            int globalPartTotalSwap = globalParitionSwapPrimary + globalPartSwapBackup;
+            int globalPartTotalOffheap = globalPartOffheapPrimary + globalPartOffheapBackup;
+
+            log.info("Global keys [total=" + globalTotal +
+                    ", offheap=" + globalPartTotalOffheap +
+                    ", swap=" + globalPartTotalSwap + ']');
+
+            for (int i = 0; i < gridCount(); i++) {
+                IgniteCache<Integer, String> cache = jcache(i);
+
+                assertEquals(totalKeys, cache.size(PRIMARY));
+                assertEquals(globalTotal, cache.size(ALL));
+                assertEquals(globalTotal, cache.size(PRIMARY, BACKUP, NEAR, ONHEAP, OFFHEAP, SWAP));
+                assertEquals(globalTotal, cache.size(ONHEAP, OFFHEAP, SWAP, PRIMARY, BACKUP));
+
+                assertEquals(globalPartTotalSwap, cache.sizeLong(part, PRIMARY, BACKUP, NEAR, SWAP));
+                assertEquals(globalParitionSwapPrimary, cache.sizeLong(part, SWAP, PRIMARY));
+                assertEquals(globalPartSwapBackup, cache.sizeLong(part, SWAP, BACKUP));
+
+                assertEquals(globalPartTotalOffheap, cache.sizeLong(part, PRIMARY, BACKUP, NEAR, OFFHEAP));
+                assertEquals(globalPartOffheapPrimary, cache.sizeLong(part, OFFHEAP, PRIMARY));
+                assertEquals(globalPartOffheapBackup, cache.sizeLong(part, OFFHEAP, BACKUP));
+
+                assertEquals(globalPartTotalSwap + globalPartTotalOffheap, cache.sizeLong(part, PRIMARY, BACKUP, NEAR, SWAP, OFFHEAP));
+                assertEquals(globalParitionSwapPrimary + globalPartOffheapPrimary, cache.sizeLong(part, SWAP, OFFHEAP, PRIMARY));
+                assertEquals(globalPartSwapBackup + globalPartOffheapBackup, cache.sizeLong(part, SWAP, OFFHEAP, BACKUP));
+            }
+        }
+        finally {
+            cache0.removeAll(new HashSet<>(primaryKeys));
+            cache0.removeAll(new HashSet<>(backupKeys));
+        }
+
+        checkEmpty();
+    }
+
+    /**
      * @param exp Expected size.
      */
     private void checkPrimarySize(int exp) {
@@ -1167,4 +1628,4 @@ public abstract class IgniteCachePeekModesAbstractTest extends IgniteCacheAbstra
 
         assertTrue("Expected entries not found: " + allExp, allExp.isEmpty());
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/0b118553/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
index 205dc83..9cbbbd2 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java
@@ -202,6 +202,11 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override public long sizeLong(int partition, CachePeekMode... peekModes) throws CacheException {
+        return compute.call(new PartitionSizeLongTask(cacheName, isAsync, peekModes, partition, false));
+    }
+
+    /** {@inheritDoc} */
     @Override public int localSize(CachePeekMode... peekModes) {
         return compute.call(new SizeTask(cacheName, isAsync, peekModes, true));
     }
@@ -212,6 +217,11 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
     }
 
     /** {@inheritDoc} */
+    @Override public long localSizeLong(int partition, CachePeekMode... peekModes) {
+        return compute.call(new PartitionSizeLongTask(cacheName, isAsync, peekModes, partition, true));
+    }
+
+    /** {@inheritDoc} */
     @Override  public <T> Map<K, EntryProcessorResult<T>> invokeAll(
         Map<? extends K, ? extends EntryProcessor<K, V, T>> map,
         Object... args)
@@ -706,6 +716,40 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
     /**
      *
      */
+    private static class PartitionSizeLongTask extends CacheTaskAdapter<Void, Void, Long> {
+
+        /** Partition. */
+        int partition;
+
+        /** Peek modes. */
+        private final CachePeekMode[] peekModes;
+
+        /** Local. */
+        private final boolean loc;
+
+        /**
+         * @param cacheName Cache name.
+         * @param async Async.
+         * @param peekModes Peek modes.
+         * @param partition partition.
+         * @param loc Local.
+         */
+        public PartitionSizeLongTask(String cacheName, boolean async, CachePeekMode[] peekModes, int partition, boolean loc) {
+            super(cacheName, async, null);
+            this.loc = loc;
+            this.peekModes = peekModes;
+            this.partition = partition;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Long call() throws Exception {
+            return loc ? cache().localSizeLong(partition, peekModes) : cache().sizeLong(partition, peekModes);
+        }
+    }
+
+    /**
+     *
+     */
     private static class GetTask<K, V> extends CacheTaskAdapter<K, V, V> {
         /** Key. */
         private final K key;
@@ -1494,4 +1538,4 @@ public class IgniteCacheProcessProxy<K, V> implements IgniteCache<K, V> {
             return async ? cache.withAsync() : cache;
         }
     }
-}
\ No newline at end of file
+}


[15/46] ignite git commit: IGNITE-3446 Visor CMD: improve usability for batch mode. (cherry picked from commit 4897315)

Posted by sb...@apache.org.
IGNITE-3446 Visor CMD: improve usability for batch mode.
(cherry picked from commit 4897315)


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

Branch: refs/heads/ignite-1232
Commit: 89fd76fa2e85cfa1c06fbd5151086f958aefa685
Parents: 2b5067b
Author: Andrey Novikov <an...@gridgain.com>
Authored: Fri Jul 15 16:54:21 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Fri Jul 15 17:08:33 2016 +0700

----------------------------------------------------------------------
 .../ignite/visor/commands/VisorConsole.scala    |   5 +-
 .../commands/alert/VisorAlertCommand.scala      |   2 +-
 .../commands/cache/VisorCacheCommand.scala      |  40 ++--
 .../commands/cache/VisorCacheStopCommand.scala  |   2 +-
 .../config/VisorConfigurationCommand.scala      |  23 ++-
 .../commands/events/VisorEventsCommand.scala    |  29 +--
 .../visor/commands/gc/VisorGcCommand.scala      |  11 +-
 .../visor/commands/kill/VisorKillCommand.scala  | 184 ++++++++++++++-----
 .../visor/commands/node/VisorNodeCommand.scala  |  13 +-
 .../visor/commands/vvm/VisorVvmCommand.scala    |  11 +-
 .../scala/org/apache/ignite/visor/visor.scala   |  76 +++++---
 11 files changed, 276 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/VisorConsole.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/VisorConsole.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/VisorConsole.scala
index 6d91b05..b4d78b5 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/VisorConsole.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/VisorConsole.scala
@@ -146,7 +146,10 @@ class VisorConsole {
         batchCommand.foreach(commands => batchStream = Some(commands.replaceAll(";", "\n")))
 
         val inputStream = batchStream match {
-            case Some(cmd) => new ByteArrayInputStream((cmd + "\nquit\n").getBytes("UTF-8"))
+            case Some(cmd) =>
+                visor.batchMode = true
+
+                new ByteArrayInputStream((cmd + "\nquit\n").getBytes("UTF-8"))
             case None => new FileInputStream(FileDescriptor.in)
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/alert/VisorAlertCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/alert/VisorAlertCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/alert/VisorAlertCommand.scala
index db60443..401a3f2 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/alert/VisorAlertCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/alert/VisorAlertCommand.scala
@@ -751,7 +751,7 @@ private case class VisorSentAlert(
     assert(spec != null)
 
     def idVar: String = {
-        val v = mfind(id)
+        val v = mfindHead(id)
 
         if (v.isDefined) id + "(@" + v.get._1 + ")" else id
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommand.scala
index b4ed6b8..a9f9137 100755
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheCommand.scala
@@ -73,12 +73,15 @@ import scala.language.{implicitConversions, reflectiveCalls}
  *
  * ====Arguments====
  * {{{
- *     -id=<node-id>
- *         Full ID of the node to get cache statistics from.
- *         Either '-id8' or '-id' can be specified.
- *         If neither is specified statistics will be gathered from all nodes.
  *     -id8=<node-id>
  *         ID8 of the node to get cache statistics from.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
+ *         If neither is specified statistics will be gathered from all nodes.
+ *     -id=<node-id>
+ *         Full ID of the node to get cache statistics from.
  *         Either '-id8' or '-id' can be specified.
  *         If neither is specified statistics will be gathered from all nodes.
  *     -c=<cache-name>
@@ -278,7 +281,7 @@ class VisorCacheCommand {
                             else if (hasArgFlag("swap", argLst))
                                 VisorCacheSwapCommand().swap(argLst, node)
                             else if (hasArgFlag("stop", argLst))
-                                VisorCacheStopCommand().scan(argLst, node)
+                                VisorCacheStopCommand().stop(argLst, node)
                         }
                         else {
                             if (hasArgFlag("clear", argLst))
@@ -311,7 +314,12 @@ class VisorCacheCommand {
                 return
             }
 
-            println("Time of the snapshot: " + formatDateTime(System.currentTimeMillis))
+            node match {
+                case Some(n) =>
+                    println("ID8=" + nid8(n) + ", time of the snapshot: " + formatDateTime(System.currentTimeMillis))
+                case None =>
+                    println("Time of the snapshot: " + formatDateTime(System.currentTimeMillis))
+            }
 
             val sumT = VisorTextTable()
 
@@ -459,12 +467,12 @@ class VisorCacheCommand {
      */
     private def mkCacheName(@Nullable s: String): String = {
         if (s == null) {
-            val v = mfind(DFLT_CACHE_KEY)
+            val v = mfindHead(DFLT_CACHE_KEY)
 
             DFLT_CACHE_NAME + (if (v.isDefined) "(@" + v.get._1 + ')' else "")
         }
         else {
-            val v = mfind(s)
+            val v = mfindHead(s)
 
             s + (if (v.isDefined) "(@" + v.get._1 + ')' else "")
         }
@@ -649,7 +657,7 @@ class VisorCacheCommand {
 
         sumT.render()
 
-        val a = ask("\nChoose cache number ('c' to cancel) [c]: ", "c")
+        val a = ask("\nChoose cache number ('c' to cancel) [c]: ", "0")
 
         if (a.toLowerCase == "c")
             None
@@ -703,17 +711,19 @@ object VisorCacheCommand {
             "cache -stop -c=<cache-name>"
     ),
         args = Seq(
+            "-id8=<node-id>" -> Seq(
+                "ID8 of the node to get cache statistics from.",
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'.",
+                "If neither is specified statistics will be gathered from all nodes."
+            ),
             "-id=<node-id>" -> Seq(
                 "Full ID of the node to get cache statistics from.",
                 "Either '-id8' or '-id' can be specified.",
                 "If neither is specified statistics will be gathered from all nodes."
             ),
-            "-id8=<node-id>" -> Seq(
-                "ID8 of the node to get cache statistics from.",
-                "Either '-id8' or '-id' can be specified.",
-                "If neither is specified statistics will be gathered from all nodes.",
-                "Note you can also use '@n0' ... '@nn' variables as shortcut to <node-id>."
-            ),
             "-c=<cache-name>" -> Seq(
                 "Name of the cache.",
                 "Note you can also use '@c0' ... '@cn' variables as shortcut to <cache-name>."

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheStopCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheStopCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheStopCommand.scala
index bf81f73..1b55505 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheStopCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/cache/VisorCacheStopCommand.scala
@@ -76,7 +76,7 @@ class VisorCacheStopCommand {
      *
      * @param argLst Command arguments.
      */
-    def scan(argLst: ArgList, node: Option[ClusterNode]) {
+    def stop(argLst: ArgList, node: Option[ClusterNode]) {
         val cacheArg = argValue("c", argLst)
 
         val cacheName = cacheArg match {

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/config/VisorConfigurationCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/config/VisorConfigurationCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/config/VisorConfigurationCommand.scala
index 3f0f52f..1b8bbd5 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/config/VisorConfigurationCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/config/VisorConfigurationCommand.scala
@@ -54,12 +54,16 @@ import scala.language.implicitConversions
  *
  * ====Arguments====
  * {{{
+ *     -id8=<node-id8>
+ *         Node ID8.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
+ *         If neither is specified - command starts in interactive mode.
  *     -id=<node-id>
  *         Full node ID. Either '-id8' or '-id' can be specified.
  *         If neither is specified - command starts in interactive mode.
- *     -id8=<node-id8>
- *         Node ID8. Either '-id8' or '-id' can be specified.
- *         If neither is specified - command starts in interactive mode.
  * }}}
  *
  * ====Examples====
@@ -388,14 +392,17 @@ object VisorConfigurationCommand {
             s"${cmd.name} {-id=<node-id>|id8=<node-id8>}"
         ),
         args = List(
+            "-id8=<node-id8>" -> List(
+                "Node ID8.",
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'.",
+                "If neither is specified - command starts in interactive mode."
+            ),
             "-id=<node-id>" -> List(
                 "Full node ID. Either '-id8' or '-id' can be specified.",
                 "If neither is specified - command starts in interactive mode."
-            ),
-            "-id8=<node-id8>" -> List(
-                "Node ID8. Either '-id8' or '-id' can be specified.",
-                "If neither is specified - command starts in interactive mode.",
-                "Note you can also use '@n0' ... '@nn' variables as shortcut to <node-id>."
             )
         ),
         examples = List(

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/events/VisorEventsCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/events/VisorEventsCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/events/VisorEventsCommand.scala
index f7ea625..e3e73c7 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/events/VisorEventsCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/events/VisorEventsCommand.scala
@@ -65,12 +65,15 @@ import scala.language.implicitConversions
  *
  * ====Arguments====
  * {{{
- *     -id=<node-id>
- *         Full node ID.
- *         Either '-id' or '-id8' can be specified.
- *         If called without the arguments - starts in interactive mode.
  *     -id8
  *         Node ID8.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
+ *         If called without the arguments - starts in interactive mode.
+ *     -id=<node-id>
+ *         Full node ID.
  *         Either '-id' or '-id8' can be specified.
  *         If called without the arguments - starts in interactive mode.
  *     -e=<ch,de,di,jo,ta,ca,cr,sw>
@@ -146,7 +149,7 @@ class VisorEventsCommand extends VisorConsoleCommand {
      */
     @throws[IllegalArgumentException]("In case unknown event mnemonic.")
     protected def typeFilter(typeArg: Option[String]) = {
-        typeArg.map(_.split(",").map(typeIds).flatten).orNull
+        typeArg.map(_.split(",").flatMap(typeIds)).orNull
     }
 
     /**
@@ -229,6 +232,8 @@ class VisorEventsCommand extends VisorConsoleCommand {
                             return
                     }
 
+                    println("ID8=" + nid8(node))
+
                     if (evts == null || evts.isEmpty) {
                         println("No events found.")
 
@@ -402,17 +407,19 @@ object VisorEventsCommand {
             "    {-t=<num>s|m|h|d} {-s=e|t} {-r} {-c=<n>}"
         ),
         args = List(
+            "-id8=<node-id8>" -> List(
+                "Node ID8.",
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'.",
+                "If called without the arguments - starts in interactive mode."
+            ),
             "-id=<node-id>" -> List(
                 "Full node ID.",
                 "Either '-id' or '-id8' can be specified.",
                 "If called without the arguments - starts in interactive mode."
             ),
-            "-id8=<node-id8>" -> List(
-                "Node ID8.",
-                "Note that either '-id8' or '-id' can be specified and " +
-                    "you can also use '@n0' ... '@nn' variables as shortcut to <node-id8>.",
-                "If called without the arguments - starts in interactive mode."
-            ),
             "-e=<ch,de,di,jo,ta,ca,cr,sw>" -> List(
                 "Comma separated list of event types that should be queried:",
                 "   ch Checkpoint events.",

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/gc/VisorGcCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/gc/VisorGcCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/gc/VisorGcCommand.scala
index a9bf39f..990fd00 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/gc/VisorGcCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/gc/VisorGcCommand.scala
@@ -52,7 +52,10 @@ import scala.language.{implicitConversions, reflectiveCalls}
  * {{{
  *     -id8=<node-id8>
  *         ID8 of the node.
- *         Note that either '-id8' or '-id' can be specified.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
  *     -id=<node-id>
  *         ID of the node.
  *         Note that either '-id8' or '-id' can be specified.
@@ -159,8 +162,10 @@ object VisorGcCommand {
         args = List(
             "-id8=<node-id8>" -> List(
                 "ID8 of the node.",
-                "Note that either '-id8' or '-id' can be specified and " +
-                    "you can also use '@n0' ... '@nn' variables as shortcut to <node-id8>."
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'."
             ),
             "-id=<node-id>" -> List(
                 "ID of the node.",

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
index dffd5f1..c705e21 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/kill/VisorKillCommand.scala
@@ -46,7 +46,7 @@ import scala.util.control.Breaks._
  * {{{
  *     kill
  *     kill "-in|-ih"
- *     kill "{-r|-k} {-id8=<node-id8>|-id=<node-id>}"
+ *     kill "{-r|-k} {-sc} {-al|-ar|-id8=<node-id8>|-id=<node-id>}"
  * }}}
  *
  * ====Arguments====
@@ -61,17 +61,28 @@ import scala.util.control.Breaks._
  *         Run command in interactive mode with ability to
  *         choose a host where to kill or restart nodes.
  *         Note that either '-in' or '-ih' can be specified.
+ *     -al
+ *         Kill or restart all nodes on this host.
+ *         Note that either '-al' or '-ar' can be specified.
+ *     -ar
+ *         Kill or restart all nodes on other hosts.
+ *         Note that either '-al', '-ar' can be specified.
+ *     -sc
+ *         Skip kill or restart of client nodes for group nodes command.
  *     -r
  *         Restart node mode.
  *         Note that either '-r' or '-k' can be specified.
- *         If no parameters provided - command starts in interactive mode.
+ *         If no other parameters provided - command executes on all nodes.
  *     -k
  *         Kill (stop) node mode.
  *         Note that either '-r' or '-k' can be specified.
- *         If no parameters provided - command starts in interactive mode.
+ *         If no other parameters provided - command executes on all nodes.
  *     -id8=<node-id8>
  *         ID8 of the node to kill or restart.
- *         Note that either '-id8' or '-id' can be specified.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
  *         If no parameters provided - command starts in interactive mode.
  *     -id=<node-id>
  *         ID of the node to kill or restart.
@@ -85,6 +96,16 @@ import scala.util.control.Breaks._
  *         Starts command in interactive mode.
  *     kill "-id8=12345678 -r"
  *         Restart node with '12345678' ID8.
+ *     kill -id8=@n0 -r" ->
+ *         Restart specified node with id8 taken from 'n0' memory variable.
+ *     kill -id8=@nl -r" ->
+ *         Restart oldest local node with id8 taken from 'nl' memory variable.
+ *     kill -id8=@nl -k" ->
+ *         Kill (stop) oldest remote node with id8 taken from 'nr' memory variable.
+ *     kill -r -ar" ->
+ *         Restart all remote nodes.
+ *     kill -k -sc -al" ->
+ *         Kill (stop) all local server nodes.
  *     kill "-k"
  *         Kill (stop) all nodes.
  * }}}
@@ -114,8 +135,12 @@ class VisorKillCommand extends VisorConsoleCommand {
             val iNodes = hasArgFlag("in", argLst)
             val iHosts = hasArgFlag("ih", argLst)
 
+            val skipClient = hasArgFlag("sc", argLst)
+
             if (iNodes && iHosts)
                 scold("Only one of '-in' or '-ih' can be specified.").^^
+            else if ((iNodes || iHosts) && skipClient)
+                scold("Skip client flag is not allowed in interactive mode.").^^
             else if (iNodes)
                 interactiveNodes().^^
             else if (iHosts)
@@ -126,52 +151,94 @@ class VisorKillCommand extends VisorConsoleCommand {
             val restart = hasArgFlag("r", argLst)
             val kill = hasArgFlag("k", argLst)
 
-            var node: ClusterNode = null
+            val allLocal = hasArgFlag("al", argLst)
+            val allRemote = hasArgFlag("ar", argLst)
 
             if (kill && restart)
                 scold("Only one of '-k' or '-r' can be specified.")
             else if (!kill && !restart)
                 scold("Missing '-k' or '-r' option in command: " + args)
-            else if (id8.isDefined && id.isDefined)
-                scold("Only one of -id8 or -id is allowed.")
+            else if (Seq(allLocal, allRemote, id8.isDefined, id.isDefined).count((v) => v) > 1)
+                scold("Only one of -al, -ar, -id8 or -id is allowed.")
+            else if ((id8.isDefined || id.isDefined) && skipClient)
+                scold("Skip client flag is allowed only for group command.")
             else {
-                if (id8.isDefined) {
+                val localGroup = ignite.cluster.forHost(ignite.localNode)
+
+                var nodes = if (id8.isDefined) {
                     val ns = nodeById8(id8.get)
 
                     if (ns.isEmpty)
                         scold("Unknown 'id8' value: " + id8.get).^^
-                    else if (ns.size != 1) {
+
+                    if (ns.size != 1)
                         scold("'id8' resolves to more than one node (use full 'id' instead) : " + args).^^
-                    }
-                    else
-                        node = ns.head
+
+                    ns.toSeq
                 }
-                else if (id.isDefined)
-                    try {
-                        node = ignite.cluster.node(java.util.UUID.fromString(id.get))
+                else if (id.isDefined) {
+                    var nid: UUID = null
 
-                        if (node == null)
-                            scold("'id' does not match any node : " + args).^^
+                    try {
+                        nid = UUID.fromString(id.get)
                     }
                     catch {
                         case e: IllegalArgumentException => scold("Invalid node 'id' in args: " + args).^^
                     }
 
-                if (node == null && (id.isDefined || id8.isDefined))
-                    scold("Node with given ID cannot be found.").^^
+                    val nodes = ignite.cluster.forNodeId(nid).nodes()
+
+                    if (nodes.isEmpty)
+                        scold("'id' does not match any node : " + args).^^
+
+                    nodes.toSeq
+                } else if (allLocal) {
+                    if (skipClient)
+                        localGroup.forServers().nodes().toSeq
+                    else
+                        localGroup.nodes().toSeq
+                }
+                else if (allRemote) {
+                    val remoteGroup = ignite.cluster.forOthers(localGroup)
+
+                    if (skipClient)
+                        remoteGroup.forServers().nodes().toSeq
+                    else
+                        remoteGroup.nodes().toSeq
+                }
+                else {
+                    if (skipClient)
+                        ignite.cluster.forServers().nodes().toSeq
+                    else
+                        ignite.cluster.nodes().toSeq
+                }
+
+                if (nodes.isEmpty) {
+                    if (id.isDefined || id8.isDefined)
+                        scold("Node with given ID cannot be found.").^^
+                    else if (allLocal)
+                        scold("Local nodes cannot be found.").^^
+                    else if (allRemote)
+                        scold("Remote nodes cannot be found.").^^
+                }
+
+                if (restart) {
+                    val excludeNodes = nodes.filter(_.attribute[String](ATTR_RESTART_ENABLED) == "false")
+
+                    nodes = nodes.filter(_.attribute[String](ATTR_RESTART_ENABLED) == "true")
 
-                try
                     // In case of the restart - check that target node supports it.
-                    if (restart && node != null && node.attribute[String](ATTR_RESTART_ENABLED) != "true")
-                        scold("Node doesn't support restart: " + nid8(node)).^^
-                catch {
-                    case e: IgniteException => scold("Failed to restart the node. " + e.getMessage).^^
+                    if (excludeNodes.nonEmpty)
+                        scold("Node(s) doesn't support restart: " + excludeNodes.map(nid8).mkString("[", ", ", "]")).^^
+
+                    if (nodes.isEmpty)
+                        break
                 }
 
                 val op = if (restart) "restart" else "kill"
 
                 try
-                    killOrRestart(if (node == null) ignite.cluster.nodes().map(_.id()) else Collections.singleton(node.id()), restart)
+                    killOrRestart(nodes.map(_.id()), restart)
                 catch {
                     case _: IgniteException => scold("Failed to " + op + " due to system error.").^^
                 }
@@ -205,29 +272,31 @@ class VisorKillCommand extends VisorConsoleCommand {
 
         val op = if (restart) "restart" else "kill"
 
-        if (nodes.size == ignite.cluster.nodes().size())
-            ask("Are you sure you want to " + op + " ALL nodes? (y/n) [n]: ", "n") match {
-                case "y" | "Y" =>  ask("You are about to " + op + " ALL nodes. " +
-                    "Are you 100% sure? (y/n) [n]: ", "n") match {
+        if (!batchMode) {
+            if (nodes.size == ignite.cluster.nodes().size())
+                ask("Are you sure you want to " + op + " ALL nodes? (y/n) [n]: ", "n") match {
+                    case "y" | "Y" => ask("You are about to " + op + " ALL nodes. " +
+                        "Are you 100% sure? (y/n) [n]: ", "n") match {
                         case "y" | "Y" => ()
                         case "n" | "N" => break()
                         case x => nl(); warn("Invalid answer: " + x); break()
                     }
-                case "n" | "N" => break()
-                case x => nl(); warn("Invalid answer: " + x); break()
-            }
-        else if (nodes.size > 1)
-            ask("Are you sure you want to " + op + " several nodes? (y/n) [n]: ", "n") match {
-                case "y" | "Y" => ()
-                case "n" | "N" => break()
-                case x => nl(); warn("Invalid answer: " + x); break()
-            }
-        else
-            ask("Are you sure you want to " + op + " this node? (y/n) [n]: ", "n") match {
-                case "y" | "Y" => ()
-                case "n" | "N" => break()
-                case x => nl(); warn("Invalid answer: " + x); break()
-            }
+                    case "n" | "N" => break()
+                    case x => nl(); warn("Invalid answer: " + x); break()
+                }
+            else if (nodes.size > 1)
+                ask("Are you sure you want to " + op + " several nodes? (y/n) [n]: ", "n") match {
+                    case "y" | "Y" => ()
+                    case "n" | "N" => break()
+                    case x => nl(); warn("Invalid answer: " + x); break()
+                }
+            else
+                ask("Are you sure you want to " + op + " " + nid8(nodes.head) + " node? (y/n) [n]: ", "n") match {
+                    case "y" | "Y" => ()
+                    case "n" | "N" => break()
+                    case x => nl(); warn("Invalid answer: " + x); break()
+                }
+        }
 
         if (restart)
             ignite.cluster.restartNodes(nodes)
@@ -278,7 +347,7 @@ object VisorKillCommand {
         spec = List(
             cmd.name,
             s"${cmd.name} -in|-ih",
-            s"${cmd.name} {-r|-k} {-id8=<node-id8>|-id=<node-id>}"
+            s"${cmd.name} {-r|-k} {-sc} {-al|-ar|-id8=<node-id8>|-id=<node-id>}"
         ),
         args = List(
             "-in" -> List(
@@ -293,6 +362,17 @@ object VisorKillCommand {
                 "choose a host where to kill or restart nodes.",
                 "Note that either '-in' or '-ih' can be specified."
             ),
+            "-al" -> List(
+                "Kill (stop) all local nodes.",
+                "Note that either '-al' or '-ar' can be specified."
+            ),
+            "-ar" -> List(
+                "Kill (stop) all remote nodes.",
+                "Note that either '-al' or '-ar' can be specified."
+            ),
+            "-sc" -> List(
+                "Skip kill or restart of client nodes for group nodes command."
+            ),
             "-r" -> List(
                 "Restart node mode.",
                 "Note that either '-r' or '-k' can be specified.",
@@ -305,8 +385,10 @@ object VisorKillCommand {
             ),
             "-id8=<node-id8>" -> List(
                 "ID8 of the node to kill or restart.",
-                "Note that either '-id8' or '-id' can be specified and " +
-                    "you can also use '@n0' ... '@nn' variables as shortcut to <node-id8>.",
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'.",
                 "If no parameters provided - command starts in interactive mode."
             ),
             "-id=<node-id>" -> List(
@@ -322,6 +404,14 @@ object VisorKillCommand {
                 "Restart node with id8.",
             s"${cmd.name} -id8=@n0 -r" ->
                 "Restart specified node with id8 taken from 'n0' memory variable.",
+            s"${cmd.name} -id8=@nl -r" ->
+                "Restart oldest local node with id8 taken from 'nl' memory variable.",
+            s"${cmd.name} -id8=@nl -k" ->
+                "Kill (stop) oldest remote node with id8 taken from 'nr' memory variable.",
+            s"${cmd.name} -r -ar" ->
+                "Restart all remote nodes.",
+            s"${cmd.name} -k -sc -al" ->
+                "Kill (stop) all local server nodes.",
             s"${cmd.name} -k" ->
                 "Kill (stop) all nodes."
         ),

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/node/VisorNodeCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/node/VisorNodeCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/node/VisorNodeCommand.scala
index 9ba0129..899e495 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/node/VisorNodeCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/node/VisorNodeCommand.scala
@@ -57,7 +57,11 @@ import scala.util.control.Breaks._
  * ====Arguments====
  * {{{
  *     -id8=<node-id8>
- *         ID8 of node. Either '-id8' or '-id' can be specified.
+ *         ID8 of node.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
  *         If neither specified - command starts in interactive mode.
  *     -id=<node-id>
  *         Full ID of node. Either '-id8' or '-id' can  be specified.
@@ -295,8 +299,11 @@ object VisorNodeCommand {
         ),
         args = List(
             "-id8=<node-id8>" -> List(
-                "Note that either '-id8' or '-id' can be specified and " +
-                    "you can also use '@n0' ... '@nn' variables as shortcut to <node-id8>.",
+                "ID8 of node.",
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'.",
                 "If neither specified - command starts in interactive mode."
             ),
             "-id=<node-id>" -> List(

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/vvm/VisorVvmCommand.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/vvm/VisorVvmCommand.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/vvm/VisorVvmCommand.scala
index ff5cf82..e935256 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/vvm/VisorVvmCommand.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/commands/vvm/VisorVvmCommand.scala
@@ -60,7 +60,10 @@ import scala.util.control.Breaks._
  *         If not specified, PATH and JAVA_HOME will be searched.
  *     -id8=<node-id8>
  *         ID8 of node.
- *         Either '-id8' or '-id' can be specified.
+ *         Note that either '-id8' or '-id' should be specified.
+ *         You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.
+ *         To specify oldest node on the same host as visor use variable '@nl'.
+ *         To specify oldest node on other hosts that are not running visor use variable '@nr'.
  *     -id=<node-id>
  *         Full ID of node.
  *         Either '-id8' or '-id' can be specified.
@@ -260,8 +263,10 @@ object VisorVvmCommand {
             ),
             "-id8=<node-id8>" -> List(
                 "ID8 of node.",
-                "Note that either '-id8' or '-id' can be specified and " +
-                    "you can also use '@n0' ... '@nn' variables as shortcut to <node-id8>."
+                "Note that either '-id8' or '-id' should be specified.",
+                "You can also use '@n0' ... '@nn' variables as a shortcut for <node-id8>.",
+                "To specify oldest node on the same host as visor use variable '@nl'.",
+                "To specify oldest node on other hosts that are not running visor use variable '@nr'."
             ),
             "-id=<node-id>" -> List(
                 "Full ID of node.",

http://git-wip-us.apache.org/repos/asf/ignite/blob/89fd76fa/modules/visor-console/src/main/scala/org/apache/ignite/visor/visor.scala
----------------------------------------------------------------------
diff --git a/modules/visor-console/src/main/scala/org/apache/ignite/visor/visor.scala b/modules/visor-console/src/main/scala/org/apache/ignite/visor/visor.scala
index 7f7d1f9..1e8b634 100644
--- a/modules/visor-console/src/main/scala/org/apache/ignite/visor/visor.scala
+++ b/modules/visor-console/src/main/scala/org/apache/ignite/visor/visor.scala
@@ -234,6 +234,8 @@ object visor extends VisorTag {
 
     private var reader: ConsoleReader = null
 
+    var batchMode: Boolean = false
+
     def reader(reader: ConsoleReader) {
         assert(reader != null)
 
@@ -661,12 +663,18 @@ object visor extends VisorTag {
     }
 
     /**
-     * Finds variable by its value.
+     * Finds variables by its value.
      *
      * @param v Value to find by.
      */
-    def mfind(@Nullable v: String): Option[(String, String)] =
-        mem find(t => t._2 == v)
+    def mfind(@Nullable v: String) = mem.filter(t => t._2 == v).toSeq
+
+    /**
+      * Finds variable by its value.
+      *
+      * @param v Value to find by.
+      */
+    def mfindHead(@Nullable v: String) = mfind(v).filterNot(entry => Seq("nl", "nr").contains(entry._1)).headOption
 
     /**
      * Sets Visor console memory variable. Note that this method '''does not'''
@@ -872,7 +880,7 @@ object visor extends VisorTag {
                 case _ => Left("'id8' resolves to more than one node (use full 'id' instead): " + id8.get)
             }
         }
-        else if (id.isDefined)
+        else if (id.isDefined) {
             try {
                 val node = Option(ignite.cluster.node(java.util.UUID.fromString(id.get)))
 
@@ -884,6 +892,7 @@ object visor extends VisorTag {
             catch {
                 case e: IllegalArgumentException => Left("Invalid node 'id': " + id.get)
             }
+        }
         else
             Right(None)
     }
@@ -1522,15 +1531,27 @@ object visor extends VisorTag {
                 setVarIfAbsent(ip.get, "h")
         })
 
+        val onHost = ignite.cluster.forHost(ignite.localNode())
+
+        Option(onHost.forServers().forOldest().node()).foreach(n => msetOpt("nl", nid8(n)))
+        Option(ignite.cluster.forOthers(onHost).forServers.forOldest().node()).foreach(n => msetOpt("nr", nid8(n)))
+
         nodeJoinLsnr = new IgnitePredicate[Event]() {
             override def apply(e: Event): Boolean = {
                 e match {
                     case de: DiscoveryEvent =>
-                        setVarIfAbsent(nid8(de.eventNode()), "n")
+                        val n = nid8(de.eventNode())
+
+                        setVarIfAbsent(n, "n")
 
                         val node = ignite.cluster.node(de.eventNode().id())
 
                         if (node != null) {
+                            val alias = if (U.sameMacs(ignite.localNode(), node)) "nl" else "nr"
+
+                            if (mgetOpt(alias).isEmpty)
+                                msetOpt(alias, n)
+
                             val ip = sortAddresses(node.addresses).headOption
 
                             if (ip.isDefined)
@@ -1551,29 +1572,25 @@ object visor extends VisorTag {
 
         ignite.events().localListen(nodeJoinLsnr, EVT_NODE_JOINED)
 
-        nodeLeftLsnr = new IgnitePredicate[Event]() {
-            override def apply(e: Event): Boolean = {
-                e match {
-                    case (de: DiscoveryEvent) =>
-                        val nv = mfind(nid8(de.eventNode()))
+        val mclear = (node: ClusterNode) => {
+            mfind(nid8(node)).foreach(nv => mem.remove(nv._1))
 
-                        if (nv.isDefined)
-                            mem.remove(nv.get._1)
+            val onHost = ignite.cluster.forHost(ignite.localNode())
 
-                        val ip = sortAddresses(de.eventNode().addresses).headOption
+            if (mgetOpt("nl").isEmpty)
+                Option(onHost.forServers().forOldest().node()).foreach(n => msetOpt("nl", nid8(n)))
 
-                        if (ip.isDefined) {
-                            val last = !ignite.cluster.nodes().exists(n =>
-                                n.addresses.size > 0 && sortAddresses(n.addresses).head == ip.get
-                            )
+            if (mgetOpt("nr").isEmpty)
+                Option(ignite.cluster.forOthers(onHost).forServers.forOldest().node()).foreach(n => msetOpt("nr", nid8(n)))
 
-                            if (last) {
-                                val hv = mfind(ip.get)
+            if (onHost.nodes().isEmpty)
+                sortAddresses(node.addresses).headOption.foreach((ip) => mfind(ip).foreach(hv => mem.remove(hv._1)))
+        }
 
-                                if (hv.isDefined)
-                                    mem.remove(hv.get._1)
-                            }
-                        }
+        nodeLeftLsnr = new IgnitePredicate[Event]() {
+            override def apply(e: Event): Boolean = {
+                e match {
+                    case (de: DiscoveryEvent) => mclear(de.eventNode())
                 }
 
                 true
@@ -1594,6 +1611,8 @@ object visor extends VisorTag {
 
                             close()
                         }
+                        else
+                            mclear(de.eventNode())
                 }
 
                 true
@@ -1658,7 +1677,7 @@ object visor extends VisorTag {
             val n = ignite.cluster.node(id)
 
             val id8 = nid8(id)
-            val v = mfind(id8)
+            val v = mfindHead(id8)
 
             id8 +
                 (if (v.isDefined) "(@" + v.get._1 + ")" else "") +
@@ -1678,7 +1697,7 @@ object visor extends VisorTag {
         assert(isCon)
 
         val id8 = nid8(id)
-        val v = mfind(id8)
+        val v = mfindHead(id8)
 
         id8 + (if (v.isDefined) "(@" + v.get._1 + ")" else "")
     }
@@ -1846,7 +1865,7 @@ object visor extends VisorTag {
 
             t.render()
 
-            val a = ask("\nChoose node number ('c' to cancel) [c]: ", "c")
+            val a = ask("\nChoose node number ('c' to cancel) [0]: ", "0")
 
             if (a.toLowerCase == "c")
                 None
@@ -1929,7 +1948,7 @@ object visor extends VisorTag {
 
             t.render()
 
-            val a = ask("\nChoose host number ('c' to cancel) [c]: ", "c")
+            val a = ask("\nChoose host number ('c' to cancel) [0]: ", "0")
 
             if (a.toLowerCase == "c")
                 None
@@ -2000,6 +2019,9 @@ object visor extends VisorTag {
         assert(prompt != null)
         assert(dflt != null)
 
+        if (batchMode)
+            return dflt
+
         readLineOpt(prompt, if (passwd) Some('*') else None) match {
             case None => dflt
             case Some(s) if s.length == 0 => dflt


[44/46] ignite git commit: Merge branch 'gridgain-7.6.2'

Posted by sb...@apache.org.
Merge branch 'gridgain-7.6.2'


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

Branch: refs/heads/ignite-1232
Commit: 5b0dbcae00a5237862e73b73f203e1c35710e834
Parents: 869db21
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Jul 20 11:49:36 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Jul 20 11:49:36 2016 +0300

----------------------------------------------------------------------
 assembly/LICENSE_FABRIC                         |   7 +-
 assembly/LICENSE_HADOOP                         |   7 +-
 examples/pom-standalone-lgpl.xml                |   6 +-
 examples/pom-standalone.xml                     |   6 +-
 examples/pom.xml                                |   6 +-
 examples/schema-import/pom-standalone.xml       |   6 +-
 examples/schema-import/pom.xml                  |   6 +-
 modules/cassandra/pom.xml                       |   2 +-
 modules/core/pom.xml                            |   6 +-
 .../ignite/cache/query/ContinuousQuery.java     |  47 +++++--
 .../processors/cache/IgniteCacheProxy.java      |   3 +-
 .../continuous/CacheContinuousQueryManager.java |   9 +-
 .../PlatformAffinityFunctionTarget.java         |   8 +-
 .../cache/affinity/PlatformAffinityUtils.java   |   5 +
 ...ridCacheContinuousQueryAbstractSelfTest.java |  47 +++++++
 modules/flume/README.txt                        |   2 +-
 modules/kafka/README.txt                        |   4 +-
 .../platforms/cpp/jni/include/ignite/jni/java.h |   8 +-
 .../Apache.Ignite.Core.Tests.csproj             |   3 +
 .../Affinity/AffinityFunctionSpringTest.cs      | 104 +++++++-------
 .../Cache/CacheConfigurationTest.cs             |   1 +
 .../Cache/Affinity/affinity-function2.xml       |  49 +++++++
 .../Apache.Ignite.Core.Tests/DeploymentTest.cs  |   2 +-
 .../Apache.Ignite.Core.Tests/TestRunner.cs      |   2 +-
 .../Apache.Ignite.Core.csproj                   |  13 +-
 .../Cache/Affinity/Fair/FairAffinityFunction.cs |   1 +
 .../Cache/Affinity/Fair/Package-Info.cs         |  26 ++++
 .../Cache/Affinity/Package-Info.cs              |  26 ++++
 .../Cache/Affinity/Rendezvous/Package-Info.cs   |  26 ++++
 .../Rendezvous/RendezvousAffinityFunction.cs    |   1 +
 .../Cache/Configuration/Package-Info.cs         |  26 ++++
 .../Cache/Eviction/Package-Info.cs              |  26 ++++
 .../Communication/Package-Info.cs               |  26 ++++
 .../Communication/Tcp/Package-Info.cs           |  26 ++++
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |   2 +-
 .../Impl/Binary/BinaryReaderExtensions.cs       |   2 +-
 .../Impl/Cache/Affinity/AffinityFunctionBase.cs | 140 +++++++++++++++++++
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |   2 +-
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        |   2 +-
 parent/pom.xml                                  |   1 +
 40 files changed, 585 insertions(+), 107 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/assembly/LICENSE_FABRIC
----------------------------------------------------------------------
diff --git a/assembly/LICENSE_FABRIC b/assembly/LICENSE_FABRIC
index 8cb5730..b9c75b2 100644
--- a/assembly/LICENSE_FABRIC
+++ b/assembly/LICENSE_FABRIC
@@ -1,4 +1,3 @@
-
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
@@ -227,6 +226,12 @@ For details, see CC0 1.0 Universal (1.0), Public Domain Dedication,
 http://creativecommons.org/publicdomain/zero/1.0/
 
 ==============================================================================
+For JSR107 API and SPI (https://github.com/jsr107/jsr107spec) javax.cache:cache-api:jar:1.0.0
+==============================================================================
+This product bundles JSR107 API and SPI which is available under a:
+JSR-000107 JCACHE 2.9 Public Review - Updated Specification License. For details, see https://raw.github.com/jsr107/jsr107spec/master/LICENSE.txt.
+
+==============================================================================
 For JSch (http://www.jcraft.com/jsch/) com.jcraft:jsch:jar:0.1.50
 ==============================================================================
 This product bundles JSch which is available under a:

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/assembly/LICENSE_HADOOP
----------------------------------------------------------------------
diff --git a/assembly/LICENSE_HADOOP b/assembly/LICENSE_HADOOP
index 0d05d52..0256b20 100644
--- a/assembly/LICENSE_HADOOP
+++ b/assembly/LICENSE_HADOOP
@@ -1,4 +1,3 @@
-
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
@@ -227,6 +226,12 @@ For details, see CC0 1.0 Universal (1.0), Public Domain Dedication,
 http://creativecommons.org/publicdomain/zero/1.0/
 
 ==============================================================================
+For JSR107 API and SPI (https://github.com/jsr107/jsr107spec) javax.cache:cache-api:jar:1.0.0
+==============================================================================
+This product bundles JSR107 API and SPI which is available under a:
+JSR-000107 JCACHE 2.9 Public Review - Updated Specification License. For details, see https://raw.github.com/jsr107/jsr107spec/master/LICENSE.txt.
+
+==============================================================================
 For JSch (http://www.jcraft.com/jsch/) com.jcraft:jsch:jar:0.1.50
 ==============================================================================
 This product bundles JSch which is available under a:

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/examples/pom-standalone-lgpl.xml
----------------------------------------------------------------------
diff --git a/examples/pom-standalone-lgpl.xml b/examples/pom-standalone-lgpl.xml
index 951fab6..7e7ccc2 100644
--- a/examples/pom-standalone-lgpl.xml
+++ b/examples/pom-standalone-lgpl.xml
@@ -41,9 +41,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>1.0.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/examples/pom-standalone.xml
----------------------------------------------------------------------
diff --git a/examples/pom-standalone.xml b/examples/pom-standalone.xml
index 20399ee..6247ced 100644
--- a/examples/pom-standalone.xml
+++ b/examples/pom-standalone.xml
@@ -41,9 +41,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>1.0.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index cba056d..979a46f 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -32,9 +32,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>${javax.cache.version}</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/examples/schema-import/pom-standalone.xml
----------------------------------------------------------------------
diff --git a/examples/schema-import/pom-standalone.xml b/examples/schema-import/pom-standalone.xml
index 43b76d8..e443728 100644
--- a/examples/schema-import/pom-standalone.xml
+++ b/examples/schema-import/pom-standalone.xml
@@ -36,9 +36,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>1.0.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/examples/schema-import/pom.xml
----------------------------------------------------------------------
diff --git a/examples/schema-import/pom.xml b/examples/schema-import/pom.xml
index f5ccac0..b6e36ef 100644
--- a/examples/schema-import/pom.xml
+++ b/examples/schema-import/pom.xml
@@ -39,9 +39,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>${javax.cache.version}</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/modules/cassandra/pom.xml b/modules/cassandra/pom.xml
index c9ff87d..dc8b08c 100644
--- a/modules/cassandra/pom.xml
+++ b/modules/cassandra/pom.xml
@@ -236,7 +236,7 @@
                                 org.apache.ignite,org.springframework,org.gridgain
                             </excludeGroupIds>
                             <excludeArtifactIds>
-                                commons-logging,slf4j-api,geronimo-jcache_1.0_spec,slf4j-api,aopalliance
+                                commons-logging,slf4j-api,cache-api,slf4j-api,aopalliance
                             </excludeArtifactIds>
                             <includeScope>runtime</includeScope>
                         </configuration>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/pom.xml
----------------------------------------------------------------------
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index 7529b0b..5e32caf 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -63,9 +63,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>${javax.cache.version}</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
index bbfe8cc..49d471e 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/ContinuousQuery.java
@@ -21,6 +21,7 @@ import javax.cache.Cache;
 import javax.cache.configuration.Factory;
 import javax.cache.event.CacheEntryEventFilter;
 import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.event.EventType;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.cache.CacheEntryEventSerializableFilter;
 import org.apache.ignite.configuration.IgniteConfiguration;
@@ -142,6 +143,9 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
     /** Automatic unsubscription flag. */
     private boolean autoUnsubscribe = DFLT_AUTO_UNSUBSCRIBE;
 
+    /** Whether to notify about {@link EventType#EXPIRED} events. */
+    private boolean includeExpired;
+
     /**
      * Creates new continuous query.
      */
@@ -324,6 +328,38 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
         return this;
     }
 
+    /**
+     * Gets automatic unsubscription flag value.
+     *
+     * @return Automatic unsubscription flag.
+     */
+    public boolean isAutoUnsubscribe() {
+        return autoUnsubscribe;
+    }
+
+    /**
+     * Sets the flag value defining whether to notify about {@link EventType#EXPIRED} events.
+     * If {@code true}, then the remote listener will get notifications about entries
+     * expired in cache. Otherwise, only {@link EventType#CREATED}, {@link EventType#UPDATED}
+     * and {@link EventType#REMOVED} events will be fired in the remote listener.
+     * <p>
+     * This flag is {@code false} by default, so {@link EventType#EXPIRED} events are disabled.
+     *
+     * @param includeExpired Whether to notify about {@link EventType#EXPIRED} events.
+     */
+    public void setIncludeExpired(boolean includeExpired) {
+        this.includeExpired = includeExpired;
+    }
+
+    /**
+     * Gets the flag value defining whether to notify about {@link EventType#EXPIRED} events.
+     *
+     * @return Whether to notify about {@link EventType#EXPIRED} events.
+     */
+    public boolean isIncludeExpired() {
+        return includeExpired;
+    }
+
     /** {@inheritDoc} */
     @Override public ContinuousQuery<K, V> setPageSize(int pageSize) {
         return (ContinuousQuery<K, V>)super.setPageSize(pageSize);
@@ -333,13 +369,4 @@ public final class ContinuousQuery<K, V> extends Query<Cache.Entry<K, V>> {
     @Override public ContinuousQuery<K, V> setLocal(boolean loc) {
         return (ContinuousQuery<K, V>)super.setLocal(loc);
     }
-
-    /**
-     * Gets automatic unsubscription flag value.
-     *
-     * @return Automatic unsubscription flag.
-     */
-    public boolean isAutoUnsubscribe() {
-        return autoUnsubscribe;
-    }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
index fe4f79c..0d7bc6a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
@@ -616,7 +616,8 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
                 qry.getTimeInterval(),
                 qry.isAutoUnsubscribe(),
                 loc,
-                keepBinary);
+                keepBinary,
+                qry.isIncludeExpired());
 
             final QueryCursor<Cache.Entry<K, V>> cur =
                 qry.getInitialQuery() != null ? query(qry.getInitialQuery()) : null;

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
index 195f3ae..a8e5a6b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/continuous/CacheContinuousQueryManager.java
@@ -421,7 +421,8 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
         long timeInterval,
         boolean autoUnsubscribe,
         boolean loc,
-        final boolean keepBinary) throws IgniteCheckedException
+        final boolean keepBinary,
+        final boolean includeExpired) throws IgniteCheckedException
     {
         IgniteClosure<Boolean, CacheContinuousQueryHandler> clsr;
 
@@ -438,7 +439,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                             rmtFilterFactory,
                             true,
                             false,
-                            true,
+                            !includeExpired,
                             false,
                             null);
                     else {
@@ -456,7 +457,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                             (CacheEntryEventSerializableFilter)fltr,
                             true,
                             false,
-                            true,
+                            !includeExpired,
                             false);
                     }
 
@@ -473,7 +474,7 @@ public class CacheContinuousQueryManager extends GridCacheManagerAdapter {
                         rmtFilter,
                         true,
                         false,
-                        true,
+                        !includeExpired,
                         false);
                 }
             };

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
index d83dd08..8a07b33 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
@@ -64,7 +64,8 @@ public class PlatformAffinityFunctionTarget extends PlatformAbstractTarget {
 
         try {
             platformCtx.kernalContext().resource().injectGeneric(baseFunc);
-        } catch (IgniteCheckedException e) {
+        }
+        catch (IgniteCheckedException e) {
             throw U.convertException(e);
         }
     }
@@ -75,6 +76,7 @@ public class PlatformAffinityFunctionTarget extends PlatformAbstractTarget {
             return baseFunc.partition(reader.readObjectDetached());
         else if (type == OP_REMOVE_NODE) {
             baseFunc.removeNode(reader.readUuid());
+
             return 0;
         }
 
@@ -88,7 +90,7 @@ public class PlatformAffinityFunctionTarget extends PlatformAbstractTarget {
 
             if (affCtx == null)
                 throw new IgniteException("Thread-local AffinityFunctionContext is null. " +
-                        "This may indicate an unsupported call to the base AffinityFunction");
+                        "This may indicate an unsupported call to the base AffinityFunction.");
 
             final List<List<ClusterNode>> partitions = baseFunc.assignPartitions(affCtx);
 
@@ -100,8 +102,6 @@ public class PlatformAffinityFunctionTarget extends PlatformAbstractTarget {
         super.processOutStream(type, writer);
     }
 
-
-
     /**
      * Sets the context for current operation.
      *

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
index 6d14cab..bff6cd2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
@@ -47,9 +47,11 @@ public class PlatformAffinityUtils {
         assert ctx != null;
 
         ctx.writeNodes(writer, affCtx.currentTopologySnapshot());
+
         writer.writeInt(affCtx.backups());
         writer.writeLong(affCtx.currentTopologyVersion().topologyVersion());
         writer.writeInt(affCtx.currentTopologyVersion().minorTopologyVersion());
+
         ctx.writeEvent(writer, affCtx.discoveryEvent());
 
         // Write previous assignment
@@ -95,11 +97,14 @@ public class PlatformAffinityUtils {
         assert ctx != null;
 
         int partCnt = reader.readInt();
+
         List<List<ClusterNode>> res = new ArrayList<>(partCnt);
+
         IgniteClusterEx cluster = ctx.kernalContext().grid().cluster();
 
         for (int i = 0; i < partCnt; i++) {
             int partSize = reader.readInt();
+
             List<ClusterNode> part = new ArrayList<>(partSize);
 
             for (int j = 0; j < partSize; j++)

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
index f372e0d..d5dc557 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/query/continuous/GridCacheContinuousQueryAbstractSelfTest.java
@@ -34,6 +34,9 @@ import javax.cache.Cache;
 import javax.cache.configuration.Factory;
 import javax.cache.event.CacheEntryEvent;
 import javax.cache.event.CacheEntryUpdatedListener;
+import javax.cache.event.EventType;
+import javax.cache.expiry.CreatedExpiryPolicy;
+import javax.cache.expiry.Duration;
 import javax.cache.integration.CacheWriterException;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
@@ -1093,6 +1096,50 @@ public abstract class GridCacheContinuousQueryAbstractSelfTest extends GridCommo
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testExpired() throws Exception {
+        IgniteCache<Object, Object> cache = grid(0).cache(null).
+            withExpiryPolicy(new CreatedExpiryPolicy(new Duration(MILLISECONDS, 1000)));
+
+        final Map<Object, Object> map = new ConcurrentHashMap8<>();
+        final CountDownLatch latch = new CountDownLatch(2);
+
+        ContinuousQuery<Object, Object> qry = new ContinuousQuery<>();
+
+        qry.setIncludeExpired(true);
+
+        qry.setLocalListener(new CacheEntryUpdatedListener<Object, Object>() {
+            @Override public void onUpdated(Iterable<CacheEntryEvent<?, ?>> evts) {
+                for (CacheEntryEvent<?, ?> e : evts) {
+                    if (e.getEventType() == EventType.EXPIRED) {
+                        assertNull(e.getValue());
+
+                        map.put(e.getKey(), e.getOldValue());
+
+                        latch.countDown();
+                    }
+                }
+            }
+        });
+
+        try (QueryCursor<Cache.Entry<Object, Object>> ignored = cache.query(qry)) {
+            cache.put(1, 1);
+            cache.put(2, 2);
+
+            // Wait for expiration.
+            Thread.sleep(2000);
+
+            assert latch.await(LATCH_TIMEOUT, MILLISECONDS);
+
+            assertEquals(2, map.size());
+
+            assertEquals(1, (int)map.get(1));
+            assertEquals(2, (int)map.get(2));
+        }
+    }
+
+    /**
      *
      */
     private static class StoreFactory implements Factory<CacheStore> {

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/flume/README.txt
----------------------------------------------------------------------
diff --git a/modules/flume/README.txt b/modules/flume/README.txt
index 97d8cac..bf7e0ff 100644
--- a/modules/flume/README.txt
+++ b/modules/flume/README.txt
@@ -20,7 +20,7 @@ plugins.d/
     |-- lib
     |   `-- ignite-flume-transformer-x.x.x.jar <-- your jar
     `-- libext
-        |-- geronimo-jcache_1.0_spec-1.0-alpha-1.jar
+        |-- cache-api-1.0.0.jar
         |-- ignite-core-x.x.x.jar
         |-- ignite-flume-x.x.x.jar <-- IgniteSink
         |-- ignite-spring-x.x.x.jar

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/kafka/README.txt
----------------------------------------------------------------------
diff --git a/modules/kafka/README.txt b/modules/kafka/README.txt
index 80103a6..259a4f6 100644
--- a/modules/kafka/README.txt
+++ b/modules/kafka/README.txt
@@ -47,7 +47,7 @@ as described in the following subsection.
 - ignite-kafka-connect-x.x.x-SNAPSHOT.jar
 - ignite-core-x.x.x-SNAPSHOT.jar
 - ignite-spring-x.x.x-SNAPSHOT.jar
-- geronimo-jcache_1.0_spec-1.0-alpha-1.jar
+- cache-api-1.0.0.jar
 - spring-aop-4.1.0.RELEASE.jar
 - spring-beans-4.1.0.RELEASE.jar
 - spring-context-4.1.0.RELEASE.jar
@@ -140,7 +140,7 @@ as described in the following subsection.
 1. Put the following jar files on Kafka's classpath
 - ignite-kafka-connect-x.x.x-SNAPSHOT.jar
 - ignite-core-x.x.x-SNAPSHOT.jar
-- geronimo-jcache_1.0_spec-1.0-alpha-1.jar
+- cache-api-1.0.0.jar
 - ignite-spring-x.x.x-SNAPSHOT.jar
 - spring-aop-4.1.0.RELEASE.jar
 - spring-beans-4.1.0.RELEASE.jar

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/cpp/jni/include/ignite/jni/java.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/jni/include/ignite/jni/java.h b/modules/platforms/cpp/jni/include/ignite/jni/java.h
index 41d7caa..e862f93 100644
--- a/modules/platforms/cpp/jni/include/ignite/jni/java.h
+++ b/modules/platforms/cpp/jni/include/ignite/jni/java.h
@@ -105,7 +105,7 @@ namespace ignite
             typedef void(JNICALL *AffinityFunctionAssignPartitionsHandler)(void* target, long long ptr, long long inMemPtr, long long outMemPtr);
             typedef void(JNICALL *AffinityFunctionRemoveNodeHandler)(void* target, long long ptr, long long memPtr);
             typedef void(JNICALL *AffinityFunctionDestroyHandler)(void* target, long long ptr);
-            
+
             typedef void(JNICALL *ConsoleWriteHandler)(const char* chars, int charsLen, unsigned char isErr);
 
             /**
@@ -185,7 +185,7 @@ namespace ignite
 
                 OnClientDisconnectedHandler onClientDisconnected;
                 OnClientReconnectedHandler onClientReconnected;
-                
+
                 AffinityFunctionInitHandler affinityFunctionInit;
                 AffinityFunctionPartitionHandler affinityFunctionPartition;
                 AffinityFunctionAssignPartitionsHandler affinityFunctionAssignPartitions;
@@ -550,7 +550,7 @@ namespace ignite
                 jobject ProcessorAtomicReference(jobject obj, char* name, long long memPtr, bool create);
 				void ProcessorGetIgniteConfiguration(jobject obj, long long memPtr);
 				void ProcessorGetCacheNames(jobject obj, long long memPtr);
-                
+
                 long long TargetInStreamOutLong(jobject obj, int type, long long memPtr, JniErrorInfo* errInfo = NULL);
                 void TargetInStreamOutStream(jobject obj, int opType, long long inMemPtr, long long outMemPtr, JniErrorInfo* errInfo = NULL);
                 jobject TargetInStreamOutObject(jobject obj, int type, long long memPtr, JniErrorInfo* errInfo = NULL);
@@ -761,7 +761,7 @@ namespace ignite
             JNIEXPORT void JNICALL JniAffinityFunctionAssignPartitions(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong inMemPtr, jlong outMemPtr);
             JNIEXPORT void JNICALL JniAffinityFunctionRemoveNode(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong memPtr);
             JNIEXPORT void JNICALL JniAffinityFunctionDestroy(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr);
-            
+
             JNIEXPORT void JNICALL JniConsoleWrite(JNIEnv *env, jclass cls, jstring str, jboolean isErr);
         }
     }

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 d0d1934..5c10612 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
@@ -210,6 +210,9 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       <SubType>Designer</SubType>
     </Content>
+    <Content Include="Config\Cache\Affinity\affinity-function2.xml">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="Config\Cache\Affinity\affinity-function.xml">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
index a1e2ad8..8d118be 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
@@ -1,4 +1,4 @@
-\ufeff/*
+\ufeff\ufeff/*
  * 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.
@@ -34,40 +34,26 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
     /// </summary>
     public class AffinityFunctionSpringTest : IgniteTestBase
     {
-        /** */
-        private IIgnite _ignite;
-
         /// <summary>
         /// Initializes a new instance of the <see cref="AffinityFunctionSpringTest"/> class.
         /// </summary>
-        public AffinityFunctionSpringTest() : base(6, "config\\cache\\affinity\\affinity-function.xml")
+        public AffinityFunctionSpringTest() : base(6,
+            "config\\cache\\affinity\\affinity-function.xml",
+            "config\\cache\\affinity\\affinity-function2.xml")
         {
             // No-op.
         }
 
-        /** <inheritdoc /> */
-        public override void TestSetUp()
-        {
-            base.TestSetUp();
-
-            // Start another node without spring config
-            if (Ignition.TryGetIgnite("grid2") == null)
-            {
-                var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) {GridName = "grid2"};
-                _ignite = Ignition.Start(cfg);
-            }
-        }
-
         /// <summary>
         /// Tests the static cache.
         /// </summary>
         [Test]
         public void TestStaticCache()
         {
-            ValidateAffinityFunction(Grid.GetCache<int, int>("cache1"));
-            ValidateAffinityFunction(_ignite.GetCache<int, int>("cache1"));
-            ValidateAffinityFunction(Grid.GetCache<int, int>("cache2"));
-            ValidateAffinityFunction(_ignite.GetCache<int, int>("cache2"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("cache1"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("cache1"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("cache2"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("cache2"));
         }
 
         /// <summary>
@@ -76,51 +62,46 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
         [Test]
         public void TestDynamicCache()
         {
-            ValidateAffinityFunction(Grid.CreateCache<int, int>("dyn-cache-1"));
-            ValidateAffinityFunction(_ignite.GetCache<int, int>("dyn-cache-1"));
+            ValidateAffinityFunction(Grid.CreateCache<long, int>("dyn-cache-1"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("dyn-cache-1"));
 
-            ValidateAffinityFunction(_ignite.CreateCache<int, int>("dyn-cache-2"));
-            ValidateAffinityFunction(Grid.GetCache<int, int>("dyn-cache-2"));
+            ValidateAffinityFunction(Grid2.CreateCache<long, int>("dyn-cache-2"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("dyn-cache-2"));
 
-            ValidateAffinityFunction(Grid.CreateCache<int, int>("dyn-cache2-1"));
-            ValidateAffinityFunction(_ignite.GetCache<int, int>("dyn-cache2-1"));
+            ValidateAffinityFunction(Grid.CreateCache<long, int>("dyn-cache2-1"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("dyn-cache2-1"));
 
-            ValidateAffinityFunction(_ignite.CreateCache<int, int>("dyn-cache2-2"));
-            ValidateAffinityFunction(Grid.GetCache<int, int>("dyn-cache2-2"));
+            ValidateAffinityFunction(Grid2.CreateCache<long, int>("dyn-cache2-2"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("dyn-cache2-2"));
         }
 
         /// <summary>
         /// Validates the affinity function.
         /// </summary>
         /// <param name="cache">The cache.</param>
-        private static void ValidateAffinityFunction(ICache<int, int> cache)
+        private static void ValidateAffinityFunction(ICache<long, int> cache)
         {
             var aff = cache.Ignite.GetAffinity(cache.Name);
-            Assert.AreEqual(5, aff.Partitions);
-            Assert.AreEqual(4, aff.GetPartition(2));
-            Assert.AreEqual(3, aff.GetPartition(4));
 
-            var func = (ITestFunc) cache.GetConfiguration().AffinityFunction;
-            Assert.AreEqual(5, func.Partitions);
-            Assert.AreEqual(1, func.Property1);
-            Assert.AreEqual("1", func.Property2);
-        }
+            Assert.AreEqual(5, aff.Partitions);
 
-        private interface ITestFunc : IAffinityFunction
-        {
-            int Property1 { get; set; }
+            // Predefined map
+            Assert.AreEqual(2, aff.GetPartition(1L));
+            Assert.AreEqual(1, aff.GetPartition(2L));
 
-            string Property2 { get; set; }
+            // Other keys
+            Assert.AreEqual(1, aff.GetPartition(13L));
+            Assert.AreEqual(3, aff.GetPartition(4L));
         }
 
-        private class TestFunc : ITestFunc   // [Serializable] is not necessary
+        private class TestFunc : IAffinityFunction   // [Serializable] is not necessary
         {
             [InstanceResource]
             private readonly IIgnite _ignite = null;
 
-            public int Property1 { get; set; }
+            private int Property1 { get; set; }
 
-            public string Property2 { get; set; }
+            private string Property2 { get; set; }
 
             public int Partitions
             {
@@ -133,9 +114,16 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
                 Assert.AreEqual(1, Property1);
                 Assert.AreEqual("1", Property2);
 
-                return (int) key * 2 % 5;
+                var longKey = (long)key;
+                int res;
+
+                if (TestFairFunc.PredefinedParts.TryGetValue(longKey, out res))
+                    return res;
+
+                return (int)(longKey * 2 % 5);
             }
 
+            // ReSharper disable once UnusedParameter.Local
             public void RemoveNode(Guid nodeId)
             {
                 // No-op.
@@ -147,14 +135,20 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
             }
         }
 
-        private class TestFairFunc : FairAffinityFunction, ITestFunc   // [Serializable] is not necessary
+        private class TestFairFunc : FairAffinityFunction   // [Serializable] is not necessary
         {
+            public static readonly Dictionary<long, int> PredefinedParts = new Dictionary<long, int>
+            {
+                {1, 2},
+                {2, 1}
+            };
+
             [InstanceResource]
             private readonly IIgnite _ignite = null;
 
-            public int Property1 { get; set; }
+            private int Property1 { get; set; }
 
-            public string Property2 { get; set; }
+            private string Property2 { get; set; }
 
             public override int GetPartition(object key)
             {
@@ -162,11 +156,19 @@ namespace Apache.Ignite.Core.Tests.Cache.Affinity
                 Assert.AreEqual(1, Property1);
                 Assert.AreEqual("1", Property2);
 
+                Assert.IsInstanceOf<long>(key);
+
                 var basePart = base.GetPartition(key);
                 Assert.Greater(basePart, -1);
                 Assert.Less(basePart, Partitions);
 
-                return (int) key * 2 % 5;
+                var longKey = (long) key;
+                int res;
+
+                if (PredefinedParts.TryGetValue(longKey, out res))
+                    return res;
+
+                return (int) (longKey * 2 % 5);
             }
 
             public override IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 da68ca2..7bd1ba5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/CacheConfigurationTest.cs
@@ -28,6 +28,7 @@ namespace Apache.Ignite.Core.Tests.Cache
     using Apache.Ignite.Core.Cache.Eviction;
     using Apache.Ignite.Core.Cache.Store;
     using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Impl.Cache.Affinity;
     using NUnit.Framework;
 
     /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml
new file mode 100644
index 0000000..cab34b5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml
@@ -0,0 +1,49 @@
+\ufeff<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+    <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration"><null/></property>
+        <property name="gridName" value="grid2" />
+
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <!-- In distributed environment, replace with actual host IP address. -->
+                                <value>127.0.0.1:47500</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+                <property name="socketTimeout" value="300" />
+            </bean>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 e890dc8..ab5a1a6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
@@ -45,7 +45,7 @@ namespace Apache.Ignite.Core.Tests
             // Copy jars
             var home = IgniteHome.Resolve(null);
 
-            var jarNames = new[] {@"\ignite-core-", @"\geronimo-jcache_1.0_spec-1.0-alpha-1.jar", @"\modules\spring\" };
+            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();

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
index 5403ebe..facc598 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
@@ -1,4 +1,4 @@
-\ufeff/*
+\ufeff\ufeff/*
  * 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.

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 fac94a8..b0adf61 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -84,16 +84,18 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Binary\BinaryReflectiveSerializer.cs" />
-    <Compile Include="Cache\Affinity\AffinityTopologyVersion.cs" />
-    <Compile Include="Cache\Affinity\AffinityFunctionContext.cs" />
     <Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
     <Compile Include="Impl\Binary\IBinarySerializerInternal.cs" />
     <Compile Include="Binary\Package-Info.cs" />
-    <Compile Include="Cache\Affinity\AffinityFunctionBase.cs" />
     <Compile Include="Cache\Affinity\AffinityKey.cs" />
     <Compile Include="Cache\Affinity\AffinityKeyMappedAttribute.cs" />
+    <Compile Include="Cache\Affinity\AffinityFunctionContext.cs" />
+    <Compile Include="Cache\Affinity\AffinityTopologyVersion.cs" />
     <Compile Include="Cache\Affinity\Fair\FairAffinityFunction.cs" />
+    <Compile Include="Cache\Affinity\Fair\Package-Info.cs" />
     <Compile Include="Cache\Affinity\IAffinityFunction.cs" />
+    <Compile Include="Cache\Affinity\Package-Info.cs" />
+    <Compile Include="Cache\Affinity\Rendezvous\Package-Info.cs" />
     <Compile Include="Cache\Affinity\Rendezvous\RendezvousAffinityFunction.cs" />
     <Compile Include="Cache\CacheAtomicUpdateTimeoutException.cs" />
     <Compile Include="Cache\CacheEntryProcessorException.cs" />
@@ -101,7 +103,11 @@
     <Compile Include="Cache\CachePartialUpdateException.cs" />
     <Compile Include="Cache\CachePeekMode.cs" />
     <Compile Include="Cache\Configuration\NearCacheConfiguration.cs" />
+    <Compile Include="Cache\Configuration\Package-Info.cs" />
+    <Compile Include="Cache\Eviction\Package-Info.cs" />
     <Compile Include="Communication\ICommunicationSpi.cs" />
+    <Compile Include="Communication\Package-Info.cs" />
+    <Compile Include="Communication\Tcp\Package-Info.cs" />
     <Compile Include="Communication\Tcp\TcpCommunicationSpi.cs" />
     <Compile Include="DataStructures\Configuration\AtomicConfiguration.cs" />
     <Compile Include="Cache\Configuration\QueryAlias.cs" />
@@ -163,6 +169,7 @@
     <Compile Include="Impl\Binary\DateTimeSerializer.cs" />
     <Compile Include="Impl\Binary\SerializableSerializer.cs" />
     <Compile Include="Impl\Binary\BinaryWriterExtensions.cs" />
+    <Compile Include="Impl\Cache\Affinity\AffinityFunctionBase.cs" />
     <Compile Include="Impl\Binary\UserSerializerProxy.cs" />
     <Compile Include="Impl\Cache\Affinity\AffinityFunctionSerializer.cs" />
     <Compile Include="Impl\Cache\Affinity\PlatformAffinityFunction.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
index 4a3885f..f06937d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Core.Cache.Affinity.Fair
 {
     using System;
+    using Apache.Ignite.Core.Impl.Cache.Affinity;
 
     /// <summary>
     /// Fair affinity function which tries to ensure that all nodes get equal number of partitions with 

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs
new file mode 100644
index 0000000..29a21bd
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Fair affinity API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Affinity.Fair
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs
new file mode 100644
index 0000000..dfbdf08
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Cache affinity API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Affinity
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs
new file mode 100644
index 0000000..4b7f9af
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Rendezvous affinity API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Affinity.Rendezvous
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
index 98ec364..928324c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
@@ -18,6 +18,7 @@
 namespace Apache.Ignite.Core.Cache.Affinity.Rendezvous
 {
     using System;
+    using Apache.Ignite.Core.Impl.Cache.Affinity;
 
     /// <summary>
     /// Affinity function for partitioned cache based on Highest Random Weight algorithm.

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs
new file mode 100644
index 0000000..fb8ed61
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Ignite Configuration API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Configuration
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs
new file mode 100644
index 0000000..13f56a8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Eviction API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Eviction
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs
new file mode 100644
index 0000000..b504809
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Communication API.
+/// </summary>
+namespace Apache.Ignite.Core.Communication
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs
new file mode 100644
index 0000000..b33e01f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// TCP communication API.
+/// </summary>
+namespace Apache.Ignite.Core.Communication.Tcp
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 c7e7eff..7fbd100 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -312,7 +312,7 @@ namespace Apache.Ignite.Core
         /// <param name="reader">Reader.</param>
         /// <param name="outStream">Output stream.</param>
         /// <param name="handleRegistry">Handle registry.</param>
-        private static void PrepareLifecycleBeans(IBinaryRawReader reader, IBinaryStream outStream, 
+        private static void PrepareLifecycleBeans(IBinaryRawReader reader, IBinaryStream outStream,
             HandleRegistry handleRegistry)
         {
             IList<LifecycleBeanHolder> beans = new List<LifecycleBeanHolder>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 7f949d0..7556c41 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
@@ -76,7 +76,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             return reader.ReadBoolean() ? reader.ReadLongAsTimespan() : (TimeSpan?) null;
         }
-        
+
         /// <summary>
         /// Reads the nullable int.
         /// </summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs
new file mode 100644
index 0000000..8536e4c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs
@@ -0,0 +1,140 @@
+/*
+ * 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.Cache.Affinity
+{
+    using System;
+    using System.Collections.Generic;
+    using System.ComponentModel;
+    using Apache.Ignite.Core.Cache.Affinity;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// Base class for predefined affinity functions.
+    /// </summary>
+    [Serializable]
+    public abstract class AffinityFunctionBase : IAffinityFunction
+    {
+        /// <summary> The default value for <see cref="Partitions"/> property. </summary>
+        public const int DefaultPartitions = 1024;
+
+        /** */
+        private int _partitions = DefaultPartitions;
+
+        /** */
+        private IAffinityFunction _baseFunction;
+
+
+        /// <summary>
+        /// Gets or sets the total number of partitions.
+        /// </summary>
+        [DefaultValue(DefaultPartitions)]
+        public virtual int Partitions
+        {
+            get { return _partitions; }
+            set { _partitions = value; }
+        }
+
+        /// <summary>
+        /// Gets partition number for a given key starting from 0. Partitioned caches
+        /// should make sure that keys are about evenly distributed across all partitions
+        /// from 0 to <see cref="Partitions" /> for best performance.
+        /// <para />
+        /// Note that for fully replicated caches it is possible to segment key sets among different
+        /// grid node groups. In that case each node group should return a unique partition
+        /// number. However, unlike partitioned cache, mappings of keys to nodes in
+        /// replicated caches are constant and a node cannot migrate from one partition
+        /// to another.
+        /// </summary>
+        /// <param name="key">Key to get partition for.</param>
+        /// <returns>
+        /// Partition number for a given key.
+        /// </returns>
+        public virtual int GetPartition(object key)
+        {
+            ThrowIfUninitialized();
+
+            return _baseFunction.GetPartition(key);
+        }
+
+        /// <summary>
+        /// Removes node from affinity. This method is called when it is safe to remove
+        /// disconnected node from affinity mapping.
+        /// </summary>
+        /// <param name="nodeId">The node identifier.</param>
+        public virtual void RemoveNode(Guid nodeId)
+        {
+            ThrowIfUninitialized();
+
+            _baseFunction.RemoveNode(nodeId);
+        }
+
+        /// <summary>
+        /// Gets affinity nodes for a partition. In case of replicated cache, all returned
+        /// nodes are updated in the same manner. In case of partitioned cache, the returned
+        /// list should contain only the primary and back up nodes with primary node being
+        /// always first.
+        /// <pare />
+        /// Note that partitioned affinity must obey the following contract: given that node
+        /// <code>N</code> is primary for some key <code>K</code>, if any other node(s) leave
+        /// grid and no node joins grid, node <code>N</code> will remain primary for key <code>K</code>.
+        /// </summary>
+        /// <param name="context">The affinity function context.</param>
+        /// <returns>
+        /// A collection of partitions, where each partition is a collection of nodes,
+        /// where first node is a primary node, and other nodes are backup nodes.
+        /// </returns>
+        public virtual IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
+        {
+            ThrowIfUninitialized();
+
+            return _baseFunction.AssignPartitions(context);
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether to exclude same-host-neighbors from being backups of each other.
+        /// </summary>
+        public virtual bool ExcludeNeighbors { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AffinityFunctionBase"/> class.
+        /// </summary>
+        internal AffinityFunctionBase()
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Sets the base function.
+        /// </summary>
+        /// <param name="baseFunc">The base function.</param>
+        internal void SetBaseFunction(IAffinityFunction baseFunc)
+        {
+            _baseFunction = baseFunc;
+        }
+
+        /// <summary>
+        /// Gets the direct usage error.
+        /// </summary>
+        private void ThrowIfUninitialized()
+        {
+            if (_baseFunction == null)
+                throw new IgniteException(GetType() + " has not yet been initialized.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 fdadb1c..048c8ac 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
@@ -199,7 +199,7 @@ namespace Apache.Ignite.Core.Impl
                 if (errCode == 0)
                     return;
 
-                messages.Add(string.Format(CultureInfo.InvariantCulture, "[option={0}, path={1}, error={2}]", 
+                messages.Add(string.Format(CultureInfo.InvariantCulture, "[option={0}, path={1}, error={2}]",
                     dllPath.Key, dllPath.Value, FormatWin32Error(errCode)));
 
                 if (dllPath.Value == configJvmDllPath)

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/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 4cbdf8f..9719bba 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -1,4 +1,4 @@
-\ufeff/*
+\ufeff\ufeff/*
  * 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.

http://git-wip-us.apache.org/repos/asf/ignite/blob/5b0dbcae/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index e4a6f84..3e9a71c 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -76,6 +76,7 @@
         <jackson.version>1.9.13</jackson.version>
         <jackson2.version>2.7.5</jackson2.version>
         <javax.cache.bundle.version>1.0.0_1</javax.cache.bundle.version>
+        <javax.cache.version>1.0.0</javax.cache.version>
         <jetty.version>9.2.11.v20150529</jetty.version>
         <jms.spec.version>1.1.1</jms.spec.version>
         <jsch.bundle.version>0.1.53_1</jsch.bundle.version>


[25/46] ignite git commit: IGNITE-3394 Added jdbc types transformer.

Posted by sb...@apache.org.
IGNITE-3394 Added jdbc types transformer.


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

Branch: refs/heads/ignite-1232
Commit: 054b4eb9da776fb499f5914335be6e5a7157ce7c
Parents: 4f038c1
Author: Vasiliy Sisko <vs...@gridgain.com>
Authored: Tue Jul 19 11:28:32 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Tue Jul 19 11:28:32 2016 +0700

----------------------------------------------------------------------
 .../store/jdbc/CacheAbstractJdbcStore.java      | 101 ++++------------
 .../cache/store/jdbc/CacheJdbcPojoStore.java    |   7 +-
 .../store/jdbc/CacheJdbcPojoStoreFactory.java   |  26 +++++
 .../store/jdbc/JdbcTypesDefaultTransformer.java | 117 +++++++++++++++++++
 .../cache/store/jdbc/JdbcTypesTransformer.java  |  39 +++++++
 5 files changed, 207 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/054b4eb9/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
index c16f2c6..de2d977 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheAbstractJdbcStore.java
@@ -17,7 +17,6 @@
 
 package org.apache.ignite.cache.store.jdbc;
 
-import java.nio.ByteBuffer;
 import java.sql.BatchUpdateException;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -187,6 +186,9 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     /** Hash calculator.  */
     protected JdbcTypeHasher hasher = JdbcTypeDefaultHasher.INSTANCE;
 
+    /** Types transformer. */
+    protected JdbcTypesTransformer transformer = JdbcTypesDefaultTransformer.INSTANCE;
+
     /**
      * Get field value from object for use as query parameter.
      *
@@ -410,85 +412,6 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     }
 
     /**
-     * Retrieves the value of the designated column in the current row of this <code>ResultSet</code> object and
-     * will convert to the requested Java data type.
-     *
-     * @param rs Result set.
-     * @param colIdx Column index in result set.
-     * @param type Class representing the Java data type to convert the designated column to.
-     * @return Value in column.
-     * @throws SQLException If a database access error occurs or this method is called.
-     */
-    protected Object getColumnValue(ResultSet rs, int colIdx, Class<?> type) throws SQLException {
-        Object val = rs.getObject(colIdx);
-
-        if (val == null)
-            return null;
-
-        if (type == int.class)
-            return rs.getInt(colIdx);
-
-        if (type == long.class)
-            return rs.getLong(colIdx);
-
-        if (type == double.class)
-            return rs.getDouble(colIdx);
-
-        if (type == boolean.class || type == Boolean.class)
-            return rs.getBoolean(colIdx);
-
-        if (type == byte.class)
-            return rs.getByte(colIdx);
-
-        if (type == short.class)
-            return rs.getShort(colIdx);
-
-        if (type == float.class)
-            return rs.getFloat(colIdx);
-
-        if (type == Integer.class || type == Long.class || type == Double.class ||
-            type == Byte.class || type == Short.class ||  type == Float.class) {
-            Number num = (Number)val;
-
-            if (type == Integer.class)
-                return num.intValue();
-            else if (type == Long.class)
-                return num.longValue();
-            else if (type == Double.class)
-                return num.doubleValue();
-            else if (type == Byte.class)
-                return num.byteValue();
-            else if (type == Short.class)
-                return num.shortValue();
-            else if (type == Float.class)
-                return num.floatValue();
-        }
-
-        if (type == UUID.class) {
-            if (val instanceof UUID)
-                return val;
-
-            if (val instanceof byte[]) {
-                ByteBuffer bb = ByteBuffer.wrap((byte[])val);
-
-                long most = bb.getLong();
-                long least = bb.getLong();
-
-                return new UUID(most, least);
-            }
-
-            if (val instanceof String)
-                return UUID.fromString((String)val);
-        }
-
-        // Workaround for known issue with Oracle JDBC driver https://community.oracle.com/thread/2355464?tstart=0
-        if (type == java.sql.Date.class && val instanceof java.util.Date)
-            return new java.sql.Date(((java.util.Date)val).getTime());
-
-        return val;
-    }
-
-    /**
      * Construct load cache from range.
      *
      * @param em Type mapping description.
@@ -1597,6 +1520,24 @@ public abstract class CacheAbstractJdbcStore<K, V> implements CacheStore<K, V>,
     }
 
     /**
+     * Gets types transformer.
+     *
+     * @return Types transformer.
+     */
+    public JdbcTypesTransformer getTransformer() {
+        return transformer;
+    }
+
+    /**
+     * Sets types transformer.
+     *
+     * @param transformer Types transformer.
+     */
+    public void setTransformer(JdbcTypesTransformer transformer) {
+        this.transformer = transformer;
+    }
+
+    /**
      * Get maximum batch size for delete and delete operations.
      *
      * @return Maximum batch size.

http://git-wip-us.apache.org/repos/asf/ignite/blob/054b4eb9/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
index b9a3118..ef4e246 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStore.java
@@ -150,8 +150,9 @@ public class CacheJdbcPojoStore<K, V> extends CacheAbstractJdbcStore<K, V> {
         ResultSet rs) throws CacheLoaderException {
         try {
             JdbcTypeField field = fields[0];
+            int colIdx = loadColIdxs.get(field.getDatabaseFieldName());
 
-            return getColumnValue(rs, loadColIdxs.get(field.getDatabaseFieldName()), field.getJavaFieldType());
+            return transformer.getColumnValue(rs, colIdx, field.getJavaFieldType());
         }
         catch (SQLException e) {
             throw new CacheLoaderException("Failed to read object of class: " + typeName, e);
@@ -200,7 +201,7 @@ public class CacheJdbcPojoStore<K, V> extends CacheAbstractJdbcStore<K, V> {
                 Integer colIdx = loadColIdxs.get(fldDbName);
 
                 try {
-                    Object colVal = getColumnValue(rs, colIdx, fld.getJavaFieldType());
+                    Object colVal = transformer.getColumnValue(rs, colIdx, fld.getJavaFieldType());
 
                     try {
                         prop.set(obj, colVal);
@@ -246,7 +247,7 @@ public class CacheJdbcPojoStore<K, V> extends CacheAbstractJdbcStore<K, V> {
             for (JdbcTypeField field : fields) {
                 Integer colIdx = loadColIdxs.get(field.getDatabaseFieldName());
 
-                Object colVal = getColumnValue(rs, colIdx, field.getJavaFieldType());
+                Object colVal = transformer.getColumnValue(rs, colIdx, field.getJavaFieldType());
 
                 builder.setField(field.getJavaFieldName(), colVal, (Class<Object>)field.getJavaFieldType());
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/054b4eb9/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
index 0fca3ab..32f54fb 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/CacheJdbcPojoStoreFactory.java
@@ -131,6 +131,9 @@ public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheAbstractJdb
     /** Hash calculator.  */
     private JdbcTypeHasher hasher = JdbcTypeDefaultHasher.INSTANCE;
 
+    /** Types transformer.  */
+    private JdbcTypesTransformer transformer = JdbcTypesDefaultTransformer.INSTANCE;
+
     /** Types that store could process. */
     private JdbcType[] types;
 
@@ -154,6 +157,8 @@ public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheAbstractJdb
         store.setMaximumWriteAttempts(maxWriteAttempts);
         store.setParallelLoadCacheMinimumThreshold(parallelLoadCacheMinThreshold);
         store.setTypes(types);
+        store.setHasher(hasher);
+        store.setTransformer(transformer);
 
         if (dataSrc != null)
             store.setDataSource(dataSrc);
@@ -364,6 +369,27 @@ public class CacheJdbcPojoStoreFactory<K, V> implements Factory<CacheAbstractJdb
     }
 
     /**
+     * Gets types transformer.
+     *
+     * @return Types transformer.
+     */
+    public JdbcTypesTransformer getTransformer() {
+        return transformer;
+    }
+
+    /**
+     * Sets types transformer.
+     *
+     * @param transformer Types transformer.
+     * @return {@code This} for chaining.
+     */
+    public CacheJdbcPojoStoreFactory setTransformer(JdbcTypesTransformer transformer) {
+        this.transformer = transformer;
+
+        return this;
+    }
+
+    /**
      * Gets factory for underlying datasource.
      *
      * @return Cache store factory.

http://git-wip-us.apache.org/repos/asf/ignite/blob/054b4eb9/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesDefaultTransformer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesDefaultTransformer.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesDefaultTransformer.java
new file mode 100644
index 0000000..e91c2d3
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesDefaultTransformer.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.cache.store.jdbc;
+
+import java.nio.ByteBuffer;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.UUID;
+
+/**
+ * Default implementation of {@link JdbcTypesTransformer}.
+ */
+public class JdbcTypesDefaultTransformer implements JdbcTypesTransformer {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** Singleton instance to use. */
+    public static final JdbcTypesDefaultTransformer INSTANCE = new JdbcTypesDefaultTransformer();
+
+    /** {@inheritDoc} */
+    @Override public Object getColumnValue(ResultSet rs, int colIdx, Class<?> type) throws SQLException {
+        Object val = rs.getObject(colIdx);
+
+        if (val == null)
+            return null;
+
+        if (type == int.class)
+            return rs.getInt(colIdx);
+
+        if (type == long.class)
+            return rs.getLong(colIdx);
+
+        if (type == double.class)
+            return rs.getDouble(colIdx);
+
+        if (type == boolean.class || type == Boolean.class)
+            return rs.getBoolean(colIdx);
+
+        if (type == byte.class)
+            return rs.getByte(colIdx);
+
+        if (type == short.class)
+            return rs.getShort(colIdx);
+
+        if (type == float.class)
+            return rs.getFloat(colIdx);
+
+        if (type == Integer.class || type == Long.class || type == Double.class ||
+            type == Byte.class || type == Short.class ||  type == Float.class) {
+            Number num = (Number)val;
+
+            if (type == Integer.class)
+                return num.intValue();
+            else if (type == Long.class)
+                return num.longValue();
+            else if (type == Double.class)
+                return num.doubleValue();
+            else if (type == Byte.class)
+                return num.byteValue();
+            else if (type == Short.class)
+                return num.shortValue();
+            else if (type == Float.class)
+                return num.floatValue();
+        }
+
+        if (type == UUID.class) {
+            if (val instanceof UUID)
+                return val;
+
+            if (val instanceof byte[]) {
+                ByteBuffer bb = ByteBuffer.wrap((byte[])val);
+
+                long most = bb.getLong();
+                long least = bb.getLong();
+
+                return new UUID(most, least);
+            }
+
+            if (val instanceof String)
+                return UUID.fromString((String)val);
+        }
+
+        // Workaround for known issue with Oracle JDBC driver https://community.oracle.com/thread/2355464?tstart=0
+        if (type == java.sql.Date.class && val instanceof java.util.Date)
+            return new java.sql.Date(((java.util.Date)val).getTime());
+
+        // Workaround for known issue with Oracle JDBC driver and timestamp.
+        // http://stackoverflow.com/questions/13269564/java-lang-classcastexception-oracle-sql-timestamp-cannot-be-cast-to-java-sql-ti
+        if (type == Timestamp.class && !(val instanceof Timestamp) &&
+            val.getClass().getName().startsWith("oracle.sql.TIMESTAMP")) {
+            try {
+                return val.getClass().getMethod("timestampValue").invoke(val);
+            }
+            catch (Exception e) {
+                throw new SQLException("Failed to read data of oracle.sql.TIMESTAMP type.", e);
+            }
+        }
+
+        return val;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/054b4eb9/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesTransformer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesTransformer.java b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesTransformer.java
new file mode 100644
index 0000000..76fb00b
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/cache/store/jdbc/JdbcTypesTransformer.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.cache.store.jdbc;
+
+import java.io.Serializable;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * API for implementing custom mapping logic for loaded from store data.
+ */
+public interface JdbcTypesTransformer extends Serializable {
+    /**
+     * Retrieves the value of the designated column in the current row of this <code>ResultSet</code> object and
+     * will convert to the requested Java data type.
+     *
+     * @param rs Result set.
+     * @param colIdx Column index in result set.
+     * @param type Class representing the Java data type to convert the designated column to.
+     * @return Value in column.
+     * @throws SQLException If a database access error occurs or this method is called.
+     */
+    public Object getColumnValue(ResultSet rs, int colIdx, Class<?> type) throws SQLException;
+}


[42/46] ignite git commit: Revert IGNITE-2949 due to broken compatibility

Posted by sb...@apache.org.
Revert IGNITE-2949 due to broken compatibility


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

Branch: refs/heads/ignite-1232
Commit: 7140ee9ded458e5aedd1c5a98522043366667fc3
Parents: d767e51
Author: Valentin Kulichenko <va...@gmail.com>
Authored: Tue Jul 19 16:23:27 2016 -0700
Committer: Valentin Kulichenko <va...@gmail.com>
Committed: Tue Jul 19 16:23:27 2016 -0700

----------------------------------------------------------------------
 modules/kafka/README.txt                                         | 4 ++--
 .../platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs  | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/7140ee9d/modules/kafka/README.txt
----------------------------------------------------------------------
diff --git a/modules/kafka/README.txt b/modules/kafka/README.txt
index 80103a6..259a4f6 100644
--- a/modules/kafka/README.txt
+++ b/modules/kafka/README.txt
@@ -47,7 +47,7 @@ as described in the following subsection.
 - ignite-kafka-connect-x.x.x-SNAPSHOT.jar
 - ignite-core-x.x.x-SNAPSHOT.jar
 - ignite-spring-x.x.x-SNAPSHOT.jar
-- geronimo-jcache_1.0_spec-1.0-alpha-1.jar
+- cache-api-1.0.0.jar
 - spring-aop-4.1.0.RELEASE.jar
 - spring-beans-4.1.0.RELEASE.jar
 - spring-context-4.1.0.RELEASE.jar
@@ -140,7 +140,7 @@ as described in the following subsection.
 1. Put the following jar files on Kafka's classpath
 - ignite-kafka-connect-x.x.x-SNAPSHOT.jar
 - ignite-core-x.x.x-SNAPSHOT.jar
-- geronimo-jcache_1.0_spec-1.0-alpha-1.jar
+- cache-api-1.0.0.jar
 - ignite-spring-x.x.x-SNAPSHOT.jar
 - spring-aop-4.1.0.RELEASE.jar
 - spring-beans-4.1.0.RELEASE.jar

http://git-wip-us.apache.org/repos/asf/ignite/blob/7140ee9d/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 e890dc8..ab5a1a6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/DeploymentTest.cs
@@ -45,7 +45,7 @@ namespace Apache.Ignite.Core.Tests
             // Copy jars
             var home = IgniteHome.Resolve(null);
 
-            var jarNames = new[] {@"\ignite-core-", @"\geronimo-jcache_1.0_spec-1.0-alpha-1.jar", @"\modules\spring\" };
+            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();


[43/46] ignite git commit: ignite-3254 - fixed (cherry picked from commit 4d2be72)

Posted by sb...@apache.org.
ignite-3254 - fixed
(cherry picked from commit 4d2be72)


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

Branch: refs/heads/ignite-1232
Commit: 6b8020d3ffef55039d0afa55ed5925d9fdb914d2
Parents: 7140ee9
Author: Sergi Vladykin <se...@vladykin.com>
Authored: Wed Jul 13 20:19:25 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Wed Jul 20 11:13:42 2016 +0300

----------------------------------------------------------------------
 .../examples/IndexingBridgeMethodTest.java      | 93 ++++++++++++++++++++
 .../IgniteExamplesJ8SelfTestSuite.java          |  2 +
 .../configuration/CacheConfiguration.java       |  3 +
 3 files changed, 98 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/6b8020d3/examples/src/test/java8/org/apache/ignite/java8/examples/IndexingBridgeMethodTest.java
----------------------------------------------------------------------
diff --git a/examples/src/test/java8/org/apache/ignite/java8/examples/IndexingBridgeMethodTest.java b/examples/src/test/java8/org/apache/ignite/java8/examples/IndexingBridgeMethodTest.java
new file mode 100644
index 0000000..2837ed6
--- /dev/null
+++ b/examples/src/test/java8/org/apache/ignite/java8/examples/IndexingBridgeMethodTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.java8.examples;
+
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ * Test covering bridge methods changes in Java 8.
+ */
+public class IndexingBridgeMethodTest extends GridCommonAbstractTest {
+    /**
+     * @throws Exception If failed.
+     */
+    public void testBridgeMethod() throws Exception {
+        Ignite ignite = startGrid();
+
+        CacheConfiguration<Integer, MyType> ccfg = new CacheConfiguration<>();
+
+        ccfg.setName("mytype");
+        ccfg.setIndexedTypes(Integer.class, MyType.class);
+
+        IgniteCache<Integer,MyType> c = ignite.getOrCreateCache(ccfg);
+
+        for (int i = 0; i < 100; i++)
+            c.put(i, new MyType(i));
+
+        assertEquals(100L, c.query(new SqlFieldsQuery(
+            "select count(*) from MyType")).getAll().get(0).get(0));
+        assertEquals(15, c.query(new SqlFieldsQuery(
+            "select id from MyType where _key = 15")).getAll().get(0).get(0));
+        assertEquals(25, c.query(new SqlFieldsQuery(
+            "select _key from MyType where id = 25")).getAll().get(0).get(0));
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * Classes implementing this method, will have bridge method.
+     */
+    private static interface HasId<T extends Number> {
+        /**
+         * @return ID.
+         */
+        public T getId();
+    }
+
+    /**
+     *
+     */
+    private static class MyType implements HasId<Integer> {
+        /** */
+        private int id;
+
+        /**
+         * @param id Id.
+         */
+        private MyType(int id) {
+            this.id = id;
+        }
+
+        /**
+         * @return ID.
+         */
+        @QuerySqlField(index = true)
+        @Override public Integer getId() {
+            return id;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/6b8020d3/examples/src/test/java8/org/apache/ignite/java8/testsuites/IgniteExamplesJ8SelfTestSuite.java
----------------------------------------------------------------------
diff --git a/examples/src/test/java8/org/apache/ignite/java8/testsuites/IgniteExamplesJ8SelfTestSuite.java b/examples/src/test/java8/org/apache/ignite/java8/testsuites/IgniteExamplesJ8SelfTestSuite.java
index 57e48f9..949324c 100644
--- a/examples/src/test/java8/org/apache/ignite/java8/testsuites/IgniteExamplesJ8SelfTestSuite.java
+++ b/examples/src/test/java8/org/apache/ignite/java8/testsuites/IgniteExamplesJ8SelfTestSuite.java
@@ -24,6 +24,7 @@ import org.apache.ignite.java8.examples.CacheExamplesMultiNodeSelfTest;
 import org.apache.ignite.java8.examples.CacheExamplesSelfTest;
 import org.apache.ignite.java8.examples.EventsExamplesMultiNodeSelfTest;
 import org.apache.ignite.java8.examples.EventsExamplesSelfTest;
+import org.apache.ignite.java8.examples.IndexingBridgeMethodTest;
 import org.apache.ignite.java8.examples.MessagingExamplesSelfTest;
 import org.apache.ignite.testframework.GridTestUtils;
 
@@ -45,6 +46,7 @@ public class IgniteExamplesJ8SelfTestSuite extends TestSuite {
 
         TestSuite suite = new TestSuite("Ignite Examples Test Suite");
 
+        suite.addTest(new TestSuite(IndexingBridgeMethodTest.class));
         suite.addTest(new TestSuite(CacheExamplesSelfTest.class));
         suite.addTest(new TestSuite(BasicExamplesSelfTest.class));
 //        suite.addTest(new TestSuite(ContinuationExamplesSelfTest.class));

http://git-wip-us.apache.org/repos/asf/ignite/blob/6b8020d3/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 3408834..64b7e1f 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
@@ -2299,6 +2299,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
             }
 
             for (Method mtd : c.getDeclaredMethods()) {
+                if (mtd.isBridge())
+                    continue;
+
                 QuerySqlField sqlAnn = mtd.getAnnotation(QuerySqlField.class);
                 QueryTextField txtAnn = mtd.getAnnotation(QueryTextField.class);
 


[28/46] ignite git commit: IGNITE-945: HTTP REST prepend/append commands failed. Reviewed and merged by Denis Magda (dmagda@gridgain.com)

Posted by sb...@apache.org.
IGNITE-945: HTTP REST prepend/append commands failed.
Reviewed and merged by Denis Magda (dmagda@gridgain.com)


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

Branch: refs/heads/ignite-1232
Commit: 4a2a08b729e8939041de658efbeb885a513d10e6
Parents: 054b4eb
Author: Saikat Maitra <sa...@gmail.com>
Authored: Tue Jul 19 12:26:56 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Tue Jul 19 12:26:56 2016 +0300

----------------------------------------------------------------------
 .../handlers/cache/GridCacheCommandHandler.java | 84 ++++++++++++--------
 .../GridCacheAtomicCommandHandlerSelfTest.java  | 39 +++++++++
 .../cache/GridCacheCommandHandlerSelfTest.java  | 19 ++++-
 .../testsuites/IgniteRestHandlerTestSuite.java  |  2 +
 4 files changed, 110 insertions(+), 34 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/4a2a08b7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
index e8179d9..a8062ca 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandler.java
@@ -31,6 +31,11 @@ import java.util.UUID;
 import java.util.concurrent.Callable;
 import javax.cache.expiry.Duration;
 import javax.cache.expiry.ModifiedExpiryPolicy;
+import javax.cache.processor.EntryProcessor;
+import javax.cache.processor.EntryProcessorException;
+import javax.cache.processor.EntryProcessorResult;
+import javax.cache.processor.MutableEntry;
+
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
@@ -55,6 +60,7 @@ import org.apache.ignite.internal.processors.cache.query.GridCacheSqlMetadata;
 import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx;
 import org.apache.ignite.internal.processors.rest.GridRestCommand;
 import org.apache.ignite.internal.processors.rest.GridRestResponse;
+import org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandler;
 import org.apache.ignite.internal.processors.rest.handlers.GridRestCommandHandlerAdapter;
 import org.apache.ignite.internal.processors.rest.request.GridRestCacheRequest;
 import org.apache.ignite.internal.processors.rest.request.GridRestRequest;
@@ -100,8 +106,6 @@ import static org.apache.ignite.internal.processors.rest.GridRestCommand.CACHE_S
 import static org.apache.ignite.internal.processors.rest.GridRestCommand.DESTROY_CACHE;
 import static org.apache.ignite.internal.processors.rest.GridRestCommand.GET_OR_CREATE_CACHE;
 import static org.apache.ignite.internal.processors.task.GridTaskThreadContextKey.TC_NO_FAILOVER;
-import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
-import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
 
 /**
  * Command handler for API requests.
@@ -195,7 +199,8 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
     private static IgniteInternalFuture<?> appendOrPrepend(
         final GridKernalContext ctx,
         final IgniteInternalCache<Object, Object> cache,
-        final Object key, GridRestCacheRequest req, final boolean prepend) throws IgniteCheckedException {
+        final Object key, GridRestCacheRequest req,
+        final boolean prepend) throws IgniteCheckedException {
         assert cache != null;
         assert key != null;
         assert req != null;
@@ -206,23 +211,38 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
             throw new IgniteCheckedException(GridRestCommandHandlerAdapter.missingParameter("val"));
 
         return ctx.closure().callLocalSafe(new Callable<Object>() {
-            @Override public Object call() throws Exception {
-                try (IgniteInternalTx tx = cache.txStartEx(PESSIMISTIC, REPEATABLE_READ)) {
-                    Object curVal = cache.get(key);
-
-                    if (curVal == null)
-                        return false;
-
-                    // Modify current value with appendix one.
-                    Object newVal = appendOrPrepend(curVal, val, !prepend);
-
-                    // Put new value asynchronously.
-                    cache.put(key, newVal);
+            @Override
+            public Object call() throws Exception {
+                EntryProcessorResult<Boolean> res = cache.invoke(key, new EntryProcessor<Object, Object, Boolean>() {
+                    @Override
+                    public Boolean process(MutableEntry<Object, Object> entry,
+                        Object... objects) throws EntryProcessorException {
+                        try {
+                            Object curVal = entry.getValue();
+
+                            if (curVal == null)
+                                return false;
+
+                            // Modify current value with appendix one.
+                            Object newVal = appendOrPrepend(curVal, val, !prepend);
+
+                            // Put new value asynchronously.
+                            entry.setValue(newVal);
+
+                            return true;
+                        }
+                        catch (IgniteCheckedException e) {
+                            throw new EntryProcessorException(e);
+                        }
+                    }
+                });
 
-                    tx.commit();
+                try {
+                    return res.get();
+                }
+                catch (EntryProcessorException e) {
+                    throw new IgniteCheckedException(e.getCause());
                 }
-
-                return true;
             }
         }, false);
     }
@@ -236,7 +256,8 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
      * @return Resulting value.
      * @throws IgniteCheckedException In case of grid exceptions.
      */
-    private static Object appendOrPrepend(Object origVal, Object appendVal, boolean appendPlc) throws IgniteCheckedException {
+    private static Object appendOrPrepend(Object origVal, Object appendVal,
+        boolean appendPlc) throws IgniteCheckedException {
         // Strings.
         if (appendVal instanceof String && origVal instanceof String)
             return appendPlc ? origVal + (String)appendVal : (String)appendVal + origVal;
@@ -313,7 +334,8 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
      * @return Instance on the named cache.
      * @throws IgniteCheckedException If cache not found.
      */
-    private static IgniteInternalCache<Object, Object> cache(Ignite ignite, String cacheName) throws IgniteCheckedException {
+    private static IgniteInternalCache<Object, Object> cache(Ignite ignite,
+        String cacheName) throws IgniteCheckedException {
         IgniteInternalCache<Object, Object> cache = ((IgniteKernal)ignite).getCache(cacheName);
 
         if (cache == null)
@@ -630,11 +652,10 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
     }
 
     /**
-     * Executes command on flagged cache projection. Checks {@code destId} to find
-     * if command could be performed locally or routed to a remote node.
+     * Executes command on flagged cache projection. Checks {@code destId} to find if command could be performed locally
+     * or routed to a remote node.
      *
-     * @param destId Target node Id for the operation.
-     *      If {@code null} - operation could be executed anywhere.
+     * @param destId Target node Id for the operation. If {@code null} - operation could be executed anywhere.
      * @param clientId Client ID.
      * @param cacheName Cache name.
      * @param skipStore Skip store.
@@ -655,7 +676,7 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
             destId == null || destId.equals(ctx.localNodeId()) || replicatedCacheAvailable(cacheName);
 
         if (locExec) {
-            IgniteInternalCache<?,?> prj = localCache(cacheName).forSubjectId(clientId).setSkipStore(skipStore);
+            IgniteInternalCache<?, ?> prj = localCache(cacheName).forSubjectId(clientId).setSkipStore(skipStore);
 
             return op.apply((IgniteInternalCache<Object, Object>)prj, ctx).
                 chain(resultWrapper((IgniteInternalCache<Object, Object>)prj, key));
@@ -672,11 +693,10 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
     }
 
     /**
-     * Executes command on cache. Checks {@code destId} to find
-     * if command could be performed locally or routed to a remote node.
+     * Executes command on cache. Checks {@code destId} to find if command could be performed locally or routed to a
+     * remote node.
      *
-     * @param destId Target node Id for the operation.
-     *      If {@code null} - operation could be executed anywhere.
+     * @param destId Target node Id for the operation. If {@code null} - operation could be executed anywhere.
      * @param clientId Client ID.
      * @param cacheName Cache name.
      * @param key Key to set affinity mapping in the response.
@@ -719,7 +739,7 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
      * @return If replicated cache with given name is locally available.
      */
     private boolean replicatedCacheAvailable(String cacheName) {
-        GridCacheAdapter<Object,Object> cache = ctx.cache().internalCache(cacheName);
+        GridCacheAdapter<Object, Object> cache = ctx.cache().internalCache(cacheName);
 
         return cache != null && cache.configuration().getCacheMode() == CacheMode.REPLICATED;
     }
@@ -1049,7 +1069,7 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
         /** Key. */
         protected final Object key;
 
-        /** Value.*/
+        /** Value. */
         protected final Object val;
 
         /**
@@ -1496,7 +1516,7 @@ public class GridCacheCommandHandler extends GridRestCommandHandlerAdapter {
 
         /** {@inheritDoc} */
         @Override public IgniteInternalFuture<?> applyx(IgniteInternalCache<Object, Object> c, GridKernalContext ctx) {
-            return c.sizeAsync(new CachePeekMode[]{CachePeekMode.PRIMARY});
+            return c.sizeAsync(new CachePeekMode[] {CachePeekMode.PRIMARY});
         }
     }
 }

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

http://git-wip-us.apache.org/repos/asf/ignite/blob/4a2a08b7/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandlerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandlerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandlerSelfTest.java
index 3d00626..eadf674 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandlerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/rest/handlers/cache/GridCacheCommandHandlerSelfTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.CacheAtomicityMode;
 import org.apache.ignite.cache.CacheMode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.ConnectorConfiguration;
@@ -46,6 +47,8 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 
+import javax.cache.processor.EntryProcessorException;
+
 /**
  * Tests command handler directly.
  */
@@ -70,6 +73,8 @@ public class GridCacheCommandHandlerSelfTest extends GridCommonAbstractTest {
 
         cacheCfg.setCacheMode(CacheMode.LOCAL);
 
+        cacheCfg.setAtomicityMode(atomicityMode());
+
         // Grid config.
         IgniteConfiguration cfg = super.getConfiguration();
 
@@ -86,6 +91,14 @@ public class GridCacheCommandHandlerSelfTest extends GridCommonAbstractTest {
     }
 
     /**
+     *
+     * @return CacheAtomicityMode for the cache.
+     */
+    protected CacheAtomicityMode atomicityMode(){
+        return CacheAtomicityMode.TRANSACTIONAL;
+    }
+
+    /**
      * Tests the cache failure during the execution of the CACHE_GET command.
      *
      * @throws Exception If failed.
@@ -150,6 +163,8 @@ public class GridCacheCommandHandlerSelfTest extends GridCommonAbstractTest {
         catch (IgniteCheckedException e) {
             info("Got expected exception: " + e);
 
+            e.printStackTrace();
+
             assertTrue(e.getMessage().startsWith("Incompatible types"));
         }
     }
@@ -164,7 +179,7 @@ public class GridCacheCommandHandlerSelfTest extends GridCommonAbstractTest {
      * @return Resulting value in cache.
      * @throws IgniteCheckedException In case of any grid exception.
      */
-    private <T> T testAppend(T curVal, T newVal, boolean append) throws IgniteCheckedException {
+    private <T> T testAppend(T curVal, T newVal, boolean append) throws IgniteCheckedException, EntryProcessorException {
         GridRestCommandHandler hnd = new GridCacheCommandHandler(((IgniteKernal)grid()).context());
 
         String key = UUID.randomUUID().toString();
@@ -185,7 +200,7 @@ public class GridCacheCommandHandlerSelfTest extends GridCommonAbstractTest {
             jcache().put(key, curVal);
 
             // Validate behavior for initialized cache (has current value).
-            assertTrue("Expects succeed.", (Boolean)hnd.handleAsync(req).get().getResponse());
+            assertTrue((Boolean) hnd.handleAsync(req).get().getResponse());
         }
         finally {
             res = (T)jcache().getAndRemove(key);

http://git-wip-us.apache.org/repos/asf/ignite/blob/4a2a08b7/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteRestHandlerTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteRestHandlerTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteRestHandlerTestSuite.java
index d5de376..42c6752 100644
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteRestHandlerTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteRestHandlerTestSuite.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.testsuites;
 
 import junit.framework.TestSuite;
+import org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheAtomicCommandHandlerSelfTest;
 import org.apache.ignite.internal.processors.rest.handlers.cache.GridCacheCommandHandlerSelfTest;
 import org.apache.ignite.internal.processors.rest.handlers.log.GridLogCommandHandlerTest;
 
@@ -33,6 +34,7 @@ public class IgniteRestHandlerTestSuite extends TestSuite {
         TestSuite suite = new TestSuite("REST Support Test Suite");
 
         suite.addTestSuite(GridCacheCommandHandlerSelfTest.class);
+        suite.addTestSuite(GridCacheAtomicCommandHandlerSelfTest.class);
         suite.addTestSuite(GridLogCommandHandlerTest.class);
 
         return suite;


[38/46] ignite git commit: IGNITE-3511: .NET: Fixed AffinityFunctionBase.cs placement, added missing Package-Info.cs files.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/IAffinityFunction.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/IAffinityFunction.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/IAffinityFunction.cs
new file mode 100644
index 0000000..b6c190c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/IAffinityFunction.cs
@@ -0,0 +1,82 @@
+\ufeff/*
+ * 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.Affinity
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache.Affinity.Fair;
+    using Apache.Ignite.Core.Cache.Affinity.Rendezvous;
+    using Apache.Ignite.Core.Cluster;
+
+    /// <summary>
+    /// Represents a function that maps cache keys to cluster nodes.
+    /// <para />
+    /// Predefined implementations: 
+    /// <see cref="RendezvousAffinityFunction"/>, <see cref="FairAffinityFunction"/>.
+    /// </summary>
+    public interface IAffinityFunction
+    {
+        /// <summary>
+        /// Gets the total number of partitions.
+        /// <para />
+        /// All caches should always provide correct partition count which should be the same on all 
+        /// participating nodes. Note that partitions should always be numbered from 0 inclusively 
+        /// to N exclusively without any gaps.
+        /// </summary>
+        int Partitions { get; }
+
+        /// <summary>
+        /// Gets partition number for a given key starting from 0. Partitioned caches
+        /// should make sure that keys are about evenly distributed across all partitions
+        /// from 0 to <see cref="Partitions"/> for best performance.
+        /// <para />
+        /// Note that for fully replicated caches it is possible to segment key sets among different
+        /// grid node groups. In that case each node group should return a unique partition
+        /// number. However, unlike partitioned cache, mappings of keys to nodes in
+        /// replicated caches are constant and a node cannot migrate from one partition
+        /// to another.
+        /// </summary>
+        /// <param name="key">Key to get partition for.</param>
+        /// <returns>Partition number for a given key.</returns>
+        int GetPartition(object key);
+
+        /// <summary>
+        /// Removes node from affinity. This method is called when it is safe to remove 
+        /// disconnected node from affinity mapping.
+        /// </summary>
+        /// <param name="nodeId">The node identifier.</param>
+        void RemoveNode(Guid nodeId);
+
+        /// <summary>
+        /// Gets affinity nodes for a partition. In case of replicated cache, all returned
+        /// nodes are updated in the same manner. In case of partitioned cache, the returned
+        /// list should contain only the primary and back up nodes with primary node being
+        /// always first.
+        /// <pare />
+        /// Note that partitioned affinity must obey the following contract: given that node
+        /// <code>N</code> is primary for some key <code>K</code>, if any other node(s) leave
+        /// grid and no node joins grid, node <code>N</code> will remain primary for key <code>K</code>.
+        /// </summary>
+        /// <param name="context">The affinity function context.</param>
+        /// <returns>
+        /// A collection of partitions, where each partition is a collection of nodes,
+        /// where first node is a primary node, and other nodes are backup nodes.
+        /// </returns>
+        IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context);
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs
new file mode 100644
index 0000000..dfbdf08
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Cache affinity API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Affinity
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs
new file mode 100644
index 0000000..4b7f9af
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Rendezvous affinity API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Affinity.Rendezvous
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
new file mode 100644
index 0000000..928324c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Rendezvous/RendezvousAffinityFunction.cs
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Apache.Ignite.Core.Cache.Affinity.Rendezvous
+{
+    using System;
+    using Apache.Ignite.Core.Impl.Cache.Affinity;
+
+    /// <summary>
+    /// Affinity function for partitioned cache based on Highest Random Weight algorithm.
+    /// </summary>
+    [Serializable]
+    public class RendezvousAffinityFunction : AffinityFunctionBase
+    {
+        // No-op.
+        // Actual implementation is in Java, see AffinityFunctionSerializer.Write method.
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs
new file mode 100644
index 0000000..fb8ed61
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Configuration/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Ignite Configuration API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Configuration
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs
new file mode 100644
index 0000000..13f56a8
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Eviction/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Eviction API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Eviction
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs
new file mode 100644
index 0000000..b504809
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Communication API.
+/// </summary>
+namespace Apache.Ignite.Core.Communication
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs
new file mode 100644
index 0000000..b33e01f
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Communication/Tcp/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// TCP communication API.
+/// </summary>
+namespace Apache.Ignite.Core.Communication.Tcp
+{
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Events/EventReader.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Events/EventReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Events/EventReader.cs
index cb1c715..ee1c837 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Events/EventReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Events/EventReader.cs
@@ -32,16 +32,14 @@ namespace Apache.Ignite.Core.Events
         /// <param name="reader">Reader.</param>
         /// <returns>Deserialized event.</returns>
         /// <exception cref="System.InvalidCastException">Incompatible event type.</exception>
-        public static T Read<T>(IBinaryReader reader) where T : IEvent
+        public static T Read<T>(IBinaryRawReader reader) where T : IEvent
         {
-            var r = reader.GetRawReader();
-
-            var clsId = r.ReadInt();
+            var clsId = reader.ReadInt();
 
             if (clsId == -1)
                 return default(T);
 
-            return (T) CreateInstance(clsId, r);
+            return (T) CreateInstance(clsId, reader);
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 c551735..ee6b1ce 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -27,10 +27,12 @@ namespace Apache.Ignite.Core
     using System.Runtime;
     using System.Threading;
     using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cache.Affinity;
     using Apache.Ignite.Core.Common;
     using Apache.Ignite.Core.Impl;
     using Apache.Ignite.Core.Impl.Binary;
     using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Cache.Affinity;
     using Apache.Ignite.Core.Impl.Common;
     using Apache.Ignite.Core.Impl.Handle;
     using Apache.Ignite.Core.Impl.Memory;
@@ -261,6 +263,8 @@ namespace Apache.Ignite.Core
                 PrepareConfiguration(reader, outStream);
 
                 PrepareLifecycleBeans(reader, outStream, handleRegistry);
+
+                PrepareAffinityFunctions(reader, outStream);
             }
             catch (Exception e)
             {
@@ -314,7 +318,7 @@ namespace Apache.Ignite.Core
             int cnt = reader.ReadInt();
 
             for (int i = 0; i < cnt; i++)
-                beans.Add(new LifecycleBeanHolder(CreateLifecycleBean(reader)));
+                beans.Add(new LifecycleBeanHolder(CreateObject<ILifecycleBean>(reader)));
 
             // 2. Append beans definied in local configuration.
             ICollection<ILifecycleBean> nativeBeans = _startup.Configuration.LifecycleBeans;
@@ -338,21 +342,33 @@ namespace Apache.Ignite.Core
         }
 
         /// <summary>
-        /// Create lifecycle bean.
+        /// Prepares the affinity functions.
         /// </summary>
-        /// <param name="reader">Reader.</param>
-        /// <returns>Lifecycle bean.</returns>
-        private static ILifecycleBean CreateLifecycleBean(BinaryReader reader)
+        private static void PrepareAffinityFunctions(BinaryReader reader, PlatformMemoryStream outStream)
         {
-            // 1. Instantiate.
-            var bean = IgniteUtils.CreateInstance<ILifecycleBean>(reader.ReadString());
+            var cnt = reader.ReadInt();
+
+            var writer = reader.Marshaller.StartMarshal(outStream);
 
-            // 2. Set properties.
-            var props = reader.ReadDictionaryAsGeneric<string, object>();
+            for (var i = 0; i < cnt; i++)
+            {
+                var objHolder = new ObjectInfoHolder(reader);
+                AffinityFunctionSerializer.Write(writer, objHolder.CreateInstance<IAffinityFunction>(), objHolder);
+            }
+        }
+
+        /// <summary>
+        /// Creates an object and sets the properties.
+        /// </summary>
+        /// <param name="reader">Reader.</param>
+        /// <returns>Resulting object.</returns>
+        private static T CreateObject<T>(IBinaryRawReader reader)
+        {
+            var res =  IgniteUtils.CreateInstance<T>(reader.ReadString());
 
-            IgniteUtils.SetProperties(bean, props);
+            IgniteUtils.SetProperties(res, reader.ReadDictionaryAsGeneric<string, object>());
 
-            return bean;
+            return res;
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 87de0eb..77fd7b6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReaderExtensions.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Impl.Binary
     using System;
     using System.Collections.Generic;
     using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Common;
 
     /// <summary>
     /// Reader extensions.
@@ -75,7 +76,7 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             return reader.ReadBoolean() ? reader.ReadLongAsTimespan() : (TimeSpan?) null;
         }
-        
+
         /// <summary>
         /// Reads the nullable int.
         /// </summary>
@@ -91,5 +92,18 @@ namespace Apache.Ignite.Core.Impl.Binary
         {
             return reader.ReadBoolean() ? reader.ReadBoolean() : (bool?) null;
         }
+
+        /// <summary>
+        /// Reads the object either as a normal object or as a [typeName+props] wrapper.
+        /// </summary>
+        public static T ReadObjectEx<T>(this IBinaryRawReader reader)
+        {
+            var obj = reader.ReadObject<object>();
+
+            if (obj == null)
+                return default(T);
+
+            return obj is T ? (T)obj : ((ObjectInfoHolder)obj).CreateInstance<T>();
+        }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 aa881bb..473fdf8 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
@@ -576,6 +576,7 @@ namespace Apache.Ignite.Core.Impl.Binary
             AddSystemType(BinaryUtils.TypeStreamReceiverHolder, w => new StreamReceiverHolder(w));
             AddSystemType(0, w => new AffinityKey(w), "affKey");
             AddSystemType(BinaryUtils.TypePlatformJavaObjectFactoryProxy, w => new PlatformJavaObjectFactoryProxy());
+            AddSystemType(0, w => new ObjectInfoHolder(w));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs
new file mode 100644
index 0000000..8536e4c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionBase.cs
@@ -0,0 +1,140 @@
+/*
+ * 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.Cache.Affinity
+{
+    using System;
+    using System.Collections.Generic;
+    using System.ComponentModel;
+    using Apache.Ignite.Core.Cache.Affinity;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Common;
+
+    /// <summary>
+    /// Base class for predefined affinity functions.
+    /// </summary>
+    [Serializable]
+    public abstract class AffinityFunctionBase : IAffinityFunction
+    {
+        /// <summary> The default value for <see cref="Partitions"/> property. </summary>
+        public const int DefaultPartitions = 1024;
+
+        /** */
+        private int _partitions = DefaultPartitions;
+
+        /** */
+        private IAffinityFunction _baseFunction;
+
+
+        /// <summary>
+        /// Gets or sets the total number of partitions.
+        /// </summary>
+        [DefaultValue(DefaultPartitions)]
+        public virtual int Partitions
+        {
+            get { return _partitions; }
+            set { _partitions = value; }
+        }
+
+        /// <summary>
+        /// Gets partition number for a given key starting from 0. Partitioned caches
+        /// should make sure that keys are about evenly distributed across all partitions
+        /// from 0 to <see cref="Partitions" /> for best performance.
+        /// <para />
+        /// Note that for fully replicated caches it is possible to segment key sets among different
+        /// grid node groups. In that case each node group should return a unique partition
+        /// number. However, unlike partitioned cache, mappings of keys to nodes in
+        /// replicated caches are constant and a node cannot migrate from one partition
+        /// to another.
+        /// </summary>
+        /// <param name="key">Key to get partition for.</param>
+        /// <returns>
+        /// Partition number for a given key.
+        /// </returns>
+        public virtual int GetPartition(object key)
+        {
+            ThrowIfUninitialized();
+
+            return _baseFunction.GetPartition(key);
+        }
+
+        /// <summary>
+        /// Removes node from affinity. This method is called when it is safe to remove
+        /// disconnected node from affinity mapping.
+        /// </summary>
+        /// <param name="nodeId">The node identifier.</param>
+        public virtual void RemoveNode(Guid nodeId)
+        {
+            ThrowIfUninitialized();
+
+            _baseFunction.RemoveNode(nodeId);
+        }
+
+        /// <summary>
+        /// Gets affinity nodes for a partition. In case of replicated cache, all returned
+        /// nodes are updated in the same manner. In case of partitioned cache, the returned
+        /// list should contain only the primary and back up nodes with primary node being
+        /// always first.
+        /// <pare />
+        /// Note that partitioned affinity must obey the following contract: given that node
+        /// <code>N</code> is primary for some key <code>K</code>, if any other node(s) leave
+        /// grid and no node joins grid, node <code>N</code> will remain primary for key <code>K</code>.
+        /// </summary>
+        /// <param name="context">The affinity function context.</param>
+        /// <returns>
+        /// A collection of partitions, where each partition is a collection of nodes,
+        /// where first node is a primary node, and other nodes are backup nodes.
+        /// </returns>
+        public virtual IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
+        {
+            ThrowIfUninitialized();
+
+            return _baseFunction.AssignPartitions(context);
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether to exclude same-host-neighbors from being backups of each other.
+        /// </summary>
+        public virtual bool ExcludeNeighbors { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AffinityFunctionBase"/> class.
+        /// </summary>
+        internal AffinityFunctionBase()
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Sets the base function.
+        /// </summary>
+        /// <param name="baseFunc">The base function.</param>
+        internal void SetBaseFunction(IAffinityFunction baseFunc)
+        {
+            _baseFunction = baseFunc;
+        }
+
+        /// <summary>
+        /// Gets the direct usage error.
+        /// </summary>
+        private void ThrowIfUninitialized()
+        {
+            if (_baseFunction == null)
+                throw new IgniteException(GetType() + " has not yet been initialized.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
new file mode 100644
index 0000000..888445a
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/AffinityFunctionSerializer.cs
@@ -0,0 +1,277 @@
+\ufeff/*
+ * 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.Cache.Affinity
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using System.IO;
+    using System.Linq;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cache.Affinity;
+    using Apache.Ignite.Core.Cache.Affinity.Fair;
+    using Apache.Ignite.Core.Cache.Affinity.Rendezvous;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Common;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Binary.IO;
+    using Apache.Ignite.Core.Impl.Memory;
+
+    /// <summary>
+    /// Affinity function read/write methods.
+    /// </summary>
+    internal static class AffinityFunctionSerializer
+    {
+        /** */
+        private const byte TypeCodeNull = 0;
+
+        /** */
+        private const byte TypeCodeFair = 1;
+
+        /** */
+        private const byte TypeCodeRendezvous = 2;
+
+        /** */
+        private const byte TypeCodeUser = 3;
+
+        /// <summary>
+        /// Writes the instance.
+        /// </summary>
+        internal static void Write(IBinaryRawWriter writer, IAffinityFunction fun, object userFuncOverride = null)
+        {
+            Debug.Assert(writer != null);
+
+            if (fun == null)
+            {
+                writer.WriteByte(TypeCodeNull);
+                return;
+            }
+
+            // 1) Type code
+            // 2) Partitions
+            // 3) ExcludeNeighbors
+            // 4) Override flags
+            // 5) User object
+
+            var p = fun as AffinityFunctionBase;
+
+            if (p != null)
+            {
+                writer.WriteByte(p is FairAffinityFunction ? TypeCodeFair : TypeCodeRendezvous);
+                writer.WriteInt(p.Partitions);
+                writer.WriteBoolean(p.ExcludeNeighbors);
+
+                var overrideFlags = GetOverrideFlags(p.GetType());
+                writer.WriteByte((byte) overrideFlags);
+
+                // Do not write user func if there is nothing overridden
+                WriteUserFunc(writer, overrideFlags != UserOverrides.None ? fun : null, userFuncOverride);
+            }
+            else
+            {
+                writer.WriteByte(TypeCodeUser);
+                writer.WriteInt(fun.Partitions);
+                writer.WriteBoolean(false); // Exclude neighbors
+                writer.WriteByte((byte) UserOverrides.All);
+                WriteUserFunc(writer, fun, userFuncOverride);
+            }
+        }
+
+        /// <summary>
+        /// Reads the instance.
+        /// </summary>
+        internal static IAffinityFunction Read(IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            var typeCode = reader.ReadByte();
+
+            if (typeCode == TypeCodeNull)
+                return null;
+
+            var partitions = reader.ReadInt();
+            var exclNeighbors = reader.ReadBoolean();
+            var overrideFlags = (UserOverrides)reader.ReadByte();
+            var userFunc = reader.ReadObjectEx<IAffinityFunction>();
+
+            if (userFunc != null)
+            {
+                Debug.Assert(overrideFlags != UserOverrides.None);
+
+                var fair = userFunc as FairAffinityFunction;
+                if (fair != null)
+                {
+                    fair.Partitions = partitions;
+                    fair.ExcludeNeighbors = exclNeighbors;
+                }
+
+                var rendezvous = userFunc as RendezvousAffinityFunction;
+                if (rendezvous != null)
+                {
+                    rendezvous.Partitions = partitions;
+                    rendezvous.ExcludeNeighbors = exclNeighbors;
+                }
+
+                return userFunc;
+            }
+
+            Debug.Assert(overrideFlags == UserOverrides.None);
+            AffinityFunctionBase fun;
+
+            switch (typeCode)
+            {
+                case TypeCodeFair:
+                    fun = new FairAffinityFunction();
+                    break;
+                case TypeCodeRendezvous:
+                    fun = new RendezvousAffinityFunction();
+                    break;
+                default:
+                    throw new InvalidOperationException("Invalid AffinityFunction type code: " + typeCode);
+            }
+
+            fun.Partitions = partitions;
+            fun.ExcludeNeighbors = exclNeighbors;
+
+            return fun;
+        }
+
+
+        /// <summary>
+        /// Writes the partitions assignment to a stream.
+        /// </summary>
+        /// <param name="parts">The parts.</param>
+        /// <param name="stream">The stream.</param>
+        /// <param name="marsh">The marshaller.</param>
+        internal static void WritePartitions(IEnumerable<IEnumerable<IClusterNode>> parts,
+            PlatformMemoryStream stream, Marshaller marsh)
+        {
+            Debug.Assert(parts != null);
+            Debug.Assert(stream != null);
+            Debug.Assert(marsh != null);
+
+            IBinaryRawWriter writer = marsh.StartMarshal(stream);
+
+            var partCnt = 0;
+            writer.WriteInt(partCnt); // reserve size
+
+            foreach (var part in parts)
+            {
+                if (part == null)
+                    throw new IgniteException("IAffinityFunction.AssignPartitions() returned invalid partition: null");
+
+                partCnt++;
+
+                var nodeCnt = 0;
+                var cntPos = stream.Position;
+                writer.WriteInt(nodeCnt); // reserve size
+
+                foreach (var node in part)
+                {
+                    nodeCnt++;
+                    writer.WriteGuid(node.Id);
+                }
+
+                var endPos = stream.Position;
+                stream.Seek(cntPos, SeekOrigin.Begin);
+                stream.WriteInt(nodeCnt);
+                stream.Seek(endPos, SeekOrigin.Begin);
+            }
+
+            stream.SynchronizeOutput();
+            stream.Seek(0, SeekOrigin.Begin);
+            writer.WriteInt(partCnt);
+        }
+
+        /// <summary>
+        /// Reads the partitions assignment from a stream.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <param name="marsh">The marshaller.</param>
+        /// <returns>Partitions assignment.</returns>
+        internal static IEnumerable<IEnumerable<IClusterNode>> ReadPartitions(IBinaryStream stream, Marshaller marsh)
+        {
+            Debug.Assert(stream != null);
+            Debug.Assert(marsh != null);
+
+            IBinaryRawReader reader = marsh.StartUnmarshal(stream);
+
+            var partCnt = reader.ReadInt();
+
+            var res = new List<IEnumerable<IClusterNode>>(partCnt);
+
+            for (var i = 0; i < partCnt; i++)
+                res.Add(IgniteUtils.ReadNodes(reader));
+
+            return res;
+        }
+
+        /// <summary>
+        /// Gets the override flags.
+        /// </summary>
+        private static UserOverrides GetOverrideFlags(Type funcType)
+        {
+            var res = UserOverrides.None;
+
+            var methods = new[] {UserOverrides.GetPartition, UserOverrides.AssignPartitions, UserOverrides.RemoveNode};
+
+            var map = funcType.GetInterfaceMap(typeof(IAffinityFunction));
+
+            foreach (var method in methods)
+            {
+                // Find whether user type overrides IAffinityFunction method from AffinityFunctionBase.
+                var methodName = method.ToString();
+
+                if (map.TargetMethods.Single(x => x.Name == methodName).DeclaringType != typeof(AffinityFunctionBase))
+                    res |= method;
+            }
+
+            return res;
+        }
+
+        /// <summary>
+        /// Writes the user function.
+        /// </summary>
+        private static void WriteUserFunc(IBinaryRawWriter writer, IAffinityFunction func, object funcOverride)
+        {
+            if (funcOverride != null)
+            {
+                writer.WriteObject(funcOverride);
+                return;
+            }
+
+            if (func != null && !func.GetType().IsSerializable)
+                throw new IgniteException("AffinityFunction should be serializable.");
+
+            writer.WriteObject(func);
+        }
+
+        /// <summary>
+        /// Overridden function flags.
+        /// </summary>
+        [Flags]
+        private enum UserOverrides : byte
+        {
+            None = 0,
+            GetPartition = 1,
+            RemoveNode = 1 << 1,
+            AssignPartitions = 1 << 2,
+            All = GetPartition | RemoveNode | AssignPartitions
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/PlatformAffinityFunction.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/PlatformAffinityFunction.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/PlatformAffinityFunction.cs
new file mode 100644
index 0000000..d335804
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/Affinity/PlatformAffinityFunction.cs
@@ -0,0 +1,74 @@
+\ufeff/*
+ * 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.Cache.Affinity
+{
+    using System;
+    using System.Collections.Generic;
+    using Apache.Ignite.Core.Cache.Affinity;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Impl.Binary;
+    using Apache.Ignite.Core.Impl.Unmanaged;
+
+    /// <summary>
+    /// Affinity function that delegates to Java.
+    /// </summary>
+    internal class PlatformAffinityFunction : PlatformTarget, IAffinityFunction
+    {
+        /** Opcodes. */
+        private enum  Op
+        {
+            Partition = 1,
+            RemoveNode = 2,
+            AssignPartitions = 3
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="PlatformAffinityFunction"/> class.
+        /// </summary>
+        /// <param name="target">Target.</param>
+        /// <param name="marsh">Marshaller.</param>
+        public PlatformAffinityFunction(IUnmanagedTarget target, Marshaller marsh) : base(target, marsh)
+        {
+            // No-op.
+        }
+
+        /** <inheritdoc /> */
+        public int Partitions
+        {
+            get { throw new NotSupportedException("PlatformAffinityFunction.Partitions is not supported."); }
+        }
+
+        /** <inheritdoc /> */
+        public int GetPartition(object key)
+        {
+            return (int) DoOutOp((int) Op.Partition, w => w.WriteObject(key));
+        }
+
+        /** <inheritdoc /> */
+        public void RemoveNode(Guid nodeId)
+        {
+            DoOutOp((int) Op.RemoveNode, w => w.WriteGuid(nodeId));
+        }
+
+        /** <inheritdoc /> */
+        public IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
+        {
+            return DoInOp((int) Op.AssignPartitions, s => AffinityFunctionSerializer.ReadPartitions(s, Marshaller));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/ObjectInfoHolder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/ObjectInfoHolder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/ObjectInfoHolder.cs
new file mode 100644
index 0000000..407fe0c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Common/ObjectInfoHolder.cs
@@ -0,0 +1,86 @@
+\ufeff/*
+ * 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.Common
+{
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Impl.Binary;
+
+    /// <summary>
+    /// Holds the information to instantiate an object and set its properties.
+    /// Typically used for .NET objects defined in Spring XML.
+    /// </summary>
+    internal class ObjectInfoHolder : IBinaryWriteAware
+    {
+        /** Type name. */
+        private readonly string _typeName;
+
+        /** Properties. */
+        private readonly Dictionary<string, object> _properties;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ObjectInfoHolder"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public ObjectInfoHolder(IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            _typeName = reader.ReadString();
+            _properties = reader.ReadDictionaryAsGeneric<string, object>();
+
+            Debug.Assert(!string.IsNullOrEmpty(_typeName));
+        }
+
+        /// <summary>
+        /// Gets the name of the type.
+        /// </summary>
+        public string TypeName
+        {
+            get { return _typeName; }
+        }
+
+        /// <summary>
+        /// Gets the properties.
+        /// </summary>
+        public Dictionary<string, object> Properties
+        {
+            get { return _properties; }
+        }
+
+        /// <summary>
+        /// Creates an instance according to type name and properties.
+        /// </summary>
+        public T CreateInstance<T>()
+        {
+            return IgniteUtils.CreateInstance<T>(TypeName, Properties);
+        }
+
+        /** <inheritdoc /> */
+        public void WriteBinary(IBinaryWriter writer)
+        {
+            Debug.Assert(writer != null);
+
+            var w = writer.GetRawWriter();
+
+            w.WriteString(_typeName);
+            w.WriteDictionary(_properties);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 5c19802..e43e332 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/IgniteUtils.cs
@@ -139,8 +139,9 @@ namespace Apache.Ignite.Core.Impl
         /// Create new instance of specified class.
         /// </summary>
         /// <param name="typeName">Class name</param>
+        /// <param name="props">Properties to set.</param>
         /// <returns>New Instance.</returns>
-        public static T CreateInstance<T>(string typeName)
+        public static T CreateInstance<T>(string typeName, IEnumerable<KeyValuePair<string, object>> props = null)
         {
             IgniteArgumentCheck.NotNullOrEmpty(typeName, "typeName");
 
@@ -149,7 +150,12 @@ namespace Apache.Ignite.Core.Impl
             if (type == null)
                 throw new IgniteException("Failed to create class instance [className=" + typeName + ']');
 
-            return (T) Activator.CreateInstance(type);
+            var res = (T)Activator.CreateInstance(type);
+
+            if (props != null)
+                SetProperties(res, props);
+
+            return res;
         }
 
         /// <summary>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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
index fb52033..51d9c74 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbackHandlers.cs
@@ -98,5 +98,11 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         internal void* onClientDisconnected;
         internal void* ocClientReconnected;
+
+        internal void* affinityFunctionInit;
+        internal void* affinityFunctionPartition;
+        internal void* affinityFunctionAssignPartitions;
+        internal void* affinityFunctionRemoveNode;
+        internal void* affinityFunctionDestroy;
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 f0e881c..b3489a2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Unmanaged/UnmanagedCallbacks.cs
@@ -21,14 +21,16 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
     using System.Collections.Generic;
     using System.Diagnostics;
     using System.Diagnostics.CodeAnalysis;
+    using System.IO;
     using System.Runtime.InteropServices;
     using System.Threading;
-
+    using Apache.Ignite.Core.Cache.Affinity;
     using Apache.Ignite.Core.Cluster;
     using Apache.Ignite.Core.Common;
     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.Affinity;
     using Apache.Ignite.Core.Impl.Cache.Query.Continuous;
     using Apache.Ignite.Core.Impl.Cache.Store;
     using Apache.Ignite.Core.Impl.Common;
@@ -165,6 +167,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         private delegate void OnClientDisconnectedDelegate(void* target);
         private delegate void OnClientReconnectedDelegate(void* target, bool clusterRestarted);
 
+        private delegate long AffinityFunctionInitDelegate(void* target, long memPtr, void* baseFunc);
+        private delegate int AffinityFunctionPartitionDelegate(void* target, long ptr, long memPtr);
+        private delegate void AffinityFunctionAssignPartitionsDelegate(void* target, long ptr, long inMemPtr, long outMemPtr);
+        private delegate void AffinityFunctionRemoveNodeDelegate(void* target, long ptr, long memPtr);
+        private delegate void AffinityFunctionDestroyDelegate(void* target, long ptr);
+
         /// <summary>
         /// constructor.
         /// </summary>
@@ -248,6 +256,12 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
                 onClientDisconnected = CreateFunctionPointer((OnClientDisconnectedDelegate)OnClientDisconnected),
                 ocClientReconnected = CreateFunctionPointer((OnClientReconnectedDelegate)OnClientReconnected),
+
+                affinityFunctionInit = CreateFunctionPointer((AffinityFunctionInitDelegate)AffinityFunctionInit),
+                affinityFunctionPartition = CreateFunctionPointer((AffinityFunctionPartitionDelegate)AffinityFunctionPartition),
+                affinityFunctionAssignPartitions = CreateFunctionPointer((AffinityFunctionAssignPartitionsDelegate)AffinityFunctionAssignPartitions),
+                affinityFunctionRemoveNode = CreateFunctionPointer((AffinityFunctionRemoveNodeDelegate)AffinityFunctionRemoveNode),
+                affinityFunctionDestroy = CreateFunctionPointer((AffinityFunctionDestroyDelegate)AffinityFunctionDestroy)
             };
 
             _cbsPtr = Marshal.AllocHGlobal(UU.HandlersSize());
@@ -612,7 +626,7 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
         }
 
         [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
-        private void DataStreamerStreamReceiverInvoke(void* target, long rcvPtr, void* cache, long memPtr, 
+        private void DataStreamerStreamReceiverInvoke(void* target, long rcvPtr, void* cache, long memPtr,
             byte keepBinary)
         {
             SafeCall(() =>
@@ -1089,6 +1103,119 @@ namespace Apache.Ignite.Core.Impl.Unmanaged
 
         #endregion
 
+        #region AffinityFunction
+
+        private long AffinityFunctionInit(void* target, long memPtr, void* baseFunc)
+        {
+            return SafeCall(() =>
+            {
+                using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
+                {
+                    var reader = _ignite.Marshaller.StartUnmarshal(stream);
+
+                    var func = reader.ReadObjectEx<IAffinityFunction>();
+
+                    ResourceProcessor.Inject(func, _ignite);
+
+                    var affBase = func as AffinityFunctionBase;
+
+                    if (affBase != null)
+                        affBase.SetBaseFunction(new PlatformAffinityFunction(
+                            _ignite.InteropProcessor.ChangeTarget(baseFunc), _ignite.Marshaller));
+
+                    return _handleRegistry.Allocate(func);
+                }
+            });
+        }
+
+        private int AffinityFunctionPartition(void* target, long ptr, long memPtr)
+        {
+            return SafeCall(() =>
+            {
+                using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
+                {
+                    var key = _ignite.Marshaller.Unmarshal<object>(stream);
+
+                    return _handleRegistry.Get<IAffinityFunction>(ptr, true).GetPartition(key);
+                }
+            });
+        }
+
+        private void AffinityFunctionAssignPartitions(void* target, long ptr, long inMemPtr, long outMemPtr)
+        {
+            SafeCall(() =>
+            {
+                using (var inStream = IgniteManager.Memory.Get(inMemPtr).GetStream())
+                {
+                    var ctx = new AffinityFunctionContext(_ignite.Marshaller.StartUnmarshal(inStream));
+                    var func = _handleRegistry.Get<IAffinityFunction>(ptr, true);
+                    var parts = func.AssignPartitions(ctx);
+
+                    if (parts == null)
+                        throw new IgniteException(func.GetType() + ".AssignPartitions() returned invalid result: null");
+
+                    using (var outStream = IgniteManager.Memory.Get(outMemPtr).GetStream())
+                    {
+                        var writer = _ignite.Marshaller.StartMarshal(outStream);
+
+                        var partCnt = 0;
+                        writer.WriteInt(partCnt);  // reserve size
+
+                        foreach (var part in parts)
+                        {
+                            if (part == null)
+                                throw new IgniteException(func.GetType() +
+                                                          ".AssignPartitions() returned invalid partition: null");
+
+                            partCnt++;
+
+                            var nodeCnt = 0;
+                            var cntPos = outStream.Position;
+                            writer.WriteInt(nodeCnt);  // reserve size
+
+                            foreach (var node in part)
+                            {
+                                nodeCnt++;
+                                writer.WriteGuid(node.Id);
+                            }
+
+                            var endPos = outStream.Position;
+                            outStream.Seek(cntPos, SeekOrigin.Begin);
+                            outStream.WriteInt(nodeCnt);
+                            outStream.Seek(endPos, SeekOrigin.Begin);
+                        }
+
+                        outStream.SynchronizeOutput();
+                        outStream.Seek(0, SeekOrigin.Begin);
+                        writer.WriteInt(partCnt);
+                    }
+                }
+            });
+        }
+
+        private void AffinityFunctionRemoveNode(void* target, long ptr, long memPtr)
+        {
+            SafeCall(() =>
+            {
+                using (var stream = IgniteManager.Memory.Get(memPtr).GetStream())
+                {
+                    var nodeId = _ignite.Marshaller.Unmarshal<Guid>(stream);
+
+                    _handleRegistry.Get<IAffinityFunction>(ptr, true).RemoveNode(nodeId);
+                }
+            });
+        }
+
+        private void AffinityFunctionDestroy(void* target, long ptr)
+        {
+            SafeCall(() =>
+            {
+                _handleRegistry.Release(ptr);
+            });
+        }
+
+        #endregion
+
         #region HELPERS
 
         [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]


[31/46] ignite git commit: ignite-3465 Do not call super.toString for not-initialized BinaryObjectImpl. (cherry picked from commit 78d7c13)

Posted by sb...@apache.org.
ignite-3465 Do not call super.toString for not-initialized BinaryObjectImpl.
(cherry picked from commit 78d7c13)


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

Branch: refs/heads/ignite-1232
Commit: 590dffbe47d015db36710ba7708fd7d83269329f
Parents: 46f4272
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 19 13:35:59 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jul 19 14:53:15 2016 +0300

----------------------------------------------------------------------
 .../org/apache/ignite/internal/binary/BinaryObjectImpl.java  | 8 ++++++++
 1 file changed, 8 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/590dffbe/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index 7998ee3..ae110f1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@ -620,4 +620,12 @@ public final class BinaryObjectImpl extends BinaryObjectExImpl implements Extern
     private BinaryReaderExImpl reader(@Nullable BinaryReaderHandles rCtx, boolean forUnmarshal) {
         return reader(rCtx, null, forUnmarshal);
     }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        if (arr == null || ctx == null)
+            return "BinaryObjectImpl [arr= " + (arr != null) + ", ctx=" + (ctx != null) + ", start=" + start + "]";
+
+        return super.toString();
+    }
 }


[23/46] ignite git commit: ignite-3392 Added test. (cherry picked from commit a056954)

Posted by sb...@apache.org.
ignite-3392 Added test.
(cherry picked from commit a056954)


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

Branch: refs/heads/ignite-1232
Commit: e1195296ddc883c0a980f64bf0d80c26ef78b233
Parents: 4f97444
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 13 12:29:33 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Mon Jul 18 16:38:00 2016 +0300

----------------------------------------------------------------------
 ...rviceDeploymentExceptionPropagationTest.java | 80 ++++++++++++++++++++
 1 file changed, 80 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/e1195296/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceDeploymentExceptionPropagationTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceDeploymentExceptionPropagationTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceDeploymentExceptionPropagationTest.java
new file mode 100644
index 0000000..811594f
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/service/GridServiceDeploymentExceptionPropagationTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.service;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.services.Service;
+import org.apache.ignite.services.ServiceContext;
+import org.apache.ignite.testframework.GridStringLogger;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/** */
+public class GridServiceDeploymentExceptionPropagationTest extends GridCommonAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+
+        super.afterTestsStopped();
+    }
+
+    /** */
+    @SuppressWarnings("unused")
+    public void testExceptionPropagation() throws Exception {
+        try (Ignite srv = startGrid("server")) {
+
+            GridStringLogger log = new GridStringLogger();
+
+            try (Ignite client = startGrid("client", getConfiguration("client").setGridLogger(log).setClientMode(true))) {
+
+                try {
+                    client.services().deployClusterSingleton("my-service", new ServiceImpl());
+                }
+                catch (IgniteException e) {
+                    assertTrue(log.toString().contains("ServiceImpl init exception"));
+
+                    return; // Exception is what we expect.
+                }
+
+                // Fail explicitly if we've managed to get here though we shouldn't have.
+                fail("https://issues.apache.org/jira/browse/IGNITE-3392");
+            }
+        }
+    }
+
+    /**
+     * Simple service implementation throwing an exception on init.
+     * Doesn't even try to do anything useful because what we're testing here is failure.
+     */
+    private static class ServiceImpl implements Service {
+        /** {@inheritDoc} */
+        @Override public void cancel(ServiceContext ctx) {
+            // No-op.
+        }
+
+        /** {@inheritDoc} */
+        @Override public void init(ServiceContext ctx) throws Exception {
+            throw new RuntimeException("ServiceImpl init exception");
+        }
+
+        /** {@inheritDoc} */
+        @Override public void execute(ServiceContext ctx) throws Exception {
+            // No-op.
+        }
+    }
+}


[41/46] ignite git commit: Revert IGNITE-2949 due to broken compatibility

Posted by sb...@apache.org.
Revert IGNITE-2949 due to broken compatibility


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

Branch: refs/heads/ignite-1232
Commit: d767e518bf7844e3dcdb3f3fdc02da5ecc1b4f54
Parents: 5ec99e8
Author: Valentin Kulichenko <va...@gmail.com>
Authored: Thu Jul 7 00:05:16 2016 -0700
Committer: Valentin Kulichenko <va...@gmail.com>
Committed: Tue Jul 19 16:10:48 2016 -0700

----------------------------------------------------------------------
 assembly/LICENSE_FABRIC                   | 7 ++++++-
 assembly/LICENSE_HADOOP                   | 7 ++++++-
 examples/pom-standalone-lgpl.xml          | 6 +++---
 examples/pom-standalone.xml               | 6 +++---
 examples/pom.xml                          | 6 +++---
 examples/schema-import/pom-standalone.xml | 6 +++---
 examples/schema-import/pom.xml            | 6 +++---
 modules/cassandra/pom.xml                 | 2 +-
 modules/core/pom.xml                      | 6 +++---
 modules/flume/README.txt                  | 2 +-
 parent/pom.xml                            | 1 +
 11 files changed, 33 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/assembly/LICENSE_FABRIC
----------------------------------------------------------------------
diff --git a/assembly/LICENSE_FABRIC b/assembly/LICENSE_FABRIC
index 8cb5730..b9c75b2 100644
--- a/assembly/LICENSE_FABRIC
+++ b/assembly/LICENSE_FABRIC
@@ -1,4 +1,3 @@
-
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
@@ -227,6 +226,12 @@ For details, see CC0 1.0 Universal (1.0), Public Domain Dedication,
 http://creativecommons.org/publicdomain/zero/1.0/
 
 ==============================================================================
+For JSR107 API and SPI (https://github.com/jsr107/jsr107spec) javax.cache:cache-api:jar:1.0.0
+==============================================================================
+This product bundles JSR107 API and SPI which is available under a:
+JSR-000107 JCACHE 2.9 Public Review - Updated Specification License. For details, see https://raw.github.com/jsr107/jsr107spec/master/LICENSE.txt.
+
+==============================================================================
 For JSch (http://www.jcraft.com/jsch/) com.jcraft:jsch:jar:0.1.50
 ==============================================================================
 This product bundles JSch which is available under a:

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/assembly/LICENSE_HADOOP
----------------------------------------------------------------------
diff --git a/assembly/LICENSE_HADOOP b/assembly/LICENSE_HADOOP
index 0d05d52..0256b20 100644
--- a/assembly/LICENSE_HADOOP
+++ b/assembly/LICENSE_HADOOP
@@ -1,4 +1,3 @@
-
                                  Apache License
                            Version 2.0, January 2004
                         http://www.apache.org/licenses/
@@ -227,6 +226,12 @@ For details, see CC0 1.0 Universal (1.0), Public Domain Dedication,
 http://creativecommons.org/publicdomain/zero/1.0/
 
 ==============================================================================
+For JSR107 API and SPI (https://github.com/jsr107/jsr107spec) javax.cache:cache-api:jar:1.0.0
+==============================================================================
+This product bundles JSR107 API and SPI which is available under a:
+JSR-000107 JCACHE 2.9 Public Review - Updated Specification License. For details, see https://raw.github.com/jsr107/jsr107spec/master/LICENSE.txt.
+
+==============================================================================
 For JSch (http://www.jcraft.com/jsch/) com.jcraft:jsch:jar:0.1.50
 ==============================================================================
 This product bundles JSch which is available under a:

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/examples/pom-standalone-lgpl.xml
----------------------------------------------------------------------
diff --git a/examples/pom-standalone-lgpl.xml b/examples/pom-standalone-lgpl.xml
index 951fab6..7e7ccc2 100644
--- a/examples/pom-standalone-lgpl.xml
+++ b/examples/pom-standalone-lgpl.xml
@@ -41,9 +41,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>1.0.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/examples/pom-standalone.xml
----------------------------------------------------------------------
diff --git a/examples/pom-standalone.xml b/examples/pom-standalone.xml
index 20399ee..6247ced 100644
--- a/examples/pom-standalone.xml
+++ b/examples/pom-standalone.xml
@@ -41,9 +41,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>1.0.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index cba056d..979a46f 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -32,9 +32,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>${javax.cache.version}</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/examples/schema-import/pom-standalone.xml
----------------------------------------------------------------------
diff --git a/examples/schema-import/pom-standalone.xml b/examples/schema-import/pom-standalone.xml
index 43b76d8..e443728 100644
--- a/examples/schema-import/pom-standalone.xml
+++ b/examples/schema-import/pom-standalone.xml
@@ -36,9 +36,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>1.0.0</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/examples/schema-import/pom.xml
----------------------------------------------------------------------
diff --git a/examples/schema-import/pom.xml b/examples/schema-import/pom.xml
index f5ccac0..b6e36ef 100644
--- a/examples/schema-import/pom.xml
+++ b/examples/schema-import/pom.xml
@@ -39,9 +39,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>${javax.cache.version}</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/modules/cassandra/pom.xml
----------------------------------------------------------------------
diff --git a/modules/cassandra/pom.xml b/modules/cassandra/pom.xml
index c9ff87d..dc8b08c 100644
--- a/modules/cassandra/pom.xml
+++ b/modules/cassandra/pom.xml
@@ -236,7 +236,7 @@
                                 org.apache.ignite,org.springframework,org.gridgain
                             </excludeGroupIds>
                             <excludeArtifactIds>
-                                commons-logging,slf4j-api,geronimo-jcache_1.0_spec,slf4j-api,aopalliance
+                                commons-logging,slf4j-api,cache-api,slf4j-api,aopalliance
                             </excludeArtifactIds>
                             <includeScope>runtime</includeScope>
                         </configuration>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/modules/core/pom.xml
----------------------------------------------------------------------
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index 7529b0b..5e32caf 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -63,9 +63,9 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcache_1.0_spec</artifactId>
-            <version>1.0-alpha-1</version>
+            <groupId>javax.cache</groupId>
+            <artifactId>cache-api</artifactId>
+            <version>${javax.cache.version}</version>
         </dependency>
 
         <dependency>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/modules/flume/README.txt
----------------------------------------------------------------------
diff --git a/modules/flume/README.txt b/modules/flume/README.txt
index 97d8cac..bf7e0ff 100644
--- a/modules/flume/README.txt
+++ b/modules/flume/README.txt
@@ -20,7 +20,7 @@ plugins.d/
     |-- lib
     |   `-- ignite-flume-transformer-x.x.x.jar <-- your jar
     `-- libext
-        |-- geronimo-jcache_1.0_spec-1.0-alpha-1.jar
+        |-- cache-api-1.0.0.jar
         |-- ignite-core-x.x.x.jar
         |-- ignite-flume-x.x.x.jar <-- IgniteSink
         |-- ignite-spring-x.x.x.jar

http://git-wip-us.apache.org/repos/asf/ignite/blob/d767e518/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index e4a6f84..3e9a71c 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -76,6 +76,7 @@
         <jackson.version>1.9.13</jackson.version>
         <jackson2.version>2.7.5</jackson2.version>
         <javax.cache.bundle.version>1.0.0_1</javax.cache.bundle.version>
+        <javax.cache.version>1.0.0</javax.cache.version>
         <jetty.version>9.2.11.v20150529</jetty.version>
         <jms.spec.version>1.1.1</jms.spec.version>
         <jsch.bundle.version>0.1.53_1</jsch.bundle.version>


[39/46] ignite git commit: IGNITE-3511: .NET: Fixed AffinityFunctionBase.cs placement, added missing Package-Info.cs files.

Posted by sb...@apache.org.
IGNITE-3511: .NET: Fixed AffinityFunctionBase.cs placement, added missing Package-Info.cs files.


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

Branch: refs/heads/ignite-1232
Commit: 51add5049c9603a143a1a8f9233d94f92c8394da
Parents: ecc77b0
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Jul 19 17:11:46 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jul 19 17:11:46 2016 +0300

----------------------------------------------------------------------
 .../GridAffinityFunctionContextImpl.java        |   9 +
 .../affinity/PlatformAffinityFunction.java      | 277 +++++++++++++++++++
 .../PlatformAffinityFunctionTarget.java         | 113 ++++++++
 .../cache/affinity/PlatformAffinityUtils.java   | 116 ++++++++
 .../callback/PlatformCallbackGateway.java       |  89 ++++++
 .../callback/PlatformCallbackUtils.java         |  49 ++++
 .../PlatformDotNetConfigurationClosure.java     |  95 +++++++
 .../dotnet/PlatformDotNetAffinityFunction.java  | 171 ++++++++++++
 .../platforms/cpp/jni/include/ignite/jni/java.h |  20 +-
 modules/platforms/cpp/jni/src/java.cpp          |  41 ++-
 .../Apache.Ignite.Core.Tests.csproj             |   7 +
 .../Affinity/AffinityFunctionSpringTest.cs      | 184 ++++++++++++
 .../Config/Cache/Affinity/affinity-function.xml | 129 +++++++++
 .../Cache/Affinity/affinity-function2.xml       |  49 ++++
 .../Apache.Ignite.Core.Tests/TestRunner.cs      |   3 +-
 .../Apache.Ignite.Core.csproj                   |  16 ++
 .../Cache/Affinity/AffinityFunctionContext.cs   | 120 ++++++++
 .../Cache/Affinity/AffinityTopologyVersion.cs   | 138 +++++++++
 .../Cache/Affinity/Fair/FairAffinityFunction.cs |  33 +++
 .../Cache/Affinity/Fair/Package-Info.cs         |  26 ++
 .../Cache/Affinity/IAffinityFunction.cs         |  82 ++++++
 .../Cache/Affinity/Package-Info.cs              |  26 ++
 .../Cache/Affinity/Rendezvous/Package-Info.cs   |  26 ++
 .../Rendezvous/RendezvousAffinityFunction.cs    |  32 +++
 .../Cache/Configuration/Package-Info.cs         |  26 ++
 .../Cache/Eviction/Package-Info.cs              |  26 ++
 .../Communication/Package-Info.cs               |  26 ++
 .../Communication/Tcp/Package-Info.cs           |  26 ++
 .../Apache.Ignite.Core/Events/EventReader.cs    |   8 +-
 .../dotnet/Apache.Ignite.Core/Ignition.cs       |  38 ++-
 .../Impl/Binary/BinaryReaderExtensions.cs       |  16 +-
 .../Impl/Binary/Marshaller.cs                   |   1 +
 .../Impl/Cache/Affinity/AffinityFunctionBase.cs | 140 ++++++++++
 .../Affinity/AffinityFunctionSerializer.cs      | 277 +++++++++++++++++++
 .../Cache/Affinity/PlatformAffinityFunction.cs  |  74 +++++
 .../Impl/Common/ObjectInfoHolder.cs             |  86 ++++++
 .../Apache.Ignite.Core/Impl/IgniteUtils.cs      |  10 +-
 .../Impl/Unmanaged/UnmanagedCallbackHandlers.cs |   6 +
 .../Impl/Unmanaged/UnmanagedCallbacks.cs        | 131 ++++++++-
 39 files changed, 2715 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityFunctionContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityFunctionContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityFunctionContextImpl.java
index 6c97efd..4ddee00 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityFunctionContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityFunctionContextImpl.java
@@ -80,4 +80,13 @@ public class GridAffinityFunctionContextImpl implements AffinityFunctionContext
     @Override public int backups() {
         return backups;
     }
+
+    /**
+     * Gets the previous assignment.
+     *
+     * @return Previous assignment.
+     */
+    public List<List<ClusterNode>> prevAssignment() {
+        return prevAssignment;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
new file mode 100644
index 0000000..6681e7a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunction.java
@@ -0,0 +1,277 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.affinity.AffinityFunctionContext;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.PlatformContext;
+import org.apache.ignite.internal.processors.platform.memory.PlatformMemory;
+import org.apache.ignite.internal.processors.platform.memory.PlatformOutputStream;
+import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
+import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Platform AffinityFunction.
+ */
+public class PlatformAffinityFunction implements AffinityFunction, Externalizable, LifecycleAware {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** */
+    private static final byte FLAG_PARTITION = 1;
+
+    /** */
+    private static final byte FLAG_REMOVE_NODE = 1 << 1;
+
+    /** */
+    private static final byte FLAG_ASSIGN_PARTITIONS = 1 << 2;
+
+    /** */
+    private Object userFunc;
+
+    /**
+     * Partition count.
+     *
+     * 1) Java calls partitions() method very early (before LifecycleAware.start) during CacheConfiguration validation.
+     * 2) Partition count never changes.
+     * Therefore, we get the value on .NET side once, and pass it along with PlatformAffinity.
+     */
+    private int partitions;
+
+    /** */
+    private AffinityFunction baseFunc;
+
+    /** */
+    private byte overrideFlags;
+
+    /** */
+    private transient Ignite ignite;
+
+    /** */
+    private transient PlatformContext ctx;
+
+    /** */
+    private transient long ptr;
+
+    /** */
+    private transient PlatformAffinityFunctionTarget baseTarget;
+
+
+    /**
+     * Ctor for serialization.
+     *
+     */
+    public PlatformAffinityFunction() {
+        partitions = -1;
+    }
+
+    /**
+     * Ctor.
+     *
+     * @param func User fun object.
+     * @param partitions Number of partitions.
+     */
+    public PlatformAffinityFunction(Object func, int partitions, byte overrideFlags, AffinityFunction baseFunc) {
+        userFunc = func;
+        this.partitions = partitions;
+        this.overrideFlags = overrideFlags;
+        this.baseFunc = baseFunc;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void reset() {
+        // userFunc is always in initial state (it is serialized only once on start).
+        if (baseFunc != null)
+            baseFunc.reset();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int partitions() {
+        // Affinity function can not return different number of partitions,
+        // so we pass this value once from the platform.
+        assert partitions > 0;
+
+        return partitions;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int partition(Object key) {
+        if ((overrideFlags & FLAG_PARTITION) == 0) {
+            assert baseFunc != null;
+
+            return baseFunc.partition(key);
+        }
+
+        assert ctx != null;
+        assert ptr != 0;
+
+        try (PlatformMemory mem = ctx.memory().allocate()) {
+            PlatformOutputStream out = mem.output();
+            BinaryRawWriterEx writer = ctx.writer(out);
+
+            writer.writeObject(key);
+
+            out.synchronize();
+
+            return ctx.gateway().affinityFunctionPartition(ptr, mem.pointer());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public List<List<ClusterNode>> assignPartitions(AffinityFunctionContext affCtx) {
+        if ((overrideFlags & FLAG_ASSIGN_PARTITIONS) == 0) {
+            assert baseFunc != null;
+
+            return baseFunc.assignPartitions(affCtx);
+        }
+
+        assert ctx != null;
+        assert ptr != 0;
+        assert affCtx != null;
+
+        try (PlatformMemory outMem = ctx.memory().allocate()) {
+            try (PlatformMemory inMem = ctx.memory().allocate()) {
+                PlatformOutputStream out = outMem.output();
+                BinaryRawWriterEx writer = ctx.writer(out);
+
+                // Write previous assignment
+                PlatformAffinityUtils.writeAffinityFunctionContext(affCtx, writer, ctx);
+
+                out.synchronize();
+
+                // Call platform
+                // We can not restore original AffinityFunctionContext after the call to platform,
+                // due to DiscoveryEvent (when node leaves, we can't get it by id anymore).
+                // Secondly, AffinityFunctionContext can't be changed by the user.
+                if (baseTarget != null)
+                    baseTarget.setCurrentAffinityFunctionContext(affCtx);
+
+                try {
+                    ctx.gateway().affinityFunctionAssignPartitions(ptr, outMem.pointer(), inMem.pointer());
+                }
+                finally {
+                    if (baseTarget != null)
+                        baseTarget.setCurrentAffinityFunctionContext(null);
+                }
+
+                // Read result
+                return PlatformAffinityUtils.readPartitionAssignment(ctx.reader(inMem), ctx);
+            }
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeNode(UUID nodeId) {
+        if ((overrideFlags & FLAG_REMOVE_NODE) == 0) {
+            assert baseFunc != null;
+
+            baseFunc.removeNode(nodeId);
+
+            return;
+        }
+
+        assert ctx != null;
+        assert ptr != 0;
+
+        try (PlatformMemory mem = ctx.memory().allocate()) {
+            PlatformOutputStream out = mem.output();
+            BinaryRawWriterEx writer = ctx.writer(out);
+
+            writer.writeUuid(nodeId);
+
+            out.synchronize();
+
+            ctx.gateway().affinityFunctionRemoveNode(ptr, mem.pointer());
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(userFunc);
+        out.writeInt(partitions);
+        out.writeByte(overrideFlags);
+        out.writeObject(baseFunc);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        userFunc = in.readObject();
+        partitions = in.readInt();
+        overrideFlags = in.readByte();
+        baseFunc = (AffinityFunction)in.readObject();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start() throws IgniteException {
+        // userFunc is null when there is nothing overridden
+        if (userFunc == null)
+            return;
+
+        assert ignite != null;
+        ctx = PlatformUtils.platformContext(ignite);
+        assert ctx != null;
+
+        try (PlatformMemory mem = ctx.memory().allocate()) {
+            PlatformOutputStream out = mem.output();
+            BinaryRawWriterEx writer = ctx.writer(out);
+
+            writer.writeObject(userFunc);
+
+            out.synchronize();
+
+            baseTarget = baseFunc != null
+                ? new PlatformAffinityFunctionTarget(ctx, baseFunc)
+                : null;
+
+            ptr = ctx.gateway().affinityFunctionInit(mem.pointer(), baseTarget);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() throws IgniteException {
+        if (ptr == 0)
+            return;
+
+        assert ctx != null;
+
+        ctx.gateway().affinityFunctionDestroy(ptr);
+    }
+
+    /**
+     * Injects the Ignite.
+     *
+     * @param ignite Ignite.
+     */
+    @SuppressWarnings("unused")
+    @IgniteInstanceResource
+    public void setIgnite(Ignite ignite) {
+        this.ignite = ignite;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
new file mode 100644
index 0000000..8a07b33
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget.java
@@ -0,0 +1,113 @@
+/*
+ * 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.cache.affinity;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.affinity.AffinityFunctionContext;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.binary.BinaryRawReaderEx;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget;
+import org.apache.ignite.internal.processors.platform.PlatformContext;
+import org.apache.ignite.internal.util.typedef.internal.U;
+
+import java.util.List;
+
+/**
+ * Platform affinity function target:
+ * to be invoked when Platform function calls base implementation of one of the AffinityFunction methods.
+ */
+public class PlatformAffinityFunctionTarget extends PlatformAbstractTarget {
+    /** */
+    private static final int OP_PARTITION = 1;
+
+    /** */
+    private static final int OP_REMOVE_NODE = 2;
+
+    /** */
+    private static final int OP_ASSIGN_PARTITIONS = 3;
+
+    /** Inner function to delegate calls to. */
+    private final AffinityFunction baseFunc;
+
+    /** Thread local to hold the current affinity function context. */
+    private static final ThreadLocal<AffinityFunctionContext> currentAffCtx = new ThreadLocal<>();
+
+    /**
+     * Constructor.
+     *
+     * @param platformCtx Context.
+     * @param baseFunc Function to wrap.
+     */
+    protected PlatformAffinityFunctionTarget(PlatformContext platformCtx, AffinityFunction baseFunc) {
+        super(platformCtx);
+
+        assert baseFunc != null;
+        this.baseFunc = baseFunc;
+
+        try {
+            platformCtx.kernalContext().resource().injectGeneric(baseFunc);
+        }
+        catch (IgniteCheckedException e) {
+            throw U.convertException(e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected long processInStreamOutLong(int type, BinaryRawReaderEx reader) throws IgniteCheckedException {
+        if (type == OP_PARTITION)
+            return baseFunc.partition(reader.readObjectDetached());
+        else if (type == OP_REMOVE_NODE) {
+            baseFunc.removeNode(reader.readUuid());
+
+            return 0;
+        }
+
+        return super.processInStreamOutLong(type, reader);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void processOutStream(int type, BinaryRawWriterEx writer) throws IgniteCheckedException {
+        if (type == OP_ASSIGN_PARTITIONS) {
+            AffinityFunctionContext affCtx = currentAffCtx.get();
+
+            if (affCtx == null)
+                throw new IgniteException("Thread-local AffinityFunctionContext is null. " +
+                        "This may indicate an unsupported call to the base AffinityFunction.");
+
+            final List<List<ClusterNode>> partitions = baseFunc.assignPartitions(affCtx);
+
+            PlatformAffinityUtils.writePartitionAssignment(partitions, writer, platformContext());
+
+            return;
+        }
+
+        super.processOutStream(type, writer);
+    }
+
+    /**
+     * Sets the context for current operation.
+     *
+     * @param ctx Context.
+     */
+    void setCurrentAffinityFunctionContext(AffinityFunctionContext ctx) {
+        currentAffCtx.set(ctx);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
new file mode 100644
index 0000000..b1e1b23
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityUtils.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.platform.cache.affinity;
+
+import org.apache.ignite.binary.BinaryRawReader;
+import org.apache.ignite.cache.affinity.AffinityFunctionContext;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.binary.BinaryRawWriterEx;
+import org.apache.ignite.internal.cluster.IgniteClusterEx;
+import org.apache.ignite.internal.processors.affinity.GridAffinityFunctionContextImpl;
+import org.apache.ignite.internal.processors.platform.PlatformContext;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Affinity serialization functions.
+ */
+public class PlatformAffinityUtils {
+    /**
+     * Writes the affinity function context.
+     * @param affCtx Affinity context.
+     * @param writer Writer.
+     * @param ctx Platform context.
+     */
+    public static void writeAffinityFunctionContext(AffinityFunctionContext affCtx, BinaryRawWriterEx writer,
+        PlatformContext ctx) {
+        assert affCtx != null;
+        assert writer != null;
+        assert ctx != null;
+
+        ctx.writeNodes(writer, affCtx.currentTopologySnapshot());
+
+        writer.writeInt(affCtx.backups());
+        writer.writeLong(affCtx.currentTopologyVersion().topologyVersion());
+        writer.writeInt(affCtx.currentTopologyVersion().minorTopologyVersion());
+
+        ctx.writeEvent(writer, affCtx.discoveryEvent());
+
+        // Write previous assignment
+        List<List<ClusterNode>> prevAssignment = ((GridAffinityFunctionContextImpl)affCtx).prevAssignment();
+
+        if (prevAssignment == null)
+            writer.writeInt(-1);
+        else {
+            writer.writeInt(prevAssignment.size());
+
+            for (List<ClusterNode> part : prevAssignment)
+                ctx.writeNodes(writer, part);
+        }
+    }
+
+    /**
+     * Writes the partition assignment to a stream.
+     *
+     * @param partitions Partitions.
+     * @param writer Writer.
+     */
+    public static void writePartitionAssignment(Collection<List<ClusterNode>> partitions, BinaryRawWriterEx writer,
+        PlatformContext ctx) {
+        assert partitions != null;
+        assert writer != null;
+
+        writer.writeInt(partitions.size());
+
+        for (List<ClusterNode> part : partitions)
+            ctx.writeNodes(writer, part);
+    }
+
+    /**
+     * Reads the partition assignment.
+     *
+     * @param reader Reader.
+     * @param ctx Platform context.
+     * @return Partitions.
+     */
+    public static List<List<ClusterNode>> readPartitionAssignment(BinaryRawReader reader, PlatformContext ctx) {
+        assert reader != null;
+        assert ctx != null;
+
+        int partCnt = reader.readInt();
+
+        List<List<ClusterNode>> res = new ArrayList<>(partCnt);
+
+        IgniteClusterEx cluster = ctx.kernalContext().grid().cluster();
+
+        for (int i = 0; i < partCnt; i++) {
+            int partSize = reader.readInt();
+
+            List<ClusterNode> part = new ArrayList<>(partSize);
+
+            for (int j = 0; j < partSize; j++)
+                part.add(cluster.node(reader.readUuid()));
+
+            res.add(part);
+        }
+
+        return res;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
index 5093773..ac1416c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackGateway.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.platform.callback;
 
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAffinityFunctionTarget;
 import org.apache.ignite.internal.util.GridStripedSpinBusyLock;
 
 /**
@@ -950,6 +951,94 @@ public class PlatformCallbackGateway {
     }
 
     /**
+     * Initializes affinity function.
+     *
+     * @param memPtr Pointer to a stream with serialized affinity function.
+     * @param baseFunc Optional func for base calls.
+     * @return Affinity function pointer.
+     */
+    public long affinityFunctionInit(long memPtr, PlatformAffinityFunctionTarget baseFunc) {
+        enter();
+
+        try {
+            return PlatformCallbackUtils.affinityFunctionInit(envPtr, memPtr, baseFunc);
+        }
+        finally {
+            leave();
+        }
+    }
+
+    /**
+     * Gets the partition from affinity function.
+     *
+     * @param ptr Affinity function pointer.
+     * @param memPtr Pointer to a stream with key object.
+     * @return Partition number for a given key.
+     */
+    public int affinityFunctionPartition(long ptr, long memPtr) {
+        enter();
+
+        try {
+            return PlatformCallbackUtils.affinityFunctionPartition(envPtr, ptr, memPtr);
+        }
+        finally {
+            leave();
+        }
+    }
+
+    /**
+     * Assigns the affinity partitions.
+     *
+     * @param ptr Affinity function pointer.
+     * @param outMemPtr Pointer to a stream with affinity context.
+     * @param inMemPtr Pointer to a stream with result.
+     */
+    public void affinityFunctionAssignPartitions(long ptr, long outMemPtr, long inMemPtr){
+        enter();
+
+        try {
+            PlatformCallbackUtils.affinityFunctionAssignPartitions(envPtr, ptr, outMemPtr, inMemPtr);
+        }
+        finally {
+            leave();
+        }
+    }
+
+    /**
+     * Removes the node from affinity function.
+     *
+     * @param ptr Affinity function pointer.
+     * @param memPtr Pointer to a stream with node id.
+     */
+    public void affinityFunctionRemoveNode(long ptr, long memPtr) {
+        enter();
+
+        try {
+            PlatformCallbackUtils.affinityFunctionRemoveNode(envPtr, ptr, memPtr);
+        }
+        finally {
+            leave();
+        }
+    }
+
+    /**
+     * Destroys the affinity function.
+     *
+     * @param ptr Affinity function pointer.
+     */
+    public void affinityFunctionDestroy(long ptr) {
+        if (!lock.enterBusy())
+            return;  // skip: destroy is not necessary during shutdown.
+
+        try {
+            PlatformCallbackUtils.affinityFunctionDestroy(envPtr, ptr);
+        }
+        finally {
+            leave();
+        }
+    }
+
+    /**
      * Enter gateway.
      */
     protected void enter() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils.java
index f7d6586..7b36e5e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/callback/PlatformCallbackUtils.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.internal.processors.platform.callback;
 
+import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAffinityFunctionTarget;
+
 /**
  * Platform callback utility methods. Implemented in target platform. All methods in this class must be
  * package-visible and invoked only through {@link PlatformCallbackGateway}.
@@ -496,6 +498,53 @@ public class PlatformCallbackUtils {
     static native void onClientReconnected(long envPtr, boolean clusterRestarted);
 
     /**
+     * Initializes affinity function.
+     *
+     * @param envPtr Environment pointer.
+     * @param memPtr Pointer to a stream with serialized affinity function.
+     * @param baseFunc Optional func for base calls.
+     * @return Affinity function pointer.
+     */
+    static native long affinityFunctionInit(long envPtr, long memPtr, PlatformAffinityFunctionTarget baseFunc);
+
+    /**
+     * Gets the partition from affinity function.
+     *
+     * @param envPtr Environment pointer.
+     * @param ptr Affinity function pointer.
+     * @param memPtr Pointer to a stream with key object.
+     * @return Partition number for a given key.
+     */
+    static native int affinityFunctionPartition(long envPtr, long ptr, long memPtr);
+
+    /**
+     * Assigns the affinity partitions.
+     *
+     * @param envPtr Environment pointer.
+     * @param ptr Affinity function pointer.
+     * @param outMemPtr Pointer to a stream with affinity context.
+     * @param inMemPtr Pointer to a stream with result.
+     */
+    static native void affinityFunctionAssignPartitions(long envPtr, long ptr, long outMemPtr, long inMemPtr);
+
+    /**
+     * Removes the node from affinity function.
+     *
+     * @param envPtr Environment pointer.
+     * @param ptr Affinity function pointer.
+     * @param memPtr Pointer to a stream with node id.
+     */
+    static native void affinityFunctionRemoveNode(long envPtr, long ptr, long memPtr);
+
+    /**
+     * Destroys the affinity function.
+     *
+     * @param envPtr Environment pointer.
+     * @param ptr Affinity function pointer.
+     */
+    static native void affinityFunctionDestroy(long envPtr, long ptr);
+
+    /**
      * Private constructor.
      */
     private PlatformCallbackUtils() {

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 db2fa4d..5a7d15d 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
@@ -23,14 +23,20 @@ import org.apache.ignite.binary.BinaryBasicIdMapper;
 import org.apache.ignite.binary.BinaryBasicNameMapper;
 import org.apache.ignite.binary.BinaryIdMapper;
 import org.apache.ignite.binary.BinaryNameMapper;
+import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.affinity.fair.FairAffinityFunction;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
 import org.apache.ignite.configuration.BinaryConfiguration;
+import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.configuration.PlatformConfiguration;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.binary.BinaryRawReaderEx;
 import org.apache.ignite.internal.binary.BinaryRawWriterEx;
 import org.apache.ignite.internal.binary.BinaryReaderExImpl;
 import org.apache.ignite.internal.binary.GridBinaryMarshaller;
 import org.apache.ignite.internal.processors.platform.PlatformAbstractConfigurationClosure;
+import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAffinityFunction;
 import org.apache.ignite.internal.processors.platform.lifecycle.PlatformLifecycleBean;
 import org.apache.ignite.internal.processors.platform.memory.PlatformMemory;
 import org.apache.ignite.internal.processors.platform.memory.PlatformMemoryManagerImpl;
@@ -40,6 +46,7 @@ import org.apache.ignite.internal.processors.platform.utils.PlatformUtils;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lifecycle.LifecycleBean;
 import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction;
 import org.apache.ignite.platform.dotnet.PlatformDotNetConfiguration;
 import org.apache.ignite.platform.dotnet.PlatformDotNetLifecycleBean;
 
@@ -189,6 +196,16 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
                     writer.writeMap(bean.getProperties());
                 }
 
+                // Write .NET affinity funcs
+                List<PlatformDotNetAffinityFunction> affFuncs = affinityFunctions(igniteCfg);
+
+                writer.writeInt(affFuncs.size());
+
+                for (PlatformDotNetAffinityFunction func : affFuncs) {
+                    writer.writeString(func.getTypeName());
+                    writer.writeMap(func.getProperties());
+                }
+
                 out.synchronize();
 
                 gate.extensionCallbackInLongLongOutLong(
@@ -240,6 +257,63 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
                 cfg.setLifecycleBeans(mergedBeans);
             }
         }
+
+        // Process affinity functions
+        List<PlatformDotNetAffinityFunction> affFuncs = affinityFunctions(cfg);
+
+        if (!affFuncs.isEmpty()) {
+            for (PlatformDotNetAffinityFunction aff : affFuncs)
+                aff.init(readAffinityFunction(in));
+        }
+    }
+
+    /**
+     * Reads the affinity function.
+     *
+     * @param in Stream.
+     * @return Affinity function.
+     */
+    private static PlatformAffinityFunction readAffinityFunction(BinaryRawReaderEx in) {
+        byte plcTyp = in.readByte();
+
+        if (plcTyp == 0)
+            return null;
+
+        int partitions = in.readInt();
+        boolean exclNeighbours = in.readBoolean();
+        byte overrideFlags = in.readByte();
+        Object userFunc = in.readObjectDetached();
+
+        AffinityFunction baseFunc = null;
+
+        switch (plcTyp) {
+            case 1: {
+                FairAffinityFunction f = new FairAffinityFunction();
+
+                f.setPartitions(partitions);
+                f.setExcludeNeighbors(exclNeighbours);
+
+                baseFunc = f;
+
+                break;
+            }
+
+            case 2: {
+                RendezvousAffinityFunction f = new RendezvousAffinityFunction();
+
+                f.setPartitions(partitions);
+                f.setExcludeNeighbors(exclNeighbours);
+
+                baseFunc = f;
+
+                break;
+            }
+
+            default:
+                assert plcTyp == 3 : "Unknown affinity function policy type: " + plcTyp;
+        }
+
+        return new PlatformAffinityFunction(userFunc, partitions, overrideFlags, baseFunc);
     }
 
     /**
@@ -260,4 +334,25 @@ public class PlatformDotNetConfigurationClosure extends PlatformAbstractConfigur
 
         return res;
     }
+
+    /**
+     * Find .NET affinity functions in configuration.
+     *
+     * @param cfg Configuration.
+     * @return affinity functions.
+     */
+    private static List<PlatformDotNetAffinityFunction> affinityFunctions(IgniteConfiguration cfg) {
+        List<PlatformDotNetAffinityFunction> res = new ArrayList<>();
+
+        CacheConfiguration[] cacheCfg = cfg.getCacheConfiguration();
+
+        if (cacheCfg != null) {
+            for (CacheConfiguration ccfg : cacheCfg) {
+                if (ccfg.getAffinity() instanceof PlatformDotNetAffinityFunction)
+                    res.add((PlatformDotNetAffinityFunction)ccfg.getAffinity());
+            }
+        }
+
+        return res;
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java b/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java
new file mode 100644
index 0000000..254c379
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/platform/dotnet/PlatformDotNetAffinityFunction.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.platform.dotnet;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.affinity.AffinityFunctionContext;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.processors.platform.cache.affinity.PlatformAffinityFunction;
+import org.apache.ignite.lifecycle.LifecycleAware;
+import org.apache.ignite.resources.IgniteInstanceResource;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * AffinityFunction implementation which can be used to configure .NET affinity function in Java Spring configuration.
+ */
+public class PlatformDotNetAffinityFunction implements AffinityFunction, Externalizable, LifecycleAware {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /** .NET type name. */
+    private transient String typName;
+
+    /** Properties. */
+    private transient Map<String, ?> props;
+
+    /** Inner function. */
+    private PlatformAffinityFunction func;
+
+    /**
+     * Gets .NET type name.
+     *
+     * @return .NET type name.
+     */
+    public String getTypeName() {
+        return typName;
+    }
+
+    /**
+     * Sets .NET type name.
+     *
+     * @param typName .NET type name.
+     */
+    public void setTypeName(String typName) {
+        this.typName = typName;
+    }
+
+    /**
+     * Get properties.
+     *
+     * @return Properties.
+     */
+    public Map<String, ?> getProperties() {
+        return props;
+    }
+
+    /**
+     * Set properties.
+     *
+     * @param props Properties.
+     */
+    public void setProperties(Map<String, ?> props) {
+        this.props = props;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void reset() {
+        assert func != null;
+
+        func.reset();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int partitions() {
+        assert func != null;
+
+        return func.partitions();
+    }
+
+    /** {@inheritDoc} */
+    @Override public int partition(Object key) {
+        assert func != null;
+
+        return func.partition(key);
+    }
+
+    /** {@inheritDoc} */
+    @Override public List<List<ClusterNode>> assignPartitions(AffinityFunctionContext affCtx) {
+        assert func != null;
+
+        return func.assignPartitions(affCtx);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void removeNode(UUID nodeId) {
+        assert func != null;
+
+        func.removeNode(nodeId);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void writeExternal(ObjectOutput out) throws IOException {
+        out.writeObject(func);
+    }
+
+    /** {@inheritDoc} */
+    @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+        func = (PlatformAffinityFunction) in.readObject();
+    }
+
+    /**
+     * Initializes this instance.
+     *
+     * @param func Underlying func.
+     */
+    public void init(PlatformAffinityFunction func) {
+        assert func != null;
+
+        this.func = func;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void start() throws IgniteException {
+        assert func != null;
+
+        func.start();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop() throws IgniteException {
+        assert func != null;
+
+        func.stop();
+    }
+
+    /**
+     * Injects the Ignite.
+     *
+     * @param ignite Ignite.
+     */
+    @SuppressWarnings("unused")
+    @IgniteInstanceResource
+    private void setIgnite(Ignite ignite) {
+        assert func != null;
+
+        func.setIgnite(ignite);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/cpp/jni/include/ignite/jni/java.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/jni/include/ignite/jni/java.h b/modules/platforms/cpp/jni/include/ignite/jni/java.h
index 8be8a32..18a15e2 100644
--- a/modules/platforms/cpp/jni/include/ignite/jni/java.h
+++ b/modules/platforms/cpp/jni/include/ignite/jni/java.h
@@ -101,6 +101,12 @@ namespace ignite
             typedef void(JNICALL *OnClientDisconnectedHandler)(void* target);
             typedef void(JNICALL *OnClientReconnectedHandler)(void* target, unsigned char clusterRestarted);
 
+            typedef long long(JNICALL *AffinityFunctionInitHandler)(void* target, long long memPtr, void* baseFunc);
+            typedef int(JNICALL *AffinityFunctionPartitionHandler)(void* target, long long ptr, long long memPtr);
+            typedef void(JNICALL *AffinityFunctionAssignPartitionsHandler)(void* target, long long ptr, long long inMemPtr, long long outMemPtr);
+            typedef void(JNICALL *AffinityFunctionRemoveNodeHandler)(void* target, long long ptr, long long memPtr);
+            typedef void(JNICALL *AffinityFunctionDestroyHandler)(void* target, long long ptr);
+
             /**
              * JNI handlers holder.
              */
@@ -178,6 +184,12 @@ namespace ignite
 
                 OnClientDisconnectedHandler onClientDisconnected;
                 OnClientReconnectedHandler onClientReconnected;
+
+                AffinityFunctionInitHandler affinityFunctionInit;
+                AffinityFunctionPartitionHandler affinityFunctionPartition;
+                AffinityFunctionAssignPartitionsHandler affinityFunctionAssignPartitions;
+                AffinityFunctionRemoveNodeHandler affinityFunctionRemoveNode;
+                AffinityFunctionDestroyHandler affinityFunctionDestroy;
             };
 
             /**
@@ -534,7 +546,7 @@ namespace ignite
                 jobject ProcessorAtomicReference(jobject obj, char* name, long long memPtr, bool create);
 				void ProcessorGetIgniteConfiguration(jobject obj, long long memPtr);
 				void ProcessorGetCacheNames(jobject obj, long long memPtr);
-                
+
                 long long TargetInStreamOutLong(jobject obj, int type, long long memPtr, JniErrorInfo* errInfo = NULL);
                 void TargetInStreamOutStream(jobject obj, int opType, long long inMemPtr, long long outMemPtr, JniErrorInfo* errInfo = NULL);
                 jobject TargetInStreamOutObject(jobject obj, int type, long long memPtr, JniErrorInfo* errInfo = NULL);
@@ -738,6 +750,12 @@ namespace ignite
 
             JNIEXPORT void JNICALL JniOnClientDisconnected(JNIEnv *env, jclass cls, jlong envPtr);
             JNIEXPORT void JNICALL JniOnClientReconnected(JNIEnv *env, jclass cls, jlong envPtr, jboolean clusterRestarted);
+
+            JNIEXPORT jlong JNICALL JniAffinityFunctionInit(JNIEnv *env, jclass cls, jlong envPtr, jlong memPtr, jobject baseFunc);
+            JNIEXPORT jint JNICALL JniAffinityFunctionPartition(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong memPtr);
+            JNIEXPORT void JNICALL JniAffinityFunctionAssignPartitions(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong inMemPtr, jlong outMemPtr);
+            JNIEXPORT void JNICALL JniAffinityFunctionRemoveNode(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong memPtr);
+            JNIEXPORT void JNICALL JniAffinityFunctionDestroy(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/cpp/jni/src/java.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/jni/src/java.cpp b/modules/platforms/cpp/jni/src/java.cpp
index 282b874..56e042c 100644
--- a/modules/platforms/cpp/jni/src/java.cpp
+++ b/modules/platforms/cpp/jni/src/java.cpp
@@ -209,7 +209,7 @@ namespace ignite
             JniMethod M_PLATFORM_PROCESSOR_EXTENSIONS = JniMethod("extensions", "()Lorg/apache/ignite/internal/processors/platform/PlatformTarget;", false);
             JniMethod M_PLATFORM_PROCESSOR_ATOMIC_LONG = JniMethod("atomicLong", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTarget;", false);
             JniMethod M_PLATFORM_PROCESSOR_ATOMIC_SEQUENCE = JniMethod("atomicSequence", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTarget;", false);
-            JniMethod M_PLATFORM_PROCESSOR_ATOMIC_REFERENCE = JniMethod("atomicReference", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTarget;", false);            
+            JniMethod M_PLATFORM_PROCESSOR_ATOMIC_REFERENCE = JniMethod("atomicReference", "(Ljava/lang/String;JZ)Lorg/apache/ignite/internal/processors/platform/PlatformTarget;", false);
             JniMethod M_PLATFORM_PROCESSOR_GET_IGNITE_CONFIGURATION = JniMethod("getIgniteConfiguration", "(J)V", false);
             JniMethod M_PLATFORM_PROCESSOR_GET_CACHE_NAMES = JniMethod("getCacheNames", "(J)V", false);
 
@@ -361,6 +361,12 @@ namespace ignite
             JniMethod M_PLATFORM_CALLBACK_UTILS_ON_CLIENT_DISCONNECTED = JniMethod("onClientDisconnected", "(J)V", true);
             JniMethod M_PLATFORM_CALLBACK_UTILS_ON_CLIENT_RECONNECTED = JniMethod("onClientReconnected", "(JZ)V", true);
 
+            JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_INIT = JniMethod("affinityFunctionInit", "(JJLorg/apache/ignite/internal/processors/platform/cache/affinity/PlatformAffinityFunctionTarget;)J", true);
+            JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_PARTITION = JniMethod("affinityFunctionPartition", "(JJJ)I", true);
+            JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_ASSIGN_PARTITIONS = JniMethod("affinityFunctionAssignPartitions", "(JJJJ)V", true);
+            JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_REMOVE_NODE = JniMethod("affinityFunctionRemoveNode", "(JJJ)V", true);
+            JniMethod M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_DESTROY = JniMethod("affinityFunctionDestroy", "(JJ)V", true);
+
             const char* C_PLATFORM_UTILS = "org/apache/ignite/internal/processors/platform/utils/PlatformUtils";
             JniMethod M_PLATFORM_UTILS_REALLOC = JniMethod("reallocate", "(JI)V", true);
             JniMethod M_PLATFORM_UTILS_ERR_DATA = JniMethod("errorData", "(Ljava/lang/Throwable;)[B", true);
@@ -819,7 +825,7 @@ namespace ignite
 
             void RegisterNatives(JNIEnv* env) {
                 {
-					JNINativeMethod methods[54];
+					JNINativeMethod methods[59];
 
                     int idx = 0;
 
@@ -896,6 +902,12 @@ namespace ignite
                     AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_ON_CLIENT_DISCONNECTED, reinterpret_cast<void*>(JniOnClientDisconnected));
                     AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_ON_CLIENT_RECONNECTED, reinterpret_cast<void*>(JniOnClientReconnected));
 
+                    AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_INIT, reinterpret_cast<void*>(JniAffinityFunctionInit));
+                    AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_PARTITION, reinterpret_cast<void*>(JniAffinityFunctionPartition));
+                    AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_ASSIGN_PARTITIONS, reinterpret_cast<void*>(JniAffinityFunctionAssignPartitions));
+                    AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_REMOVE_NODE, reinterpret_cast<void*>(JniAffinityFunctionRemoveNode));
+                    AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_AFFINITY_FUNCTION_DESTROY, reinterpret_cast<void*>(JniAffinityFunctionDestroy));
+
                     jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx);
 
                     if (res != JNI_OK)
@@ -968,7 +980,7 @@ namespace ignite
                 int errMsgLen = 0;
 
                 try {
-                    if (!JVM.GetJvm()) 
+                    if (!JVM.GetJvm())
                     {
                         // 1. Create JVM itself.
                         jint res = CreateJvm(opts, optsLen, &jvm, &env);
@@ -2813,7 +2825,7 @@ namespace ignite
             JNIEXPORT jlong JNICALL JniExtensionCallbackInLongLongOutLong(JNIEnv *env, jclass cls, jlong envPtr, jint typ, jlong arg1, jlong arg2) {
                 IGNITE_SAFE_FUNC(env, envPtr, ExtensionCallbackInLongLongOutLongHandler, extensionCallbackInLongLongOutLong, typ, arg1, arg2);
             }
-            
+
             JNIEXPORT void JNICALL JniOnClientDisconnected(JNIEnv *env, jclass cls, jlong envPtr) {
                 IGNITE_SAFE_PROC_NO_ARG(env, envPtr, OnClientDisconnectedHandler, onClientDisconnected);
             }
@@ -2821,6 +2833,27 @@ namespace ignite
             JNIEXPORT void JNICALL JniOnClientReconnected(JNIEnv *env, jclass cls, jlong envPtr, jboolean clusterRestarted) {
                 IGNITE_SAFE_PROC(env, envPtr, OnClientReconnectedHandler, onClientReconnected, clusterRestarted);
             }
+
+            JNIEXPORT jlong JNICALL JniAffinityFunctionInit(JNIEnv *env, jclass cls, jlong envPtr, jlong memPtr, jobject baseFunc) {
+                void* baseFuncRef = baseFunc ? env->NewGlobalRef(baseFunc) : nullptr;
+                IGNITE_SAFE_FUNC(env, envPtr, AffinityFunctionInitHandler, affinityFunctionInit, memPtr, baseFuncRef);
+            }
+
+            JNIEXPORT jint JNICALL JniAffinityFunctionPartition(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong memPtr) {
+                IGNITE_SAFE_FUNC(env, envPtr, AffinityFunctionPartitionHandler, affinityFunctionPartition, ptr, memPtr);
+            }
+
+            JNIEXPORT void JNICALL JniAffinityFunctionAssignPartitions(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong inMemPtr, jlong outMemPtr) {
+                IGNITE_SAFE_PROC(env, envPtr, AffinityFunctionAssignPartitionsHandler, affinityFunctionAssignPartitions, ptr, inMemPtr, outMemPtr);
+            }
+
+            JNIEXPORT void JNICALL JniAffinityFunctionRemoveNode(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr, jlong memPtr) {
+                IGNITE_SAFE_PROC(env, envPtr, AffinityFunctionRemoveNodeHandler, affinityFunctionRemoveNode, ptr, memPtr);
+            }
+
+            JNIEXPORT void JNICALL JniAffinityFunctionDestroy(JNIEnv *env, jclass cls, jlong envPtr, jlong ptr) {
+                IGNITE_SAFE_PROC(env, envPtr, AffinityFunctionDestroyHandler, affinityFunctionDestroy, ptr);
+            }        
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 b937d28..f5eef65 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
@@ -58,6 +58,7 @@
     <Compile Include="Binary\BinarySelfTestFullFooter.cs" />
     <Compile Include="Cache\CacheAffinityFieldTest.cs" />
     <Compile Include="Cache\CacheConfigurationTest.cs" />
+    <Compile Include="Cache\Affinity\AffinityFunctionSpringTest.cs" />
     <Compile Include="Cache\CacheDynamicStartTest.cs" />
     <Compile Include="Cache\CacheNearTest.cs" />
     <Compile Include="Cache\CacheTestAsyncWrapper.cs" />
@@ -200,6 +201,12 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
       <SubType>Designer</SubType>
     </Content>
+    <Content Include="Config\Cache\Affinity\affinity-function2.xml">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="Config\Cache\Affinity\affinity-function.xml">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="Config\Cache\Store\cache-store-session.xml">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
new file mode 100644
index 0000000..7b317ac
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Affinity/AffinityFunctionSpringTest.cs
@@ -0,0 +1,184 @@
+\ufeff/*
+ * 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.
+ */
+
+// ReSharper disable UnusedAutoPropertyAccessor.Local
+// ReSharper disable UnusedMember.Local
+namespace Apache.Ignite.Core.Tests.Cache.Affinity
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using Apache.Ignite.Core.Cache;
+    using Apache.Ignite.Core.Cache.Affinity;
+    using Apache.Ignite.Core.Cache.Affinity.Fair;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Resource;
+    using NUnit.Framework;
+
+    /// <summary>
+    /// Tests AffinityFunction defined in Spring XML.
+    /// </summary>
+    public class AffinityFunctionSpringTest : IgniteTestBase
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AffinityFunctionSpringTest"/> class.
+        /// </summary>
+        public AffinityFunctionSpringTest() : base(6,
+            "config\\cache\\affinity\\affinity-function.xml",
+            "config\\cache\\affinity\\affinity-function2.xml")
+        {
+            // No-op.
+        }
+
+        /// <summary>
+        /// Tests the static cache.
+        /// </summary>
+        [Test]
+        public void TestStaticCache()
+        {
+            ValidateAffinityFunction(Grid.GetCache<long, int>("cache1"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("cache1"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("cache2"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("cache2"));
+        }
+
+        /// <summary>
+        /// Tests the dynamic cache.
+        /// </summary>
+        [Test]
+        public void TestDynamicCache()
+        {
+            ValidateAffinityFunction(Grid.CreateCache<long, int>("dyn-cache-1"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("dyn-cache-1"));
+
+            ValidateAffinityFunction(Grid2.CreateCache<long, int>("dyn-cache-2"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("dyn-cache-2"));
+
+            ValidateAffinityFunction(Grid.CreateCache<long, int>("dyn-cache2-1"));
+            ValidateAffinityFunction(Grid2.GetCache<long, int>("dyn-cache2-1"));
+
+            ValidateAffinityFunction(Grid2.CreateCache<long, int>("dyn-cache2-2"));
+            ValidateAffinityFunction(Grid.GetCache<long, int>("dyn-cache2-2"));
+        }
+
+        /// <summary>
+        /// Validates the affinity function.
+        /// </summary>
+        /// <param name="cache">The cache.</param>
+        private static void ValidateAffinityFunction(ICache<long, int> cache)
+        {
+            var aff = cache.Ignite.GetAffinity(cache.Name);
+
+            Assert.AreEqual(5, aff.Partitions);
+
+            // Predefined map
+            Assert.AreEqual(2, aff.GetPartition(1L));
+            Assert.AreEqual(1, aff.GetPartition(2L));
+
+            // Other keys
+            Assert.AreEqual(1, aff.GetPartition(13L));
+            Assert.AreEqual(3, aff.GetPartition(4L));
+        }
+
+        private class TestFunc : IAffinityFunction   // [Serializable] is not necessary
+        {
+            [InstanceResource]
+            private readonly IIgnite _ignite = null;
+
+            private int Property1 { get; set; }
+
+            private string Property2 { get; set; }
+
+            public int Partitions
+            {
+                get { return 5; }
+            }
+
+            public int GetPartition(object key)
+            {
+                Assert.IsNotNull(_ignite);
+                Assert.AreEqual(1, Property1);
+                Assert.AreEqual("1", Property2);
+
+                var longKey = (long)key;
+                int res;
+
+                if (TestFairFunc.PredefinedParts.TryGetValue(longKey, out res))
+                    return res;
+
+                return (int)(longKey * 2 % 5);
+            }
+
+            // ReSharper disable once UnusedParameter.Local
+            public void RemoveNode(Guid nodeId)
+            {
+                // No-op.
+            }
+
+            public IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
+            {
+                return Enumerable.Range(0, Partitions).Select(x => context.CurrentTopologySnapshot);
+            }
+        }
+
+        private class TestFairFunc : FairAffinityFunction   // [Serializable] is not necessary
+        {
+            public static readonly Dictionary<long, int> PredefinedParts = new Dictionary<long, int>
+            {
+                {1, 2},
+                {2, 1}
+            };
+
+            [InstanceResource]
+            private readonly IIgnite _ignite = null;
+
+            private int Property1 { get; set; }
+
+            private string Property2 { get; set; }
+
+            public override int GetPartition(object key)
+            {
+                Assert.IsNotNull(_ignite);
+                Assert.AreEqual(1, Property1);
+                Assert.AreEqual("1", Property2);
+
+                Assert.IsInstanceOf<long>(key);
+
+                var basePart = base.GetPartition(key);
+                Assert.Greater(basePart, -1);
+                Assert.Less(basePart, Partitions);
+
+                var longKey = (long) key;
+                int res;
+
+                if (PredefinedParts.TryGetValue(longKey, out res))
+                    return res;
+
+                return (int) (longKey * 2 % 5);
+            }
+
+            public override IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
+            {
+                var baseRes = base.AssignPartitions(context).ToList();  // test base call
+
+                Assert.AreEqual(Partitions, baseRes.Count);
+
+                return baseRes;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
new file mode 100644
index 0000000..67ff128
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function.xml
@@ -0,0 +1,129 @@
+\ufeff<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+    <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration">
+            <null/>
+        </property>
+
+        <property name="cacheConfiguration">
+            <list>
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="cache1"/>
+
+                    <property name="affinity">
+                        <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction">
+                            <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionSpringTest+TestFunc, Apache.Ignite.Core.Tests"/>
+                            <property name="properties">
+                                <map>
+                                    <entry key="Property1">
+                                        <value type="java.lang.Integer">1</value>
+                                    </entry>
+                                    <entry key="Property2" value="1"/>
+                                </map>
+                            </property>
+                        </bean>
+                    </property>
+                </bean>
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="dyn-cache-*"/>
+
+                    <property name="affinity">
+                        <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction">
+                            <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionSpringTest+TestFunc, Apache.Ignite.Core.Tests"/>
+                            <property name="properties">
+                                <map>
+                                    <entry key="Property1">
+                                        <value type="java.lang.Integer">1</value>
+                                    </entry>
+                                    <entry key="Property2" value="1"/>
+                                </map>
+                            </property>
+                        </bean>
+                    </property>
+                </bean>
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="cache2"/>
+
+                    <property name="affinity">
+                        <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction">
+                            <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionSpringTest+TestFairFunc, Apache.Ignite.Core.Tests"/>
+                            <property name="properties">
+                                <map>
+                                    <entry key="Property1">
+                                        <value type="java.lang.Integer">1</value>
+                                    </entry>
+                                    <entry key="Property2" value="1"/>
+                                    <entry key="Partitions">
+                                        <value type="java.lang.Integer">5</value>
+                                    </entry>
+                                </map>
+                            </property>
+                        </bean>
+                    </property>
+                </bean>
+                <bean class="org.apache.ignite.configuration.CacheConfiguration">
+                    <property name="name" value="dyn-cache2-*"/>
+
+                    <property name="affinity">
+                        <bean class="org.apache.ignite.platform.dotnet.PlatformDotNetAffinityFunction">
+                            <property name="typeName" value="Apache.Ignite.Core.Tests.Cache.Affinity.AffinityFunctionSpringTest+TestFairFunc, Apache.Ignite.Core.Tests"/>
+                            <property name="properties">
+                                <map>
+                                    <entry key="Property1">
+                                        <value type="java.lang.Integer">1</value>
+                                    </entry>
+                                    <entry key="Property2" value="1"/>
+                                    <entry key="Partitions">
+                                        <value type="java.lang.Integer">5</value>
+                                    </entry>
+                                </map>
+                            </property>
+                        </bean>
+                    </property>
+                </bean>
+            </list>
+        </property>
+
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <!-- In distributed environment, replace with actual host IP address. -->
+                                <value>127.0.0.1:47500</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+                <property name="socketTimeout" value="300" />
+            </bean>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml
new file mode 100644
index 0000000..cab34b5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Config/Cache/Affinity/affinity-function2.xml
@@ -0,0 +1,49 @@
+\ufeff<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:util="http://www.springframework.org/schema/util"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/util
+        http://www.springframework.org/schema/util/spring-util.xsd">
+    <bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+        <property name="localHost" value="127.0.0.1"/>
+        <property name="connectorConfiguration"><null/></property>
+        <property name="gridName" value="grid2" />
+
+        <property name="discoverySpi">
+            <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                <property name="ipFinder">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                        <property name="addresses">
+                            <list>
+                                <!-- In distributed environment, replace with actual host IP address. -->
+                                <value>127.0.0.1:47500</value>
+                            </list>
+                        </property>
+                    </bean>
+                </property>
+                <property name="socketTimeout" value="300" />
+            </bean>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
index 74ea846..2537445 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/TestRunner.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Core.Tests
     using System;
     using System.Diagnostics;
     using System.Reflection;
+    using Apache.Ignite.Core.Tests.Cache.Affinity;
     using Apache.Ignite.Core.Tests.Cache.Query;
     using Apache.Ignite.Core.Tests.Memory;
     using NUnit.ConsoleRunner;
@@ -34,7 +35,7 @@ namespace Apache.Ignite.Core.Tests
 
             TestOne(typeof(CacheLinqTest), "TestExcept");
 
-            //TestAll(typeof (CacheQueriesCodeConfigurationTest));
+            TestAll(typeof (AffinityFunctionSpringTest));
             //TestAllInAssembly();
         }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/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 649de2e..823f9f2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -87,13 +87,25 @@
     <Compile Include="Binary\Package-Info.cs" />
     <Compile Include="Cache\Affinity\AffinityKey.cs" />
     <Compile Include="Cache\Affinity\AffinityKeyMappedAttribute.cs" />
+    <Compile Include="Cache\Affinity\AffinityFunctionContext.cs" />
+    <Compile Include="Cache\Affinity\AffinityTopologyVersion.cs" />
+    <Compile Include="Cache\Affinity\Fair\FairAffinityFunction.cs" />
+    <Compile Include="Cache\Affinity\Fair\Package-Info.cs" />
+    <Compile Include="Cache\Affinity\IAffinityFunction.cs" />
+    <Compile Include="Cache\Affinity\Package-Info.cs" />
+    <Compile Include="Cache\Affinity\Rendezvous\Package-Info.cs" />
+    <Compile Include="Cache\Affinity\Rendezvous\RendezvousAffinityFunction.cs" />
     <Compile Include="Cache\CacheAtomicUpdateTimeoutException.cs" />
     <Compile Include="Cache\CacheEntryProcessorException.cs" />
     <Compile Include="Cache\CacheException.cs" />
     <Compile Include="Cache\CachePartialUpdateException.cs" />
     <Compile Include="Cache\CachePeekMode.cs" />
     <Compile Include="Cache\Configuration\NearCacheConfiguration.cs" />
+    <Compile Include="Cache\Configuration\Package-Info.cs" />
+    <Compile Include="Cache\Eviction\Package-Info.cs" />
     <Compile Include="Communication\ICommunicationSpi.cs" />
+    <Compile Include="Communication\Package-Info.cs" />
+    <Compile Include="Communication\Tcp\Package-Info.cs" />
     <Compile Include="Communication\Tcp\TcpCommunicationSpi.cs" />
     <Compile Include="DataStructures\Configuration\AtomicConfiguration.cs" />
     <Compile Include="Cache\Configuration\QueryAlias.cs" />
@@ -153,8 +165,12 @@
     <Compile Include="Common\IgniteGuid.cs" />
     <Compile Include="Common\Package-Info.cs" />
     <Compile Include="Impl\Binary\BinaryWriterExtensions.cs" />
+    <Compile Include="Impl\Cache\Affinity\AffinityFunctionBase.cs" />
     <Compile Include="Impl\Common\Platform.cs" />
+    <Compile Include="Impl\Cache\Affinity\AffinityFunctionSerializer.cs" />
+    <Compile Include="Impl\Cache\Affinity\PlatformAffinityFunction.cs" />
     <Compile Include="Impl\Cache\Event\JavaCacheEntryEventFilter.cs" />
+    <Compile Include="Impl\Common\ObjectInfoHolder.cs" />
     <Compile Include="Impl\Common\PlatformJavaObjectFactoryProxy.cs" />
     <Compile Include="Compute\ComputeExecutionRejectedException.cs" />
     <Compile Include="Compute\ComputeJobAdapter.cs" />

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionContext.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionContext.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionContext.cs
new file mode 100644
index 0000000..6067af4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionContext.cs
@@ -0,0 +1,120 @@
+/*
+ * 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.Affinity
+{
+    using System.Collections.Generic;
+    using System.Diagnostics;
+    using Apache.Ignite.Core.Binary;
+    using Apache.Ignite.Core.Cluster;
+    using Apache.Ignite.Core.Events;
+    using Apache.Ignite.Core.Impl;
+
+    /// <summary>
+    /// Affinity function context.
+    /// </summary>
+    public class AffinityFunctionContext
+    {
+        /** */
+        private readonly List<List<IClusterNode>> _previousAssignment;
+
+        /** */
+        private readonly int _backups;
+
+        /** */
+        private readonly ICollection<IClusterNode> _currentTopologySnapshot;
+
+        /** */
+        private readonly AffinityTopologyVersion _currentTopologyVersion;
+
+        /** */
+        private readonly DiscoveryEvent _discoveryEvent;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AffinityFunctionContext"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        internal AffinityFunctionContext(IBinaryRawReader reader)
+        {
+            Debug.Assert(reader != null);
+
+            _currentTopologySnapshot = IgniteUtils.ReadNodes(reader);
+            _backups = reader.ReadInt();
+            _currentTopologyVersion = new AffinityTopologyVersion(reader.ReadLong(), reader.ReadInt());
+            _discoveryEvent = EventReader.Read<DiscoveryEvent>(reader);
+
+            // Prev assignment
+            var cnt = reader.ReadInt();
+
+            if (cnt > 0)
+            {
+                _previousAssignment = new List<List<IClusterNode>>(cnt);
+
+                for (var i = 0; i < cnt; i++)
+                    _previousAssignment.Add(IgniteUtils.ReadNodes(reader));
+            }
+        }
+
+        /// <summary>
+        /// Gets the affinity assignment for given partition on previous topology version.
+        /// First node in returned list is a primary node, other nodes are backups.
+        /// </summary>
+        /// <param name="partition">The partition to get previous assignment for.</param>
+        /// <returns>
+        /// List of nodes assigned to a given partition on previous topology version or <code>null</code>
+        /// if this information is not available.
+        /// </returns>
+        public ICollection<IClusterNode> GetPreviousAssignment(int partition)
+        {
+            return _previousAssignment == null ? null : _previousAssignment[partition];
+        }
+
+        /// <summary>
+        /// Gets number of backups for new assignment.
+        /// </summary>
+        public int Backups
+        {
+            get { return _backups; }
+        }
+
+        /// <summary>
+        /// Gets the current topology snapshot. Snapshot will contain only nodes on which the particular
+        /// cache is configured. List of passed nodes is guaranteed to be sorted in a same order
+        /// on all nodes on which partition assignment is performed.
+        /// </summary>
+        public ICollection<IClusterNode> CurrentTopologySnapshot
+        {
+            get { return _currentTopologySnapshot; }
+        }
+
+        /// <summary>
+        /// Gets the current topology version.
+        /// </summary>
+        public AffinityTopologyVersion CurrentTopologyVersion
+        {
+            get { return _currentTopologyVersion; }
+        }
+
+        /// <summary>
+        /// Gets the discovery event that caused the topology change.
+        /// </summary>
+        public DiscoveryEvent DiscoveryEvent
+        {
+            get { return _discoveryEvent; }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityTopologyVersion.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityTopologyVersion.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityTopologyVersion.cs
new file mode 100644
index 0000000..9bfdfb4
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityTopologyVersion.cs
@@ -0,0 +1,138 @@
+/*
+ * 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.Affinity
+{
+    using System;
+    using Apache.Ignite.Core.Cluster;
+
+    /// <summary>
+    /// Affinity topology version.
+    /// </summary>
+    public struct AffinityTopologyVersion : IEquatable<AffinityTopologyVersion>
+    {
+        /** */
+        private readonly long _version;
+
+        /** */
+        private readonly int _minorVersion;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="AffinityTopologyVersion"/> struct.
+        /// </summary>
+        /// <param name="version">The version.</param>
+        /// <param name="minorVersion">The minor version.</param>
+        public AffinityTopologyVersion(long version, int minorVersion)
+        {
+            _version = version;
+            _minorVersion = minorVersion;
+        }
+
+        /// <summary>
+        /// Gets the major version, same as <see cref="ICluster.TopologyVersion"/>.
+        /// </summary>
+        public long Version
+        {
+            get { return _version; }
+        }
+
+        /// <summary>
+        /// Gets the minor version, which is increased when new caches start.
+        /// </summary>
+        public int MinorVersion
+        {
+            get { return _minorVersion; }
+        }
+
+        /// <summary>
+        /// Indicates whether the current object is equal to another object of the same type.
+        /// </summary>
+        /// <param name="other">An object to compare with this object.</param>
+        /// <returns>
+        /// true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.
+        /// </returns>
+        public bool Equals(AffinityTopologyVersion other)
+        {
+            return _version == other._version && _minorVersion == other._minorVersion;
+        }
+
+        /// <summary>
+        /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
+        /// </summary>
+        /// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
+        /// <returns>
+        /// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, 
+        /// <c>false</c>.
+        /// </returns>
+        public override bool Equals(object obj)
+        {
+            if (ReferenceEquals(null, obj)) return false;
+            return obj is AffinityTopologyVersion && Equals((AffinityTopologyVersion) obj);
+        }
+
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
+        /// </returns>
+        public override int GetHashCode()
+        {
+            unchecked
+            {
+                return (_version.GetHashCode()*397) ^ _minorVersion;
+            }
+        }
+
+        /// <summary>
+        /// Implements the operator ==.
+        /// </summary>
+        /// <param name="left">The left.</param>
+        /// <param name="right">The right.</param>
+        /// <returns>
+        /// The result of the operator.
+        /// </returns>
+        public static bool operator ==(AffinityTopologyVersion left, AffinityTopologyVersion right)
+        {
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Implements the operator !=.
+        /// </summary>
+        /// <param name="left">The left.</param>
+        /// <param name="right">The right.</param>
+        /// <returns>
+        /// The result of the operator.
+        /// </returns>
+        public static bool operator !=(AffinityTopologyVersion left, AffinityTopologyVersion right)
+        {
+            return !left.Equals(right);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="string" /> that represents this instance.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="string" /> that represents this instance.
+        /// </returns>
+        public override string ToString()
+        {
+            return string.Format("AffinityTopologyVersion [Version={0}, MinorVersion={1}]", _version, _minorVersion);
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
new file mode 100644
index 0000000..f06937d
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/FairAffinityFunction.cs
@@ -0,0 +1,33 @@
+/*
+ * 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.Affinity.Fair
+{
+    using System;
+    using Apache.Ignite.Core.Impl.Cache.Affinity;
+
+    /// <summary>
+    /// Fair affinity function which tries to ensure that all nodes get equal number of partitions with 
+    /// minimum amount of reassignments between existing nodes.
+    /// </summary>
+    [Serializable]
+    public class FairAffinityFunction : AffinityFunctionBase
+    {
+        // No-op.
+        // Actual implementation is in Java, see AffinityFunctionSerializer.Write method.
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/51add504/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs
new file mode 100644
index 0000000..29a21bd
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/Fair/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587   // invalid XML comment
+
+/// <summary>
+/// Fair affinity API.
+/// </summary>
+namespace Apache.Ignite.Core.Cache.Affinity.Fair
+{
+    // No-op.
+}


[34/46] ignite git commit: IGNITE-3414: Hadoop: implemented new weight-based map-reduce planner.

Posted by sb...@apache.org.
IGNITE-3414: Hadoop: implemented new weight-based map-reduce planner.


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

Branch: refs/heads/ignite-1232
Commit: 1dc8bcc20d89eb4172c4b1c8f718419f059c6cc2
Parents: 279de8f
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Jul 19 15:16:21 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jul 19 16:05:44 2016 +0300

----------------------------------------------------------------------
 .../processors/igfs/IgfsIgniteMock.java         | 492 +++++++++++
 .../internal/processors/igfs/IgfsMock.java      | 397 +++++++++
 .../mapreduce/IgniteHadoopMapReducePlanner.java |  48 +-
 .../IgniteHadoopWeightedMapReducePlanner.java   | 846 +++++++++++++++++++
 .../internal/processors/hadoop/HadoopUtils.java |  81 ++
 .../planner/HadoopAbstractMapReducePlanner.java | 116 +++
 .../planner/HadoopMapReducePlanGroup.java       | 150 ++++
 .../planner/HadoopMapReducePlanTopology.java    |  89 ++
 .../HadoopDefaultMapReducePlannerSelfTest.java  | 451 +---------
 .../processors/hadoop/HadoopMapReduceTest.java  | 395 ++++++++-
 .../processors/hadoop/HadoopPlannerMockJob.java | 168 ++++
 .../HadoopWeightedMapReducePlannerTest.java     | 599 +++++++++++++
 .../HadoopWeightedPlannerMapReduceTest.java     |  38 +
 .../testsuites/IgniteHadoopTestSuite.java       |   8 +-
 14 files changed, 3385 insertions(+), 493 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
new file mode 100644
index 0000000..0c55595
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
@@ -0,0 +1,492 @@
+/*
+ * 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.igfs;
+
+import org.apache.ignite.IgniteAtomicLong;
+import org.apache.ignite.IgniteAtomicReference;
+import org.apache.ignite.IgniteAtomicSequence;
+import org.apache.ignite.IgniteAtomicStamped;
+import org.apache.ignite.IgniteBinary;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCompute;
+import org.apache.ignite.IgniteCountDownLatch;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.IgniteEvents;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteFileSystem;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.IgniteMessaging;
+import org.apache.ignite.IgniteQueue;
+import org.apache.ignite.IgniteScheduler;
+import org.apache.ignite.IgniteSemaphore;
+import org.apache.ignite.IgniteServices;
+import org.apache.ignite.IgniteSet;
+import org.apache.ignite.IgniteTransactions;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cluster.ClusterGroup;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.CollectionConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.configuration.NearCacheConfiguration;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.cluster.IgniteClusterEx;
+import org.apache.ignite.internal.processors.cache.GridCacheUtilityKey;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.hadoop.Hadoop;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.lang.IgniteProductVersion;
+import org.apache.ignite.plugin.IgnitePlugin;
+import org.apache.ignite.plugin.PluginNotFoundException;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.ExecutorService;
+
+/**
+ * Mocked Ignite implementation for IGFS tests.
+ */
+public class IgfsIgniteMock implements IgniteEx {
+    /** Name. */
+    private final String name;
+
+    /** IGFS. */
+    private final IgniteFileSystem igfs;
+
+    /**
+     * Constructor.
+     *
+     * @param igfs IGFS instance.
+     */
+    public IgfsIgniteMock(@Nullable String name, IgniteFileSystem igfs) {
+        this.name = name;
+        this.igfs = igfs;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K extends GridCacheUtilityKey, V> IgniteInternalCache<K, V> utilityCache() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public <K, V> IgniteInternalCache<K, V> cachex(@Nullable String name) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public <K, V> IgniteInternalCache<K, V> cachex() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings("unchecked")
+    @Override public Collection<IgniteInternalCache<?, ?>> cachesx(
+        @Nullable IgnitePredicate<? super IgniteInternalCache<?, ?>>... p) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean eventUserRecordable(int type) {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean allEventsUserRecordable(int[] types) {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isJmxRemoteEnabled() {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isRestartEnabled() {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public IgniteFileSystem igfsx(@Nullable String name) {
+        return F.eq(name, igfs.name()) ? igfs : null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Hadoop hadoop() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteClusterEx cluster() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public String latestVersion() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ClusterNode localNode() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public GridKernalContext context() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteLogger log() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteConfiguration configuration() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCompute compute() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCompute compute(ClusterGroup grp) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteMessaging message() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteMessaging message(ClusterGroup grp) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteEvents events() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteEvents events(ClusterGroup grp) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteServices services() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteServices services(ClusterGroup grp) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ExecutorService executorService() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public ExecutorService executorService(ClusterGroup grp) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteProductVersion version() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteScheduler scheduler() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> createCache(CacheConfiguration<K, V> cacheCfg) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> createCache(String cacheName) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> getOrCreateCache(CacheConfiguration<K, V> cacheCfg) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> getOrCreateCache(String cacheName) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> void addCacheConfiguration(CacheConfiguration<K, V> cacheCfg) {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> createCache(CacheConfiguration<K, V> cacheCfg,
+        NearCacheConfiguration<K, V> nearCfg) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> getOrCreateCache(CacheConfiguration<K, V> cacheCfg,
+        NearCacheConfiguration<K, V> nearCfg) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> createNearCache(@Nullable String cacheName,
+        NearCacheConfiguration<K, V> nearCfg) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> getOrCreateNearCache(@Nullable String cacheName,
+        NearCacheConfiguration<K, V> nearCfg) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void destroyCache(String cacheName) {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteCache<K, V> cache(@Nullable String name) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<String> cacheNames() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteTransactions transactions() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K, V> IgniteDataStreamer<K, V> dataStreamer(@Nullable String cacheName) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteFileSystem fileSystem(String name) {
+        IgniteFileSystem res = igfsx(name);
+
+        if (res == null)
+            throw new IllegalArgumentException("IGFS is not configured: " + name);
+
+        return res;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgniteFileSystem> fileSystems() {
+        return Collections.singleton(igfs);
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteAtomicSequence atomicSequence(String name, long initVal, boolean create)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteAtomicLong atomicLong(String name, long initVal, boolean create) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> IgniteAtomicReference<T> atomicReference(String name, @Nullable T initVal, boolean create)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T, S> IgniteAtomicStamped<T, S> atomicStamped(String name, @Nullable T initVal,
+        @Nullable S initStamp, boolean create) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteCountDownLatch countDownLatch(String name, int cnt, boolean autoDel, boolean create)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteSemaphore semaphore(String name, int cnt, boolean failoverSafe, boolean create)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> IgniteQueue<T> queue(String name, int cap, @Nullable CollectionConfiguration cfg)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T> IgniteSet<T> set(String name, @Nullable CollectionConfiguration cfg) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T extends IgnitePlugin> T plugin(String name) throws PluginNotFoundException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteBinary binary() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void close() throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public <K> Affinity<K> affinity(String cacheName) {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /**
+     * Throw {@link UnsupportedOperationException}.
+     */
+    private static void throwUnsupported() {
+        throw new UnsupportedOperationException("Should not be called!");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
new file mode 100644
index 0000000..dccab4a
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
@@ -0,0 +1,397 @@
+/*
+ * 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.igfs;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteFileSystem;
+import org.apache.ignite.configuration.FileSystemConfiguration;
+import org.apache.ignite.igfs.IgfsBlockLocation;
+import org.apache.ignite.igfs.IgfsFile;
+import org.apache.ignite.igfs.IgfsMetrics;
+import org.apache.ignite.igfs.IgfsOutputStream;
+import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.igfs.IgfsPathSummary;
+import org.apache.ignite.igfs.mapreduce.IgfsRecordResolver;
+import org.apache.ignite.igfs.mapreduce.IgfsTask;
+import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
+import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteUuid;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Mocked IGFS implementation for IGFS tests.
+ */
+public class IgfsMock implements IgfsEx {
+    /** Name. */
+    private final String name;
+
+    /**
+     * Constructor.
+     *
+     * @param name Name.
+     */
+    public IgfsMock(@Nullable String name) {
+        this.name = name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void stop(boolean cancel) {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsContext context() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsPaths proxyPaths() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsInputStreamAdapter open(IgfsPath path, int bufSize, int seqReadsBeforePrefetch) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsInputStreamAdapter open(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsInputStreamAdapter open(IgfsPath path, int bufSize) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsStatus globalSpace() throws IgniteCheckedException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void globalSampling(@Nullable Boolean val) throws IgniteCheckedException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public Boolean globalSampling() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsLocalMetrics localMetrics() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long groupBlockSize() {
+        throwUnsupported();
+
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public String clientLogDirectory() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void clientLogDirectory(String logDir) {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean evictExclude(IgfsPath path, boolean primary) {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteUuid nextAffinityKey() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isProxy(URI path) {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsSecondaryFileSystem asSecondary() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String name() {
+        return name;
+    }
+
+    /** {@inheritDoc} */
+    @Override public FileSystemConfiguration configuration() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsPathSummary summary(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsOutputStream create(IgfsPath path, boolean overwrite) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsOutputStream create(IgfsPath path, int bufSize, boolean overwrite, int replication,
+        long blockSize, @Nullable Map<String, String> props) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsOutputStream create(IgfsPath path, int bufSize, boolean overwrite, @Nullable IgniteUuid affKey,
+        int replication, long blockSize, @Nullable Map<String, String> props) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsOutputStream append(IgfsPath path, boolean create) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsOutputStream append(IgfsPath path, int bufSize, boolean create,
+        @Nullable Map<String, String> props) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void setTimes(IgfsPath path, long accessTime, long modificationTime) throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgfsBlockLocation> affinity(IgfsPath path, long start, long len)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgfsBlockLocation> affinity(IgfsPath path, long start, long len, long maxLen)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsMetrics metrics() throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void resetMetrics() throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public long size(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void format() throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T, R> R execute(IgfsTask<T, R> task, @Nullable IgfsRecordResolver rslvr,
+        Collection<IgfsPath> paths, @Nullable T arg) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T, R> R execute(IgfsTask<T, R> task, @Nullable IgfsRecordResolver rslvr,
+        Collection<IgfsPath> paths, boolean skipNonExistentFiles, long maxRangeLen, @Nullable T arg)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T, R> R execute(Class<? extends IgfsTask<T, R>> taskCls, @Nullable IgfsRecordResolver rslvr,
+        Collection<IgfsPath> paths, @Nullable T arg) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <T, R> R execute(Class<? extends IgfsTask<T, R>> taskCls, @Nullable IgfsRecordResolver rslvr,
+        Collection<IgfsPath> paths, boolean skipNonExistentFiles, long maxRangeLen, @Nullable T arg)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean exists(IgfsPath path) {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgfsFile update(IgfsPath path, Map<String, String> props) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void rename(IgfsPath src, IgfsPath dest) throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean delete(IgfsPath path, boolean recursive) throws IgniteException {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void mkdirs(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public void mkdirs(IgfsPath path, @Nullable Map<String, String> props) throws IgniteException {
+        throwUnsupported();
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgfsPath> listPaths(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Collection<IgfsFile> listFiles(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Nullable @Override public IgfsFile info(IgfsPath path) throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long usedSpaceSize() throws IgniteException {
+        throwUnsupported();
+
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override public IgniteFileSystem withAsync() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean isAsync() {
+        throwUnsupported();
+
+        return false;
+    }
+
+    /** {@inheritDoc} */
+    @Override public <R> IgniteFuture<R> future() {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /**
+     * Throw {@link UnsupportedOperationException}.
+     */
+    private static void throwUnsupported() {
+        throw new UnsupportedOperationException("Should not be called!");
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopMapReducePlanner.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopMapReducePlanner.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopMapReducePlanner.java
index 287b5ec..d4a44fa 100644
--- a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopMapReducePlanner.java
+++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopMapReducePlanner.java
@@ -26,10 +26,9 @@ import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.UUID;
-import org.apache.ignite.Ignite;
+
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteException;
-import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.igfs.IgfsBlockLocation;
 import org.apache.ignite.igfs.IgfsPath;
@@ -38,14 +37,11 @@ import org.apache.ignite.internal.processors.hadoop.HadoopFileBlock;
 import org.apache.ignite.internal.processors.hadoop.HadoopInputSplit;
 import org.apache.ignite.internal.processors.hadoop.HadoopJob;
 import org.apache.ignite.internal.processors.hadoop.HadoopMapReducePlan;
-import org.apache.ignite.internal.processors.hadoop.HadoopMapReducePlanner;
 import org.apache.ignite.internal.processors.hadoop.igfs.HadoopIgfsEndpoint;
 import org.apache.ignite.internal.processors.hadoop.planner.HadoopDefaultMapReducePlan;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopAbstractMapReducePlanner;
 import org.apache.ignite.internal.processors.igfs.IgfsEx;
 import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.resources.IgniteInstanceResource;
-import org.apache.ignite.resources.LoggerResource;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -54,16 +50,7 @@ import static org.apache.ignite.IgniteFileSystem.IGFS_SCHEME;
 /**
  * Default map-reduce planner implementation.
  */
-public class IgniteHadoopMapReducePlanner implements HadoopMapReducePlanner {
-    /** Injected grid. */
-    @IgniteInstanceResource
-    private Ignite ignite;
-
-    /** Logger. */
-    @SuppressWarnings("UnusedDeclaration")
-    @LoggerResource
-    private IgniteLogger log;
-
+public class IgniteHadoopMapReducePlanner extends HadoopAbstractMapReducePlanner {
     /** {@inheritDoc} */
     @Override public HadoopMapReducePlan preparePlan(HadoopJob job, Collection<ClusterNode> top,
         @Nullable HadoopMapReducePlan oldPlan) throws IgniteCheckedException {
@@ -98,7 +85,7 @@ public class IgniteHadoopMapReducePlanner implements HadoopMapReducePlanner {
         Iterable<HadoopInputSplit> splits) throws IgniteCheckedException {
         Map<UUID, Collection<HadoopInputSplit>> mappers = new HashMap<>();
 
-        Map<String, Collection<UUID>> nodes = hosts(top);
+        Map<String, Collection<UUID>> nodes = groupByHost(top);
 
         Map<UUID, Integer> nodeLoads = new HashMap<>(top.size(), 1.0f); // Track node load.
 
@@ -129,33 +116,6 @@ public class IgniteHadoopMapReducePlanner implements HadoopMapReducePlanner {
     }
 
     /**
-     * Groups nodes by host names.
-     *
-     * @param top Topology to group.
-     * @return Map.
-     */
-    private static Map<String, Collection<UUID>> hosts(Collection<ClusterNode> top) {
-        Map<String, Collection<UUID>> grouped = U.newHashMap(top.size());
-
-        for (ClusterNode node : top) {
-            for (String host : node.hostNames()) {
-                Collection<UUID> nodeIds = grouped.get(host);
-
-                if (nodeIds == null) {
-                    // Expecting 1-2 nodes per host.
-                    nodeIds = new ArrayList<>(2);
-
-                    grouped.put(host, nodeIds);
-                }
-
-                nodeIds.add(node.id());
-            }
-        }
-
-        return grouped;
-    }
-
-    /**
      * Determine the best node for this split.
      *
      * @param split Split.

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopWeightedMapReducePlanner.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopWeightedMapReducePlanner.java b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopWeightedMapReducePlanner.java
new file mode 100644
index 0000000..27ffc19
--- /dev/null
+++ b/modules/hadoop/src/main/java/org/apache/ignite/hadoop/mapreduce/IgniteHadoopWeightedMapReducePlanner.java
@@ -0,0 +1,846 @@
+/*
+ * 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.hadoop.mapreduce;
+
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteFileSystem;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.igfs.IgfsBlockLocation;
+import org.apache.ignite.igfs.IgfsPath;
+import org.apache.ignite.internal.IgniteEx;
+import org.apache.ignite.internal.processors.hadoop.HadoopFileBlock;
+import org.apache.ignite.internal.processors.hadoop.HadoopInputSplit;
+import org.apache.ignite.internal.processors.hadoop.HadoopJob;
+import org.apache.ignite.internal.processors.hadoop.HadoopMapReducePlan;
+import org.apache.ignite.internal.processors.hadoop.HadoopUtils;
+import org.apache.ignite.internal.processors.hadoop.igfs.HadoopIgfsEndpoint;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopAbstractMapReducePlanner;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopDefaultMapReducePlan;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopMapReducePlanGroup;
+import org.apache.ignite.internal.processors.hadoop.planner.HadoopMapReducePlanTopology;
+import org.apache.ignite.internal.processors.igfs.IgfsEx;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * Map-reduce planner which assigns mappers and reducers based on their "weights". Weight describes how much resources
+ * are required to execute particular map or reduce task.
+ * <p>
+ * Plan creation consists of two steps: assigning mappers and assigning reducers.
+ * <p>
+ * Mappers are assigned based on input split data location. For each input split we search for nodes where
+ * its data is stored. Planner tries to assign mappers to their affinity nodes first. This process is governed by two
+ * properties:
+ * <ul>
+ *     <li><b>{@code localMapperWeight}</b> - weight of a map task when it is executed on an affinity node;</li>
+ *     <li><b>{@code remoteMapperWeight}</b> - weight of a map task when it is executed on a non-affinity node.</li>
+ * </ul>
+ * Planning algorithm assign mappers so that total resulting weight on all nodes is minimum possible.
+ * <p>
+ * Reducers are assigned differently. First we try to distribute reducers across nodes with mappers. This approach
+ * could minimize expensive data transfer over network. Reducer assigned to a node with mapper is considered
+ * <b>{@code local}</b>. Otherwise it is considered <b>{@code remote}</b>. This process continue until certain weight
+ * threshold is reached what means that current node is already too busy and it should not have higher priority over
+ * other nodes any more. Threshold can be configured using <b>{@code preferLocalReducerThresholdWeight}</b> property.
+ * <p>
+ * When local reducer threshold is reached on all nodes, we distribute remaining reducers based on their local and
+ * remote weights in the same way as it is done for mappers. This process is governed by two
+ * properties:
+ * <ul>
+ *     <li><b>{@code localReducerWeight}</b> - weight of a reduce task when it is executed on a node with mappers;</li>
+ *     <li><b>{@code remoteReducerWeight}</b> - weight of a map task when it is executed on a node without mappers.</li>
+ * </ul>
+ */
+public class IgniteHadoopWeightedMapReducePlanner extends HadoopAbstractMapReducePlanner {
+    /** Default local mapper weight. */
+    public static final int DFLT_LOC_MAPPER_WEIGHT = 100;
+
+    /** Default remote mapper weight. */
+    public static final int DFLT_RMT_MAPPER_WEIGHT = 100;
+
+    /** Default local reducer weight. */
+    public static final int DFLT_LOC_REDUCER_WEIGHT = 100;
+
+    /** Default remote reducer weight. */
+    public static final int DFLT_RMT_REDUCER_WEIGHT = 100;
+
+    /** Default reducer migration threshold weight. */
+    public static final int DFLT_PREFER_LOCAL_REDUCER_THRESHOLD_WEIGHT = 200;
+
+    /** Local mapper weight. */
+    private int locMapperWeight = DFLT_LOC_MAPPER_WEIGHT;
+
+    /** Remote mapper weight. */
+    private int rmtMapperWeight = DFLT_RMT_MAPPER_WEIGHT;
+
+    /** Local reducer weight. */
+    private int locReducerWeight = DFLT_LOC_REDUCER_WEIGHT;
+
+    /** Remote reducer weight. */
+    private int rmtReducerWeight = DFLT_RMT_REDUCER_WEIGHT;
+
+    /** Reducer migration threshold weight. */
+    private int preferLocReducerThresholdWeight = DFLT_PREFER_LOCAL_REDUCER_THRESHOLD_WEIGHT;
+
+    /** {@inheritDoc} */
+    @Override public HadoopMapReducePlan preparePlan(HadoopJob job, Collection<ClusterNode> nodes,
+        @Nullable HadoopMapReducePlan oldPlan) throws IgniteCheckedException {
+        List<HadoopInputSplit> splits = HadoopUtils.sortInputSplits(job.input());
+        int reducerCnt = job.info().reducers();
+
+        if (reducerCnt < 0)
+            throw new IgniteCheckedException("Number of reducers must be non-negative, actual: " + reducerCnt);
+
+        HadoopMapReducePlanTopology top = topology(nodes);
+
+        Mappers mappers = assignMappers(splits, top);
+
+        Map<UUID, int[]> reducers = assignReducers(splits, top, mappers, reducerCnt);
+
+        return new HadoopDefaultMapReducePlan(mappers.nodeToSplits, reducers);
+    }
+
+    /**
+     * Assign mappers to nodes.
+     *
+     * @param splits Input splits.
+     * @param top Topology.
+     * @return Mappers.
+     * @throws IgniteCheckedException If failed.
+     */
+    private Mappers assignMappers(Collection<HadoopInputSplit> splits,
+        HadoopMapReducePlanTopology top) throws IgniteCheckedException {
+        Mappers res = new Mappers();
+
+        for (HadoopInputSplit split : splits) {
+            // Try getting IGFS affinity.
+            Collection<UUID> nodeIds = affinityNodesForSplit(split, top);
+
+            // Get best node.
+            UUID node = bestMapperNode(nodeIds, top);
+
+            assert node != null;
+
+            res.add(split, node);
+        }
+
+        return res;
+    }
+
+    /**
+     * Get affinity nodes for the given input split.
+     * <p>
+     * Order in the returned collection *is* significant, meaning that nodes containing more data
+     * go first. This way, the 1st nodes in the collection considered to be preferable for scheduling.
+     *
+     * @param split Split.
+     * @param top Topology.
+     * @return Affintiy nodes.
+     * @throws IgniteCheckedException If failed.
+     */
+    private Collection<UUID> affinityNodesForSplit(HadoopInputSplit split, HadoopMapReducePlanTopology top)
+        throws IgniteCheckedException {
+        Collection<UUID> igfsNodeIds = igfsAffinityNodesForSplit(split);
+
+        if (igfsNodeIds != null)
+            return igfsNodeIds;
+
+        Map<NodeIdAndLength, UUID> res = new TreeMap<>();
+
+        for (String host : split.hosts()) {
+            long len = split instanceof HadoopFileBlock ? ((HadoopFileBlock)split).length() : 0L;
+
+            HadoopMapReducePlanGroup grp = top.groupForHost(host);
+
+            if (grp != null) {
+                for (int i = 0; i < grp.nodeCount(); i++) {
+                    UUID nodeId = grp.nodeId(i);
+
+                    res.put(new NodeIdAndLength(nodeId, len), nodeId);
+                }
+            }
+        }
+
+        return new LinkedHashSet<>(res.values());
+    }
+
+    /**
+     * Get IGFS affinity nodes for split if possible.
+     * <p>
+     * Order in the returned collection *is* significant, meaning that nodes containing more data
+     * go first. This way, the 1st nodes in the collection considered to be preferable for scheduling.
+     *
+     * @param split Input split.
+     * @return IGFS affinity or {@code null} if IGFS is not available.
+     * @throws IgniteCheckedException If failed.
+     */
+    @Nullable private Collection<UUID> igfsAffinityNodesForSplit(HadoopInputSplit split) throws IgniteCheckedException {
+        if (split instanceof HadoopFileBlock) {
+            HadoopFileBlock split0 = (HadoopFileBlock)split;
+
+            if (IgniteFileSystem.IGFS_SCHEME.equalsIgnoreCase(split0.file().getScheme())) {
+                HadoopIgfsEndpoint endpoint = new HadoopIgfsEndpoint(split0.file().getAuthority());
+
+                IgfsEx igfs = null;
+
+                if (F.eq(ignite.name(), endpoint.grid()))
+                    igfs = (IgfsEx)((IgniteEx)ignite).igfsx(endpoint.igfs());
+
+                if (igfs != null && !igfs.isProxy(split0.file())) {
+                    IgfsPath path = new IgfsPath(split0.file());
+
+                    if (igfs.exists(path)) {
+                        Collection<IgfsBlockLocation> blocks;
+
+                        try {
+                            blocks = igfs.affinity(path, split0.start(), split0.length());
+                        }
+                        catch (IgniteException e) {
+                            throw new IgniteCheckedException("Failed to get IGFS file block affinity [path=" + path +
+                                ", start=" + split0.start() + ", len=" + split0.length() + ']', e);
+                        }
+
+                        assert blocks != null;
+
+                        if (blocks.size() == 1)
+                            return blocks.iterator().next().nodeIds();
+                        else {
+                            // The most "local" nodes go first.
+                            Map<UUID, Long> idToLen = new HashMap<>();
+
+                            for (IgfsBlockLocation block : blocks) {
+                                for (UUID id : block.nodeIds()) {
+                                    Long len = idToLen.get(id);
+
+                                    idToLen.put(id, len == null ? block.length() : block.length() + len);
+                                }
+                            }
+
+                            // Sort the nodes in non-ascending order by contained data lengths.
+                            Map<NodeIdAndLength, UUID> res = new TreeMap<>();
+
+                            for (Map.Entry<UUID, Long> idToLenEntry : idToLen.entrySet()) {
+                                UUID id = idToLenEntry.getKey();
+
+                                res.put(new NodeIdAndLength(id, idToLenEntry.getValue()), id);
+                            }
+
+                            return new LinkedHashSet<>(res.values());
+                        }
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Find best mapper node.
+     *
+     * @param affIds Affinity node IDs.
+     * @param top Topology.
+     * @return Result.
+     */
+    private UUID bestMapperNode(@Nullable Collection<UUID> affIds, HadoopMapReducePlanTopology top) {
+        // Priority node.
+        UUID prioAffId = F.first(affIds);
+
+        // Find group with the least weight.
+        HadoopMapReducePlanGroup resGrp = null;
+        MapperPriority resPrio = MapperPriority.NORMAL;
+        int resWeight = Integer.MAX_VALUE;
+
+        for (HadoopMapReducePlanGroup grp : top.groups()) {
+            MapperPriority prio = groupPriority(grp, affIds, prioAffId);
+
+            int weight = grp.weight() + (prio == MapperPriority.NORMAL ? rmtMapperWeight : locMapperWeight);
+
+            if (resGrp == null || weight < resWeight || weight == resWeight && prio.value() > resPrio.value()) {
+                resGrp = grp;
+                resPrio = prio;
+                resWeight = weight;
+            }
+        }
+
+        assert resGrp != null;
+
+        // Update group weight for further runs.
+        resGrp.weight(resWeight);
+
+        // Return the best node from the group.
+        return bestMapperNodeForGroup(resGrp, resPrio, affIds, prioAffId);
+    }
+
+    /**
+     * Get best node in the group.
+     *
+     * @param grp Group.
+     * @param priority Priority.
+     * @param affIds Affinity IDs.
+     * @param prioAffId Priority affinity IDs.
+     * @return Best node ID in the group.
+     */
+    private static UUID bestMapperNodeForGroup(HadoopMapReducePlanGroup grp, MapperPriority priority,
+        @Nullable Collection<UUID> affIds, @Nullable UUID prioAffId) {
+        // Return the best node from the group.
+        int idx = 0;
+
+        // This is rare situation when several nodes are started on the same host.
+        if (!grp.single()) {
+            switch (priority) {
+                case NORMAL: {
+                    // Pick any node.
+                    idx = ThreadLocalRandom.current().nextInt(grp.nodeCount());
+
+                    break;
+                }
+                case HIGH: {
+                    // Pick any affinity node.
+                    assert affIds != null;
+
+                    List<Integer> cands = new ArrayList<>();
+
+                    for (int i = 0; i < grp.nodeCount(); i++) {
+                        UUID id = grp.nodeId(i);
+
+                        if (affIds.contains(id))
+                            cands.add(i);
+                    }
+
+                    idx = cands.get(ThreadLocalRandom.current().nextInt(cands.size()));
+
+                    break;
+                }
+                default: {
+                    // Find primary node.
+                    assert prioAffId != null;
+
+                    for (int i = 0; i < grp.nodeCount(); i++) {
+                        UUID id = grp.nodeId(i);
+
+                        if (F.eq(id, prioAffId)) {
+                            idx = i;
+
+                            break;
+                        }
+                    }
+
+                    assert priority == MapperPriority.HIGHEST;
+                }
+            }
+        }
+
+        return grp.nodeId(idx);
+    }
+
+    /**
+     * Generate reducers.
+     *
+     * @param splits Input splits.
+     * @param top Topology.
+     * @param mappers Mappers.
+     * @param reducerCnt Reducer count.
+     * @return Reducers.
+     */
+    private Map<UUID, int[]> assignReducers(Collection<HadoopInputSplit> splits, HadoopMapReducePlanTopology top,
+        Mappers mappers, int reducerCnt) {
+        Map<UUID, Integer> reducers = assignReducers0(top, splits, mappers, reducerCnt);
+
+        int cnt = 0;
+
+        Map<UUID, int[]> res = new HashMap<>(reducers.size());
+
+        for (Map.Entry<UUID, Integer> reducerEntry : reducers.entrySet()) {
+            int[] arr = new int[reducerEntry.getValue()];
+
+            for (int i = 0; i < arr.length; i++)
+                arr[i] = cnt++;
+
+            res.put(reducerEntry.getKey(), arr);
+        }
+
+        assert reducerCnt == cnt : reducerCnt + " != " + cnt;
+
+        return res;
+    }
+
+    /**
+     * Generate reducers.
+     *
+     * @param top Topology.
+     * @param splits Input splits.
+     * @param mappers Mappers.
+     * @param reducerCnt Reducer count.
+     * @return Reducers.
+     */
+    private Map<UUID, Integer> assignReducers0(HadoopMapReducePlanTopology top, Collection<HadoopInputSplit> splits,
+        Mappers mappers, int reducerCnt) {
+        Map<UUID, Integer> res = new HashMap<>();
+
+        // Assign reducers to splits.
+        Map<HadoopInputSplit, Integer> splitToReducerCnt = assignReducersToSplits(splits, reducerCnt);
+
+        // Assign as much local reducers as possible.
+        int remaining = 0;
+
+        for (Map.Entry<HadoopInputSplit, Integer> entry : splitToReducerCnt.entrySet()) {
+            HadoopInputSplit split = entry.getKey();
+            int cnt = entry.getValue();
+
+            if (cnt > 0) {
+                int assigned = assignLocalReducers(split, cnt, top, mappers, res);
+
+                assert assigned <= cnt;
+
+                remaining += cnt - assigned;
+            }
+        }
+
+        // Assign the rest reducers.
+        if (remaining > 0)
+            assignRemoteReducers(remaining, top, mappers, res);
+
+        return res;
+    }
+
+    /**
+     * Assign local split reducers.
+     *
+     * @param split Split.
+     * @param cnt Reducer count.
+     * @param top Topology.
+     * @param mappers Mappers.
+     * @param resMap Reducers result map.
+     * @return Number of locally assigned reducers.
+     */
+    private int assignLocalReducers(HadoopInputSplit split, int cnt, HadoopMapReducePlanTopology top, Mappers mappers,
+        Map<UUID, Integer> resMap) {
+        // Dereference node.
+        UUID nodeId = mappers.splitToNode.get(split);
+
+        assert nodeId != null;
+
+        // Dereference group.
+        HadoopMapReducePlanGroup grp = top.groupForId(nodeId);
+
+        assert grp != null;
+
+        // Assign more reducers to the node until threshold is reached.
+        int res = 0;
+
+        while (res < cnt && grp.weight() < preferLocReducerThresholdWeight) {
+            res++;
+
+            grp.weight(grp.weight() + locReducerWeight);
+        }
+
+        // Update result map.
+        if (res > 0) {
+            Integer reducerCnt = resMap.get(nodeId);
+
+            resMap.put(nodeId, reducerCnt == null ? res : reducerCnt + res);
+        }
+
+        return res;
+    }
+
+    /**
+     * Assign remote reducers. Assign to the least loaded first.
+     *
+     * @param cnt Count.
+     * @param top Topology.
+     * @param mappers Mappers.
+     * @param resMap Reducers result map.
+     */
+    private void assignRemoteReducers(int cnt, HadoopMapReducePlanTopology top, Mappers mappers,
+        Map<UUID, Integer> resMap) {
+
+        TreeSet<HadoopMapReducePlanGroup> set = new TreeSet<>(new GroupWeightComparator());
+
+        set.addAll(top.groups());
+
+        while (cnt-- > 0) {
+            // The least loaded machine.
+            HadoopMapReducePlanGroup grp = set.first();
+
+            // Look for nodes with assigned splits.
+            List<UUID> splitNodeIds = null;
+
+            for (int i = 0; i < grp.nodeCount(); i++) {
+                UUID nodeId = grp.nodeId(i);
+
+                if (mappers.nodeToSplits.containsKey(nodeId)) {
+                    if (splitNodeIds == null)
+                        splitNodeIds = new ArrayList<>(2);
+
+                    splitNodeIds.add(nodeId);
+                }
+            }
+
+            // Select best node.
+            UUID id;
+            int newWeight;
+
+            if (splitNodeIds != null) {
+                id = splitNodeIds.get(ThreadLocalRandom.current().nextInt(splitNodeIds.size()));
+
+                newWeight = grp.weight() + locReducerWeight;
+            }
+            else {
+                id = grp.nodeId(ThreadLocalRandom.current().nextInt(grp.nodeCount()));
+
+                newWeight = grp.weight() + rmtReducerWeight;
+            }
+
+            // Re-add entry with new weight.
+            boolean rmv = set.remove(grp);
+
+            assert rmv;
+
+            grp.weight(newWeight);
+
+            boolean add = set.add(grp);
+
+            assert add;
+
+            // Update result map.
+            Integer res = resMap.get(id);
+
+            resMap.put(id, res == null ? 1 : res + 1);
+        }
+    }
+
+    /**
+     * Comparator based on group's weight.
+     */
+    private static class GroupWeightComparator implements Comparator<HadoopMapReducePlanGroup> {
+        /** {@inheritDoc} */
+        @Override public int compare(HadoopMapReducePlanGroup first, HadoopMapReducePlanGroup second) {
+            int res = first.weight() - second.weight();
+
+            if (res < 0)
+                return -1;
+            else if (res > 0)
+                return 1;
+            else
+                return first.macs().compareTo(second.macs());
+        }
+    }
+
+    /**
+     * Distribute reducers between splits.
+     *
+     * @param splits Splits.
+     * @param reducerCnt Reducer count.
+     * @return Map from input split to reducer count.
+     */
+    private Map<HadoopInputSplit, Integer> assignReducersToSplits(Collection<HadoopInputSplit> splits,
+        int reducerCnt) {
+        Map<HadoopInputSplit, Integer> res = new IdentityHashMap<>(splits.size());
+
+        int base = reducerCnt / splits.size();
+        int remainder = reducerCnt % splits.size();
+
+        for (HadoopInputSplit split : splits) {
+            int val = base;
+
+            if (remainder > 0) {
+                val++;
+
+                remainder--;
+            }
+
+            res.put(split, val);
+        }
+
+        assert remainder == 0;
+
+        return res;
+    }
+
+    /**
+     * Calculate group priority.
+     *
+     * @param grp Group.
+     * @param affIds Affinity IDs.
+     * @param prioAffId Priority affinity ID.
+     * @return Group priority.
+     */
+    private static MapperPriority groupPriority(HadoopMapReducePlanGroup grp, @Nullable Collection<UUID> affIds,
+        @Nullable UUID prioAffId) {
+        assert F.isEmpty(affIds) ? prioAffId == null : prioAffId == F.first(affIds);
+        assert grp != null;
+
+        MapperPriority prio = MapperPriority.NORMAL;
+
+        if (!F.isEmpty(affIds)) {
+            for (int i = 0; i < grp.nodeCount(); i++) {
+                UUID id = grp.nodeId(i);
+
+                if (affIds.contains(id)) {
+                    prio = MapperPriority.HIGH;
+
+                    if (F.eq(prioAffId, id)) {
+                        prio = MapperPriority.HIGHEST;
+
+                        break;
+                    }
+                }
+            }
+        }
+
+        return prio;
+    }
+
+    /**
+     * Get local mapper weight. This weight is added to a node when a mapper is assigned and it's input split data is
+     * located on this node (at least partially).
+     * <p>
+     * Defaults to {@link #DFLT_LOC_MAPPER_WEIGHT}.
+     *
+     * @return Remote mapper weight.
+     */
+    public int getLocalMapperWeight() {
+        return locMapperWeight;
+    }
+
+    /**
+     * Set local mapper weight. See {@link #getLocalMapperWeight()} for more information.
+     *
+     * @param locMapperWeight Local mapper weight.
+     */
+    public void setLocalMapperWeight(int locMapperWeight) {
+        this.locMapperWeight = locMapperWeight;
+    }
+
+    /**
+     * Get remote mapper weight. This weight is added to a node when a mapper is assigned, but it's input
+     * split data is not located on this node.
+     * <p>
+     * Defaults to {@link #DFLT_RMT_MAPPER_WEIGHT}.
+     *
+     * @return Remote mapper weight.
+     */
+    public int getRemoteMapperWeight() {
+        return rmtMapperWeight;
+    }
+
+    /**
+     * Set remote mapper weight. See {@link #getRemoteMapperWeight()} for more information.
+     *
+     * @param rmtMapperWeight Remote mapper weight.
+     */
+    public void setRemoteMapperWeight(int rmtMapperWeight) {
+        this.rmtMapperWeight = rmtMapperWeight;
+    }
+
+    /**
+     * Get local reducer weight. This weight is added to a node when a reducer is assigned and the node have at least
+     * one assigned mapper.
+     * <p>
+     * Defaults to {@link #DFLT_LOC_REDUCER_WEIGHT}.
+     *
+     * @return Local reducer weight.
+     */
+    public int getLocalReducerWeight() {
+        return locReducerWeight;
+    }
+
+    /**
+     * Set local reducer weight. See {@link #getLocalReducerWeight()} for more information.
+     *
+     * @param locReducerWeight Local reducer weight.
+     */
+    public void setLocalReducerWeight(int locReducerWeight) {
+        this.locReducerWeight = locReducerWeight;
+    }
+
+    /**
+     * Get remote reducer weight. This weight is added to a node when a reducer is assigned, but the node doesn't have
+     * any assigned mappers.
+     * <p>
+     * Defaults to {@link #DFLT_RMT_REDUCER_WEIGHT}.
+     *
+     * @return Remote reducer weight.
+     */
+    public int getRemoteReducerWeight() {
+        return rmtReducerWeight;
+    }
+
+    /**
+     * Set remote reducer weight. See {@link #getRemoteReducerWeight()} for more information.
+     *
+     * @param rmtReducerWeight Remote reducer weight.
+     */
+    public void setRemoteReducerWeight(int rmtReducerWeight) {
+        this.rmtReducerWeight = rmtReducerWeight;
+    }
+
+    /**
+     * Get reducer migration threshold weight. When threshold is reached, a node with mappers is no longer considered
+     * as preferred for further reducer assignments.
+     * <p>
+     * Defaults to {@link #DFLT_PREFER_LOCAL_REDUCER_THRESHOLD_WEIGHT}.
+     *
+     * @return Reducer migration threshold weight.
+     */
+    public int getPreferLocalReducerThresholdWeight() {
+        return preferLocReducerThresholdWeight;
+    }
+
+    /**
+     * Set reducer migration threshold weight. See {@link #getPreferLocalReducerThresholdWeight()} for more
+     * information.
+     *
+     * @param reducerMigrationThresholdWeight Reducer migration threshold weight.
+     */
+    public void setPreferLocalReducerThresholdWeight(int reducerMigrationThresholdWeight) {
+        this.preferLocReducerThresholdWeight = reducerMigrationThresholdWeight;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(IgniteHadoopWeightedMapReducePlanner.class, this);
+    }
+
+    /**
+     * Node ID and length.
+     */
+    private static class NodeIdAndLength implements Comparable<NodeIdAndLength> {
+        /** Node ID. */
+        private final UUID id;
+
+        /** Length. */
+        private final long len;
+
+        /**
+         * Constructor.
+         *
+         * @param id Node ID.
+         * @param len Length.
+         */
+        public NodeIdAndLength(UUID id, long len) {
+            this.id = id;
+            this.len = len;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("NullableProblems")
+        @Override public int compareTo(NodeIdAndLength obj) {
+            long res = len - obj.len;
+
+            if (res > 0)
+                return -1;
+            else if (res < 0)
+                return 1;
+            else
+                return id.compareTo(obj.id);
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return id.hashCode();
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object obj) {
+            return obj instanceof NodeIdAndLength && F.eq(id, ((NodeIdAndLength)obj).id);
+        }
+    }
+
+    /**
+     * Mappers.
+     */
+    private static class Mappers {
+        /** Node-to-splits map. */
+        private final Map<UUID, Collection<HadoopInputSplit>> nodeToSplits = new HashMap<>();
+
+        /** Split-to-node map. */
+        private final Map<HadoopInputSplit, UUID> splitToNode = new IdentityHashMap<>();
+
+        /**
+         * Add mapping.
+         *
+         * @param split Split.
+         * @param node Node.
+         */
+        public void add(HadoopInputSplit split, UUID node) {
+            Collection<HadoopInputSplit> nodeSplits = nodeToSplits.get(node);
+
+            if (nodeSplits == null) {
+                nodeSplits = new HashSet<>();
+
+                nodeToSplits.put(node, nodeSplits);
+            }
+
+            nodeSplits.add(split);
+
+            splitToNode.put(split, node);
+        }
+    }
+
+    /**
+     * Mapper priority enumeration.
+     */
+    private enum MapperPriority {
+        /** Normal node. */
+        NORMAL(0),
+
+        /** (likely) Affinity node. */
+        HIGH(1),
+
+        /** (likely) Affinity node with the highest priority (e.g. because it hosts more data than other nodes). */
+        HIGHEST(2);
+
+        /** Value. */
+        private final int val;
+
+        /**
+         * Constructor.
+         *
+         * @param val Value.
+         */
+        MapperPriority(int val) {
+            this.val = val;
+        }
+
+        /**
+         * @return Value.
+         */
+        public int value() {
+            return val;
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/HadoopUtils.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/HadoopUtils.java b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/HadoopUtils.java
index 3fa963f..44d871a 100644
--- a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/HadoopUtils.java
+++ b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/HadoopUtils.java
@@ -25,8 +25,12 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutput;
 import java.io.ObjectOutputStream;
 import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.TreeSet;
 import java.util.UUID;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.Path;
@@ -352,4 +356,81 @@ public class HadoopUtils {
         }
     }
 
+    /**
+     * Sort input splits by length.
+     *
+     * @param splits Splits.
+     * @return Sorted splits.
+     */
+    public static List<HadoopInputSplit> sortInputSplits(Collection<HadoopInputSplit> splits) {
+        int id = 0;
+
+        TreeSet<SplitSortWrapper> sortedSplits = new TreeSet<>();
+
+        for (HadoopInputSplit split : splits) {
+            long len = split instanceof HadoopFileBlock ? ((HadoopFileBlock)split).length() : 0;
+
+            sortedSplits.add(new SplitSortWrapper(id++, split, len));
+        }
+
+        ArrayList<HadoopInputSplit> res = new ArrayList<>(sortedSplits.size());
+
+        for (SplitSortWrapper sortedSplit : sortedSplits)
+            res.add(sortedSplit.split);
+
+        return res;
+    }
+
+    /**
+     * Split wrapper for sorting.
+     */
+    private static class SplitSortWrapper implements Comparable<SplitSortWrapper> {
+        /** Unique ID. */
+        private final int id;
+
+        /** Split. */
+        private final HadoopInputSplit split;
+
+        /** Split length. */
+        private final long len;
+
+        /**
+         * Constructor.
+         *
+         * @param id Unique ID.
+         * @param split Split.
+         * @param len Split length.
+         */
+        public SplitSortWrapper(int id, HadoopInputSplit split, long len) {
+            this.id = id;
+            this.split = split;
+            this.len = len;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("NullableProblems")
+        @Override public int compareTo(SplitSortWrapper other) {
+            assert other != null;
+
+            long res = len - other.len;
+
+            if (res > 0)
+                return -1;
+            else if (res < 0)
+                return 1;
+            else
+                return id - other.id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public int hashCode() {
+            return id;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean equals(Object obj) {
+            return obj instanceof SplitSortWrapper && id == ((SplitSortWrapper)obj).id;
+        }
+    }
+
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopAbstractMapReducePlanner.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopAbstractMapReducePlanner.java b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopAbstractMapReducePlanner.java
new file mode 100644
index 0000000..f01f72b
--- /dev/null
+++ b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopAbstractMapReducePlanner.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.hadoop.planner;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.processors.hadoop.HadoopMapReducePlanner;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.resources.LoggerResource;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.apache.ignite.internal.IgniteNodeAttributes.ATTR_MACS;
+
+/**
+ * Base class for map-reduce planners.
+ */
+public abstract class HadoopAbstractMapReducePlanner implements HadoopMapReducePlanner {
+    /** Injected grid. */
+    @IgniteInstanceResource
+    protected Ignite ignite;
+
+    /** Logger. */
+    @SuppressWarnings("UnusedDeclaration")
+    @LoggerResource
+    protected IgniteLogger log;
+
+    /**
+     * Create plan topology.
+     *
+     * @param nodes Topology nodes.
+     * @return Plan topology.
+     */
+    protected static HadoopMapReducePlanTopology topology(Collection<ClusterNode> nodes) {
+        Map<String, HadoopMapReducePlanGroup> macsMap = new HashMap<>(nodes.size());
+
+        Map<UUID, HadoopMapReducePlanGroup> idToGrp = new HashMap<>(nodes.size());
+        Map<String, HadoopMapReducePlanGroup> hostToGrp = new HashMap<>(nodes.size());
+
+        for (ClusterNode node : nodes) {
+            String macs = node.attribute(ATTR_MACS);
+
+            HadoopMapReducePlanGroup grp = macsMap.get(macs);
+
+            if (grp == null) {
+                grp = new HadoopMapReducePlanGroup(node, macs);
+
+                macsMap.put(macs, grp);
+            }
+            else
+                grp.add(node);
+
+            idToGrp.put(node.id(), grp);
+
+            for (String host : node.addresses()) {
+                HadoopMapReducePlanGroup hostGrp = hostToGrp.get(host);
+
+                if (hostGrp == null)
+                    hostToGrp.put(host, grp);
+                else
+                    assert hostGrp == grp;
+            }
+        }
+
+        return new HadoopMapReducePlanTopology(new ArrayList<>(macsMap.values()), idToGrp, hostToGrp);
+    }
+
+
+    /**
+     * Groups nodes by host names.
+     *
+     * @param top Topology to group.
+     * @return Map.
+     */
+    protected static Map<String, Collection<UUID>> groupByHost(Collection<ClusterNode> top) {
+        Map<String, Collection<UUID>> grouped = U.newHashMap(top.size());
+
+        for (ClusterNode node : top) {
+            for (String host : node.hostNames()) {
+                Collection<UUID> nodeIds = grouped.get(host);
+
+                if (nodeIds == null) {
+                    // Expecting 1-2 nodes per host.
+                    nodeIds = new ArrayList<>(2);
+
+                    grouped.put(host, nodeIds);
+                }
+
+                nodeIds.add(node.id());
+            }
+        }
+
+        return grouped;
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanGroup.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanGroup.java b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanGroup.java
new file mode 100644
index 0000000..2fe8682
--- /dev/null
+++ b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanGroup.java
@@ -0,0 +1,150 @@
+/*
+ * 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.hadoop.planner;
+
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+
+import java.util.ArrayList;
+import java.util.UUID;
+
+/**
+ * Map-reduce plan group of nodes on a single physical machine.
+ */
+public class HadoopMapReducePlanGroup {
+    /** Node. */
+    private ClusterNode node;
+
+    /** Nodes. */
+    private ArrayList<ClusterNode> nodes;
+
+    /** MAC addresses. */
+    private final String macs;
+
+    /** Weight. */
+    private int weight;
+
+    /**
+     * Constructor.
+     *
+     * @param node First node in the group.
+     * @param macs MAC addresses.
+     */
+    public HadoopMapReducePlanGroup(ClusterNode node, String macs) {
+        assert node != null;
+        assert macs != null;
+
+        this.node = node;
+        this.macs = macs;
+    }
+
+    /**
+     * Add node to the group.
+     *
+     * @param newNode New node.
+     */
+    public void add(ClusterNode newNode) {
+        if (node != null) {
+            nodes = new ArrayList<>(2);
+
+            nodes.add(node);
+
+            node = null;
+        }
+
+        nodes.add(newNode);
+    }
+
+    /**
+     * @return MAC addresses.
+     */
+    public String macs() {
+        return macs;
+    }
+
+    /**
+     * @return {@code True} if only sinle node present.
+     */
+    public boolean single() {
+        return nodeCount() == 1;
+    }
+
+    /**
+     * Get node ID by index.
+     *
+     * @param idx Index.
+     * @return Node.
+     */
+    public UUID nodeId(int idx) {
+        ClusterNode res;
+
+        if (node != null) {
+            assert idx == 0;
+
+            res = node;
+        }
+        else {
+            assert nodes != null;
+            assert idx < nodes.size();
+
+            res = nodes.get(idx);
+        }
+
+        assert res != null;
+
+        return res.id();
+    }
+
+    /**
+     * @return Node count.
+     */
+    public int nodeCount() {
+        return node != null ? 1 : nodes.size();
+    }
+
+    /**
+     * @return weight.
+     */
+    public int weight() {
+        return weight;
+    }
+
+    /**
+     * @param weight weight.
+     */
+    public void weight(int weight) {
+        this.weight = weight;
+    }
+
+
+    /** {@inheritDoc} */
+    @Override public int hashCode() {
+        return macs.hashCode();
+    }
+
+    /** {@inheritDoc} */
+    @Override public boolean equals(Object obj) {
+        return obj instanceof HadoopMapReducePlanGroup && F.eq(macs, ((HadoopMapReducePlanGroup)obj).macs);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(HadoopMapReducePlanGroup.class, this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/1dc8bcc2/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanTopology.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanTopology.java b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanTopology.java
new file mode 100644
index 0000000..fa5c469
--- /dev/null
+++ b/modules/hadoop/src/main/java/org/apache/ignite/internal/processors/hadoop/planner/HadoopMapReducePlanTopology.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.hadoop.planner;
+
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * Map-reduce plan topology.
+ */
+public class HadoopMapReducePlanTopology {
+    /** All groups. */
+    private final List<HadoopMapReducePlanGroup> grps;
+
+    /** Node ID to group map. */
+    private final Map<UUID, HadoopMapReducePlanGroup> idToGrp;
+
+    /** Host to group map. */
+    private final Map<String, HadoopMapReducePlanGroup> hostToGrp;
+
+    /**
+     * Constructor.
+     *
+     * @param grps All groups.
+     * @param idToGrp ID to group map.
+     * @param hostToGrp Host to group map.
+     */
+    public HadoopMapReducePlanTopology(List<HadoopMapReducePlanGroup> grps,
+        Map<UUID, HadoopMapReducePlanGroup> idToGrp, Map<String, HadoopMapReducePlanGroup> hostToGrp) {
+        assert grps != null;
+        assert idToGrp != null;
+        assert hostToGrp != null;
+
+        this.grps = grps;
+        this.idToGrp = idToGrp;
+        this.hostToGrp = hostToGrp;
+    }
+
+    /**
+     * @return All groups.
+     */
+    public List<HadoopMapReducePlanGroup> groups() {
+        return grps;
+    }
+
+    /**
+     * Get group for node ID.
+     *
+     * @param id Node ID.
+     * @return Group.
+     */
+    public HadoopMapReducePlanGroup groupForId(UUID id) {
+        return idToGrp.get(id);
+    }
+
+    /**
+     * Get group for host.
+     *
+     * @param host Host.
+     * @return Group.
+     */
+    @Nullable public HadoopMapReducePlanGroup groupForHost(String host) {
+        return hostToGrp.get(host);
+    }
+
+    /** {@inheritDoc} */
+    @Override public String toString() {
+        return S.toString(HadoopMapReducePlanTopology.class, this);
+    }
+}


[36/46] ignite git commit: Merge branch 'gridgain-7.6.2'

Posted by sb...@apache.org.
Merge branch 'gridgain-7.6.2'

# Conflicts:
#	modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
#	modules/core/src/test/java/org/apache/ignite/testframework/junits/multijvm/IgniteCacheProcessProxy.java


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

Branch: refs/heads/ignite-1232
Commit: 84fddee18240776fce2466c3d58ac36cefce7e9f
Parents: 96f25ae ecc77b0
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Jul 19 17:04:50 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jul 19 17:04:50 2016 +0300

----------------------------------------------------------------------
 .../org/apache/ignite/IgniteDataStreamer.java   |   52 +-
 .../IgniteDataStreamerTimeoutException.java     |   45 +
 .../ignite/internal/binary/BinaryContext.java   |    6 +-
 .../internal/binary/BinaryObjectImpl.java       |    8 +
 .../cache/CacheEvictableEntryImpl.java          |   11 +-
 .../processors/cache/GridCacheAdapter.java      |   46 +
 .../processors/cache/GridCacheProcessor.java    |    2 +
 .../dht/GridDhtPartitionTopologyImpl.java       |    9 +-
 .../continuous/CacheContinuousQueryManager.java |    4 +-
 .../datastreamer/DataStreamerImpl.java          |   71 +-
 .../service/GridServiceProcessor.java           |   70 +-
 .../ignite/internal/util/IgniteUtils.java       |   21 +
 .../binary/BinaryMarshallerSelfTest.java        |   41 +
 .../CacheKeepBinaryIterationTest.java           |   36 +-
 ...eContinuousQueryMultiNodesFilteringTest.java |  278 +++
 ...dCacheContinuousQueryNodesFilteringTest.java |  168 ++
 .../datastreamer/DataStreamerTimeoutTest.java   |  163 ++
 .../processors/igfs/IgfsIgniteMock.java         |  501 +++++
 .../internal/processors/igfs/IgfsMock.java      |  397 ++++
 ...rviceDeploymentExceptionPropagationTest.java |   80 +
 .../multijvm/IgniteCacheProcessProxy.java       |    1 -
 .../ignite/testsuites/IgniteCacheTestSuite.java |    2 +
 .../mapreduce/IgniteHadoopMapReducePlanner.java |   48 +-
 .../IgniteHadoopWeightedMapReducePlanner.java   |  846 +++++++++
 .../internal/processors/hadoop/HadoopUtils.java |   81 +
 .../planner/HadoopAbstractMapReducePlanner.java |  116 ++
 .../planner/HadoopMapReducePlanGroup.java       |  150 ++
 .../planner/HadoopMapReducePlanTopology.java    |   89 +
 .../hadoop/HadoopAbstractMapReduceTest.java     |   15 +
 .../HadoopDefaultMapReducePlannerSelfTest.java  |  451 +----
 .../processors/hadoop/HadoopPlannerMockJob.java |  168 ++
 .../HadoopWeightedMapReducePlannerTest.java     |  599 ++++++
 .../HadoopWeightedPlannerMapReduceTest.java     |   38 +
 .../testsuites/IgniteHadoopTestSuite.java       |    8 +-
 .../IgniteCacheQuerySelfTestSuite3.java         |    4 +
 .../ignite/impl/binary/binary_id_resolver.h     |   10 +-
 .../ignite/impl/binary/binary_reader_impl.h     |   21 +-
 .../src/impl/binary/binary_reader_impl.cpp      |   14 +-
 .../src/impl/interop/interop_input_stream.cpp   |   14 +-
 modules/schema-import-db/pom.xml                |   12 +
 modules/schema-import/pom.xml                   |    8 +
 .../ignite/visor/commands/VisorConsole.scala    |    5 +-
 .../commands/alert/VisorAlertCommand.scala      |    2 +-
 .../commands/cache/VisorCacheCommand.scala      |   40 +-
 .../commands/cache/VisorCacheStopCommand.scala  |    2 +-
 .../config/VisorConfigurationCommand.scala      |   23 +-
 .../commands/events/VisorEventsCommand.scala    |   29 +-
 .../visor/commands/gc/VisorGcCommand.scala      |   11 +-
 .../visor/commands/kill/VisorKillCommand.scala  |  184 +-
 .../visor/commands/node/VisorNodeCommand.scala  |   13 +-
 .../visor/commands/vvm/VisorVvmCommand.scala    |   11 +-
 .../scala/org/apache/ignite/visor/visor.scala   |   76 +-
 modules/web-console/DEVNOTES.txt                |   29 +-
 modules/web-console/src/main/js/.gitignore      |    2 -
 .../web-console/src/main/js/app/app.config.js   |   86 +
 modules/web-console/src/main/js/app/app.js      |  274 +++
 .../main/js/app/controllers/auth.controller.js  |   30 +
 .../js/app/controllers/notebooks.controller.js  |   69 +
 .../controllers/reset-password.controller.js    |   51 +
 .../js/app/directives/auto-focus.directive.js   |   26 +
 .../directives/centered/centered.directive.js   |    2 +-
 .../directives/copy-to-clipboard.directive.js   |   29 +
 .../information/information.directive.js        |    4 +-
 .../main/js/app/directives/match.directive.js   |   27 +
 .../app/directives/on-click-focus.directive.js  |   26 +
 .../directives/on-enter-focus-move.directive.js |   29 +
 .../js/app/directives/on-enter.directive.js     |   32 +
 .../js/app/directives/on-escape.directive.js    |   32 +
 .../ui-ace-docker/ui-ace-docker.directive.js    |    4 +-
 .../ui-ace-java/ui-ace-java.directive.js        |    4 +-
 .../ui-ace-pojos/ui-ace-pojos.directive.js      |    4 +-
 .../ui-ace-pom/ui-ace-pom.directive.js          |    4 +-
 .../ui-ace-xml/ui-ace-xml.directive.js          |    4 +-
 .../js/app/filters/domainsValidation.filter.js  |   33 +
 .../src/main/js/app/helpers/jade/mixins.jade    |   26 +-
 modules/web-console/src/main/js/app/index.js    |  241 ---
 .../src/main/js/app/modules/Demo/Demo.module.js |   15 +-
 .../src/main/js/app/modules/ace.module.js       |    4 +-
 .../main/js/app/modules/agent/agent.module.js   |   10 +-
 .../js/app/modules/branding/branding.module.js  |    1 -
 .../modules/branding/header-logo.directive.js   |    4 +-
 .../branding/powered-by-apache.directive.js     |    4 +-
 .../configuration/EventGroups.provider.js       |    2 +-
 .../configuration/generator/Pom.service.js      |    2 +-
 .../js/app/modules/dialog/dialog.factory.js     |    4 +-
 .../field/bs-select-placeholder.directive.js    |    7 +-
 .../modules/form/field/dropdown.directive.js    |    9 +-
 .../js/app/modules/form/field/dropdown.jade     |    4 +-
 .../main/js/app/modules/form/field/field.css    |    2 +-
 .../app/modules/form/field/field.directive.js   |    6 +-
 .../form/field/input/checkbox.directive.js      |    9 +-
 .../form/field/input/datalist.directive.js      |    9 +-
 .../app/modules/form/field/input/datalist.jade  |    2 +-
 .../form/field/input/number.directive.js        |    9 +-
 .../modules/form/field/input/text.directive.js  |   11 +-
 .../app/modules/form/group/group.directive.js   |    4 +-
 .../app/modules/form/group/table.directive.js   |    4 +-
 .../app/modules/form/panel/revert.directive.js  |    4 +-
 .../getting-started/GettingStarted.provider.js  |    2 +-
 .../js/app/modules/loading/loading.directive.js |   10 +-
 .../js/app/modules/loading/loading.service.js   |    2 +-
 .../caches/concurrency.directive.js             |    4 +-
 .../configuration/caches/general.directive.js   |    4 +-
 .../states/configuration/caches/general.jade    |    2 +-
 .../configuration/caches/memory.directive.js    |    4 +-
 .../configuration/caches/query.directive.js     |    4 +-
 .../configuration/caches/rebalance.directive.js |    4 +-
 .../caches/server-near-cache.directive.js       |    4 +-
 .../caches/statistics.directive.js              |    4 +-
 .../configuration/caches/store.directive.js     |    4 +-
 .../states/configuration/caches/store.jade      |    4 +-
 .../configuration/clusters/atomic.directive.js  |    4 +-
 .../clusters/attributes.directive.js            |    4 +-
 .../configuration/clusters/binary.directive.js  |    4 +-
 .../clusters/collision.directive.js             |    4 +-
 .../clusters/collision/custom.directive.js      |    4 +-
 .../clusters/collision/fifo-queue.directive.js  |    4 +-
 .../collision/job-stealing.directive.js         |    4 +-
 .../collision/priority-queue.directive.js       |    4 +-
 .../clusters/communication.directive.js         |    4 +-
 .../clusters/connector.directive.js             |    4 +-
 .../clusters/deployment.directive.js            |    4 +-
 .../clusters/discovery.directive.js             |    4 +-
 .../configuration/clusters/events.directive.js  |    4 +-
 .../clusters/failover.directive.js              |    4 +-
 .../configuration/clusters/general.directive.js |    4 +-
 .../general/discovery/cloud.directive.js        |    4 +-
 .../general/discovery/google.directive.js       |    4 +-
 .../general/discovery/jdbc.directive.js         |    4 +-
 .../general/discovery/multicast.directive.js    |    4 +-
 .../clusters/general/discovery/s3.directive.js  |    4 +-
 .../general/discovery/shared.directive.js       |    4 +-
 .../clusters/general/discovery/vm.directive.js  |    4 +-
 .../clusters/general/discovery/vm.jade          |    2 +-
 .../general/discovery/zookeeper.directive.js    |    4 +-
 .../bounded-exponential-backoff.directive.js    |    4 +-
 .../zookeeper/retrypolicy/custom.directive.js   |    4 +-
 .../exponential-backoff.directive.js            |    4 +-
 .../zookeeper/retrypolicy/forever.directive.js  |    4 +-
 .../zookeeper/retrypolicy/n-times.directive.js  |    4 +-
 .../zookeeper/retrypolicy/one-time.directive.js |    4 +-
 .../retrypolicy/until-elapsed.directive.js      |    4 +-
 .../configuration/clusters/igfs.directive.js    |    4 +-
 .../configuration/clusters/logger.directive.js  |    4 +-
 .../clusters/logger/custom.directive.js         |    4 +-
 .../clusters/logger/log4j.directive.js          |    4 +-
 .../clusters/logger/log4j2.directive.js         |    4 +-
 .../clusters/marshaller.directive.js            |    4 +-
 .../configuration/clusters/metrics.directive.js |    4 +-
 .../configuration/clusters/ssl.directive.js     |    4 +-
 .../configuration/clusters/swap.directive.js    |    4 +-
 .../configuration/clusters/thread.directive.js  |    4 +-
 .../configuration/clusters/time.directive.js    |    4 +-
 .../clusters/transactions.directive.js          |    4 +-
 .../configuration/domains/general.directive.js  |    4 +-
 .../configuration/domains/query.directive.js    |    4 +-
 .../states/configuration/domains/query.jade     |   14 +-
 .../configuration/domains/store.directive.js    |    4 +-
 .../states/configuration/domains/store.jade     |    8 +-
 .../states/configuration/igfs/dual.directive.js |    4 +-
 .../modules/states/configuration/igfs/dual.jade |    4 +-
 .../igfs/fragmentizer.directive.js              |    4 +-
 .../configuration/igfs/general.directive.js     |    4 +-
 .../states/configuration/igfs/ipc.directive.js  |    4 +-
 .../states/configuration/igfs/misc.directive.js |    4 +-
 .../modules/states/configuration/igfs/misc.jade |   12 +-
 .../configuration/igfs/secondary.directive.js   |    4 +-
 .../configuration/preview-panel.directive.js    |    4 +-
 .../configuration/summary/summary.controller.js |   17 +-
 .../main/js/app/modules/states/signin.state.js  |    3 +-
 .../main/js/app/modules/user/Auth.service.js    |   10 +-
 .../main/js/app/services/ChartColors.service.js |    2 +-
 .../src/main/js/app/services/Clone.service.js   |   64 +
 .../src/main/js/app/services/Confirm.service.js |   70 +
 .../js/app/services/ConfirmBatch.service.js     |   92 +
 .../js/app/services/CopyToClipboard.service.js  |   50 +
 .../main/js/app/services/Countries.service.js   |    2 +-
 .../src/main/js/app/services/Focus.service.js   |   33 +
 .../main/js/app/services/JavaTypes.service.js   |    6 +-
 .../main/js/app/services/LegacyTable.service.js |  205 +++
 .../main/js/app/services/LegacyUtils.service.js |  948 ++++++++++
 .../main/js/app/services/Messages.service.js    |   63 +
 .../js/app/services/ModelNormalizer.service.js  |   59 +
 .../app/services/UnsavedChangesGuard.service.js |   38 +
 .../src/main/js/app/services/cleanup.service.js |   46 -
 .../src/main/js/app/services/confirm.service.js |   70 -
 modules/web-console/src/main/js/app/vendor.js   |   54 +
 .../src/main/js/build/system.config.js          |  424 -----
 .../src/main/js/controllers/admin-controller.js |   33 +-
 .../main/js/controllers/caches-controller.js    |   97 +-
 .../main/js/controllers/clusters-controller.js  |  142 +-
 .../src/main/js/controllers/common-module.js    | 1741 ------------------
 .../main/js/controllers/domains-controller.js   |  295 ++-
 .../src/main/js/controllers/igfs-controller.js  |  126 +-
 .../main/js/controllers/profile-controller.js   |   27 +-
 .../src/main/js/controllers/sql-controller.js   |   75 +-
 .../src/main/js/generator/generator-java.js     |    7 +-
 .../src/main/js/generator/generator-xml.js      |    5 +-
 .../src/main/js/gulpfile.babel.js/paths.js      |   65 +-
 .../main/js/gulpfile.babel.js/tasks/build.js    |    2 +-
 .../main/js/gulpfile.babel.js/tasks/bundle.js   |   68 +-
 .../main/js/gulpfile.babel.js/tasks/clean.js    |    5 +-
 .../main/js/gulpfile.babel.js/tasks/connect.js  |   47 -
 .../src/main/js/gulpfile.babel.js/tasks/copy.js |   32 +-
 .../main/js/gulpfile.babel.js/tasks/eslint.js   |   46 -
 .../gulpfile.babel.js/tasks/ignite-modules.js   |    9 +-
 .../src/main/js/gulpfile.babel.js/tasks/sass.js |   25 -
 .../main/js/gulpfile.babel.js/tasks/watch.js    |   20 +-
 .../main/js/gulpfile.babel.js/webpack/common.js |  192 ++
 .../webpack/environments/development.js         |   64 +
 .../webpack/environments/production.js          |   45 +
 .../main/js/gulpfile.babel.js/webpack/index.js  |   32 +
 .../webpack/plugins/progress.js                 |   82 +
 modules/web-console/src/main/js/package.json    |  301 +--
 .../stylesheets/_font-awesome-custom.scss       |   27 +-
 .../src/main/js/public/stylesheets/style.scss   |   10 +-
 modules/web-console/src/main/js/serve/agent.js  |   89 +-
 .../web-console/src/main/js/serve/keys/test.crt |   13 -
 .../web-console/src/main/js/serve/keys/test.key |   18 -
 .../src/main/js/serve/routes/agent.js           |   30 +-
 .../js/views/configuration/domains-import.jade  |    2 +-
 .../main/js/views/configuration/domains.jade    |    8 +-
 .../main/js/views/configuration/summary.jade    |    2 +-
 .../src/main/js/views/includes/header.jade      |   19 +-
 .../web-console/src/main/js/views/index.jade    |   18 -
 .../web-console/src/main/js/views/reset.jade    |    4 +-
 .../src/main/js/views/settings/profile.jade     |   16 +-
 .../web-console/src/main/js/views/signin.jade   |   52 +-
 .../src/main/js/views/sql/notebook-new.jade     |    2 +-
 .../src/main/js/views/sql/paragraph-rate.jade   |    2 +-
 .../web-console/src/main/js/views/sql/sql.jade  |    6 +-
 .../main/js/views/templates/agent-download.jade |    2 +-
 .../src/main/js/views/templates/clone.jade      |    2 +-
 parent/pom.xml                                  |    8 +-
 234 files changed, 8188 insertions(+), 4575 deletions(-)
----------------------------------------------------------------------


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

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


[08/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/build/system.config.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/build/system.config.js b/modules/web-console/src/main/js/build/system.config.js
deleted file mode 100644
index 20af865..0000000
--- a/modules/web-console/src/main/js/build/system.config.js
+++ /dev/null
@@ -1,424 +0,0 @@
-System.config({
-  defaultJSExtensions: true,
-  transpiler: "babel",
-  babelOptions: {
-    "optional": [
-      "runtime",
-      "optimisation.modules.system"
-    ]
-  },
-  paths: {
-    "github:*": "build/jspm_packages/github/*",
-    "npm:*": "build/jspm_packages/npm/*"
-  },
-  separateCSS: true,
-
-  map: {
-    "ace": "github:ajaxorg/ace-builds@1.2.3",
-    "angular": "github:angular/bower-angular@1.5.5",
-    "angular-animate": "github:angular/bower-angular-animate@1.5.5",
-    "angular-drag-and-drop-lists": "github:marceljuenemann/angular-drag-and-drop-lists@1.4.0",
-    "angular-gridster": "github:ManifestWebDesign/angular-gridster@0.13.9",
-    "angular-motion": "github:mgcrea/angular-motion@0.4.4",
-    "angular-nvd3": "github:krispo/angular-nvd3@1.0.7",
-    "angular-retina": "github:jrief/angular-retina@0.3.8",
-    "angular-sanitize": "github:angular/bower-angular-sanitize@1.5.5",
-    "angular-smart-table": "github:lorenzofox3/Smart-Table@2.1.8",
-    "angular-socket-io": "github:btford/angular-socket-io@0.7.0",
-    "angular-strap": "github:mgcrea/angular-strap@2.3.8",
-    "angular-tree-control": "github:wix/angular-tree-control@0.2.26",
-    "angular-ui-grid": "github:angular-ui/bower-ui-grid@3.1.1",
-    "angular-ui-router": "github:angular-ui/ui-router@0.2.18",
-    "angular-ui-router-metatags": "github:tinusn/ui-router-metatags@1.0.3",
-    "babel": "npm:babel-core@5.8.38",
-    "babel-runtime": "npm:babel-runtime@5.8.38",
-    "blob": "github:eligrey/Blob.js@master",
-    "bootstrap-carousel": "github:twbs/bootstrap@3.3.6",
-    "clean-css": "npm:clean-css@3.4.12",
-    "core-js": "npm:core-js@1.2.6",
-    "css": "github:systemjs/plugin-css@0.1.21",
-    "file-saver": "github:eligrey/FileSaver.js@master",
-    "font-awesome": "npm:font-awesome@4.5.0",
-    "jade": "github:johnsoftek/plugin-jade@0.6.3",
-    "jquery": "github:components/jquery@2.2.1",
-    "json": "github:systemjs/plugin-json@0.1.2",
-    "jszip": "github:Stuk/jszip@2.6.0",
-    "lodash": "github:lodash/lodash@4.13.0",
-    "pdfmake": "github:bpampuch/pdfmake@0.1.20",
-    "query-command-supported": "github:zenorocha/document.queryCommandSupported@1.0.0",
-    "socket.io-client": "github:socketio/socket.io-client@1.4.5",
-    "text": "github:systemjs/plugin-text@0.0.7",
-    "github:angular-ui/bower-ui-grid@3.1.1": {
-      "pdfmake": "github:bpampuch/pdfmake@0.1.20"
-    },
-    "github:angular-ui/ui-router@0.2.18": {
-      "angular": "github:angular/bower-angular@1.5.5"
-    },
-    "github:angular/bower-angular-animate@1.5.5": {
-      "angular": "github:angular/bower-angular@1.5.5"
-    },
-    "github:angular/bower-angular-sanitize@1.5.5": {
-      "angular": "github:angular/bower-angular@1.5.5"
-    },
-    "github:angular/bower-angular@1.5.5": {
-      "jquery": "github:components/jquery@2.2.1"
-    },
-    "github:btford/angular-socket-io@0.7.0": {
-      "socket.io-client": "github:socketio/socket.io-client@1.4.5"
-    },
-    "github:eligrey/FileSaver.js@master": {
-      "blob": "github:eligrey/Blob.js@master"
-    },
-    "github:johnsoftek/plugin-jade@0.6.3": {
-      "jade-compiler": "npm:jade@1.11.0"
-    },
-    "github:jspm/nodelibs-assert@0.1.0": {
-      "assert": "npm:assert@1.4.0"
-    },
-    "github:jspm/nodelibs-buffer@0.1.0": {
-      "buffer": "npm:buffer@3.6.0"
-    },
-    "github:jspm/nodelibs-events@0.1.1": {
-      "events": "npm:events@1.0.2"
-    },
-    "github:jspm/nodelibs-http@1.7.1": {
-      "Base64": "npm:Base64@0.2.1",
-      "events": "github:jspm/nodelibs-events@0.1.1",
-      "inherits": "npm:inherits@2.0.1",
-      "stream": "github:jspm/nodelibs-stream@0.1.0",
-      "url": "github:jspm/nodelibs-url@0.1.0",
-      "util": "github:jspm/nodelibs-util@0.1.0"
-    },
-    "github:jspm/nodelibs-https@0.1.0": {
-      "https-browserify": "npm:https-browserify@0.0.0"
-    },
-    "github:jspm/nodelibs-os@0.1.0": {
-      "os-browserify": "npm:os-browserify@0.1.2"
-    },
-    "github:jspm/nodelibs-path@0.1.0": {
-      "path-browserify": "npm:path-browserify@0.0.0"
-    },
-    "github:jspm/nodelibs-process@0.1.2": {
-      "process": "npm:process@0.11.3"
-    },
-    "github:jspm/nodelibs-stream@0.1.0": {
-      "stream-browserify": "npm:stream-browserify@1.0.0"
-    },
-    "github:jspm/nodelibs-tty@0.1.0": {
-      "tty-browserify": "npm:tty-browserify@0.0.0"
-    },
-    "github:jspm/nodelibs-url@0.1.0": {
-      "url": "npm:url@0.10.3"
-    },
-    "github:jspm/nodelibs-util@0.1.0": {
-      "util": "npm:util@0.10.3"
-    },
-    "github:jspm/nodelibs-vm@0.1.0": {
-      "vm-browserify": "npm:vm-browserify@0.0.4"
-    },
-    "github:krispo/angular-nvd3@1.0.7": {
-      "d3": "npm:d3@3.5.14",
-      "nvd3": "npm:nvd3@1.8.1"
-    },
-    "github:mgcrea/angular-motion@0.4.4": {
-      "angular": "github:angular/bower-angular@1.5.5",
-      "css": "github:systemjs/plugin-css@0.1.21"
-    },
-    "github:mgcrea/angular-strap@2.3.8": {
-      "angular": "github:angular/bower-angular@1.5.5",
-      "angular-animate": "github:angular/bower-angular-animate@1.5.5",
-      "angular-motion": "github:mgcrea/angular-motion@0.4.4",
-      "angular-sanitize": "github:angular/bower-angular-sanitize@1.5.5"
-    },
-    "github:twbs/bootstrap@3.3.6": {
-      "jquery": "npm:jquery@2.2.4"
-    },
-    "npm:acorn-globals@1.0.9": {
-      "acorn": "npm:acorn@2.7.0"
-    },
-    "npm:acorn@1.2.2": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "stream": "github:jspm/nodelibs-stream@0.1.0"
-    },
-    "npm:acorn@2.7.0": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "stream": "github:jspm/nodelibs-stream@0.1.0"
-    },
-    "npm:align-text@0.1.4": {
-      "kind-of": "npm:kind-of@3.0.3",
-      "longest": "npm:longest@1.0.1",
-      "repeat-string": "npm:repeat-string@1.5.4"
-    },
-    "npm:amdefine@1.0.0": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "module": "github:jspm/nodelibs-module@0.1.0",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:asap@1.0.0": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:assert@1.4.0": {
-      "assert": "github:jspm/nodelibs-assert@0.1.0",
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0",
-      "buffer-shims": "npm:buffer-shims@1.0.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "util": "npm:util@0.10.3"
-    },
-    "npm:async@0.2.10": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:babel-runtime@5.8.38": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:buffer-shims@1.0.0": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0"
-    },
-    "npm:buffer@3.6.0": {
-      "base64-js": "npm:base64-js@0.0.8",
-      "child_process": "github:jspm/nodelibs-child_process@0.1.0",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "ieee754": "npm:ieee754@1.1.6",
-      "isarray": "npm:isarray@1.0.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:center-align@0.1.3": {
-      "align-text": "npm:align-text@0.1.4",
-      "lazy-cache": "npm:lazy-cache@1.0.4"
-    },
-    "npm:clean-css@3.4.12": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0",
-      "commander": "npm:commander@2.8.1",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "http": "github:jspm/nodelibs-http@1.7.1",
-      "https": "github:jspm/nodelibs-https@0.1.0",
-      "os": "github:jspm/nodelibs-os@0.1.0",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "source-map": "npm:source-map@0.4.4",
-      "url": "github:jspm/nodelibs-url@0.1.0",
-      "util": "github:jspm/nodelibs-util@0.1.0"
-    },
-    "npm:cliui@2.1.0": {
-      "center-align": "npm:center-align@0.1.3",
-      "right-align": "npm:right-align@0.1.3",
-      "wordwrap": "npm:wordwrap@0.0.2"
-    },
-    "npm:commander@2.6.0": {
-      "child_process": "github:jspm/nodelibs-child_process@0.1.0",
-      "events": "github:jspm/nodelibs-events@0.1.1",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:commander@2.8.1": {
-      "child_process": "github:jspm/nodelibs-child_process@0.1.0",
-      "events": "github:jspm/nodelibs-events@0.1.1",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "graceful-readlink": "npm:graceful-readlink@1.0.1",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:constantinople@3.0.2": {
-      "acorn": "npm:acorn@2.7.0"
-    },
-    "npm:core-js@1.2.6": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "systemjs-json": "github:systemjs/plugin-json@0.1.2"
-    },
-    "npm:core-util-is@1.0.2": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0"
-    },
-    "npm:css@1.0.8": {
-      "assert": "github:jspm/nodelibs-assert@0.1.0",
-      "css-parse": "npm:css-parse@1.0.4",
-      "css-stringify": "npm:css-stringify@1.0.5",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:font-awesome@4.5.0": {
-      "css": "github:systemjs/plugin-css@0.1.21"
-    },
-    "npm:graceful-readlink@1.0.1": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2"
-    },
-    "npm:https-browserify@0.0.0": {
-      "http": "github:jspm/nodelibs-http@1.7.1"
-    },
-    "npm:inherits@2.0.1": {
-      "util": "github:jspm/nodelibs-util@0.1.0"
-    },
-    "npm:is-buffer@1.1.3": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0"
-    },
-    "npm:isarray@1.0.0": {
-      "systemjs-json": "github:systemjs/plugin-json@0.1.2"
-    },
-    "npm:jade@1.11.0": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0",
-      "character-parser": "npm:character-parser@1.2.1",
-      "clean-css": "npm:clean-css@3.4.12",
-      "commander": "npm:commander@2.6.0",
-      "constantinople": "npm:constantinople@3.0.2",
-      "jstransformer": "npm:jstransformer@0.0.2",
-      "mkdirp": "npm:mkdirp@0.5.1",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "systemjs-json": "github:systemjs/plugin-json@0.1.2",
-      "transformers": "npm:transformers@2.1.0",
-      "uglify-js": "npm:uglify-js@2.6.2",
-      "void-elements": "npm:void-elements@2.0.1",
-      "with": "npm:with@4.0.3"
-    },
-    "npm:jstransformer@0.0.2": {
-      "assert": "github:jspm/nodelibs-assert@0.1.0",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "is-promise": "npm:is-promise@2.1.0",
-      "promise": "npm:promise@6.1.0"
-    },
-    "npm:kind-of@3.0.3": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0",
-      "is-buffer": "npm:is-buffer@1.1.3"
-    },
-    "npm:lazy-cache@1.0.4": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:mkdirp@0.5.1": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "minimist": "npm:minimist@0.0.8",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:nvd3@1.8.1": {
-      "d3": "npm:d3@3.5.14"
-    },
-    "npm:optimist@0.3.7": {
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "wordwrap": "npm:wordwrap@0.0.2"
-    },
-    "npm:os-browserify@0.1.2": {
-      "os": "github:jspm/nodelibs-os@0.1.0"
-    },
-    "npm:path-browserify@0.0.0": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:process@0.11.3": {
-      "assert": "github:jspm/nodelibs-assert@0.1.0"
-    },
-    "npm:promise@2.0.0": {
-      "is-promise": "npm:is-promise@1.0.1",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:promise@6.1.0": {
-      "asap": "npm:asap@1.0.0"
-    },
-    "npm:punycode@1.3.2": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:readable-stream@1.1.14": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0",
-      "core-util-is": "npm:core-util-is@1.0.2",
-      "events": "github:jspm/nodelibs-events@0.1.1",
-      "inherits": "npm:inherits@2.0.1",
-      "isarray": "npm:isarray@0.0.1",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "stream-browserify": "npm:stream-browserify@1.0.0",
-      "string_decoder": "npm:string_decoder@0.10.31"
-    },
-    "npm:right-align@0.1.3": {
-      "align-text": "npm:align-text@0.1.4"
-    },
-    "npm:source-map@0.1.43": {
-      "amdefine": "npm:amdefine@1.0.0",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:source-map@0.4.4": {
-      "amdefine": "npm:amdefine@1.0.0",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:source-map@0.5.6": {
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:stream-browserify@1.0.0": {
-      "events": "github:jspm/nodelibs-events@0.1.1",
-      "inherits": "npm:inherits@2.0.1",
-      "readable-stream": "npm:readable-stream@1.1.14"
-    },
-    "npm:string_decoder@0.10.31": {
-      "buffer": "github:jspm/nodelibs-buffer@0.1.0"
-    },
-    "npm:transformers@2.1.0": {
-      "css": "npm:css@1.0.8",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "promise": "npm:promise@2.0.0",
-      "uglify-js": "npm:uglify-js@2.2.5",
-      "vm": "github:jspm/nodelibs-vm@0.1.0"
-    },
-    "npm:uglify-js@2.2.5": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "optimist": "npm:optimist@0.3.7",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "source-map": "npm:source-map@0.1.43",
-      "util": "github:jspm/nodelibs-util@0.1.0",
-      "vm": "github:jspm/nodelibs-vm@0.1.0"
-    },
-    "npm:uglify-js@2.6.2": {
-      "async": "npm:async@0.2.10",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "source-map": "npm:source-map@0.5.6",
-      "uglify-to-browserify": "npm:uglify-to-browserify@1.0.2",
-      "yargs": "npm:yargs@3.10.0"
-    },
-    "npm:uglify-to-browserify@1.0.2": {
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "stream": "github:jspm/nodelibs-stream@0.1.0"
-    },
-    "npm:url@0.10.3": {
-      "assert": "github:jspm/nodelibs-assert@0.1.0",
-      "punycode": "npm:punycode@1.3.2",
-      "querystring": "npm:querystring@0.2.0",
-      "util": "github:jspm/nodelibs-util@0.1.0"
-    },
-    "npm:util@0.10.3": {
-      "inherits": "npm:inherits@2.0.1",
-      "process": "github:jspm/nodelibs-process@0.1.2"
-    },
-    "npm:vm-browserify@0.0.4": {
-      "indexof": "npm:indexof@0.0.1"
-    },
-    "npm:void-elements@2.0.1": {
-      "http": "github:jspm/nodelibs-http@1.7.1"
-    },
-    "npm:window-size@0.1.0": {
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "tty": "github:jspm/nodelibs-tty@0.1.0"
-    },
-    "npm:with@4.0.3": {
-      "acorn": "npm:acorn@1.2.2",
-      "acorn-globals": "npm:acorn-globals@1.0.9"
-    },
-    "npm:yargs@3.10.0": {
-      "assert": "github:jspm/nodelibs-assert@0.1.0",
-      "camelcase": "npm:camelcase@1.2.1",
-      "cliui": "npm:cliui@2.1.0",
-      "decamelize": "npm:decamelize@1.2.0",
-      "fs": "github:jspm/nodelibs-fs@0.1.2",
-      "path": "github:jspm/nodelibs-path@0.1.0",
-      "process": "github:jspm/nodelibs-process@0.1.2",
-      "window-size": "npm:window-size@0.1.0"
-    }
-  }
-});

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/admin-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/admin-controller.js b/modules/web-console/src/main/js/controllers/admin-controller.js
index f46bab0..9e5aea7 100644
--- a/modules/web-console/src/main/js/controllers/admin-controller.js
+++ b/modules/web-console/src/main/js/controllers/admin-controller.js
@@ -16,11 +16,9 @@
  */
 
 // Controller for Admin screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('adminController', [
-    '$rootScope', '$scope', '$http', '$q', '$common', '$confirm', '$state', 'User', 'IgniteCountries',
-    ($rootScope, $scope, $http, $q, $common, $confirm, $state, User, Countries) => {
+export default ['adminController', [
+    '$rootScope', '$scope', '$http', '$q', '$state', 'IgniteMessages', 'IgniteConfirm', 'User', 'IgniteCountries',
+    ($rootScope, $scope, $http, $q, $state, Messages, Confirm, User, Countries) => {
         $scope.users = null;
 
         const _reloadUsers = () => {
@@ -35,7 +33,7 @@ consoleModule.controller('adminController', [
                             (user.company || '') + ' ' + (user.countryCode || '');
                     });
                 })
-                .catch((err) => $common.showError(err));
+                .catch(Messages.showError);
         };
 
         _reloadUsers();
@@ -48,11 +46,11 @@ consoleModule.controller('adminController', [
 
                     $state.go('base.configuration.clusters');
                 })
-                .catch((errMsg) => $common.showError($common.errorMessage(errMsg)));
+                .catch(Messages.showError);
         };
 
         $scope.removeUser = (user) => {
-            $confirm.confirm('Are you sure you want to remove user: "' + user.userName + '"?')
+            Confirm.confirm('Are you sure you want to remove user: "' + user.userName + '"?')
                 .then(() => {
                     $http.post('/api/v1/admin/remove', {userId: user._id})
                         .success(() => {
@@ -61,13 +59,13 @@ consoleModule.controller('adminController', [
                             if (i >= 0)
                                 $scope.users.splice(i, 1);
 
-                            $common.showInfo('User has been removed: "' + user.userName + '"');
+                            Messages.showInfo('User has been removed: "' + user.userName + '"');
                         })
-                        .error((errMsg, status) => {
+                        .error((err, status) => {
                             if (status === 503)
-                                $common.showInfo(errMsg);
+                                Messages.showInfo(err);
                             else
-                                $common.showError('Failed to remove user: "' + $common.errorMessage(errMsg) + '"');
+                                Messages.showError(Messages.errorMessage('Failed to remove user: ', err));
                         });
                 });
         };
@@ -82,11 +80,12 @@ consoleModule.controller('adminController', [
                 .success(() => {
                     user.admin = !user.admin;
 
-                    $common.showInfo('Admin right was successfully toggled for user: "' + user.userName + '"');
-                }).error((err) => {
-                    $common.showError('Failed to toggle admin right for user: "' + $common.errorMessage(err) + '"');
+                    Messages.showInfo('Admin right was successfully toggled for user: "' + user.userName + '"');
+                })
+                .error((err) => {
+                    Messages.showError(Messages.errorMessage('Failed to toggle admin right for user: ', err));
                 })
                 .finally(() => user.adminChanging = false);
         };
-    }]
-);
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/caches-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/caches-controller.js b/modules/web-console/src/main/js/controllers/caches-controller.js
index ac4d951..cbd681e 100644
--- a/modules/web-console/src/main/js/controllers/caches-controller.js
+++ b/modules/web-console/src/main/js/controllers/caches-controller.js
@@ -16,12 +16,10 @@
  */
 
 // Controller for Caches screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('cachesController', [
-    '$scope', '$http', '$state', '$filter', '$timeout', '$common', '$confirm', '$clone', '$loading', '$cleanup', '$unsavedChangesGuard',
-    function($scope, $http, $state, $filter, $timeout, $common, $confirm, $clone, $loading, $cleanup, $unsavedChangesGuard) {
-        $unsavedChangesGuard.install($scope);
+export default ['cachesController', [
+    '$scope', '$http', '$state', '$filter', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard',
+    function($scope, $http, $state, $filter, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard) {
+        UnsavedChangesGuard.install($scope);
 
         const emptyCache = {empty: true};
 
@@ -36,15 +34,15 @@ consoleModule.controller('cachesController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyCache;
 
-        $scope.ui = $common.formUI();
+        $scope.ui = LegacyUtils.formUI();
         $scope.ui.activePanels = [0];
         $scope.ui.topPanels = [0, 1, 2, 3];
 
-        $scope.hidePopover = $common.hidePopover;
-        $scope.saveBtnTipText = $common.saveBtnTipText;
-        $scope.widthIsSufficient = $common.widthIsSufficient;
+        $scope.hidePopover = LegacyUtils.hidePopover;
+        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
+        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
 
-        const showPopoverMessage = $common.showPopoverMessage;
+        const showPopoverMessage = LegacyUtils.showPopoverMessage;
 
         $scope.contentVisible = function() {
             const item = $scope.backupItem;
@@ -55,7 +53,7 @@ consoleModule.controller('cachesController', [
         $scope.toggleExpanded = function() {
             $scope.ui.expanded = !$scope.ui.expanded;
 
-            $common.hidePopover();
+            LegacyUtils.hidePopover();
         };
 
         $scope.caches = [];
@@ -79,7 +77,7 @@ consoleModule.controller('cachesController', [
             }, []);
         }
 
-        $loading.start('loadingCachesScreen');
+        Loading.start('loadingCachesScreen');
 
         // When landing on the page, get caches and show them.
         $http.post('/api/v1/configuration/caches/list')
@@ -131,32 +129,33 @@ consoleModule.controller('cachesController', [
                 }
 
                 $scope.$watch('ui.inputForm.$valid', function(valid) {
-                    if (valid && _.isEqual(__original_value, $cleanup($scope.backupItem)))
+                    if (valid && ModelNormalizer.isEqual(__original_value, $scope.backupItem))
                         $scope.ui.inputForm.$dirty = false;
                 });
 
                 $scope.$watch('backupItem', function(val) {
                     const form = $scope.ui.inputForm;
 
-                    if (form.$pristine || (form.$valid && _.isEqual(__original_value, $cleanup(val))))
+                    if (form.$pristine || (form.$valid && ModelNormalizer.isEqual(__original_value, val)))
                         form.$setPristine();
                     else
                         form.$setDirty();
                 }, true);
             })
-            .catch(function(errMsg) {
-                $common.showError(errMsg);
-            })
+            .catch(Messages.showError)
             .finally(function() {
                 $scope.ui.ready = true;
                 $scope.ui.inputForm.$setPristine();
-                $loading.finish('loadingCachesScreen');
+                Loading.finish('loadingCachesScreen');
             });
 
         $scope.selectItem = function(item, backup) {
             function selectItem() {
                 $scope.selectedItem = item;
 
+                if (item && !_.get(item.cacheStoreFactory.CacheJdbcBlobStoreFactory, 'connectVia'))
+                    _.set(item.cacheStoreFactory, 'CacheJdbcBlobStoreFactory.connectVia', 'DataSource');
+
                 try {
                     if (item && item._id)
                         sessionStorage.lastSelectedCache = angular.toJson(item._id);
@@ -176,13 +175,13 @@ consoleModule.controller('cachesController', [
 
                 $scope.backupItem = angular.merge({}, blank, $scope.backupItem);
 
-                __original_value = $cleanup($scope.backupItem);
+                __original_value = ModelNormalizer.normalize($scope.backupItem);
 
-                if ($common.getQueryVariable('new'))
+                if (LegacyUtils.getQueryVariable('new'))
                     $state.go('base.configuration.caches');
             }
 
-            $common.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
+            LegacyUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
         };
 
         $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
@@ -203,7 +202,7 @@ consoleModule.controller('cachesController', [
 
         // Add new cache.
         $scope.createItem = function(linkId) {
-            $timeout(() => $common.ensureActivePanel($scope.ui, 'general', 'cacheName'));
+            $timeout(() => LegacyUtils.ensureActivePanel($scope.ui, 'general', 'cacheName'));
 
             $scope.selectItem(null, prepareNewItem(linkId));
         };
@@ -229,7 +228,7 @@ consoleModule.controller('cachesController', [
             const failCluster = _.find(clusters, (cluster) => {
                 const caches = clusterCaches(cluster);
 
-                checkRes = $common.checkCachesDataSources(caches, $scope.backupItem);
+                checkRes = LegacyUtils.checkCachesDataSources(caches, $scope.backupItem);
 
                 return !checkRes.checked;
             });
@@ -238,8 +237,8 @@ consoleModule.controller('cachesController', [
                 return showPopoverMessage($scope.ui, 'store', checkRes.firstCache.cacheStoreFactory.kind === 'CacheJdbcPojoStoreFactory' ? 'pojoDialect' : 'blobDialect',
                     'Found cache "' + checkRes.secondCache.name + '" in cluster "' + failCluster.label + '" ' +
                     'with the same data source bean name "' + checkRes.firstCache.cacheStoreFactory[checkRes.firstCache.cacheStoreFactory.kind].dataSourceBean +
-                    '" and different database: "' + $common.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in current cache and "' +
-                    $common.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondCache.name + '"', 10000);
+                    '" and different database: "' + LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in current cache and "' +
+                    LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondCache.name + '"', 10000);
             }
 
             return true;
@@ -253,7 +252,7 @@ consoleModule.controller('cachesController', [
             const failCluster = _.find(clusters, (cluster) => {
                 const caches = clusterCaches(cluster);
 
-                checkRes = $common.checkCacheSQLSchemas(caches, $scope.backupItem);
+                checkRes = LegacyUtils.checkCacheSQLSchemas(caches, $scope.backupItem);
 
                 return !checkRes.checked;
             });
@@ -268,7 +267,7 @@ consoleModule.controller('cachesController', [
         }
 
         function checkStoreFactoryBean(storeFactory, beanFieldId) {
-            if (!$common.isValidJavaIdentifier('Data source bean', storeFactory.dataSourceBean, beanFieldId, $scope.ui, 'store'))
+            if (!LegacyUtils.isValidJavaIdentifier('Data source bean', storeFactory.dataSourceBean, beanFieldId, $scope.ui, 'store'))
                 return false;
 
             return checkDataSources();
@@ -302,21 +301,21 @@ consoleModule.controller('cachesController', [
 
         // Check cache logical consistency.
         function validate(item) {
-            $common.hidePopover();
+            LegacyUtils.hidePopover();
 
-            if ($common.isEmptyString(item.name))
+            if (LegacyUtils.isEmptyString(item.name))
                 return showPopoverMessage($scope.ui, 'general', 'cacheName', 'Cache name should not be empty!');
 
-            if (item.memoryMode === 'ONHEAP_TIERED' && item.offHeapMaxMemory > 0 && !$common.isDefined(item.evictionPolicy.kind))
+            if (item.memoryMode === 'ONHEAP_TIERED' && item.offHeapMaxMemory > 0 && !LegacyUtils.isDefined(item.evictionPolicy.kind))
                 return showPopoverMessage($scope.ui, 'memory', 'evictionPolicyKind', 'Eviction policy should not be configured!');
 
-            if (!$common.checkFieldValidators($scope.ui))
+            if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
             if (item.memoryMode === 'OFFHEAP_VALUES' && !_.isEmpty(item.domains))
                 return showPopoverMessage($scope.ui, 'memory', 'memoryMode', 'Query indexing could not be enabled while values are stored off-heap!');
 
-            if (item.memoryMode === 'OFFHEAP_TIERED' && (!$common.isDefined(item.offHeapMaxMemory) || item.offHeapMaxMemory < 0))
+            if (item.memoryMode === 'OFFHEAP_TIERED' && (!LegacyUtils.isDefined(item.offHeapMaxMemory) || item.offHeapMaxMemory < 0))
                 return showPopoverMessage($scope.ui, 'memory', 'offHeapMaxMemory', 'Off-heap max memory should be specified!');
 
             if (!checkSQLSchemas())
@@ -366,18 +365,16 @@ consoleModule.controller('cachesController', [
 
                     $scope.selectItem(item);
 
-                    $common.showInfo('Cache "' + item.name + '" saved.');
+                    Messages.showInfo('Cache "' + item.name + '" saved.');
                 })
-                .error(function(errMsg) {
-                    $common.showError(errMsg);
-                });
+                .error(Messages.showError);
         }
 
         // Save cache.
         $scope.saveItem = function() {
             const item = $scope.backupItem;
 
-            angular.extend(item, $common.autoCacheStoreConfiguration(item, cacheDomains(item)));
+            angular.extend(item, LegacyUtils.autoCacheStoreConfiguration(item, cacheDomains(item)));
 
             if (validate(item))
                 save(item);
@@ -392,7 +389,7 @@ consoleModule.controller('cachesController', [
         // Clone cache with new name.
         $scope.cloneItem = function() {
             if (validate($scope.backupItem)) {
-                $clone.confirm($scope.backupItem.name, _cacheNames()).then(function(newName) {
+                Clone.confirm($scope.backupItem.name, _cacheNames()).then(function(newName) {
                     const item = angular.copy($scope.backupItem);
 
                     delete item._id;
@@ -410,13 +407,13 @@ consoleModule.controller('cachesController', [
         $scope.removeItem = function() {
             const selectedItem = $scope.selectedItem;
 
-            $confirm.confirm('Are you sure you want to remove cache: "' + selectedItem.name + '"?')
+            Confirm.confirm('Are you sure you want to remove cache: "' + selectedItem.name + '"?')
                 .then(function() {
                     const _id = selectedItem._id;
 
                     $http.post('/api/v1/configuration/caches/remove', {_id})
                         .success(function() {
-                            $common.showInfo('Cache has been removed: ' + selectedItem.name);
+                            Messages.showInfo('Cache has been removed: ' + selectedItem.name);
 
                             const caches = $scope.caches;
 
@@ -438,19 +435,17 @@ consoleModule.controller('cachesController', [
                                 _.forEach($scope.domains, (domain) => _.remove(domain.meta.caches, (id) => id === _id));
                             }
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         // Remove all caches from db.
         $scope.removeAllItems = function() {
-            $confirm.confirm('Are you sure you want to remove all caches?')
+            Confirm.confirm('Are you sure you want to remove all caches?')
                 .then(function() {
                     $http.post('/api/v1/configuration/caches/remove/all')
                         .success(function() {
-                            $common.showInfo('All caches have been removed');
+                            Messages.showInfo('All caches have been removed');
 
                             $scope.caches = [];
 
@@ -460,18 +455,16 @@ consoleModule.controller('cachesController', [
                             $scope.backupItem = emptyCache;
                             $scope.ui.inputForm.$setPristine();
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         $scope.resetAll = function() {
-            $confirm.confirm('Are you sure you want to undo all changes for current cache?')
+            Confirm.confirm('Are you sure you want to undo all changes for current cache?')
                 .then(function() {
                     $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
                     $scope.ui.inputForm.$setPristine();
                 });
         };
-    }]
-);
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/clusters-controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/clusters-controller.js b/modules/web-console/src/main/js/controllers/clusters-controller.js
index 3277397..5f86d08 100644
--- a/modules/web-console/src/main/js/controllers/clusters-controller.js
+++ b/modules/web-console/src/main/js/controllers/clusters-controller.js
@@ -16,12 +16,10 @@
  */
 
 // Controller for Clusters screen.
-import consoleModule from 'controllers/common-module';
-
-consoleModule.controller('clustersController', [
-    '$rootScope', '$scope', '$http', '$state', '$timeout', '$common', '$confirm', '$clone', '$loading', '$cleanup', '$unsavedChangesGuard', 'igniteEventGroups', 'DemoInfo', '$table',
-    function($root, $scope, $http, $state, $timeout, $common, $confirm, $clone, $loading, $cleanup, $unsavedChangesGuard, igniteEventGroups, DemoInfo, $table) {
-        $unsavedChangesGuard.install($scope);
+export default ['clustersController', [
+    '$rootScope', '$scope', '$http', '$state', '$timeout', 'IgniteLegacyUtils', 'IgniteMessages', 'IgniteConfirm', 'IgniteClone', 'IgniteLoading', 'IgniteModelNormalizer', 'IgniteUnsavedChangesGuard', 'igniteEventGroups', 'DemoInfo', 'IgniteLegacyTable',
+    function($root, $scope, $http, $state, $timeout, LegacyUtils, Messages, Confirm, Clone, Loading, ModelNormalizer, UnsavedChangesGuard, igniteEventGroups, DemoInfo, LegacyTable) {
+        UnsavedChangesGuard.install($scope);
 
         const emptyCluster = {empty: true};
 
@@ -45,24 +43,24 @@ consoleModule.controller('clustersController', [
             'collision.JobStealing.stealingAttributes': {id: 'CAttribute', idPrefix: 'Key', searchCol: 'name', valueCol: 'key', dupObjName: 'name', group: 'collision'}
         };
 
-        const showPopoverMessage = $common.showPopoverMessage;
+        const showPopoverMessage = LegacyUtils.showPopoverMessage;
 
         $scope.tablePairValid = function(item, field, index) {
             const pairField = pairFields[field.model];
 
-            const pairValue = $table.tablePairValue(field, index);
+            const pairValue = LegacyTable.tablePairValue(field, index);
 
             if (pairField) {
                 const model = _.get(item, field.model);
 
-                if ($common.isDefined(model)) {
+                if (LegacyUtils.isDefined(model)) {
                     const idx = _.findIndex(model, (pair) => {
                         return pair[pairField.searchCol] === pairValue[pairField.valueCol];
                     });
 
                     // Found duplicate by key.
                     if (idx >= 0 && idx !== index)
-                        return showPopoverMessage($scope.ui, pairField.group, $table.tableFieldId(index, pairField.idPrefix + pairField.id), 'Attribute with such ' + pairField.dupObjName + ' already exists!');
+                        return showPopoverMessage($scope.ui, pairField.group, LegacyTable.tableFieldId(index, pairField.idPrefix + pairField.id), 'Attribute with such ' + pairField.dupObjName + ' already exists!');
                 }
             }
 
@@ -70,19 +68,19 @@ consoleModule.controller('clustersController', [
         };
 
         $scope.tableSave = function(field, index, stopEdit) {
-            if ($table.tablePairSaveVisible(field, index))
-                return $table.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
+            if (LegacyTable.tablePairSaveVisible(field, index))
+                return LegacyTable.tablePairSave($scope.tablePairValid, $scope.backupItem, field, index, stopEdit);
 
             return true;
         };
 
         $scope.tableReset = (trySave) => {
-            const field = $table.tableField();
+            const field = LegacyTable.tableField();
 
-            if (trySave && $common.isDefined(field) && !$scope.tableSave(field, $table.tableEditedRowIndex(), true))
+            if (trySave && LegacyUtils.isDefined(field) && !$scope.tableSave(field, LegacyTable.tableEditedRowIndex(), true))
                 return false;
 
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             return true;
         };
@@ -90,32 +88,32 @@ consoleModule.controller('clustersController', [
         $scope.tableNewItem = function(field) {
             if ($scope.tableReset(true)) {
                 if (field.type === 'failoverSpi') {
-                    if ($common.isDefined($scope.backupItem.failoverSpi))
+                    if (LegacyUtils.isDefined($scope.backupItem.failoverSpi))
                         $scope.backupItem.failoverSpi.push({});
                     else
                         $scope.backupItem.failoverSpi = {};
                 }
                 else
-                    $table.tableNewItem(field);
+                    LegacyTable.tableNewItem(field);
             }
         };
 
-        $scope.tableNewItemActive = $table.tableNewItemActive;
+        $scope.tableNewItemActive = LegacyTable.tableNewItemActive;
 
         $scope.tableStartEdit = function(item, field, index) {
             if ($scope.tableReset(true))
-                $table.tableStartEdit(item, field, index, $scope.tableSave);
+                LegacyTable.tableStartEdit(item, field, index, $scope.tableSave);
         };
 
-        $scope.tableEditing = $table.tableEditing;
+        $scope.tableEditing = LegacyTable.tableEditing;
 
         $scope.tableRemove = function(item, field, index) {
             if ($scope.tableReset(true))
-                $table.tableRemove(item, field, index);
+                LegacyTable.tableRemove(item, field, index);
         };
 
-        $scope.tablePairSave = $table.tablePairSave;
-        $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+        $scope.tablePairSave = LegacyTable.tablePairSave;
+        $scope.tablePairSaveVisible = LegacyTable.tablePairSaveVisible;
 
         $scope.attributesTbl = {
             type: 'attributes',
@@ -144,13 +142,13 @@ consoleModule.controller('clustersController', [
         // We need to initialize backupItem with empty object in order to properly used from angular directives.
         $scope.backupItem = emptyCluster;
 
-        $scope.ui = $common.formUI();
+        $scope.ui = LegacyUtils.formUI();
         $scope.ui.activePanels = [0];
         $scope.ui.topPanels = [0];
 
-        $scope.hidePopover = $common.hidePopover;
-        $scope.saveBtnTipText = $common.saveBtnTipText;
-        $scope.widthIsSufficient = $common.widthIsSufficient;
+        $scope.hidePopover = LegacyUtils.hidePopover;
+        $scope.saveBtnTipText = LegacyUtils.saveBtnTipText;
+        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
 
         $scope.contentVisible = function() {
             const item = $scope.backupItem;
@@ -161,7 +159,7 @@ consoleModule.controller('clustersController', [
         $scope.toggleExpanded = function() {
             $scope.ui.expanded = !$scope.ui.expanded;
 
-            $common.hidePopover();
+            LegacyUtils.hidePopover();
         };
 
         $scope.discoveries = [
@@ -193,7 +191,7 @@ consoleModule.controller('clustersController', [
                 $scope.selectItem($scope.clusters[0]);
         }
 
-        $loading.start('loadingClustersScreen');
+        Loading.start('loadingClustersScreen');
 
         // When landing on the page, get clusters and show them.
         $http.post('/api/v1/configuration/clusters/list')
@@ -237,14 +235,14 @@ consoleModule.controller('clustersController', [
                 }
 
                 $scope.$watch('ui.inputForm.$valid', function(valid) {
-                    if (valid && _.isEqual(__original_value, $cleanup($scope.backupItem)))
+                    if (valid && ModelNormalizer.isEqual(__original_value, $scope.backupItem))
                         $scope.ui.inputForm.$dirty = false;
                 });
 
                 $scope.$watch('backupItem', function(val) {
                     const form = $scope.ui.inputForm;
 
-                    if (form.$pristine || (form.$valid && _.isEqual(__original_value, $cleanup(val))))
+                    if (form.$pristine || (form.$valid && ModelNormalizer.isEqual(__original_value, val)))
                         form.$setPristine();
                     else
                         form.$setDirty();
@@ -256,13 +254,11 @@ consoleModule.controller('clustersController', [
                     DemoInfo.show();
                 }
             })
-            .catch(function(errMsg) {
-                $common.showError(errMsg);
-            })
+            .catch(Messages.showError)
             .finally(function() {
                 $scope.ui.ready = true;
                 $scope.ui.inputForm.$setPristine();
-                $loading.finish('loadingClustersScreen');
+                Loading.finish('loadingClustersScreen');
             });
 
         $scope.selectItem = function(item, backup) {
@@ -288,13 +284,13 @@ consoleModule.controller('clustersController', [
 
                 $scope.backupItem = angular.merge({}, blank, $scope.backupItem);
 
-                __original_value = $cleanup($scope.backupItem);
+                __original_value = ModelNormalizer.normalize($scope.backupItem);
 
-                if ($common.getQueryVariable('new'))
+                if (LegacyUtils.getQueryVariable('new'))
                     $state.go('base.configuration.clusters');
             }
 
-            $common.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
+            LegacyUtils.confirmUnsavedChanges($scope.backupItem && $scope.ui.inputForm.$dirty, selectItem);
         };
 
         $scope.linkId = () => $scope.backupItem._id ? $scope.backupItem._id : 'create';
@@ -316,7 +312,7 @@ consoleModule.controller('clustersController', [
 
         // Add new cluster.
         $scope.createItem = function(linkId) {
-            $timeout(() => $common.ensureActivePanel($scope.ui, 'general', 'clusterName'));
+            $timeout(() => LegacyUtils.ensureActivePanel($scope.ui, 'general', 'clusterName'));
 
             $scope.selectItem(null, prepareNewItem(linkId));
         };
@@ -333,14 +329,14 @@ consoleModule.controller('clustersController', [
         function checkCacheDatasources(item) {
             const caches = clusterCaches(item);
 
-            const checkRes = $common.checkCachesDataSources(caches);
+            const checkRes = LegacyUtils.checkCachesDataSources(caches);
 
             if (!checkRes.checked) {
                 return showPopoverMessage($scope.ui, 'general', 'caches',
                     'Found caches "' + checkRes.firstCache.name + '" and "' + checkRes.secondCache.name + '" ' +
                     'with the same data source bean name "' + checkRes.firstCache.cacheStoreFactory[checkRes.firstCache.cacheStoreFactory.kind].dataSourceBean +
-                    '" and different databases: "' + $common.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in "' + checkRes.firstCache.name + '" and "' +
-                    $common.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondCache.name + '"', 10000);
+                    '" and different databases: "' + LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.firstDB) + '" in "' + checkRes.firstCache.name + '" and "' +
+                    LegacyUtils.cacheStoreJdbcDialectsLabel(checkRes.secondDB) + '" in "' + checkRes.secondCache.name + '"', 10000);
             }
 
             return true;
@@ -349,7 +345,7 @@ consoleModule.controller('clustersController', [
         function checkCacheSQLSchemas(item) {
             const caches = clusterCaches(item);
 
-            const checkRes = $common.checkCacheSQLSchemas(caches);
+            const checkRes = LegacyUtils.checkCacheSQLSchemas(caches);
 
             if (!checkRes.checked) {
                 return showPopoverMessage($scope.ui, 'general', 'caches',
@@ -363,12 +359,12 @@ consoleModule.controller('clustersController', [
         function checkBinaryConfiguration(item) {
             const b = item.binaryConfiguration;
 
-            if ($common.isDefined(b)) {
+            if (LegacyUtils.isDefined(b)) {
                 if (!_.isEmpty(b.typeConfigurations)) {
                     for (let typeIx = 0; typeIx < b.typeConfigurations.length; typeIx++) {
                         const type = b.typeConfigurations[typeIx];
 
-                        if ($common.isEmptyString(type.typeName))
+                        if (LegacyUtils.isEmptyString(type.typeName))
                             return showPopoverMessage($scope.ui, 'binary', 'typeName' + typeIx, 'Type name should be specified!');
 
                         if (_.find(b.typeConfigurations, (t, ix) => ix < typeIx && t.typeName === type.typeName))
@@ -383,12 +379,12 @@ consoleModule.controller('clustersController', [
         function checkCommunicationConfiguration(item) {
             const c = item.communication;
 
-            if ($common.isDefined(c)) {
-                if ($common.isDefined(c.unacknowledgedMessagesBufferSize)) {
-                    if ($common.isDefined(c.messageQueueLimit) && c.unacknowledgedMessagesBufferSize < 5 * c.messageQueueLimit)
+            if (LegacyUtils.isDefined(c)) {
+                if (LegacyUtils.isDefined(c.unacknowledgedMessagesBufferSize)) {
+                    if (LegacyUtils.isDefined(c.messageQueueLimit) && c.unacknowledgedMessagesBufferSize < 5 * c.messageQueueLimit)
                         return showPopoverMessage($scope.ui, 'communication', 'unacknowledgedMessagesBufferSize', 'Maximum number of stored unacknowledged messages should be at least 5 * message queue limit!');
 
-                    if ($common.isDefined(c.ackSendThreshold) && c.unacknowledgedMessagesBufferSize < 5 * c.ackSendThreshold)
+                    if (LegacyUtils.isDefined(c.ackSendThreshold) && c.unacknowledgedMessagesBufferSize < 5 * c.ackSendThreshold)
                         return showPopoverMessage($scope.ui, 'communication', 'unacknowledgedMessagesBufferSize', 'Maximum number of stored unacknowledged messages should be at least 5 * ack send threshold!');
                 }
 
@@ -421,7 +417,7 @@ consoleModule.controller('clustersController', [
 
                 const sparsity = swap.maximumSparsity;
 
-                if ($common.isDefined(sparsity) && (sparsity < 0 || sparsity >= 1))
+                if (LegacyUtils.isDefined(sparsity) && (sparsity < 0 || sparsity >= 1))
                     return showPopoverMessage($scope.ui, 'swap', 'maximumSparsity', 'Maximum sparsity should be more or equal 0 and less than 1!');
 
                 const readStripesNumber = swap.readStripesNumber;
@@ -436,16 +432,16 @@ consoleModule.controller('clustersController', [
         function checkSslConfiguration(item) {
             const r = item.connector;
 
-            if ($common.isDefined(r)) {
-                if (r.sslEnabled && $common.isEmptyString(r.sslFactory))
+            if (LegacyUtils.isDefined(r)) {
+                if (r.sslEnabled && LegacyUtils.isEmptyString(r.sslFactory))
                     return showPopoverMessage($scope.ui, 'connector', 'connectorSslFactory', 'SSL factory should not be empty!');
             }
 
             if (item.sslEnabled) {
-                if (!$common.isDefined(item.sslContextFactory) || $common.isEmptyString(item.sslContextFactory.keyStoreFilePath))
+                if (!LegacyUtils.isDefined(item.sslContextFactory) || LegacyUtils.isEmptyString(item.sslContextFactory.keyStoreFilePath))
                     return showPopoverMessage($scope.ui, 'sslConfiguration', 'keyStoreFilePath', 'Key store file should not be empty!');
 
-                if ($common.isEmptyString(item.sslContextFactory.trustStoreFilePath) && _.isEmpty(item.sslContextFactory.trustManagers))
+                if (LegacyUtils.isEmptyString(item.sslContextFactory.trustStoreFilePath) && _.isEmpty(item.sslContextFactory.trustManagers))
                     return showPopoverMessage($scope.ui, 'sslConfiguration', 'sslConfiguration-title', 'Trust storage file or managers should be configured!');
             }
 
@@ -461,12 +457,12 @@ consoleModule.controller('clustersController', [
 
         // Check cluster logical consistency.
         function validate(item) {
-            $common.hidePopover();
+            LegacyUtils.hidePopover();
 
-            if ($common.isEmptyString(item.name))
+            if (LegacyUtils.isEmptyString(item.name))
                 return showPopoverMessage($scope.ui, 'general', 'clusterName', 'Cluster name should not be empty!');
 
-            if (!$common.checkFieldValidators($scope.ui))
+            if (!LegacyUtils.checkFieldValidators($scope.ui))
                 return false;
 
             if (!checkCacheSQLSchemas(item))
@@ -529,16 +525,16 @@ consoleModule.controller('clustersController', [
 
                     $scope.selectItem(item);
 
-                    $common.showInfo('Cluster "' + item.name + '" saved.');
+                    Messages.showInfo('Cluster "' + item.name + '" saved.');
                 })
-                .error((err) => $common.showError(err));
+                .error(Messages.showError);
         }
 
         // Save cluster.
         $scope.saveItem = function() {
             const item = $scope.backupItem;
 
-            const swapSpi = $common.autoClusterSwapSpiConfiguration(item, clusterCaches(item));
+            const swapSpi = LegacyUtils.autoClusterSwapSpiConfiguration(item, clusterCaches(item));
 
             if (swapSpi)
                 angular.extend(item, swapSpi);
@@ -554,7 +550,7 @@ consoleModule.controller('clustersController', [
         // Clone cluster with new name.
         $scope.cloneItem = function() {
             if (validate($scope.backupItem)) {
-                $clone.confirm($scope.backupItem.name, _clusterNames()).then(function(newName) {
+                Clone.confirm($scope.backupItem.name, _clusterNames()).then(function(newName) {
                     const item = angular.copy($scope.backupItem);
 
                     delete item._id;
@@ -569,13 +565,13 @@ consoleModule.controller('clustersController', [
         $scope.removeItem = function() {
             const selectedItem = $scope.selectedItem;
 
-            $confirm.confirm('Are you sure you want to remove cluster: "' + selectedItem.name + '"?')
+            Confirm.confirm('Are you sure you want to remove cluster: "' + selectedItem.name + '"?')
                 .then(function() {
                     const _id = selectedItem._id;
 
                     $http.post('/api/v1/configuration/clusters/remove', {_id})
                         .success(function() {
-                            $common.showInfo('Cluster has been removed: ' + selectedItem.name);
+                            Messages.showInfo('Cluster has been removed: ' + selectedItem.name);
 
                             const clusters = $scope.clusters;
 
@@ -595,19 +591,17 @@ consoleModule.controller('clustersController', [
                                 _.forEach($scope.igfss, (igfs) => _.remove(igfs.igfs.clusters, (id) => id === _id));
                             }
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         // Remove all clusters from db.
         $scope.removeAllItems = function() {
-            $confirm.confirm('Are you sure you want to remove all clusters?')
+            Confirm.confirm('Are you sure you want to remove all clusters?')
                 .then(function() {
                     $http.post('/api/v1/configuration/clusters/remove/all')
-                        .success(function() {
-                            $common.showInfo('All clusters have been removed');
+                        .success(() => {
+                            Messages.showInfo('All clusters have been removed');
 
                             $scope.clusters = [];
 
@@ -617,18 +611,16 @@ consoleModule.controller('clustersController', [
                             $scope.backupItem = emptyCluster;
                             $scope.ui.inputForm.$setPristine();
                         })
-                        .error(function(errMsg) {
-                            $common.showError(errMsg);
-                        });
+                        .error(Messages.showError);
                 });
         };
 
         $scope.resetAll = function() {
-            $confirm.confirm('Are you sure you want to undo all changes for current cluster?')
+            Confirm.confirm('Are you sure you want to undo all changes for current cluster?')
                 .then(function() {
                     $scope.backupItem = $scope.selectedItem ? angular.copy($scope.selectedItem) : prepareNewItem();
                     $scope.ui.inputForm.$setPristine();
                 });
         };
-    }]
-);
+    }
+]];


[35/46] ignite git commit: IGNITE-3414: Hadoop: implemented new weight-based map-reduce planner.

Posted by sb...@apache.org.
IGNITE-3414: Hadoop: implemented new weight-based map-reduce planner.


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

Branch: refs/heads/ignite-1232
Commit: ecc77b0180b3b16303988e1dc187b53e7b96a111
Parents: 1dc8bcc
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Tue Jul 19 16:09:06 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Tue Jul 19 16:09:06 2016 +0300

----------------------------------------------------------------------
 .../processors/igfs/IgfsIgniteMock.java         |   9 +
 .../hadoop/HadoopAbstractMapReduceTest.java     |  15 +
 .../processors/hadoop/HadoopMapReduceTest.java  | 395 +------------------
 3 files changed, 42 insertions(+), 377 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/ecc77b01/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
index 0c55595..c9f77cd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsIgniteMock.java
@@ -29,6 +29,7 @@ import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteEvents;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteFileSystem;
+import org.apache.ignite.IgniteLock;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteMessaging;
 import org.apache.ignite.IgniteQueue;
@@ -443,6 +444,14 @@ public class IgfsIgniteMock implements IgniteEx {
     }
 
     /** {@inheritDoc} */
+    @Override public IgniteLock reentrantLock(String name, boolean failoverSafe, boolean fair, boolean create)
+        throws IgniteException {
+        throwUnsupported();
+
+        return null;
+    }
+
+    /** {@inheritDoc} */
     @Override public <T> IgniteQueue<T> queue(String name, int cap, @Nullable CollectionConfiguration cfg)
         throws IgniteException {
         throwUnsupported();

http://git-wip-us.apache.org/repos/asf/ignite/blob/ecc77b01/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopAbstractMapReduceTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopAbstractMapReduceTest.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopAbstractMapReduceTest.java
index d09ec61..ef886e4 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopAbstractMapReduceTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopAbstractMapReduceTest.java
@@ -37,6 +37,7 @@ import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.cache.CacheWriteSynchronizationMode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.FileSystemConfiguration;
+import org.apache.ignite.configuration.HadoopConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
 import org.apache.ignite.hadoop.fs.IgniteHadoopFileSystemCounterWriter;
 import org.apache.ignite.hadoop.fs.IgniteHadoopIgfsSecondaryFileSystem;
@@ -389,9 +390,23 @@ public class HadoopAbstractMapReduceTest extends HadoopAbstractWordCountTest {
         cfg.setLocalHost("127.0.0.1");
         cfg.setConnectorConfiguration(null);
 
+        HadoopConfiguration hadoopCfg = createHadoopConfiguration();
+
+        if (hadoopCfg != null)
+            cfg.setHadoopConfiguration(hadoopCfg);
+
         return G.start(cfg);
     }
 
+    /**
+     * Creates custom Hadoop configuration.
+     *
+     * @return The Hadoop configuration.
+     */
+    protected HadoopConfiguration createHadoopConfiguration() {
+        return null;
+    }
+
     /** {@inheritDoc} */
     @Override public FileSystemConfiguration igfsConfiguration() throws Exception {
         FileSystemConfiguration fsCfg = super.igfsConfiguration();

http://git-wip-us.apache.org/repos/asf/ignite/blob/ecc77b01/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
----------------------------------------------------------------------
diff --git a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
index 5d1de38..b703896 100644
--- a/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
+++ b/modules/hadoop/src/test/java/org/apache/ignite/internal/processors/hadoop/HadoopMapReduceTest.java
@@ -17,130 +17,13 @@
 
 package org.apache.ignite.internal.processors.hadoop;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.UUID;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.io.IntWritable;
-import org.apache.hadoop.io.Text;
-import org.apache.hadoop.mapred.JobConf;
-import org.apache.hadoop.mapreduce.Job;
-import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
-import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
-import org.apache.ignite.Ignite;
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.cache.CacheWriteSynchronizationMode;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.FileSystemConfiguration;
-import org.apache.ignite.configuration.HadoopConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.hadoop.fs.IgniteHadoopFileSystemCounterWriter;
-import org.apache.ignite.hadoop.fs.IgniteHadoopIgfsSecondaryFileSystem;
-import org.apache.ignite.igfs.IgfsGroupDataBlocksKeyMapper;
-import org.apache.ignite.igfs.IgfsIpcEndpointConfiguration;
-import org.apache.ignite.igfs.IgfsMode;
 import org.apache.ignite.igfs.IgfsPath;
-import org.apache.ignite.igfs.IgfsUserContext;
-import org.apache.ignite.igfs.secondary.IgfsSecondaryFileSystem;
-import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.processors.hadoop.counter.HadoopCounters;
-import org.apache.ignite.internal.processors.hadoop.counter.HadoopPerformanceCounter;
-import org.apache.ignite.internal.processors.hadoop.examples.HadoopWordCount1;
 import org.apache.ignite.internal.processors.hadoop.examples.HadoopWordCount2;
-import org.apache.ignite.internal.processors.igfs.IgfsEx;
-import org.apache.ignite.internal.processors.igfs.IgfsUtils;
-import org.apache.ignite.internal.util.lang.GridAbsPredicate;
-import org.apache.ignite.internal.util.typedef.G;
-import org.apache.ignite.internal.util.typedef.T2;
-import org.apache.ignite.lang.IgniteOutClosure;
-import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import org.apache.ignite.testframework.GridTestUtils;
-import org.jetbrains.annotations.Nullable;
-
-import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
-import static org.apache.ignite.cache.CacheMode.PARTITIONED;
-import static org.apache.ignite.cache.CacheMode.REPLICATED;
-import static org.apache.ignite.igfs.IgfsMode.PRIMARY;
-import static org.apache.ignite.internal.processors.hadoop.HadoopUtils.JOB_COUNTER_WRITER_PROPERTY;
-import static org.apache.ignite.internal.processors.hadoop.HadoopUtils.createJobInfo;
 
 /**
  * Test of whole cycle of map-reduce processing via Job tracker.
  */
-public class HadoopMapReduceTest extends HadoopAbstractWordCountTest {
-    /** IGFS block size. */
-    protected static final int IGFS_BLOCK_SIZE = 512 * 1024;
-
-    /** Amount of blocks to prefetch. */
-    protected static final int PREFETCH_BLOCKS = 1;
-
-    /** Amount of sequential block reads before prefetch is triggered. */
-    protected static final int SEQ_READS_BEFORE_PREFETCH = 2;
-
-    /** Secondary file system URI. */
-    protected static final String SECONDARY_URI = "igfs://igfs-secondary:grid-secondary@127.0.0.1:11500/";
-
-    /** Secondary file system configuration path. */
-    protected static final String SECONDARY_CFG = "modules/core/src/test/config/hadoop/core-site-loopback-secondary.xml";
-
-    /** The user to run Hadoop job on behalf of. */
-    protected static final String USER = "vasya";
-
-    /** Secondary IGFS name. */
-    protected static final String SECONDARY_IGFS_NAME = "igfs-secondary";
-
-    /** The secondary Ignite node. */
-    protected Ignite igniteSecondary;
-
-    /** The secondary Fs. */
-    protected IgfsSecondaryFileSystem secondaryFs;
-
-    /** {@inheritDoc} */
-    @Override protected int gridCount() {
-        return 3;
-    }
-
-    /**
-     * Gets owner of a IgfsEx path.
-     * @param p The path.
-     * @return The owner.
-     */
-    private static String getOwner(IgfsEx i, IgfsPath p) {
-        return i.info(p).property(IgfsUtils.PROP_USER_NAME);
-    }
-
-    /**
-     * Gets owner of a secondary Fs path.
-     * @param secFs The sec Fs.
-     * @param p The path.
-     * @return The owner.
-     */
-    private static String getOwnerSecondary(final IgfsSecondaryFileSystem secFs, final IgfsPath p) {
-        return IgfsUserContext.doAs(USER, new IgniteOutClosure<String>() {
-            @Override public String apply() {
-                return secFs.info(p).property(IgfsUtils.PROP_USER_NAME);
-            }
-        });
-    }
-
-    /**
-     * Checks owner of the path.
-     * @param p The path.
-     */
-    private void checkOwner(IgfsPath p) {
-        String ownerPrim = getOwner(igfs, p);
-        assertEquals(USER, ownerPrim);
-
-        String ownerSec = getOwnerSecondary(secondaryFs, p);
-        assertEquals(USER, ownerSec);
-    }
-
+public class HadoopMapReduceTest extends HadoopAbstractMapReduceTest {
     /**
      * Tests whole job execution with all phases in all combination of new and old versions of API.
      * @throws Exception If fails.
@@ -152,274 +35,32 @@ public class HadoopMapReduceTest extends HadoopAbstractWordCountTest {
 
         IgfsPath inFile = new IgfsPath(inDir, HadoopWordCount2.class.getSimpleName() + "-input");
 
-        final int red = 10_000;
-        final int blue = 20_000;
-        final int green = 15_000;
-        final int yellow = 7_000;
-
         generateTestFile(inFile.toString(), "red", red, "blue", blue, "green", green, "yellow", yellow );
 
-        for (int i = 0; i < 3; i++) {
-            igfs.delete(new IgfsPath(PATH_OUTPUT), true);
-
-            boolean useNewMapper = (i & 1) == 0;
-            boolean useNewCombiner = (i & 2) == 0;
-            boolean useNewReducer = (i & 4) == 0;
-
-            JobConf jobConf = new JobConf();
+        for (boolean[] apiMode: getApiModes()) {
+            assert apiMode.length == 3;
 
-            jobConf.set(JOB_COUNTER_WRITER_PROPERTY, IgniteHadoopFileSystemCounterWriter.class.getName());
-            jobConf.setUser(USER);
-            jobConf.set(IgniteHadoopFileSystemCounterWriter.COUNTER_WRITER_DIR_PROPERTY, "/xxx/${USER}/zzz");
+            boolean useNewMapper = apiMode[0];
+            boolean useNewCombiner = apiMode[1];
+            boolean useNewReducer = apiMode[2];
 
-            //To split into about 40 items for v2
-            jobConf.setInt(FileInputFormat.SPLIT_MAXSIZE, 65000);
-
-            //For v1
-            jobConf.setInt("fs.local.block.size", 65000);
-
-            // File system coordinates.
-            setupFileSystems(jobConf);
-
-            HadoopWordCount1.setTasksClasses(jobConf, !useNewMapper, !useNewCombiner, !useNewReducer);
-
-            Job job = Job.getInstance(jobConf);
-
-            HadoopWordCount2.setTasksClasses(job, useNewMapper, useNewCombiner, useNewReducer, compressOutputSnappy());
-
-            job.setOutputKeyClass(Text.class);
-            job.setOutputValueClass(IntWritable.class);
-
-            FileInputFormat.setInputPaths(job, new Path(igfsScheme() + inFile.toString()));
-            FileOutputFormat.setOutputPath(job, new Path(igfsScheme() + PATH_OUTPUT));
-
-            job.setJarByClass(HadoopWordCount2.class);
-
-            HadoopJobId jobId = new HadoopJobId(UUID.randomUUID(), 1);
-
-            IgniteInternalFuture<?> fut = grid(0).hadoop().submit(jobId, createJobInfo(job.getConfiguration()));
-
-            fut.get();
-
-            checkJobStatistics(jobId);
-
-            final String outFile = PATH_OUTPUT + "/" + (useNewReducer ? "part-r-" : "part-") + "00000";
-
-            checkOwner(new IgfsPath(PATH_OUTPUT + "/" + "_SUCCESS"));
-
-            checkOwner(new IgfsPath(outFile));
-
-            String actual = readAndSortFile(outFile, job.getConfiguration());
-
-            assertEquals("Use new mapper: " + useNewMapper + ", new combiner: " + useNewCombiner + ", new reducer: " +
-                useNewReducer,
-                "blue\t" + blue + "\n" +
-                "green\t" + green + "\n" +
-                "red\t" + red + "\n" +
-                "yellow\t" + yellow + "\n",
-                actual
-            );
+            doTest(inFile, useNewMapper, useNewCombiner, useNewReducer);
         }
     }
 
     /**
-     * Gets if to compress output data with Snappy.
-     *
-     * @return If to compress output data with Snappy.
-     */
-    protected boolean compressOutputSnappy() {
-        return false;
-    }
-
-    /**
-     * Simple test job statistics.
+     * Gets API mode combinations to be tested.
+     * Each boolean[] is { newMapper, newCombiner, newReducer } flag triplet.
      *
-     * @param jobId Job id.
-     * @throws IgniteCheckedException
+     * @return Arrays of booleans indicating API combinations to test.
      */
-    private void checkJobStatistics(HadoopJobId jobId) throws IgniteCheckedException, IOException {
-        HadoopCounters cntrs = grid(0).hadoop().counters(jobId);
-
-        HadoopPerformanceCounter perfCntr = HadoopPerformanceCounter.getCounter(cntrs, null);
-
-        Map<String, SortedMap<Integer,Long>> tasks = new TreeMap<>();
-
-        Map<String, Integer> phaseOrders = new HashMap<>();
-        phaseOrders.put("submit", 0);
-        phaseOrders.put("prepare", 1);
-        phaseOrders.put("start", 2);
-        phaseOrders.put("Cstart", 3);
-        phaseOrders.put("finish", 4);
-
-        String prevTaskId = null;
-
-        long apiEvtCnt = 0;
-
-        for (T2<String, Long> evt : perfCntr.evts()) {
-            //We expect string pattern: COMBINE 1 run 7fa86a14-5a08-40e3-a7cb-98109b52a706
-            String[] parsedEvt = evt.get1().split(" ");
-
-            String taskId;
-            String taskPhase;
-
-            if ("JOB".equals(parsedEvt[0])) {
-                taskId = parsedEvt[0];
-                taskPhase = parsedEvt[1];
-            }
-            else {
-                taskId = ("COMBINE".equals(parsedEvt[0]) ? "MAP" : parsedEvt[0].substring(0, 3)) + parsedEvt[1];
-                taskPhase = ("COMBINE".equals(parsedEvt[0]) ? "C" : "") + parsedEvt[2];
-            }
-
-            if (!taskId.equals(prevTaskId))
-                tasks.put(taskId, new TreeMap<Integer,Long>());
-
-            Integer pos = phaseOrders.get(taskPhase);
-
-            assertNotNull("Invalid phase " + taskPhase, pos);
-
-            tasks.get(taskId).put(pos, evt.get2());
-
-            prevTaskId = taskId;
-
-            apiEvtCnt++;
-        }
-
-        for (Map.Entry<String ,SortedMap<Integer,Long>> task : tasks.entrySet()) {
-            Map<Integer, Long> order = task.getValue();
-
-            long prev = 0;
-
-            for (Map.Entry<Integer, Long> phase : order.entrySet()) {
-                assertTrue("Phase order of " + task.getKey() + " is invalid", phase.getValue() >= prev);
-
-                prev = phase.getValue();
-            }
-        }
-
-        final IgfsPath statPath = new IgfsPath("/xxx/" + USER + "/zzz/" + jobId + "/performance");
-
-        assert GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                return igfs.exists(statPath);
-            }
-        }, 20_000);
-
-        final long apiEvtCnt0 = apiEvtCnt;
-
-        boolean res = GridTestUtils.waitForCondition(new GridAbsPredicate() {
-            @Override public boolean apply() {
-                try {
-                    try (BufferedReader reader = new BufferedReader(new InputStreamReader(igfs.open(statPath)))) {
-                        return apiEvtCnt0 == HadoopTestUtils.simpleCheckJobStatFile(reader);
-                    }
-                }
-                catch (IOException e) {
-                    throw new RuntimeException(e);
-                }
-            }
-        }, 10000);
-
-        if (!res) {
-            BufferedReader reader = new BufferedReader(new InputStreamReader(igfs.open(statPath)));
-
-            assert false : "Invalid API events count [exp=" + apiEvtCnt0 +
-                ", actual=" + HadoopTestUtils.simpleCheckJobStatFile(reader) + ']';
-        }
-    }
-
-    /** {@inheritDoc} */
-    @Override protected void beforeTest() throws Exception {
-        igniteSecondary = startGridWithIgfs("grid-secondary", SECONDARY_IGFS_NAME, PRIMARY, null, SECONDARY_REST_CFG);
-
-        super.beforeTest();
-    }
-
-    /**
-     * Start grid with IGFS.
-     *
-     * @param gridName Grid name.
-     * @param igfsName IGFS name
-     * @param mode IGFS mode.
-     * @param secondaryFs Secondary file system (optional).
-     * @param restCfg Rest configuration string (optional).
-     * @return Started grid instance.
-     * @throws Exception If failed.
-     */
-    protected Ignite startGridWithIgfs(String gridName, String igfsName, IgfsMode mode,
-        @Nullable IgfsSecondaryFileSystem secondaryFs, @Nullable IgfsIpcEndpointConfiguration restCfg) throws Exception {
-        FileSystemConfiguration igfsCfg = new FileSystemConfiguration();
-
-        igfsCfg.setDataCacheName("dataCache");
-        igfsCfg.setMetaCacheName("metaCache");
-        igfsCfg.setName(igfsName);
-        igfsCfg.setBlockSize(IGFS_BLOCK_SIZE);
-        igfsCfg.setDefaultMode(mode);
-        igfsCfg.setIpcEndpointConfiguration(restCfg);
-        igfsCfg.setSecondaryFileSystem(secondaryFs);
-        igfsCfg.setPrefetchBlocks(PREFETCH_BLOCKS);
-        igfsCfg.setSequentialReadsBeforePrefetch(SEQ_READS_BEFORE_PREFETCH);
-
-        CacheConfiguration dataCacheCfg = defaultCacheConfiguration();
-
-        dataCacheCfg.setName("dataCache");
-        dataCacheCfg.setCacheMode(PARTITIONED);
-        dataCacheCfg.setNearConfiguration(null);
-        dataCacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
-        dataCacheCfg.setAffinityMapper(new IgfsGroupDataBlocksKeyMapper(2));
-        dataCacheCfg.setBackups(0);
-        dataCacheCfg.setAtomicityMode(TRANSACTIONAL);
-        dataCacheCfg.setOffHeapMaxMemory(0);
-
-        CacheConfiguration metaCacheCfg = defaultCacheConfiguration();
-
-        metaCacheCfg.setName("metaCache");
-        metaCacheCfg.setCacheMode(REPLICATED);
-        metaCacheCfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);
-        metaCacheCfg.setAtomicityMode(TRANSACTIONAL);
-
-        IgniteConfiguration cfg = new IgniteConfiguration();
-
-        cfg.setGridName(gridName);
-
-        TcpDiscoverySpi discoSpi = new TcpDiscoverySpi();
-
-        discoSpi.setIpFinder(new TcpDiscoveryVmIpFinder(true));
-
-        cfg.setDiscoverySpi(discoSpi);
-        cfg.setCacheConfiguration(dataCacheCfg, metaCacheCfg);
-        cfg.setFileSystemConfiguration(igfsCfg);
-
-        cfg.setLocalHost("127.0.0.1");
-        cfg.setConnectorConfiguration(null);
-
-        HadoopConfiguration hadoopCfg = createHadoopConfiguration();
-
-        if (hadoopCfg != null)
-            cfg.setHadoopConfiguration(hadoopCfg);
-
-        return G.start(cfg);
-    }
-
-    /**
-     * Creates custom Hadoop configuration.
-     *
-     * @return The Hadoop configuration.
-     */
-    protected HadoopConfiguration createHadoopConfiguration() {
-        return null;
-    }
-
-    /**
-     * @return IGFS configuration.
-     */
-    @Override public FileSystemConfiguration igfsConfiguration() throws Exception {
-        FileSystemConfiguration fsCfg = super.igfsConfiguration();
-
-        secondaryFs = new IgniteHadoopIgfsSecondaryFileSystem(SECONDARY_URI, SECONDARY_CFG);
-
-        fsCfg.setSecondaryFileSystem(secondaryFs);
-
-        return fsCfg;
+    protected boolean[][] getApiModes() {
+        return new boolean[][] {
+            { false, false, false },
+            { false, false, true },
+            { false, true,  false },
+            { true,  false, false },
+            { true,  true,  true },
+        };
     }
 }
\ No newline at end of file


[10/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/input/checkbox.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/input/checkbox.directive.js b/modules/web-console/src/main/js/app/modules/form/field/input/checkbox.directive.js
index 5d77eab..3d84b4e 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/input/checkbox.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/input/checkbox.directive.js
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-import template from './checkbox.jade!';
+import templateUrl from './checkbox.jade';
 
-export default ['igniteFormFieldInputCheckbox', ['IgniteFormGUID', '$table', (guid, $table) => {
+export default ['igniteFormFieldInputCheckbox', ['IgniteFormGUID', 'IgniteLegacyTable', (guid, LegacyTable) => {
     const link = (scope, el, attrs, [form, label]) => {
         const {id, name} = scope;
         const field = form[name];
@@ -40,9 +40,8 @@ export default ['igniteFormFieldInputCheckbox', ['IgniteFormGUID', '$table', (gu
         scope.$watch(() => form.$pristine, setAsDefault);
         scope.$watch('value', setAsDefault);
 
-        // TODO LEGACY
         scope.tableReset = () => {
-            $table.tableSaveAndReset();
+            LegacyTable.tableSaveAndReset();
         };
     };
 
@@ -59,7 +58,7 @@ export default ['igniteFormFieldInputCheckbox', ['IgniteFormGUID', '$table', (gu
             value: '=ngModel'
         },
         link,
-        template,
+        templateUrl,
         replace: true,
         transclude: true,
         require: ['^form', '?^igniteFormField']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/input/datalist.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/input/datalist.directive.js b/modules/web-console/src/main/js/app/modules/form/field/input/datalist.directive.js
index ce67897..6c43a2a 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/input/datalist.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/input/datalist.directive.js
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-import template from './datalist.jade!';
+import templateUrl from './datalist.jade';
 
-export default ['igniteFormFieldInputDatalist', ['IgniteFormGUID', '$table', (guid, $table) => {
+export default ['igniteFormFieldInputDatalist', ['IgniteFormGUID', 'IgniteLegacyTable', (guid, LegacyTable) => {
     const link = (scope, element, attrs, [ngModel, form, label], transclude) => {
         const {id, ngModelName} = scope;
 
@@ -86,9 +86,8 @@ export default ['igniteFormFieldInputDatalist', ['IgniteFormGUID', '$table', (gu
             scope.value = ngModel.$modelValue;
         };
 
-        // TODO LEGACY
         scope.tableReset = () => {
-            $table.tableSaveAndReset();
+            LegacyTable.tableSaveAndReset();
         };
 
         transclude(scope.$parent, function(clone, tscope) {
@@ -115,7 +114,7 @@ export default ['igniteFormFieldInputDatalist', ['IgniteFormGUID', '$table', (gu
             autofocus: '=igniteFormFieldInputAutofocus'
         },
         link,
-        template,
+        templateUrl,
         replace: true,
         transclude: true,
         require: ['ngModel', '^form', '?^igniteFormField']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/input/datalist.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/input/datalist.jade b/modules/web-console/src/main/js/app/modules/form/field/input/datalist.jade
index 723b348..7ae1411 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/input/datalist.jade
+++ b/modules/web-console/src/main/js/app/modules/form/field/input/datalist.jade
@@ -43,7 +43,7 @@ mixin feedback(isCheckPristine, error, errorMessage)
         bs-options='item for item in options'
         container='body'
         data-min-length='1'
-        retain-selection
+        ignite-retain-selection
     )
 
     +feedback(true, 'required', '{{ label.name }} could not be empty!')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/input/number.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/input/number.directive.js b/modules/web-console/src/main/js/app/modules/form/field/input/number.directive.js
index 0c7a101..0d21f5b 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/input/number.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/input/number.directive.js
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-import template from './number.jade!';
+import templateUrl from './number.jade';
 
-export default ['igniteFormFieldInputNumber', ['IgniteFormGUID', '$table', (guid, $table) => {
+export default ['igniteFormFieldInputNumber', ['IgniteFormGUID', 'IgniteLegacyTable', (guid, LegacyTable) => {
     const link = (scope, el, attrs, [form, label]) => {
         const {id, name} = scope;
         const field = form[name];
@@ -46,9 +46,8 @@ export default ['igniteFormFieldInputNumber', ['IgniteFormGUID', '$table', (guid
         scope.$watch(() => form.$pristine, setAsDefault);
         scope.$watch('value', setAsDefault);
 
-        // TODO LEGACY
         scope.tableReset = () => {
-            $table.tableSaveAndReset();
+            LegacyTable.tableSaveAndReset();
         };
     };
 
@@ -69,7 +68,7 @@ export default ['igniteFormFieldInputNumber', ['IgniteFormGUID', '$table', (guid
             value: '=ngModel'
         },
         link,
-        template,
+        templateUrl,
         replace: true,
         transclude: true,
         require: ['^form', '?^igniteFormField']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/field/input/text.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/field/input/text.directive.js b/modules/web-console/src/main/js/app/modules/form/field/input/text.directive.js
index adcc179..56c02b5 100644
--- a/modules/web-console/src/main/js/app/modules/form/field/input/text.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/field/input/text.directive.js
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 
-import template from './text.jade!';
-import './text.css!';
+import templateUrl from './text.jade';
+import './text.css';
 
-export default ['igniteFormFieldInputText', ['IgniteFormGUID', '$table', (guid, $table) => {
+export default ['igniteFormFieldInputText', ['IgniteFormGUID', 'IgniteLegacyTable', (guid, LegacyTable) => {
     const link = (scope, element, attrs, [ngModel, form, label], transclude) => {
         const {id, ngModelName} = scope;
 
@@ -90,9 +90,8 @@ export default ['igniteFormFieldInputText', ['IgniteFormGUID', '$table', (guid,
             scope.value = ngModel.$modelValue;
         };
 
-        // TODO LEGACY
         scope.tableReset = () => {
-            $table.tableSaveAndReset();
+            LegacyTable.tableSaveAndReset();
         };
 
         transclude(scope.$parent, function(clone, tscope) {
@@ -119,7 +118,7 @@ export default ['igniteFormFieldInputText', ['IgniteFormGUID', '$table', (guid,
             autofocus: '=igniteFormFieldInputAutofocus'
         },
         link,
-        template,
+        templateUrl,
         replace: true,
         transclude: true,
         require: ['ngModel', '^form', '?^igniteFormField']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/group/group.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/group/group.directive.js b/modules/web-console/src/main/js/app/modules/form/group/group.directive.js
index 0971d44..20cad22 100644
--- a/modules/web-console/src/main/js/app/modules/form/group/group.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/group/group.directive.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import template from './group.jade!';
+import templateUrl from './group.jade';
 
 export default ['igniteFormGroup', [() => {
     const controller = [function() { }];
@@ -71,7 +71,7 @@ export default ['igniteFormGroup', [() => {
             label: '@'
         },
         link,
-        template,
+        templateUrl,
         controller,
         controllerAs: 'group',
         replace: true,

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/group/table.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/group/table.directive.js b/modules/web-console/src/main/js/app/modules/form/group/table.directive.js
index 520f8c2..8c4d0ed 100644
--- a/modules/web-console/src/main/js/app/modules/form/group/table.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/group/table.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './table.jade!';
+import templateUrl from './table.jade';
 
 export default ['igniteFormGroupTable', [() => {
     return {
         restrict: 'E',
         scope: {},
-        template,
+        templateUrl,
         replace: true,
         transclude: true,
         require: ['^form', '^igniteFormGroup']

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/form/panel/revert.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/form/panel/revert.directive.js b/modules/web-console/src/main/js/app/modules/form/panel/revert.directive.js
index 2bf4c8c..d60efb8 100644
--- a/modules/web-console/src/main/js/app/modules/form/panel/revert.directive.js
+++ b/modules/web-console/src/main/js/app/modules/form/panel/revert.directive.js
@@ -17,7 +17,7 @@
 
 const template = '<i ng-show="form.$dirty" class="fa fa-undo pull-right" ng-click="revert($event)"></i>';
 
-export default ['igniteFormRevert', ['$tooltip', '$table', ($tooltip, $table) => {
+export default ['igniteFormRevert', ['$tooltip', 'IgniteLegacyTable', ($tooltip, LegacyTable) => {
     const link = (scope, $element, $attrs, [form]) => {
         $tooltip($element, { title: 'Undo unsaved changes' });
 
@@ -26,7 +26,7 @@ export default ['igniteFormRevert', ['$tooltip', '$table', ($tooltip, $table) =>
         scope.revert = (e) => {
             e.stopPropagation();
 
-            $table.tableReset();
+            LegacyTable.tableReset();
 
             _.forOwn(form.$defaults, (value, name) => {
                 const field = form[name];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/getting-started/GettingStarted.provider.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/getting-started/GettingStarted.provider.js b/modules/web-console/src/main/js/app/modules/getting-started/GettingStarted.provider.js
index 74c24c2..cf9f561 100644
--- a/modules/web-console/src/main/js/app/modules/getting-started/GettingStarted.provider.js
+++ b/modules/web-console/src/main/js/app/modules/getting-started/GettingStarted.provider.js
@@ -18,7 +18,7 @@
 import angular from 'angular';
 
 // Getting started pages.
-import PAGES from 'app/data/getting-started.json!';
+import PAGES from 'app/data/getting-started.json';
 
 angular
     .module('ignite-console.getting-started', [])

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/loading/loading.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/loading/loading.directive.js b/modules/web-console/src/main/js/app/modules/loading/loading.directive.js
index fc3e1e6..064b4c2 100644
--- a/modules/web-console/src/main/js/app/modules/loading/loading.directive.js
+++ b/modules/web-console/src/main/js/app/modules/loading/loading.directive.js
@@ -15,12 +15,12 @@
  * limitations under the License.
  */
 
-import template from './loading.jade!';
-import './loading.css!';
+import templateUrl from './loading.jade';
+import './loading.css';
 
-export default ['igniteLoading', ['$loading', '$compile', ($loading, $compile) => {
+export default ['igniteLoading', ['IgniteLoading', '$templateCache', '$compile', (Loading, $templateCache, $compile) => {
     const link = (scope, element) => {
-        const compiledTemplate = $compile(template());
+        const compiledTemplate = $compile($templateCache.get(templateUrl));
 
         const build = () => {
             scope.position = scope.position || 'middle';
@@ -30,7 +30,7 @@ export default ['igniteLoading', ['$loading', '$compile', ($loading, $compile) =
             if (!scope.loading) {
                 scope.loading = loading;
 
-                $loading.add(scope.key || 'defaultSpinnerKey', scope.loading);
+                Loading.add(scope.key || 'defaultSpinnerKey', scope.loading);
                 element.append(scope.loading);
             }
         };

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/loading/loading.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/loading/loading.service.js b/modules/web-console/src/main/js/app/modules/loading/loading.service.js
index 0664884..ec31c1a 100644
--- a/modules/web-console/src/main/js/app/modules/loading/loading.service.js
+++ b/modules/web-console/src/main/js/app/modules/loading/loading.service.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-export default ['$loading', ['$timeout', ($timeout) => {
+export default ['IgniteLoading', ['$timeout', ($timeout) => {
     const _overlays = {};
 
     const start = (key) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/concurrency.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/concurrency.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/concurrency.directive.js
index 0e00a4b..9438679 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/concurrency.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/concurrency.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './concurrency.jade!';
+import templateUrl from './concurrency.jade';
 
 export default ['igniteConfigurationCachesConcurrency', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.directive.js
index d3f5f45..3edc1a3 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './general.jade!';
+import templateUrl from './general.jade';
 
 export default ['igniteConfigurationCachesGeneral', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.jade b/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.jade
index b5e0797..44304bf 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/general.jade
@@ -49,7 +49,7 @@ form.panel.panel-default(name='general' novalidate)
                         </ul>')
                 .settings-row(data-ng-show='#{model}.cacheMode === "PARTITIONED"')
                     +number('Backups:', model + '.backups', 'backups', 'true', '0', '0', 'Number of nodes used to back up single partition for partitioned cache')
-                .settings-row(data-ng-show='#{model}.backups && #{model}.cacheMode !== "LOCAL"')
+                .settings-row(data-ng-show='#{model}.cacheMode === "PARTITIONED" && #{model}.backups')
                     +checkbox('Read from backup', model + '.readFromBackup', 'readFromBackup',
                         'Flag indicating whether data can be read from backup<br/>\
                         If not set then always get data from primary node (never from backup)')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/memory.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/memory.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/memory.directive.js
index 0f8662d..c160b18 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/memory.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/memory.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './memory.jade!';
+import templateUrl from './memory.jade';
 
 export default ['igniteConfigurationCachesMemory', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/query.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/query.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/query.directive.js
index b3b6edb..9d8264e 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/query.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/query.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './query.jade!';
+import templateUrl from './query.jade';
 
 export default ['igniteConfigurationCachesQuery', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/rebalance.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/rebalance.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/rebalance.directive.js
index b3f24a1..5081578 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/rebalance.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/rebalance.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './rebalance.jade!';
+import templateUrl from './rebalance.jade';
 
 export default ['igniteConfigurationCachesRebalance', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/server-near-cache.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/server-near-cache.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/server-near-cache.directive.js
index 5a4e474..c2e83aa 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/server-near-cache.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/server-near-cache.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './server-near-cache.jade!';
+import templateUrl from './server-near-cache.jade';
 
 export default ['igniteConfigurationCachesServerNearCache', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/statistics.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/statistics.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/statistics.directive.js
index d40ac1a..ee0da3d 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/statistics.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/statistics.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './statistics.jade!';
+import templateUrl from './statistics.jade';
 
 export default ['igniteConfigurationCachesStatistics', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.directive.js
index 168eb85..80528e5 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './store.jade!';
+import templateUrl from './store.jade';
 
 export default ['igniteConfigurationCachesStore', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.jade b/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.jade
index cb26d03..6361e28 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/caches/store.jade
@@ -67,8 +67,8 @@ mixin hibernateField(items, field, valid, save, newItem)
         data-ignite-property-unique=items
         data-ignite-property-value-specified
         data-ignite-form-field-input-autofocus='true'
-        on-enter=onEnter
-        on-escape=reset
+        ignite-on-enter=onEnter
+        ignite-on-escape=reset
         ng-blur=onBlur
     )
         block

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/atomic.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/atomic.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/atomic.directive.js
index 062a527..64b80a0 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/atomic.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/atomic.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './atomic.jade!';
+import templateUrl from './atomic.jade';
 
 export default ['igniteConfigurationClustersAtomic', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/attributes.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/attributes.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/attributes.directive.js
index cc9d474..f5f431c 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/attributes.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/attributes.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './attributes.jade!';
+import templateUrl from './attributes.jade';
 
 export default ['igniteConfigurationUserAttributes', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/binary.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/binary.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/binary.directive.js
index 68c8dcb..7d701bc 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/binary.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/binary.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './binary.jade!';
+import templateUrl from './binary.jade';
 
 export default ['igniteConfigurationClustersBinary', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision.directive.js
index 624056e..b8e0b43 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './collision.jade!';
+import templateUrl from './collision.jade';
 
 export default ['igniteConfigurationClustersCollision', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/custom.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/custom.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/custom.directive.js
index 9a8d414..2299133 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/custom.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/custom.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './custom.jade!';
+import templateUrl from './custom.jade';
 
 export default ['igniteConfigurationClustersCollisionCustom', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/fifo-queue.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/fifo-queue.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/fifo-queue.directive.js
index 240c98a..f14c1bb 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/fifo-queue.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/fifo-queue.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './fifo-queue.jade!';
+import templateUrl from './fifo-queue.jade';
 
 export default ['igniteConfigurationClustersCollisionFifoQueue', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/job-stealing.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/job-stealing.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/job-stealing.directive.js
index 3c187d1..0cc9cfa 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/job-stealing.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/job-stealing.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './job-stealing.jade!';
+import templateUrl from './job-stealing.jade';
 
 export default ['igniteConfigurationClustersCollisionJobStealing', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/priority-queue.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/priority-queue.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/priority-queue.directive.js
index e7e8798..95ebd5e 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/priority-queue.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/collision/priority-queue.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './priority-queue.jade!';
+import templateUrl from './priority-queue.jade';
 
 export default ['igniteConfigurationClustersCollisionPriorityQueue', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/communication.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/communication.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/communication.directive.js
index 5203a9e..e578dc6 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/communication.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/communication.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './communication.jade!';
+import templateUrl from './communication.jade';
 
 export default ['igniteConfigurationClustersCommunication', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/connector.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/connector.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/connector.directive.js
index 6c085b6..ea0b04d 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/connector.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/connector.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './connector.jade!';
+import templateUrl from './connector.jade';
 
 export default ['igniteConfigurationClustersConnector', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/deployment.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/deployment.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/deployment.directive.js
index bc71379..392ed7e 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/deployment.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/deployment.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './deployment.jade!';
+import templateUrl from './deployment.jade';
 
 export default ['igniteConfigurationClustersDeployment', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/discovery.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/discovery.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/discovery.directive.js
index f61d625..80286ac 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/discovery.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/discovery.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './discovery.jade!';
+import templateUrl from './discovery.jade';
 
 export default ['igniteConfigurationClustersDiscovery', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/events.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/events.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/events.directive.js
index c04829d..ee25ae2 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/events.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/events.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './events.jade!';
+import templateUrl from './events.jade';
 
 export default ['igniteConfigurationClustersEvents', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/failover.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/failover.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/failover.directive.js
index 98335a7..b9f59ba 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/failover.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/failover.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './failover.jade!';
+import templateUrl from './failover.jade';
 
 export default ['igniteConfigurationClustersFailover', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general.directive.js
index 29644fc..ccfadbe 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './general.jade!';
+import templateUrl from './general.jade';
 
 export default ['igniteConfigurationClustersGeneral', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/cloud.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/cloud.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/cloud.directive.js
index a785395..8fa7edc 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/cloud.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/cloud.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './cloud.jade!';
+import templateUrl from './cloud.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryCloud', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/google.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/google.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/google.directive.js
index d7df6d2..a409946 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/google.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/google.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './google.jade!';
+import templateUrl from './google.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryGoogle', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/jdbc.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/jdbc.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/jdbc.directive.js
index 44d4624..6edd6ed 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/jdbc.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/jdbc.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './jdbc.jade!';
+import templateUrl from './jdbc.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryJdbc', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/multicast.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/multicast.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/multicast.directive.js
index 606bb9d..67775d2 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/multicast.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/multicast.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './multicast.jade!';
+import templateUrl from './multicast.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryMulticast', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/s3.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/s3.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/s3.directive.js
index c0624f0..25fd90a 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/s3.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/s3.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './s3.jade!';
+import templateUrl from './s3.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryS3', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/shared.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/shared.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/shared.directive.js
index 6a5dce7..da1ee0c 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/shared.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/shared.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './shared.jade!';
+import templateUrl from './shared.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryShared', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.directive.js
index 2bb3efd..d07adc8 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './vm.jade!';
+import templateUrl from './vm.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryVm', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.jade b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.jade
index cc39790..1f20613 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/vm.jade
@@ -37,7 +37,7 @@ include ../../../../../../../app/helpers/jade/mixins.jade
                 li Hostname and port range (e.g. host1.com:47500..47510, host2:47502..47508, etc)
             | If port is 0 or not provided then default port will be used (depends on discovery SPI configuration)#[br]
             | If port range is provided (e.g. host:port1..port2) the following should be considered:
-            ul: li port1 < port2 should be true
+            ul: li port1 &lt; port2 should be true
                 li Both port1 and port2 should be greater than 0
         ignite-form-group-add(ng-click='group.add = [{}]')
             | Add new address

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper.directive.js
index 42925a9..3081443 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './zookeeper.jade!';
+import templateUrl from './zookeeper.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeper', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/bounded-exponential-backoff.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/bounded-exponential-backoff.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/bounded-exponential-backoff.directive.js
index 68e338b..42fb229 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/bounded-exponential-backoff.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/bounded-exponential-backoff.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './bounded-exponential-backoff.jade!';
+import templateUrl from './bounded-exponential-backoff.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperBoundedExponential', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/custom.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/custom.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/custom.directive.js
index dfd9b08..969356b 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/custom.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/custom.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './custom.jade!';
+import templateUrl from './custom.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperCustom', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/exponential-backoff.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/exponential-backoff.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/exponential-backoff.directive.js
index 29c968c..e68dff6 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/exponential-backoff.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/exponential-backoff.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './exponential-backoff.jade!';
+import templateUrl from './exponential-backoff.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperExponential', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/forever.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/forever.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/forever.directive.js
index ec39f66..38bc2d8 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/forever.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/forever.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './forever.jade!';
+import templateUrl from './forever.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperForever', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/n-times.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/n-times.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/n-times.directive.js
index ce83da4..f369af8 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/n-times.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/n-times.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './n-times.jade!';
+import templateUrl from './n-times.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperNTimes', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/one-time.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/one-time.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/one-time.directive.js
index 7329cc2..e9e114d 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/one-time.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/one-time.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './one-time.jade!';
+import templateUrl from './one-time.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperOneTime', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/until-elapsed.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/until-elapsed.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/until-elapsed.directive.js
index 8997159..4ab76b2 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/until-elapsed.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/general/discovery/zookeeper/retrypolicy/until-elapsed.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './until-elapsed.jade!';
+import templateUrl from './until-elapsed.jade';
 
 export default ['igniteConfigurationClustersGeneralDiscoveryZookeeperUntilElapsed', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/igfs.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/igfs.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/igfs.directive.js
index 1d0e3d8..74d4826 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/igfs.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/igfs.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './igfs.jade!';
+import templateUrl from './igfs.jade';
 
 export default ['igniteConfigurationClustersIgfs', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger.directive.js
index 3df231f..8aec165 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './logger.jade!';
+import templateUrl from './logger.jade';
 
 export default ['igniteConfigurationClustersLogger', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/custom.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/custom.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/custom.directive.js
index 5bd586b..999a3ca 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/custom.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/custom.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './custom.jade!';
+import templateUrl from './custom.jade';
 
 export default ['igniteConfigurationClustersLoggerCustom', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j.directive.js
index 64e4337..32f55e9 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './log4j.jade!';
+import templateUrl from './log4j.jade';
 
 export default ['igniteConfigurationClustersLoggerLog4j', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j2.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j2.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j2.directive.js
index ad891f7..81ae296 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j2.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/logger/log4j2.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './log4j2.jade!';
+import templateUrl from './log4j2.jade';
 
 export default ['igniteConfigurationClustersLoggerLog4j2', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/marshaller.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/marshaller.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/marshaller.directive.js
index 6c266a8..b4175b0 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/marshaller.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/marshaller.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './marshaller.jade!';
+import templateUrl from './marshaller.jade';
 
 export default ['igniteConfigurationClustersMarshaller', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/metrics.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/metrics.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/metrics.directive.js
index fc572a6..9b8ddc3 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/metrics.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/metrics.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './metrics.jade!';
+import templateUrl from './metrics.jade';
 
 export default ['igniteConfigurationClustersMetrics', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/ssl.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/ssl.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/ssl.directive.js
index d875c59..ded5bf0 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/ssl.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/ssl.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './ssl.jade!';
+import templateUrl from './ssl.jade';
 
 export default ['igniteConfigurationClustersSsl', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/swap.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/swap.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/swap.directive.js
index db83d50..c340c4b 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/swap.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/swap.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './swap.jade!';
+import templateUrl from './swap.jade';
 
 export default ['igniteConfigurationClustersSwap', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/thread.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/thread.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/thread.directive.js
index dabc574..f504e67 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/thread.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/thread.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './thread.jade!';
+import templateUrl from './thread.jade';
 
 export default ['igniteConfigurationClustersThread', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/time.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/time.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/time.directive.js
index b55b8a1..8ab3e89 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/time.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/time.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './time.jade!';
+import templateUrl from './time.jade';
 
 export default ['igniteConfigurationClustersTime', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/clusters/transactions.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/transactions.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/transactions.directive.js
index 985de49..faca0fa 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/clusters/transactions.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/clusters/transactions.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './transactions.jade!';
+import templateUrl from './transactions.jade';
 
 export default ['igniteConfigurationClustersTransactions', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/domains/general.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/domains/general.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/domains/general.directive.js
index ab03eb0..9ca02f9 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/domains/general.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/domains/general.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './general.jade!';
+import templateUrl from './general.jade';
 
 export default ['igniteConfigurationDomainsGeneral', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.directive.js
index c5aa79e..2033394 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './query.jade!';
+import templateUrl from './query.jade';
 
 export default ['igniteConfigurationDomainsQuery', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.jade b/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.jade
index f66de92..9ac0d00 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/domains/query.jade
@@ -39,15 +39,15 @@ mixin table-index-item-edit(prefix, index, sortAvailable, idAddition)
     .col-xs-8.col-sm-8.col-md-8(ng-show=sortAvailable)
         label.fieldSep /
         .input-tip
-            input.form-control(id='{{::"#{fieldName}S" + #{idAddition}}}' enter-focus-next='{{::"#{direction}S" + #{idAddition}}}' type='text' ng-model=fieldNameModel placeholder='Field name' on-escape='tableReset()')
+            input.form-control(id='{{::"#{fieldName}S" + #{idAddition}}}' ignite-on-enter-focus-move='{{::"#{direction}S" + #{idAddition}}}' type='text' ng-model=fieldNameModel placeholder='Field name' ignite-on-escape='tableReset()')
     .col-xs-4.col-sm-4.col-md-4(ng-show=sortAvailable)
         +btn-save(btnVisible, btnSave)
         .input-tip
-            button.select-toggle.form-control(id='{{::"#{direction}S" + #{idAddition}}}' ng-model=directionModel bs-select bs-options='item.value as item.label for item in {{sortDirections}}' on-enter=btnVisibleAndSave on-escape='tableReset()' tabindex='0')
+            button.select-toggle.form-control(id='{{::"#{direction}S" + #{idAddition}}}' ng-model=directionModel bs-select bs-options='item.value as item.label for item in {{sortDirections}}' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()' tabindex='0')
     .col-xs-12(ng-show='!(#{sortAvailable})')
         +btn-save(btnVisible, btnSave)
         .input-tip
-            input.form-control(id='{{::"#{fieldName}" + #{idAddition}}}' type='text' ng-model=fieldNameModel placeholder='Field name' on-enter=btnVisibleAndSave on-escape='tableReset()')
+            input.form-control(id='{{::"#{fieldName}" + #{idAddition}}}' type='text' ng-model=fieldNameModel placeholder='Field name' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')
 
 form.panel.panel-default(name='query' novalidate)
     .panel-heading(bs-collapse-toggle)
@@ -134,11 +134,11 @@ form.panel.panel-default(name='query' novalidate)
                                                     .col-sm-7
                                                         label.fieldSep /
                                                         .input-tip
-                                                            input.form-control(id='curIndexName{{$index}}' type='text' enter-focus-next='curIndexType{{$index}}' ng-model='indexesTbl.curIndexName' placeholder='Index name' on-enter=btnVisibleAndSave on-escape='tableReset()')
+                                                            input.form-control(id='curIndexName{{$index}}' type='text' ignite-on-enter-focus-move='curIndexType{{$index}}' ng-model='indexesTbl.curIndexName' placeholder='Index name' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')
                                                     .col-sm-5
                                                         +btn-save('tableIndexSaveVisible(indexesTbl, $index)', 'tableIndexSave(indexesTbl, $index)')
                                                         .input-tip
-                                                            button.select-toggle.form-control(id='curIndexType{{$index}}' bs-select ng-model='indexesTbl.curIndexType' data-placeholder='Select index type' bs-options='item.value as item.label for item in indexType' tabindex='0' on-enter=btnVisibleAndSave on-escape='tableReset()')
+                                                            button.select-toggle.form-control(id='curIndexType{{$index}}' bs-select ng-model='indexesTbl.curIndexType' data-placeholder='Select index type' bs-options='item.value as item.label for item in indexType' tabindex='0' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')
                                                 .margin-left-dflt
                                                     table.links-edit-sub(st-table='item.fields' ng-init='itemIndex = $index')
                                                         tbody
@@ -160,10 +160,10 @@ form.panel.panel-default(name='query' novalidate)
                                                 .col-sm-7
                                                     .fieldSep /
                                                     .input-tip
-                                                        input#newIndexName.form-control(type='text' enter-focus-next='newIndexType' ng-model='indexesTbl.newIndexName' placeholder='Index name' on-enter='tableIndexSaveVisible(indexesTbl, -1) && tableIndexSave(indexesTbl, -1)' on-escape='tableReset()')
+                                                        input#newIndexName.form-control(type='text' ignite-on-enter-focus-move='newIndexType' ng-model='indexesTbl.newIndexName' placeholder='Index name' ignite-on-enter='tableIndexSaveVisible(indexesTbl, -1) && tableIndexSave(indexesTbl, -1)' ignite-on-escape='tableReset()')
                                                 .col-sm-5
                                                     +btn-save('tableIndexSaveVisible(indexesTbl, -1)', 'tableIndexSave(indexesTbl, -1)')
                                                     .input-tip
-                                                        button#newIndexType.select-toggle.form-control(bs-select ng-model='indexesTbl.newIndexType' data-placeholder='Select index type' bs-options='item.value as item.label for item in indexType' tabindex='0' on-enter=btnVisibleAndSave on-escape='tableReset()')
+                                                        button#newIndexType.select-toggle.form-control(bs-select ng-model='indexesTbl.newIndexType' data-placeholder='Select index type' bs-options='item.value as item.label for item in indexType' tabindex='0' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')
             .col-sm-6
                 +preview-xml-java(model, 'domainModelQuery')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.directive.js
index 39dc184..a69b025 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './store.jade!';
+import templateUrl from './store.jade';
 
 export default ['igniteConfigurationDomainsStore', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade b/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
index d2a1dc6..8d3c65b 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/domains/store.jade
@@ -43,15 +43,15 @@ mixin table-db-field-edit(tbl, prefix, focusId, index)
     .col-xs-3.col-sm-3.col-md-3
         .fieldSep /
         .input-tip
-            input.form-control(id=databaseNameId enter-focus-next=databaseTypeId type='text' ng-model=databaseNameModel placeholder='DB name' on-enter='#{javaNameModel} = #{javaNameModel} ? #{javaNameModel} : #{databaseNameModel}' on-escape='tableReset()')
+            input.form-control(id=databaseNameId ignite-on-enter-focus-move=databaseTypeId type='text' ng-model=databaseNameModel placeholder='DB name' ignite-on-enter='#{javaNameModel} = #{javaNameModel} ? #{javaNameModel} : #{databaseNameModel}' ignite-on-escape='tableReset()')
     .col-xs-3.col-sm-3.col-md-3
         .fieldSep /
         .input-tip
-            button.select-toggle.form-control(id=databaseTypeId enter-focus-next=javaNameId ng-model=databaseTypeModel data-placeholder='DB type' ng-class='{placeholder: !#{databaseTypeModel}}' bs-select bs-options='item.value as item.label for item in {{supportedJdbcTypes}}' on-escape='tableReset()' tabindex='0')
+            button.select-toggle.form-control(id=databaseTypeId ignite-on-enter-focus-move=javaNameId ng-model=databaseTypeModel data-placeholder='DB type' ng-class='{placeholder: !#{databaseTypeModel}}' bs-select bs-options='item.value as item.label for item in {{supportedJdbcTypes}}' ignite-on-escape='tableReset()' tabindex='0')
     .col-xs-3.col-sm-3.col-md-3
         .fieldSep /
         .input-tip
-            input.form-control(id=javaNameId enter-focus-next=javaTypeId type='text' ng-model=javaNameModel placeholder='Java name' on-escape='tableReset()')
+            input.form-control(id=javaNameId ignite-on-enter-focus-move=javaTypeId type='text' ng-model=javaNameModel placeholder='Java name' ignite-on-escape='tableReset()')
     .col-xs-3.col-sm-3.col-md-3
         -var btnVisible = 'tableDbFieldSaveVisible(' + tbl + ', ' + index +')'
         -var btnSave = 'tableDbFieldSave(' + tbl + ', ' + index +')'
@@ -59,7 +59,7 @@ mixin table-db-field-edit(tbl, prefix, focusId, index)
 
         +btn-save(btnVisible, btnSave)
         .input-tip
-            button.select-toggle.form-control(id=javaTypeId ng-model=javaTypeModel data-placeholder='Java type' ng-class='{placeholder: !#{javaTypeModel}}' bs-select bs-options='item.value as item.label for item in {{supportedJavaTypes}}' on-enter=btnVisibleAndSave on-escape='tableReset()' tabindex='0')
+            button.select-toggle.form-control(id=javaTypeId ng-model=javaTypeModel data-placeholder='Java type' ng-class='{placeholder: !#{javaTypeModel}}' bs-select bs-options='item.value as item.label for item in {{supportedJavaTypes}}' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()' tabindex='0')
 
 form.panel.panel-default(name=form novalidate)
     .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
index 109fa63..c5afc4e 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './dual.jade!';
+import templateUrl from './dual.jade';
 
 export default ['igniteConfigurationIgfsDual', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
index ba2e182..8129f0d 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/dual.jade
@@ -32,8 +32,8 @@ form.panel.panel-default(name=form novalidate)
             .col-sm-6
                 .settings-row
                     +number('Maximum pending puts size:', model + '.dualModeMaxPendingPutsSize', 'dualModeMaxPendingPutsSize', 'true', '0', 'Number.MIN_SAFE_INTEGER',
-                        'Maximum amount of pending data read from the secondary file system and waiting to be written to data cache\
-                        0 or negative value stands for unlimited size')
+                        'Maximum amount of pending data read from the secondary file system and waiting to be written to data cache<br/>\
+                        Zero or negative value stands for unlimited size')
                 .settings-row
                     +java-class('Put executor service:', model + '.dualModePutExecutorService', 'dualModePutExecutorService', 'true', 'false', 'DUAL mode put operation executor service')
                 .settings-row

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
index f93c76c..d008933 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/fragmentizer.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './fragmentizer.jade!';
+import templateUrl from './fragmentizer.jade';
 
 export default ['igniteConfigurationIgfsFragmentizer', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
index 294c3b8..bda5418 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/general.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './general.jade!';
+import templateUrl from './general.jade';
 
 export default ['igniteConfigurationIgfsGeneral', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];


[12/46] ignite git commit: IGNITE-3055: IgniteDataStreamer can't be timed out (cherry picked from commit 10224df)

Posted by sb...@apache.org.
IGNITE-3055: IgniteDataStreamer can't be timed out
(cherry picked from commit 10224df)


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

Branch: refs/heads/ignite-1232
Commit: cd1d618ea5f80f93c378a7dc4c1bec0dcd56321e
Parents: c38b3ba
Author: Vladislav Pyatkov <vl...@gmail.com>
Authored: Wed Jul 13 15:24:53 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Wed Jul 13 15:28:20 2016 +0300

----------------------------------------------------------------------
 .../org/apache/ignite/IgniteDataStreamer.java   |  52 +++++-
 .../IgniteDataStreamerTimeoutException.java     |  45 +++++
 .../datastreamer/DataStreamerImpl.java          |  71 ++++++--
 .../ignite/internal/util/IgniteUtils.java       |  21 +++
 .../datastreamer/DataStreamerTimeoutTest.java   | 163 +++++++++++++++++++
 .../ignite/testsuites/IgniteCacheTestSuite.java |   2 +
 6 files changed, 335 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/cd1d618e/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java b/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
index 2a79143..aa2e1fe 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamer.java
@@ -96,6 +96,9 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
     /** Default per node buffer size. */
     public static final int DFLT_PER_NODE_BUFFER_SIZE = 1024;
 
+    /** Default timeout for streamer's operations. */
+    public static final long DFLT_UNLIMIT_TIMEOUT = -1;
+
     /**
      * Name of cache to stream data to.
      *
@@ -197,6 +200,29 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
     public void perNodeParallelOperations(int parallelOps);
 
     /**
+     * Sets the timeout that is used in the following cases:
+     * <ul>
+     * <li>any data addition method can be blocked when all per node parallel operations are exhausted.
+     * The timeout defines the max time you will be blocked waiting for a permit to add a chunk of data
+     * into the streamer;</li>
+     * <li>Total timeout time for {@link #flush()} operation;</li>
+     * <li>Total timeout time for {@link #close()} operation.</li>
+     * </ul>
+     * By default the timeout is disabled.
+     *
+     * @param timeout Timeout in milliseconds.
+     * @throws IllegalArgumentException If {@param timeout} is zero or less than {@code -1}.
+     */
+    public void timeout(long timeout);
+
+    /**
+     * Gets timeout set by {@link #timeout(long)}.
+     *
+     * @return Timeout in milliseconds.
+     */
+    public long timeout();
+
+    /**
      * Gets automatic flush frequency. Essentially, this is the time after which the
      * streamer will make an attempt to submit all data added so far to remote nodes.
      * Note that there is no guarantee that data will be delivered after this concrete
@@ -286,10 +312,11 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @throws IgniteInterruptedException If thread has been interrupted.
      * @throws IllegalStateException If grid has been concurrently stopped or
      *      {@link #close(boolean)} has already been called on streamer.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded.
      * @see #allowOverwrite()
      */
     public IgniteFuture<?> addData(K key, @Nullable V val) throws CacheException, IgniteInterruptedException,
-        IllegalStateException;
+        IllegalStateException, IgniteDataStreamerTimeoutException;
 
     /**
      * Adds data for streaming on remote node. This method can be called from multiple
@@ -309,10 +336,11 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @throws IgniteInterruptedException If thread has been interrupted.
      * @throws IllegalStateException If grid has been concurrently stopped or
      *      {@link #close(boolean)} has already been called on streamer.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded.
      * @see #allowOverwrite()
      */
     public IgniteFuture<?> addData(Map.Entry<K, V> entry) throws CacheException, IgniteInterruptedException,
-        IllegalStateException;
+        IllegalStateException, IgniteDataStreamerTimeoutException;
 
     /**
      * Adds data for streaming on remote node. This method can be called from multiple
@@ -329,10 +357,12 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @param entries Collection of entries to be streamed.
      * @throws IllegalStateException If grid has been concurrently stopped or
      *      {@link #close(boolean)} has already been called on streamer.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded.
      * @return Future for this stream operation.
      * @see #allowOverwrite()
      */
-    public IgniteFuture<?> addData(Collection<? extends Map.Entry<K, V>> entries) throws IllegalStateException;
+    public IgniteFuture<?> addData(Collection<? extends Map.Entry<K, V>> entries) throws IllegalStateException,
+        IgniteDataStreamerTimeoutException;
 
     /**
      * Adds data for streaming on remote node. This method can be called from multiple
@@ -349,10 +379,12 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @param entries Map to be streamed.
      * @throws IllegalStateException If grid has been concurrently stopped or
      *      {@link #close(boolean)} has already been called on streamer.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded.
      * @return Future for this stream operation.
      * @see #allowOverwrite()
      */
-    public IgniteFuture<?> addData(Map<K, V> entries) throws IllegalStateException;
+    public IgniteFuture<?> addData(Map<K, V> entries) throws IllegalStateException,
+        IgniteDataStreamerTimeoutException;
 
     /**
      * Streams any remaining data, but doesn't close the streamer. Data can be still added after
@@ -367,9 +399,11 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @throws IgniteInterruptedException If thread has been interrupted.
      * @throws IllegalStateException If grid has been concurrently stopped or
      *      {@link #close(boolean)} has already been called on streamer.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded.
      * @see #tryFlush()
      */
-    public void flush() throws CacheException, IgniteInterruptedException, IllegalStateException;
+    public void flush() throws CacheException, IgniteInterruptedException, IllegalStateException,
+        IgniteDataStreamerTimeoutException;
 
     /**
      * Makes an attempt to stream remaining data. This method is mostly similar to {@link #flush},
@@ -389,8 +423,10 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      * @param cancel {@code True} to cancel ongoing streaming operations.
      * @throws CacheException If failed to map key to node.
      * @throws IgniteInterruptedException If thread has been interrupted.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded, only if {@param cancel} is {@code false}.
      */
-    public void close(boolean cancel) throws CacheException, IgniteInterruptedException;
+    public void close(boolean cancel) throws CacheException, IgniteInterruptedException,
+        IgniteDataStreamerTimeoutException;
 
     /**
      * Closes data streamer. This method is identical to calling {@link #close(boolean) close(false)} method.
@@ -400,7 +436,9 @@ public interface IgniteDataStreamer<K, V> extends AutoCloseable {
      *
      * @throws CacheException If failed to close data streamer.
      * @throws IgniteInterruptedException If thread has been interrupted.
+     * @throws IgniteDataStreamerTimeoutException If {@code timeout} is exceeded.
      */
-    @Override public void close() throws CacheException, IgniteInterruptedException;
+    @Override public void close() throws CacheException, IgniteInterruptedException,
+        IgniteDataStreamerTimeoutException;
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/cd1d618e/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamerTimeoutException.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamerTimeoutException.java b/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamerTimeoutException.java
new file mode 100644
index 0000000..c6c7367
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteDataStreamerTimeoutException.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+/**
+ * Exception is thrown when timeout of some {@link IgniteDataStreamer} operations occurs.
+ */
+public class IgniteDataStreamerTimeoutException extends IgniteException {
+    /** */
+    private static final long serialVersionUID = 0L;
+
+    /**
+     * Creates new timeout exception with given error message.
+     *
+     * @param msg Error message.
+     */
+    public IgniteDataStreamerTimeoutException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Creates new timeout exception with given error message and optional nested exception.
+     *
+     * @param msg Error message.
+     * @param cause Optional nested exception (can be {@code null}).
+     */
+    public IgniteDataStreamerTimeoutException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cd1d618e/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 9dc6a7f..21df559 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
@@ -46,6 +46,7 @@ import org.apache.ignite.IgniteDataStreamer;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteInterruptedException;
 import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.IgniteDataStreamerTimeoutException;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.cluster.ClusterTopologyException;
 import org.apache.ignite.configuration.CacheConfiguration;
@@ -53,6 +54,7 @@ import org.apache.ignite.events.DiscoveryEvent;
 import org.apache.ignite.events.Event;
 import org.apache.ignite.internal.GridKernalContext;
 import org.apache.ignite.internal.IgniteClientDisconnectedCheckedException;
+import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
 import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.IgniteInterruptedCheckedException;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
@@ -147,6 +149,9 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
     private int parallelOps = DFLT_MAX_PARALLEL_OPS;
 
     /** */
+    private long timeout = DFLT_UNLIMIT_TIMEOUT;
+
+    /** */
     private long autoFlushFreq;
 
     /** Mapping. */
@@ -453,6 +458,19 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
     }
 
     /** {@inheritDoc} */
+    @Override public void timeout(long timeout) {
+        if (timeout < -1 || timeout == 0)
+            throw new IllegalArgumentException();
+
+        this.timeout = timeout;
+    }
+
+    /** {@inheritDoc} */
+    @Override public long timeout() {
+        return this.timeout;
+    }
+
+    /** {@inheritDoc} */
     @Override public long autoFlushFrequency() {
         return autoFlushFreq;
     }
@@ -517,6 +535,9 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
 
             return new IgniteCacheFutureImpl<>(resFut);
         }
+        catch (IgniteDataStreamerTimeoutException e) {
+            throw e;
+        }
         catch (IgniteException e) {
             return new IgniteFinishedFutureImpl<>(e);
         }
@@ -572,7 +593,7 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
         catch (Throwable e) {
             resFut.onDone(e);
 
-            if (e instanceof Error)
+            if (e instanceof Error || e instanceof IgniteDataStreamerTimeoutException)
                 throw e;
 
             return new IgniteFinishedFutureImpl<>(e);
@@ -854,9 +875,20 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
 
                 boolean err = false;
 
+                long startTimeMillis = U.currentTimeMillis();
+
                 for (IgniteInternalFuture fut = q.poll(); fut != null; fut = q.poll()) {
                     try {
-                        fut.get();
+                        if (timeout == DFLT_UNLIMIT_TIMEOUT)
+                            fut.get();
+                        else {
+                            long timeRemain = timeout - U.currentTimeMillis() + startTimeMillis;
+
+                            if (timeRemain <= 0)
+                                throw new IgniteDataStreamerTimeoutException("Data streamer exceeded timeout on flush.");
+
+                            fut.get(timeRemain);
+                        }
                     }
                     catch (IgniteClientDisconnectedCheckedException e) {
                         if (log.isDebugEnabled())
@@ -864,6 +896,12 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
 
                         throw CU.convertToCacheException(e);
                     }
+                    catch (IgniteFutureTimeoutCheckedException e) {
+                        if (log.isDebugEnabled())
+                            log.debug("Failed to flush buffer: " + e);
+
+                        throw new IgniteDataStreamerTimeoutException("Data streamer exceeded timeout on flush.", e);
+                    }
                     catch (IgniteCheckedException e) {
                         if (log.isDebugEnabled())
                             log.debug("Failed to flush buffer: " + e);
@@ -976,8 +1014,6 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
         if (log.isDebugEnabled())
             log.debug("Closing data streamer [ldr=" + this + ", cancel=" + cancel + ']');
 
-        IgniteCheckedException e = null;
-
         try {
             // Assuming that no methods are called on this loader after this method is called.
             if (cancel) {
@@ -993,14 +1029,12 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
 
             ctx.io().removeMessageListener(topic);
         }
-        catch (IgniteCheckedException e0) {
-            e = e0;
+        catch (IgniteCheckedException | IgniteDataStreamerTimeoutException e) {
+            fut.onDone(e);
+            throw e;
         }
 
-        fut.onDone(null, e != null ? e : err);
-
-        if (e != null)
-            throw e;
+        fut.onDone(err);
     }
 
     /**
@@ -1242,7 +1276,15 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
          * @throws IgniteInterruptedCheckedException If thread has been interrupted.
          */
         private void incrementActiveTasks() throws IgniteInterruptedCheckedException {
-            U.acquire(sem);
+            if (timeout == DFLT_UNLIMIT_TIMEOUT)
+                U.acquire(sem);
+            else
+                if (!U.tryAcquire(sem, timeout, TimeUnit.MILLISECONDS)) {
+                    if (log.isDebugEnabled())
+                        log.debug("Failed to add parallel operation.");
+
+                    throw new IgniteDataStreamerTimeoutException("Data streamer exceeded timeout when starts parallel operation.");
+                }
         }
 
         /**
@@ -1268,7 +1310,12 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
             assert !entries.isEmpty();
             assert curFut != null;
 
-            incrementActiveTasks();
+            try {
+                incrementActiveTasks();
+            } catch (IgniteDataStreamerTimeoutException e) {
+                curFut.onDone(e);
+                throw e;
+            }
 
             IgniteInternalFuture<Object> fut;
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/cd1d618e/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index fee4f378..269795b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -7462,6 +7462,27 @@ public abstract class IgniteUtils {
     }
 
     /**
+     * Tries to acquire a permit from provided semaphore during {@code timeout}.
+     *
+     * @param sem Semaphore.
+     * @param timeout The maximum time to wait.
+     * @param unit The unit of the {@code time} argument.
+     * @throws org.apache.ignite.internal.IgniteInterruptedCheckedException Wrapped {@link InterruptedException}.
+     * @return {@code True} if acquires a permit, {@code false} another.
+     */
+    public static boolean tryAcquire(Semaphore sem, long timeout, TimeUnit unit)
+        throws IgniteInterruptedCheckedException {
+        try {
+            return sem.tryAcquire(timeout, unit);
+        }
+        catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+
+            throw new IgniteInterruptedCheckedException(e);
+        }
+    }
+
+    /**
      * Gets cache attributes for the node.
      *
      * @param n Node to get cache attributes for.

http://git-wip-us.apache.org/repos/asf/ignite/blob/cd1d618e/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerTimeoutTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerTimeoutTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerTimeoutTest.java
new file mode 100644
index 0000000..4e981b7
--- /dev/null
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerTimeoutTest.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.processors.datastreamer;
+
+import java.util.Collection;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteDataStreamerTimeoutException;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.stream.StreamReceiver;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Test timeout for Data streamer.
+ */
+public class DataStreamerTimeoutTest extends GridCommonAbstractTest {
+
+    /** Cache name. */
+    public static final String CACHE_NAME = "cacheName";
+
+    /** Timeout. */
+    public static final int TIMEOUT = 1_000;
+
+    /** Amount of entries. */
+    public static final int ENTRY_AMOUNT = 100;
+
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+        cfg.setCacheConfiguration(cacheConfiguration());
+
+        return cfg;
+    }
+
+    /**
+     * Gets cache configuration.
+     *
+     * @return Cache configuration.
+     */
+    private CacheConfiguration cacheConfiguration() {
+        CacheConfiguration cacheCfg = defaultCacheConfiguration();
+
+        cacheCfg.setCacheMode(PARTITIONED);
+        cacheCfg.setBackups(1);
+        cacheCfg.setWriteSynchronizationMode(FULL_SYNC);
+        cacheCfg.setName(CACHE_NAME);
+
+        return cacheCfg;
+    }
+
+    /**
+     * Test timeout on {@code DataStreamer.addData()} method
+     * @throws Exception If fail.
+     */
+    public void testTimeoutOnCloseMethod() throws Exception {
+        Ignite ignite = startGrid(1);
+
+        boolean thrown = false;
+
+        try (IgniteDataStreamer ldr = ignite.dataStreamer(CACHE_NAME)) {
+            ldr.timeout(TIMEOUT);
+            ldr.receiver(new TestDataReceiver());
+            ldr.perNodeBufferSize(ENTRY_AMOUNT);
+
+            for (int i=0; i < ENTRY_AMOUNT; i++)
+                ldr.addData(i, i);
+
+        }
+        catch (IgniteDataStreamerTimeoutException e) {
+            assertEquals(e.getMessage(), "Data streamer exceeded timeout on flush.");
+            thrown = true;
+        }
+        finally {
+            stopAllGrids();
+        }
+
+        assertTrue(thrown);
+    }
+
+    /**
+     * Test timeout on {@code DataStreamer.close()} method
+     * @throws Exception If fail.
+     */
+    public void testTimeoutOnAddDataMethod() throws Exception {
+        Ignite ignite = startGrid(1);
+
+        boolean thrown = false;
+
+        IgniteDataStreamer ldr = ignite.dataStreamer(CACHE_NAME);
+
+        try {
+            ldr.timeout(TIMEOUT);
+            ldr.receiver(new TestDataReceiver());
+            ldr.perNodeBufferSize(ENTRY_AMOUNT/2);
+            ldr.perNodeParallelOperations(1);
+
+            try {
+                for (int i=0; i < ENTRY_AMOUNT; i++)
+                    ldr.addData(i, i);
+            }
+            catch (IgniteDataStreamerTimeoutException e) {
+                assertEquals(e.getMessage(), "Data streamer exceeded timeout when starts parallel operation.");
+
+                thrown = true;
+            }
+
+        }
+        finally {
+            if (thrown)
+                ldr.close(true);
+
+            stopAllGrids();
+        }
+
+        assertTrue(thrown);
+    }
+
+    /**
+     * Test receiver for timeout expiration emulation.
+     */
+    private static class TestDataReceiver implements StreamReceiver {
+
+        /** Is first. */
+        boolean isFirst = true;
+
+        /** {@inheritDoc} */
+        @Override public void receive(IgniteCache cache, Collection collection) throws IgniteException {
+            try {
+                if (isFirst)
+                    U.sleep(2 * TIMEOUT);
+
+                isFirst = false;
+            }
+            catch (IgniteInterruptedCheckedException e) {
+                throw new IgniteException(e);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/cd1d618e/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
index 2e45faa..8c3f4de 100755
--- a/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
+++ b/modules/core/src/test/java/org/apache/ignite/testsuites/IgniteCacheTestSuite.java
@@ -141,6 +141,7 @@ import org.apache.ignite.internal.processors.datastreamer.DataStreamProcessorSel
 import org.apache.ignite.internal.processors.datastreamer.DataStreamerImplSelfTest;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamerMultiThreadedSelfTest;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamerMultinodeCreateCacheTest;
+import org.apache.ignite.internal.processors.datastreamer.DataStreamerTimeoutTest;
 import org.apache.ignite.internal.processors.datastreamer.DataStreamerUpdateAfterLoadTest;
 import org.apache.ignite.testframework.GridTestUtils;
 
@@ -249,6 +250,7 @@ public class IgniteCacheTestSuite extends TestSuite {
             suite.addTestSuite(DataStreamerMultiThreadedSelfTest.class);
         suite.addTestSuite(DataStreamerMultinodeCreateCacheTest.class);
         suite.addTestSuite(DataStreamerImplSelfTest.class);
+        suite.addTestSuite(DataStreamerTimeoutTest.class);
         GridTestUtils.addTestIfNeeded(suite, GridCacheEntryMemorySizeSelfTest.class, ignoredTests);
         suite.addTestSuite(GridCacheClearAllSelfTest.class);
         suite.addTestSuite(GridCacheObjectToStringSelfTest.class);


[07/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/controllers/common-module.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/controllers/common-module.js b/modules/web-console/src/main/js/controllers/common-module.js
deleted file mode 100644
index ba6ec62..0000000
--- a/modules/web-console/src/main/js/controllers/common-module.js
+++ /dev/null
@@ -1,1741 +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.
- */
-
-const consoleModule = angular.module('ignite-console.legacy',
-    [
-        'smart-table',
-        'treeControl',
-        'ui.grid',
-        'ui.grid.saveState',
-        'ui.grid.selection',
-        'ui.grid.resizeColumns',
-        'ui.grid.autoResize',
-        'ui.grid.exporter',
-        'nvd3',
-        'dndLists'
-        /* ignite:plugins */
-        /* endignite */
-    ]);
-
-import alertTemplate from '../views/templates/alert.jade!';
-
-consoleModule.run(['$rootScope', '$http', '$state', '$common', 'Auth', 'User', 'gettingStarted',
-    ($root, $http, $state, $common, Auth, User, gettingStarted) => {
-        $root.gettingStarted = gettingStarted;
-
-        $root.revertIdentity = function() {
-            $http
-                .get('/api/v1/admin/revert/identity')
-                .then(User.read)
-                .then(function(user) {
-                    $root.$broadcast('user', user);
-
-                    $state.go('settings.admin');
-                })
-                .catch(function(errMsg) {
-                    $common.showError($common.errorMessage(errMsg));
-                });
-        };
-    }
-]);
-
-// Modal popup configuration.
-consoleModule.config(['$modalProvider', ($modalProvider) => {
-    angular.extend($modalProvider.defaults, {
-        html: true
-    });
-}]);
-
-// Comboboxes configuration.
-consoleModule.config(['$popoverProvider', ($popoverProvider) => {
-    angular.extend($popoverProvider.defaults, {
-        trigger: 'manual',
-        placement: 'right',
-        container: 'body',
-        templateUrl: '/templates/validation-error.html'
-    });
-}]);
-
-// Tooltips configuration.
-consoleModule.config(['$tooltipProvider', ($tooltipProvider) => {
-    angular.extend($tooltipProvider.defaults, {
-        container: 'body',
-        delay: 150,
-        placement: 'right',
-        html: 'true',
-        trigger: 'click hover'
-    });
-}]);
-
-// Comboboxes configuration.
-consoleModule.config(['$selectProvider', ($selectProvider) => {
-    angular.extend($selectProvider.defaults, {
-        container: 'body',
-        maxLength: '5',
-        allText: 'Select All',
-        noneText: 'Clear All',
-        templateUrl: '/templates/select.html',
-        iconCheckmark: 'fa fa-check',
-        caretHtml: ''
-    });
-}]);
-
-// Alerts configuration.
-consoleModule.config(['$alertProvider', ($alertProvider) => {
-    angular.extend($alertProvider.defaults, {
-        container: 'body',
-        placement: 'top-right',
-        duration: '5',
-        template: alertTemplate(),
-        type: 'danger'
-    });
-}]);
-
-// Modals configuration.
-consoleModule.config(['$modalProvider', ($modalProvider) => {
-    angular.extend($modalProvider.defaults, {
-        animation: 'am-fade-and-scale'
-    });
-}]);
-
-// Dropdowns configuration.
-consoleModule.config(['$dropdownProvider', ($dropdownProvider) => {
-    angular.extend($dropdownProvider.defaults, {
-        templateUrl: 'templates/dropdown.html'
-    });
-}]);
-
-// Common functions to be used in controllers.
-consoleModule.service('$common', ['$alert', '$popover', '$anchorScroll', '$location', '$timeout', '$focus', '$window',
-    ($alert, $popover, $anchorScroll, $location, $timeout, $focus, $window) => {
-        $anchorScroll.yOffset = 55;
-
-        function isDefined(v) {
-            return !_.isNil(v);
-        }
-
-        function isEmptyString(s) {
-            if (isDefined(s))
-                return s.trim().length === 0;
-
-            return true;
-        }
-
-        let msgModal;
-
-        function errorMessage(errMsg) {
-            if (errMsg) {
-                if (errMsg.hasOwnProperty('message'))
-                    return errMsg.message;
-
-                return errMsg;
-            }
-
-            return 'Internal server error.';
-        }
-
-        function showError(msg, placement, container, persistent, icon) {
-            if (msgModal)
-                msgModal.hide();
-
-            msgModal = $alert({
-                title: errorMessage(msg),
-                placement: placement ? placement : 'top-right',
-                container: container ? container : 'body',
-                duration: persistent ? false : 10
-            });
-
-            msgModal.$scope.icon = icon ? icon : 'fa-exclamation-triangle';
-
-            return false;
-        }
-
-        const javaBuiltInClasses = [
-            'BigDecimal', 'Boolean', 'Byte', 'Date', 'Double', 'Float', 'Integer', 'Long', 'Object', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
-        ];
-
-        const javaBuiltInTypes = [
-            'BigDecimal', 'boolean', 'Boolean', 'byte', 'Byte', 'Date', 'double', 'Double', 'float', 'Float',
-            'int', 'Integer', 'long', 'Long', 'Object', 'short', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
-        ];
-
-        const javaBuiltInFullNameClasses = [
-            'java.math.BigDecimal', 'java.lang.Boolean', 'java.lang.Byte', 'java.sql.Date', 'java.lang.Double',
-            'java.lang.Float', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Object', 'java.lang.Short',
-            'java.lang.String', 'java.sql.Time', 'java.sql.Timestamp', 'java.util.UUID'
-        ];
-
-        /**
-         * @param clsName Class name to check.
-         * @returns {Boolean} 'true' if given class name is a java build-in type.
-         */
-        function isJavaBuiltInClass(clsName) {
-            if (isEmptyString(clsName))
-                return false;
-
-            return _.includes(javaBuiltInClasses, clsName) || _.includes(javaBuiltInFullNameClasses, clsName);
-        }
-
-        const SUPPORTED_JDBC_TYPES = [
-            'BIGINT',
-            'BIT',
-            'BOOLEAN',
-            'BLOB',
-            'CHAR',
-            'CLOB',
-            'DATE',
-            'DECIMAL',
-            'DOUBLE',
-            'FLOAT',
-            'INTEGER',
-            'LONGNVARCHAR',
-            'LONGVARCHAR',
-            'NCHAR',
-            'NUMERIC',
-            'NVARCHAR',
-            'REAL',
-            'SMALLINT',
-            'TIME',
-            'TIMESTAMP',
-            'TINYINT',
-            'VARCHAR'
-        ];
-
-        const ALL_JDBC_TYPES = [
-            {dbName: 'BIT', dbType: -7, javaType: 'Boolean', primitiveType: 'boolean'},
-            {dbName: 'TINYINT', dbType: -6, javaType: 'Byte', primitiveType: 'byte'},
-            {dbName: 'SMALLINT', dbType: 5, javaType: 'Short', primitiveType: 'short'},
-            {dbName: 'INTEGER', dbType: 4, javaType: 'Integer', primitiveType: 'int'},
-            {dbName: 'BIGINT', dbType: -5, javaType: 'Long', primitiveType: 'long'},
-            {dbName: 'FLOAT', dbType: 6, javaType: 'Float', primitiveType: 'float'},
-            {dbName: 'REAL', dbType: 7, javaType: 'Double', primitiveType: 'double'},
-            {dbName: 'DOUBLE', dbType: 8, javaType: 'Double', primitiveType: 'double'},
-            {dbName: 'NUMERIC', dbType: 2, javaType: 'BigDecimal'},
-            {dbName: 'DECIMAL', dbType: 3, javaType: 'BigDecimal'},
-            {dbName: 'CHAR', dbType: 1, javaType: 'String'},
-            {dbName: 'VARCHAR', dbType: 12, javaType: 'String'},
-            {dbName: 'LONGVARCHAR', dbType: -1, javaType: 'String'},
-            {dbName: 'DATE', dbType: 91, javaType: 'Date'},
-            {dbName: 'TIME', dbType: 92, javaType: 'Time'},
-            {dbName: 'TIMESTAMP', dbType: 93, javaType: 'Timestamp'},
-            {dbName: 'BINARY', dbType: -2, javaType: 'Object'},
-            {dbName: 'VARBINARY', dbType: -3, javaType: 'Object'},
-            {dbName: 'LONGVARBINARY', dbType: -4, javaType: 'Object'},
-            {dbName: 'NULL', dbType: 0, javaType: 'Object'},
-            {dbName: 'OTHER', dbType: 1111, javaType: 'Object'},
-            {dbName: 'JAVA_OBJECT', dbType: 2000, javaType: 'Object'},
-            {dbName: 'DISTINCT', dbType: 2001, javaType: 'Object'},
-            {dbName: 'STRUCT', dbType: 2002, javaType: 'Object'},
-            {dbName: 'ARRAY', dbType: 2003, javaType: 'Object'},
-            {dbName: 'BLOB', dbType: 2004, javaType: 'Object'},
-            {dbName: 'CLOB', dbType: 2005, javaType: 'String'},
-            {dbName: 'REF', dbType: 2006, javaType: 'Object'},
-            {dbName: 'DATALINK', dbType: 70, javaType: 'Object'},
-            {dbName: 'BOOLEAN', dbType: 16, javaType: 'Boolean', primitiveType: 'boolean'},
-            {dbName: 'ROWID', dbType: -8, javaType: 'Object'},
-            {dbName: 'NCHAR', dbType: -15, javaType: 'String'},
-            {dbName: 'NVARCHAR', dbType: -9, javaType: 'String'},
-            {dbName: 'LONGNVARCHAR', dbType: -16, javaType: 'String'},
-            {dbName: 'NCLOB', dbType: 2011, javaType: 'String'},
-            {dbName: 'SQLXML', dbType: 2009, javaType: 'Object'}
-        ];
-
-        /*eslint-disable */
-        const JAVA_KEYWORDS = [
-            'abstract',     'assert',        'boolean',      'break',           'byte',
-            'case',         'catch',         'char',         'class',           'const',
-            'continue',     'default',       'do',           'double',          'else',
-            'enum',         'extends',       'false',        'final',           'finally',
-            'float',        'for',           'goto',         'if',              'implements',
-            'import',       'instanceof',    'int',          'interface',       'long',
-            'native',       'new',           'null',         'package',         'private',
-            'protected',    'public',        'return',       'short',           'static',
-            'strictfp',     'super',         'switch',       'synchronized',    'this',
-            'throw',        'throws',        'transient',    'true',            'try',
-            'void',         'volatile',      'while'
-        ];
-        /*eslint-enable */
-
-        const VALID_JAVA_IDENTIFIER = new RegExp('^[a-zA-Z_$][a-zA-Z\\d_$]*$');
-
-        let popover = null;
-
-        function isElementInViewport(el) {
-            const rect = el.getBoundingClientRect();
-
-            return (
-                rect.top >= 0 &&
-                rect.left >= 0 &&
-                rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
-                rect.right <= (window.innerWidth || document.documentElement.clientWidth)
-            );
-        }
-
-        const _showPopoverMessage = (id, message, showTime) => {
-            const body = $('body');
-
-            let el = body.find('#' + id);
-
-            if (!el || el.length === 0)
-                el = body.find('[name="' + id + '"]');
-
-            if (el && el.length > 0) {
-                if (!isElementInViewport(el[0])) {
-                    $location.hash(el[0].id);
-
-                    $anchorScroll();
-                }
-
-                const newPopover = $popover(el, {content: message});
-
-                popover = newPopover;
-
-                $timeout(() => newPopover.$promise.then(newPopover.show), 400);
-                $timeout(() => newPopover.hide(), showTime || 5000);
-            }
-        };
-
-        function ensureActivePanel(ui, pnl, focusId) {
-            if (ui) {
-                const collapses = $('div.panel-collapse');
-
-                ui.loadPanel(pnl);
-
-                const idx = _.findIndex(collapses, function(collapse) {
-                    return collapse.id === pnl;
-                });
-
-                if (idx >= 0) {
-                    const activePanels = ui.activePanels;
-
-                    if (!_.includes(ui.topPanels, idx)) {
-                        ui.expanded = true;
-
-                        const customExpanded = ui[pnl];
-
-                        if (customExpanded)
-                            ui[customExpanded] = true;
-                    }
-
-                    if (!activePanels || activePanels.length < 1)
-                        ui.activePanels = [idx];
-                    else if (!_.includes(activePanels, idx)) {
-                        const newActivePanels = angular.copy(activePanels);
-
-                        newActivePanels.push(idx);
-
-                        ui.activePanels = newActivePanels;
-                    }
-                }
-
-                if (isDefined(focusId))
-                    $focus(focusId);
-            }
-        }
-
-        function showPopoverMessage(ui, panelId, id, message, showTime) {
-            if (popover)
-                popover.hide();
-
-            if (ui) {
-                ensureActivePanel(ui, panelId);
-
-                $timeout(() => _showPopoverMessage(id, message, showTime), ui.isPanelLoaded(panelId) ? 200 : 500);
-            }
-            else
-                _showPopoverMessage(id, message, showTime);
-
-            return false;
-        }
-
-        function isValidJavaIdentifier(msg, ident, elemId, panels, panelId) {
-            if (isEmptyString(ident))
-                return showPopoverMessage(panels, panelId, elemId, msg + ' is invalid!');
-
-            if (_.includes(JAVA_KEYWORDS, ident))
-                return showPopoverMessage(panels, panelId, elemId, msg + ' could not contains reserved java keyword: "' + ident + '"!');
-
-            if (!VALID_JAVA_IDENTIFIER.test(ident))
-                return showPopoverMessage(panels, panelId, elemId, msg + ' contains invalid identifier: "' + ident + '"!');
-
-            return true;
-        }
-
-        let context = null;
-
-        /**
-         * Calculate width of specified text in body's font.
-         *
-         * @param text Text to calculate width.
-         * @returns {Number} Width of text in pixels.
-         */
-        function measureText(text) {
-            if (!context) {
-                const canvas = document.createElement('canvas');
-
-                context = canvas.getContext('2d');
-
-                const style = window.getComputedStyle(document.getElementsByTagName('body')[0]);
-
-                context.font = style.fontSize + ' ' + style.fontFamily;
-            }
-
-            return context.measureText(text).width;
-        }
-
-        /**
-         * Compact java full class name by max number of characters.
-         *
-         * @param names Array of class names to compact.
-         * @param nameLength Max available width in characters for simple name.
-         * @returns {*} Array of compacted class names.
-         */
-        function compactByMaxCharts(names, nameLength) {
-            for (let nameIx = 0; nameIx < names.length; nameIx++) {
-                const s = names[nameIx];
-
-                if (s.length > nameLength) {
-                    let totalLength = s.length;
-
-                    const packages = s.split('.');
-
-                    const packageCnt = packages.length - 1;
-
-                    for (let i = 0; i < packageCnt && totalLength > nameLength; i++) {
-                        if (packages[i].length > 0) {
-                            totalLength -= packages[i].length - 1;
-
-                            packages[i] = packages[i][0];
-                        }
-                    }
-
-                    if (totalLength > nameLength) {
-                        const className = packages[packageCnt];
-
-                        const classNameLen = className.length;
-
-                        let remains = Math.min(nameLength - totalLength + classNameLen, classNameLen);
-
-                        if (remains < 3)
-                            remains = Math.min(3, classNameLen);
-
-                        packages[packageCnt] = className.substring(0, remains) + '...';
-                    }
-
-                    let result = packages[0];
-
-                    for (let i = 1; i < packages.length; i++)
-                        result += '.' + packages[i];
-
-                    names[nameIx] = result;
-                }
-            }
-
-            return names;
-        }
-
-        /**
-         * Compact java full class name by max number of pixels.
-         *
-         * @param names Array of class names to compact.
-         * @param nameLength Max available width in characters for simple name. Used for calculation optimization.
-         * @param nameWidth Maximum available width in pixels for simple name.
-         * @returns {*} Array of compacted class names.
-         */
-        function compactByMaxPixels(names, nameLength, nameWidth) {
-            if (nameWidth <= 0)
-                return names;
-
-            const fitted = [];
-
-            const widthByName = [];
-
-            const len = names.length;
-
-            let divideTo = len;
-
-            for (let nameIx = 0; nameIx < len; nameIx++) {
-                fitted[nameIx] = false;
-
-                widthByName[nameIx] = nameWidth;
-            }
-
-            // Try to distribute space from short class names to long class names.
-            let remains = 0;
-
-            do {
-                for (let nameIx = 0; nameIx < len; nameIx++) {
-                    if (!fitted[nameIx]) {
-                        const curNameWidth = measureText(names[nameIx]);
-
-                        if (widthByName[nameIx] > curNameWidth) {
-                            fitted[nameIx] = true;
-
-                            remains += widthByName[nameIx] - curNameWidth;
-
-                            divideTo -= 1;
-
-                            widthByName[nameIx] = curNameWidth;
-                        }
-                    }
-                }
-
-                const remainsByName = remains / divideTo;
-
-                for (let nameIx = 0; nameIx < len; nameIx++) {
-                    if (!fitted[nameIx])
-                        widthByName[nameIx] += remainsByName;
-                }
-            }
-            while (remains > 0);
-
-            // Compact class names to available for each space.
-            for (let nameIx = 0; nameIx < len; nameIx++) {
-                const s = names[nameIx];
-
-                if (s.length > (nameLength / 2 | 0)) {
-                    let totalWidth = measureText(s);
-
-                    if (totalWidth > widthByName[nameIx]) {
-                        const packages = s.split('.');
-
-                        const packageCnt = packages.length - 1;
-
-                        for (let i = 0; i < packageCnt && totalWidth > widthByName[nameIx]; i++) {
-                            if (packages[i].length > 1) {
-                                totalWidth -= measureText(packages[i].substring(1, packages[i].length));
-
-                                packages[i] = packages[i][0];
-                            }
-                        }
-
-                        let shortPackage = '';
-
-                        for (let i = 0; i < packageCnt; i++)
-                            shortPackage += packages[i] + '.';
-
-                        const className = packages[packageCnt];
-
-                        const classLen = className.length;
-
-                        let minLen = Math.min(classLen, 3);
-
-                        totalWidth = measureText(shortPackage + className);
-
-                        // Compact class name if shorten package path is very long.
-                        if (totalWidth > widthByName[nameIx]) {
-                            let maxLen = classLen;
-                            let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
-
-                            while (middleLen !== minLen && middleLen !== maxLen) {
-                                const middleLenPx = measureText(shortPackage + className.substr(0, middleLen) + '...');
-
-                                if (middleLenPx > widthByName[nameIx])
-                                    maxLen = middleLen;
-                                else
-                                    minLen = middleLen;
-
-                                middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
-                            }
-
-                            names[nameIx] = shortPackage + className.substring(0, middleLen) + '...';
-                        }
-                        else
-                            names[nameIx] = shortPackage + className;
-                    }
-                }
-            }
-
-            return names;
-        }
-
-        /**
-         * Compact any string by max number of pixels.
-         *
-         * @param label String to compact.
-         * @param nameWidth Maximum available width in pixels for simple name.
-         * @returns {*} Compacted string.
-         */
-        function compactLabelByPixels(label, nameWidth) {
-            if (nameWidth <= 0)
-                return label;
-
-            const totalWidth = measureText(label);
-
-            if (totalWidth > nameWidth) {
-                let maxLen = label.length;
-                let minLen = Math.min(maxLen, 3);
-                let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
-
-                while (middleLen !== minLen && middleLen !== maxLen) {
-                    const middleLenPx = measureText(label.substr(0, middleLen) + '...');
-
-                    if (middleLenPx > nameWidth)
-                        maxLen = middleLen;
-                    else
-                        minLen = middleLen;
-
-                    middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
-                }
-
-                return label.substring(0, middleLen) + '...';
-            }
-
-            return label;
-        }
-
-        /**
-         * Calculate available width for text in link to edit element.
-         *
-         * @param index Showed index of element for calculation of maximum width in pixels.
-         * @param id Id of contains link table.
-         * @returns {*[]} First element is length of class for single value, second element is length for pair vlaue.
-         */
-        function availableWidth(index, id) {
-            const idElem = $('#' + id);
-
-            let width = 0;
-
-            switch (idElem.prop('tagName')) {
-                // Detection of available width in presentation table row.
-                case 'TABLE':
-                    const cont = $(idElem.find('tr')[index - 1]).find('td')[0];
-
-                    width = cont.clientWidth;
-
-                    if (width > 0) {
-                        const children = $(cont).children(':not("a")');
-
-                        _.forEach(children, function(child) {
-                            if ('offsetWidth' in child)
-                                width -= $(child).outerWidth(true);
-                        });
-                    }
-
-                    break;
-
-                // Detection of available width in dropdown row.
-                case 'A':
-                    width = idElem.width();
-
-                    $(idElem).children(':not("span")').each(function(ix, child) {
-                        if ('offsetWidth' in child)
-                            width -= child.offsetWidth;
-                    });
-
-                    break;
-
-                default:
-            }
-
-            return width | 0;
-        }
-
-        function getModel(obj, field) {
-            let path = field.path;
-
-            if (!isDefined(path) || !isDefined(obj))
-                return obj;
-
-            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
-            path = path.replace(/^\./, '');           // strip a leading dot
-
-            const segs = path.split('.');
-            let root = obj;
-
-            while (segs.length > 0) {
-                const pathStep = segs.shift();
-
-                if (typeof root[pathStep] === 'undefined')
-                    root[pathStep] = {};
-
-                root = root[pathStep];
-            }
-
-            return root;
-        }
-
-        function extractDataSource(cache) {
-            if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) {
-                const storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];
-
-                if (storeFactory.dialect || (storeFactory.connectVia === 'DataSource'))
-                    return storeFactory;
-            }
-
-            return null;
-        }
-
-        const cacheStoreJdbcDialects = [
-            {value: 'Generic', label: 'Generic JDBC'},
-            {value: 'Oracle', label: 'Oracle'},
-            {value: 'DB2', label: 'IBM DB2'},
-            {value: 'SQLServer', label: 'Microsoft SQL Server'},
-            {value: 'MySQL', label: 'MySQL'},
-            {value: 'PostgreSQL', label: 'PostgreSQL'},
-            {value: 'H2', label: 'H2 database'}
-        ];
-
-        function domainForStoreConfigured(domain) {
-            const isEmpty = !isDefined(domain) || (isEmptyString(domain.databaseSchema) &&
-                isEmptyString(domain.databaseTable) &&
-                _.isEmpty(domain.keyFields) &&
-                _.isEmpty(domain.valueFields));
-
-            return !isEmpty;
-        }
-
-        const DS_CHECK_SUCCESS = { checked: true };
-
-        function compareDataSources(firstCache, secondCache) {
-            const firstDs = extractDataSource(firstCache);
-            const secondDs = extractDataSource(secondCache);
-
-            if (firstDs && secondDs) {
-                const firstDB = firstDs.dialect;
-                const secondDB = secondDs.dialect;
-
-                if (firstDs.dataSourceBean === secondDs.dataSourceBean && firstDB !== secondDB)
-                    return {checked: false, firstCache, firstDB, secondCache, secondDB};
-            }
-
-            return DS_CHECK_SUCCESS;
-        }
-
-        function compareSQLSchemaNames(firstCache, secondCache) {
-            const firstName = firstCache.sqlSchema;
-            const secondName = secondCache.sqlSchema;
-
-            if (firstName && secondName && (firstName === secondName))
-                return {checked: false, firstCache, secondCache};
-
-            return DS_CHECK_SUCCESS;
-        }
-
-        function toJavaName(prefix, name) {
-            const javaName = name ? name.replace(/[^A-Za-z_0-9]+/g, '_') : 'dflt';
-
-            return prefix + javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
-        }
-
-        return {
-            getModel,
-            mkOptions(options) {
-                return _.map(options, (option) => {
-                    return {value: option, label: isDefined(option) ? option : 'Not set'};
-                });
-            },
-            isDefined,
-            hasProperty(obj, props) {
-                for (const propName in props) {
-                    if (props.hasOwnProperty(propName)) {
-                        if (obj[propName])
-                            return true;
-                    }
-                }
-
-                return false;
-            },
-            isEmptyString,
-            errorMessage,
-            hideAlert() {
-                if (msgModal)
-                    msgModal.hide();
-            },
-            showError,
-            showInfo(msg) {
-                if (msgModal)
-                    msgModal.hide();
-
-                msgModal = $alert({
-                    type: 'success',
-                    title: msg,
-                    duration: 2
-                });
-
-                msgModal.$scope.icon = 'fa-check-circle-o';
-            },
-            SUPPORTED_JDBC_TYPES,
-            findJdbcType(jdbcType) {
-                const res = _.find(ALL_JDBC_TYPES, function(item) {
-                    return item.dbType === jdbcType;
-                });
-
-                return res ? res : {dbName: 'Unknown', javaType: 'Unknown'};
-            },
-            javaBuiltInClasses,
-            javaBuiltInTypes,
-            isJavaBuiltInClass,
-            isValidJavaIdentifier,
-            isValidJavaClass(msg, ident, allowBuiltInClass, elemId, packageOnly, panels, panelId) {
-                if (isEmptyString(ident))
-                    return showPopoverMessage(panels, panelId, elemId, msg + ' could not be empty!');
-
-                const parts = ident.split('.');
-
-                const len = parts.length;
-
-                if (!allowBuiltInClass && isJavaBuiltInClass(ident))
-                    return showPopoverMessage(panels, panelId, elemId, msg + ' should not be the Java build-in class!');
-
-                if (len < 2 && !isJavaBuiltInClass(ident) && !packageOnly)
-                    return showPopoverMessage(panels, panelId, elemId, msg + ' does not have package specified!');
-
-                for (let i = 0; i < parts.length; i++) {
-                    const part = parts[i];
-
-                    if (!isValidJavaIdentifier(msg, part, elemId, panels, panelId))
-                        return false;
-                }
-
-                return true;
-            },
-            domainForQueryConfigured(domain) {
-                const isEmpty = !isDefined(domain) || (_.isEmpty(domain.fields) &&
-                    _.isEmpty(domain.aliases) &&
-                    _.isEmpty(domain.indexes));
-
-                return !isEmpty;
-            },
-            domainForStoreConfigured,
-            /**
-             * Cut class name by width in pixel or width in symbol count.
-             *
-             * @param id Id of parent table.
-             * @param index Row number in table.
-             * @param maxLength Maximum length in symbols for all names.
-             * @param names Array of class names to compact.
-             * @param divider String to visualy divide items.
-             * @returns {*} Array of compacted class names.
-             */
-            compactJavaName(id, index, maxLength, names, divider) {
-                divider = ' ' + divider + ' ';
-
-                const prefix = index + ') ';
-
-                const nameCnt = names.length;
-
-                const nameLength = ((maxLength - 3 * (nameCnt - 1)) / nameCnt) | 0;
-
-                try {
-                    const nameWidth = (availableWidth(index, id) - measureText(prefix) - (nameCnt - 1) * measureText(divider)) /
-                        nameCnt | 0;
-
-                    // HTML5 calculation of showed message width.
-                    names = compactByMaxPixels(names, nameLength, nameWidth);
-                }
-                catch (err) {
-                    names = compactByMaxCharts(names, nameLength);
-                }
-
-                let result = prefix + names[0];
-
-                for (let nameIx = 1; nameIx < names.length; nameIx++)
-                    result += divider + names[nameIx];
-
-                return result;
-            },
-            /**
-             * Compact text by width in pixels or symbols count.
-             *
-             * @param id Id of parent table.
-             * @param index Row number in table.
-             * @param maxLength Maximum length in symbols for all names.
-             * @param label Text to compact.
-             * @returns Compacted label text.
-             */
-            compactTableLabel(id, index, maxLength, label) {
-                label = index + ') ' + label;
-
-                try {
-                    const nameWidth = availableWidth(index, id) | 0;
-
-                    // HTML5 calculation of showed message width.
-                    label = compactLabelByPixels(label, nameWidth);
-                }
-                catch (err) {
-                    const nameLength = maxLength - 3 | 0;
-
-                    label = label.length > maxLength ? label.substr(0, nameLength) + '...' : label;
-                }
-
-                return label;
-            },
-            widthIsSufficient(id, index, text) {
-                try {
-                    const available = availableWidth(index, id);
-
-                    const required = measureText(text);
-
-                    return !available || available >= Math.floor(required);
-                }
-                catch (err) {
-                    return true;
-                }
-            },
-            ensureActivePanel(panels, id, focusId) {
-                ensureActivePanel(panels, id, focusId);
-            },
-            showPopoverMessage,
-            hidePopover() {
-                if (popover)
-                    popover.hide();
-            },
-            confirmUnsavedChanges(dirty, selectFunc) {
-                if (dirty) {
-                    if ($window.confirm('You have unsaved changes.\n\nAre you sure you want to discard them?'))
-                        selectFunc();
-                }
-                else
-                    selectFunc();
-            },
-            saveBtnTipText(dirty, objectName) {
-                if (dirty)
-                    return 'Save ' + objectName;
-
-                return 'Nothing to save';
-            },
-            download(type, name, data) {
-                const file = document.createElement('a');
-
-                file.setAttribute('href', 'data:' + type + ';charset=utf-8,' + data);
-                file.setAttribute('download', name);
-                file.setAttribute('target', '_self');
-
-                file.style.display = 'none';
-
-                document.body.appendChild(file);
-
-                file.click();
-
-                document.body.removeChild(file);
-            },
-            formUI() {
-                return {
-                    ready: false,
-                    expanded: false,
-                    loadedPanels: [],
-                    loadPanel(pnl) {
-                        if (!_.includes(this.loadedPanels, pnl))
-                            this.loadedPanels.push(pnl);
-                    },
-                    isPanelLoaded(pnl) {
-                        return _.includes(this.loadedPanels, pnl);
-                    }
-                };
-            },
-            getQueryVariable(name) {
-                const attrs = window.location.search.substring(1).split('&');
-                const attr = _.find(attrs, (a) => a === name || (a.indexOf('=') >= 0 && a.substr(0, a.indexOf('=')) === name));
-
-                if (!isDefined(attr))
-                    return null;
-
-                if (attr === name)
-                    return true;
-
-                return attr.substr(attr.indexOf('=') + 1);
-            },
-            cacheStoreJdbcDialects,
-            cacheStoreJdbcDialectsLabel(dialect) {
-                const found = _.find(cacheStoreJdbcDialects, function(dialectVal) {
-                    return dialectVal.value === dialect;
-                });
-
-                return found ? found.label : null;
-            },
-            checkCachesDataSources(caches, checkCacheExt) {
-                let res = DS_CHECK_SUCCESS;
-
-                _.find(caches, function(curCache, curIx) {
-                    if (isDefined(checkCacheExt)) {
-                        if (checkCacheExt._id !== curCache._id) {
-                            res = compareDataSources(checkCacheExt, curCache);
-
-                            return !res.checked;
-                        }
-
-                        return false;
-                    }
-
-                    return _.find(caches, function(checkCache, checkIx) {
-                        if (checkIx < curIx) {
-                            res = compareDataSources(checkCache, curCache);
-
-                            return !res.checked;
-                        }
-
-                        return false;
-                    });
-                });
-
-                return res;
-            },
-            checkCacheSQLSchemas(caches, checkCacheExt) {
-                let res = DS_CHECK_SUCCESS;
-
-                _.find(caches, (curCache, curIx) => {
-                    if (isDefined(checkCacheExt)) {
-                        if (checkCacheExt._id !== curCache._id) {
-                            res = compareSQLSchemaNames(checkCacheExt, curCache);
-
-                            return !res.checked;
-                        }
-
-                        return false;
-                    }
-
-                    return _.find(caches, function(checkCache, checkIx) {
-                        if (checkIx < curIx) {
-                            res = compareSQLSchemaNames(checkCache, curCache);
-
-                            return !res.checked;
-                        }
-
-                        return false;
-                    });
-                });
-
-                return res;
-            },
-            autoCacheStoreConfiguration(cache, domains) {
-                const cacheStoreFactory = isDefined(cache.cacheStoreFactory) &&
-                    isDefined(cache.cacheStoreFactory.kind);
-
-                if (!cacheStoreFactory && _.findIndex(domains, domainForStoreConfigured) >= 0) {
-                    const dflt = !cache.readThrough && !cache.writeThrough;
-
-                    return {
-                        cacheStoreFactory: {
-                            kind: 'CacheJdbcPojoStoreFactory',
-                            CacheJdbcPojoStoreFactory: {
-                                dataSourceBean: toJavaName('ds', cache.name),
-                                dialect: 'Generic'
-                            }
-                        },
-                        readThrough: dflt || cache.readThrough,
-                        writeThrough: dflt || cache.writeThrough
-                    };
-                }
-            },
-            autoClusterSwapSpiConfiguration(cluster, caches) {
-                const swapConfigured = cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind;
-
-                if (!swapConfigured && _.find(caches, function(cache) {
-                    return cache.swapEnabled;
-                }))
-                    return {swapSpaceSpi: {kind: 'FileSwapSpaceSpi'}};
-
-                return null;
-            },
-            randomString(len) {
-                const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
-                const possibleLen = possible.length;
-
-                let res = '';
-
-                for (let i = 0; i < len; i++)
-                    res += possible.charAt(Math.floor(Math.random() * possibleLen));
-
-                return res;
-            },
-            checkFieldValidators(ui) {
-                const form = ui.inputForm;
-                const errors = form.$error;
-                const errKeys = Object.keys(errors);
-
-                if (errKeys && errKeys.length > 0) {
-                    const firstErrorKey = errKeys[0];
-
-                    const firstError = errors[firstErrorKey][0];
-                    const actualError = firstError.$error[firstErrorKey][0];
-
-                    const errNameFull = actualError.$name;
-                    const errNameShort = errNameFull.endsWith('TextInput') ? errNameFull.substring(0, errNameFull.length - 9) : errNameFull;
-
-                    const extractErrorMessage = function(errName) {
-                        try {
-                            return errors[firstErrorKey][0].$errorMessages[errName][firstErrorKey];
-                        }
-                        catch (ignored) {
-                            try {
-                                return form[firstError.$name].$errorMessages[errName][firstErrorKey];
-                            }
-                            catch (ignited) {
-                                return false;
-                            }
-                        }
-                    };
-
-                    const msg = extractErrorMessage(errNameFull) || extractErrorMessage(errNameShort) || 'Invalid value!';
-
-                    return showPopoverMessage(ui, firstError.$name, errNameFull, msg);
-                }
-
-                return true;
-            }
-        };
-    }]);
-
-// Confirm change location.
-consoleModule.service('$unsavedChangesGuard', ['$rootScope', ($root) => {
-    return {
-        install($scope, customDirtyCheck = () => $scope.ui.inputForm.$dirty) {
-            $scope.$on('$destroy', function() {
-                window.onbeforeunload = null;
-            });
-
-            const unbind = $root.$on('$stateChangeStart', function(event) {
-                if ($scope.ui && $scope.ui.inputForm && customDirtyCheck()) {
-                    if (!confirm('You have unsaved changes.\n\nAre you sure you want to discard them?')) // eslint-disable-line no-alert
-                        event.preventDefault();
-                    else
-                        unbind();
-                }
-            });
-
-            window.onbeforeunload = function() {
-                return $scope.ui && $scope.ui.inputForm && $scope.ui.inputForm.$dirty
-                    ? 'You have unsaved changes.\n\nAre you sure you want to discard them?'
-                    : null;
-            };
-        }
-    };
-}]);
-
-// Service for confirm or skip several steps.
-consoleModule.service('$confirmBatch', ['$modal', '$rootScope', '$q', ($modal, $root, $q) => {
-    const scope = $root.$new();
-
-    scope.confirmModal = $modal({templateUrl: '/templates/batch-confirm.html', scope, placement: 'center', show: false});
-
-    function _done(cancel) {
-        scope.confirmModal.hide();
-
-        if (cancel)
-            scope.deferred.reject('cancelled');
-        else
-            scope.deferred.resolve();
-    }
-
-    function _nextElement(skip) {
-        scope.items[scope.curIx++].skip = skip;
-
-        if (scope.curIx < scope.items.length)
-            scope.content = scope.contentGenerator(scope.items[scope.curIx]);
-        else
-            _done();
-    }
-
-    scope.cancel = function() {
-        _done(true);
-    };
-
-    scope.skip = function(applyToAll) {
-        if (applyToAll) {
-            for (let i = scope.curIx; i < scope.items.length; i++)
-                scope.items[i].skip = true;
-
-            _done();
-        }
-        else
-            _nextElement(true);
-    };
-
-    scope.overwrite = function(applyToAll) {
-        if (applyToAll)
-            _done();
-        else
-            _nextElement(false);
-    };
-
-    return {
-        /**
-         * Show confirm all dialog.
-         *
-             * @param confirmMessageFn Function to generate a confirm message.
-         * @param itemsToConfirm Array of element to process by confirm.
-         */
-        confirm(confirmMessageFn, itemsToConfirm) {
-            scope.deferred = $q.defer();
-
-            scope.contentGenerator = confirmMessageFn;
-
-            scope.items = itemsToConfirm;
-            scope.curIx = 0;
-            scope.content = (scope.items && scope.items.length > 0) ? scope.contentGenerator(scope.items[0]) : null;
-
-            scope.confirmModal.$promise.then(scope.confirmModal.show);
-
-            return scope.deferred.promise;
-        }
-    };
-}]);
-
-// 'Clone' popup service.
-consoleModule.service('$clone', ['$modal', '$rootScope', '$q', ($modal, $root, $q) => {
-    const scope = $root.$new();
-
-    let _names = [];
-    let deferred;
-    let _validator;
-
-    function _nextAvailableName(name) {
-        let num = 1;
-        let tmpName = name;
-
-        while (_.includes(_names, tmpName)) {
-            tmpName = name + '_' + num.toString();
-
-            num++;
-        }
-
-        return tmpName;
-    }
-
-    const cloneModal = $modal({templateUrl: '/templates/clone.html', scope, placement: 'center', show: false});
-
-    scope.ok = function(newName) {
-        if (!_validator || _validator(newName)) {
-            deferred.resolve(_nextAvailableName(newName));
-
-            cloneModal.hide();
-        }
-    };
-
-    cloneModal.confirm = function(oldName, names, validator) {
-        _names = names;
-
-        scope.newName = _nextAvailableName(oldName);
-
-        _validator = validator;
-
-        deferred = $q.defer();
-
-        cloneModal.$promise.then(cloneModal.show);
-
-        return deferred.promise;
-    };
-
-    return cloneModal;
-}]);
-
-// Tables support service.
-consoleModule.service('$table', ['$common', '$focus', function($common, $focus) {
-    function _model(item, field) {
-        return $common.getModel(item, field);
-    }
-
-    const table = {name: 'none', editIndex: -1};
-
-    function _tableReset() {
-        delete table.field;
-        table.name = 'none';
-        table.editIndex = -1;
-
-        $common.hidePopover();
-    }
-
-    function _tableSaveAndReset() {
-        const field = table.field;
-
-        const save = $common.isDefined(field) && $common.isDefined(field.save);
-
-        if (!save || !$common.isDefined(field) || field.save(field, table.editIndex, true)) {
-            _tableReset();
-
-            return true;
-        }
-
-        return false;
-    }
-
-    function _tableState(field, editIndex, specName) {
-        table.field = field;
-        table.name = specName || field.model;
-        table.editIndex = editIndex;
-    }
-
-    function _tableUI(field) {
-        const ui = field.ui;
-
-        return ui ? ui : field.type;
-    }
-
-    function _tableFocus(focusId, index) {
-        $focus((index < 0 ? 'new' : 'cur') + focusId + (index >= 0 ? index : ''));
-    }
-
-    function _tablePairValue(filed, index) {
-        return index < 0 ? {key: filed.newKey, value: filed.newValue} : {key: filed.curKey, value: filed.curValue};
-    }
-
-    function _tableStartEdit(item, tbl, index, save) {
-        _tableState(tbl, index);
-
-        const val = _.get(_model(item, tbl), tbl.model)[index];
-
-        const ui = _tableUI(tbl);
-
-        tbl.save = save;
-
-        if (ui === 'table-pair') {
-            tbl.curKey = val[tbl.keyName];
-            tbl.curValue = val[tbl.valueName];
-
-            _tableFocus('Key' + tbl.focusId, index);
-        }
-        else if (ui === 'table-db-fields') {
-            tbl.curDatabaseFieldName = val.databaseFieldName;
-            tbl.curDatabaseFieldType = val.databaseFieldType;
-            tbl.curJavaFieldName = val.javaFieldName;
-            tbl.curJavaFieldType = val.javaFieldType;
-
-            _tableFocus('DatabaseFieldName' + tbl.focusId, index);
-        }
-        else if (ui === 'table-indexes') {
-            tbl.curIndexName = val.name;
-            tbl.curIndexType = val.indexType;
-            tbl.curIndexFields = val.fields;
-
-            _tableFocus(tbl.focusId, index);
-        }
-    }
-
-    function _tableNewItem(tbl) {
-        _tableState(tbl, -1);
-
-        const ui = _tableUI(tbl);
-
-        if (ui === 'table-pair') {
-            tbl.newKey = null;
-            tbl.newValue = null;
-
-            _tableFocus('Key' + tbl.focusId, -1);
-        }
-        else if (ui === 'table-db-fields') {
-            tbl.newDatabaseFieldName = null;
-            tbl.newDatabaseFieldType = null;
-            tbl.newJavaFieldName = null;
-            tbl.newJavaFieldType = null;
-
-            _tableFocus('DatabaseFieldName' + tbl.focusId, -1);
-        }
-        else if (ui === 'table-indexes') {
-            tbl.newIndexName = null;
-            tbl.newIndexType = 'SORTED';
-            tbl.newIndexFields = null;
-
-            _tableFocus(tbl.focusId, -1);
-        }
-    }
-
-    return {
-        tableState: _tableState,
-        tableReset: _tableReset,
-        tableSaveAndReset: _tableSaveAndReset,
-        tableNewItem: _tableNewItem,
-        tableNewItemActive(tbl) {
-            return table.name === tbl.model && table.editIndex < 0;
-        },
-        tableEditing(tbl, index) {
-            return table.name === tbl.model && table.editIndex === index;
-        },
-        tableEditedRowIndex() {
-            return table.editIndex;
-        },
-        tableField() {
-            return table.field;
-        },
-        tableStartEdit: _tableStartEdit,
-        tableRemove(item, field, index) {
-            _tableReset();
-
-            _.get(_model(item, field), field.model).splice(index, 1);
-        },
-        tablePairValue: _tablePairValue,
-        tablePairSave(pairValid, item, field, index, stopEdit) {
-            const valid = pairValid(item, field, index);
-
-            if (valid) {
-                const pairValue = _tablePairValue(field, index);
-
-                let pairModel = {};
-
-                const container = _.get(item, field.model);
-
-                if (index < 0) {
-                    pairModel[field.keyName] = pairValue.key;
-                    pairModel[field.valueName] = pairValue.value;
-
-                    if (container)
-                        container.push(pairModel);
-                    else
-                        _.set(item, field.model, [pairModel]);
-
-                    if (!stopEdit)
-                        _tableNewItem(field);
-                }
-                else {
-                    pairModel = container[index];
-
-                    pairModel[field.keyName] = pairValue.key;
-                    pairModel[field.valueName] = pairValue.value;
-
-                    if (!stopEdit) {
-                        if (index < container.length - 1)
-                            _tableStartEdit(item, field, index + 1);
-                        else
-                            _tableNewItem(field);
-                    }
-                }
-            }
-
-            return valid;
-        },
-        tablePairSaveVisible(field, index) {
-            const pairValue = _tablePairValue(field, index);
-
-            return !$common.isEmptyString(pairValue.key) && !$common.isEmptyString(pairValue.value);
-        },
-        tableFocusInvalidField(index, id) {
-            _tableFocus(id, index);
-
-            return false;
-        },
-        tableFieldId(index, id) {
-            return (index < 0 ? 'new' : 'cur') + id + (index >= 0 ? index : '');
-        }
-    };
-}]);
-
-consoleModule.service('ngCopy', ['$window', '$common', function($window, $common) {
-    const body = angular.element($window.document.body);
-
-    const textArea = angular.element('<textarea/>');
-
-    textArea.css({
-        position: 'fixed',
-        opacity: '0'
-    });
-
-    return function(toCopy) {
-        textArea.val(toCopy);
-
-        body.append(textArea);
-
-        textArea[0].select();
-
-        try {
-            if (document.execCommand('copy'))
-                $common.showInfo('Value copied to clipboard');
-            else
-                window.prompt('Copy to clipboard: Ctrl+C, Enter', toCopy);  // eslint-disable-line no-alert
-        } catch (err) {
-            window.prompt('Copy to clipboard: Ctrl+C, Enter', toCopy);  // eslint-disable-line no-alert
-        }
-
-        textArea.remove();
-    };
-}]).directive('ngClickCopy', ['ngCopy', function(ngCopy) {
-    return {
-        restrict: 'A',
-        link(scope, element, attrs) {
-            element.bind('click', function() {
-                ngCopy(attrs.ngClickCopy);
-            });
-
-            if (!document.queryCommandSupported('copy'))
-                element.hide();
-        }
-    };
-}]);
-
-// Filter domain models with key fields configuration.
-consoleModule.filter('domainsValidation', ['$common', function($common) {
-    return function(domains, valid, invalid) {
-        if (valid && invalid)
-            return domains;
-
-        const out = [];
-
-        _.forEach(domains, function(domain) {
-            const _valid = !$common.domainForStoreConfigured(domain) || $common.isJavaBuiltInClass(domain.keyType) || !_.isEmpty(domain.keyFields);
-
-            if (valid && _valid || invalid && !_valid)
-                out.push(domain);
-        });
-
-        return out;
-    };
-}]);
-
-// Directive to enable validation to match specified value.
-consoleModule.directive('match', ['$parse', ($parse) => {
-    return {
-        require: 'ngModel',
-        link(scope, elem, attrs, ctrl) {
-            scope.$watch(() => $parse(attrs.match)(scope) === ctrl.$modelValue, (currentValue) => ctrl.$setValidity('mismatch', currentValue));
-        }
-    };
-}]);
-
-// Directive to bind ENTER key press with some user action.
-consoleModule.directive('onEnter', ['$timeout', ($timeout) => {
-    return function(scope, elem, attrs) {
-        elem.on('keydown keypress', function(event) {
-            if (event.which === 13) {
-                scope.$apply(function() {
-                    $timeout(() => scope.$eval(attrs.onEnter));
-                });
-
-                event.preventDefault();
-            }
-        });
-
-        // Removes bound events in the element itself when the scope is destroyed.
-        scope.$on('$destroy', function() {
-            elem.off('keydown keypress');
-        });
-    };
-}]);
-
-// Directive to bind ESC key press with some user action.
-consoleModule.directive('onEscape', () => {
-    return function(scope, elem, attrs) {
-        elem.on('keydown keypress', function(event) {
-            if (event.which === 27) {
-                scope.$apply(function() {
-                    scope.$eval(attrs.onEscape);
-                });
-
-                event.preventDefault();
-            }
-        });
-
-        // Removes bound events in the element itself when the scope is destroyed
-        scope.$on('$destroy', function() {
-            elem.off('keydown keypress');
-        });
-    };
-});
-
-// Directive to retain selection. To fix angular-strap typeahead bug with setting cursor to the end of text.
-consoleModule.directive('retainSelection', ['$timeout', ($timeout) => {
-    let promise;
-
-    return function(scope, elem) {
-        elem.on('keydown', function(evt) {
-            const key = evt.which;
-            const ctrlDown = evt.ctrlKey || evt.metaKey;
-            const input = this;
-            let start = input.selectionStart;
-
-            if (promise)
-                $timeout.cancel(promise);
-
-            promise = $timeout(() => {
-                let setCursor = false;
-
-                // Handle Backspace[8].
-                if (key === 8 && start > 0) {
-                    start -= 1;
-
-                    setCursor = true;
-                }
-                // Handle Del[46].
-                else if (key === 46)
-                    setCursor = true;
-                // Handle: Caps Lock[20], Tab[9], Shift[16], Ctrl[17], Alt[18], Esc[27], Enter[13], Arrows[37..40], Home[36], End[35], Ins[45], PgUp[33], PgDown[34], F1..F12[111..124], Num Lock[], Scroll Lock[145].
-                else if (!(key === 8 || key === 9 || key === 13 || (key > 15 && key < 20) || key === 27 ||
-                    (key > 32 && key < 41) || key === 45 || (key > 111 && key < 124) || key === 144 || key === 145)) {
-                    // Handle: Ctrl + [A[65], C[67], V[86]].
-                    if (!(ctrlDown && (key === 65 || key === 67 || key === 86))) {
-                        start += 1;
-
-                        setCursor = true;
-                    }
-                }
-
-                if (setCursor)
-                    input.setSelectionRange(start, start);
-
-                promise = null;
-            });
-        });
-
-        // Removes bound events in the element itself when the scope is destroyed
-        scope.$on('$destroy', function() {
-            elem.off('keydown');
-        });
-    };
-}]);
-
-// Factory function to focus element.
-consoleModule.factory('$focus', ['$timeout', ($timeout) => {
-    return function(id) {
-        // Timeout makes sure that is invoked after any other event has been triggered.
-        // E.g. click events that need to run before the focus or inputs elements that are
-        // in a disabled state but are enabled when those events are triggered.
-        $timeout(() => {
-            const elem = $('#' + id);
-
-            if (elem.length > 0)
-                elem[0].focus();
-        }, 100);
-    };
-}]);
-
-// Directive to auto-focus element.
-consoleModule.directive('autoFocus', ['$timeout', ($timeout) => {
-    return {
-        restrict: 'AC',
-        link(scope, element) {
-            $timeout(() => element[0].focus());
-        }
-    };
-}]);
-
-// Directive to focus next element on ENTER key.
-consoleModule.directive('enterFocusNext', ['$focus', ($focus) => {
-    return function(scope, elem, attrs) {
-        elem.on('keydown keypress', function(event) {
-            if (event.which === 13) {
-                event.preventDefault();
-
-                $focus(attrs.enterFocusNext);
-            }
-        });
-    };
-}]);
-
-// Directive to mark elements to focus.
-consoleModule.directive('onClickFocus', ['$focus', ($focus) => {
-    return function(scope, elem, attr) {
-        elem.on('click', function() {
-            $focus(attr.onClickFocus);
-        });
-
-        // Removes bound events in the element itself when the scope is destroyed
-        scope.$on('$destroy', function() {
-            elem.off('click');
-        });
-    };
-}]);
-
-consoleModule.controller('resetPassword', [
-    '$scope', '$modal', '$http', '$common', '$focus', 'Auth', '$state',
-    ($scope, $modal, $http, $common, $focus, Auth, $state) => {
-        if ($state.params.token) {
-            $http.post('/api/v1/password/validate/token', {token: $state.params.token})
-                .success((res) => {
-                    $scope.email = res.email;
-                    $scope.token = res.token;
-                    $scope.error = res.error;
-
-                    if ($scope.token && !$scope.error)
-                        $focus('user_password');
-                });
-        }
-
-        // Try to reset user password for provided token.
-        $scope.resetPassword = function(reset_info) {
-            $http.post('/api/v1/password/reset', reset_info)
-                .success(function() {
-                    $common.showInfo('Password successfully changed');
-
-                    $state.go('base.configuration.clusters');
-                })
-                .error(function(data, state) {
-                    $common.showError(data);
-
-                    if (state === 503)
-                        $state.go('base.configuration.clusters');
-                });
-        };
-    }
-]);
-
-// Sign in controller.
-// TODO IGNITE-1936 Refactor this controller.
-consoleModule.controller('auth', ['$scope', '$focus', 'Auth', 'IgniteCountries', ($scope, $focus, Auth, Countries) => {
-    $scope.auth = Auth.auth;
-    $scope.forgotPassword = Auth.forgotPassword;
-    $scope.action = 'signin';
-    $scope.countries = Countries.getAll();
-
-    $focus('user_email');
-}]);
-
-// Navigation bar controller.
-consoleModule.controller('notebooks', ['$rootScope', '$scope', '$modal', '$state', '$http', '$common',
-    ($root, $scope, $modal, $state, $http, $common) => {
-        $root.notebooks = [];
-
-        // Pre-fetch modal dialogs.
-        const _notebookNewModal = $modal({scope: $scope, templateUrl: '/sql/notebook-new.html', show: false});
-
-        $root.rebuildDropdown = function() {
-            $scope.notebookDropdown = [
-                {text: 'Create new notebook', click: 'inputNotebookName()'},
-                {divider: true}
-            ];
-
-            _.forEach($root.notebooks, function(notebook) {
-                $scope.notebookDropdown.push({
-                    text: notebook.name,
-                    sref: 'base.sql.notebook({noteId:"' + notebook._id + '"})'
-                });
-            });
-        };
-
-        $root.reloadNotebooks = function() {
-            // When landing on the page, get clusters and show them.
-            $http.post('/api/v1/notebooks/list')
-                .success(function(data) {
-                    $root.notebooks = data;
-
-                    $root.rebuildDropdown();
-                })
-                .error(function(errMsg) {
-                    $common.showError(errMsg);
-                });
-        };
-
-        $root.inputNotebookName = function() {
-            _notebookNewModal.$promise.then(_notebookNewModal.show);
-        };
-
-        $root.createNewNotebook = function(name) {
-            $http.post('/api/v1/notebooks/new', {name})
-                .success(function(noteId) {
-                    _notebookNewModal.hide();
-
-                    $root.reloadNotebooks();
-
-                    $state.go('base.sql.notebook', {noteId});
-                })
-                .error(function(message) {
-                    $common.showError(message);
-                });
-        };
-
-        $root.reloadNotebooks();
-    }
-]);
-
-export default consoleModule;


[09/46] ignite git commit: Ignite Web Console speed up bundle rebuild and watch. Minor fixes.

Posted by sb...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
index a0bd44c..eb52e51 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/ipc.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './ipc.jade!';
+import templateUrl from './ipc.jade';
 
 export default ['igniteConfigurationIgfsIpc', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
index 6a6ca12..810944f 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './misc.jade!';
+import templateUrl from './misc.jade';
 
 export default ['igniteConfigurationIgfsMisc', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
index fd42805..dc48d07 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/misc.jade
@@ -32,7 +32,7 @@ mixin table-igfs-path-mode-edit(prefix, focusId, index)
     .col-xs-8.col-sm-8.col-md-8
         .fieldSep /
         .input-tip
-            input.form-control(id=keyFocusId enter-focus-next=valFocusId type='text' ng-model=keyModel placeholder='Path' on-escape='tableReset()')
+            input.form-control(id=keyFocusId ignite-on-enter-focus-move=valFocusId type='text' ng-model=keyModel placeholder='Path' ignite-on-escape='tableReset()')
     .col-xs-4.col-sm-4.col-md-4
         -var arg = keyModel + ', ' + valModel
         -var btnVisible = 'tablePairSaveVisible(tblPathModes, ' + index + ')'
@@ -40,7 +40,7 @@ mixin table-igfs-path-mode-edit(prefix, focusId, index)
         -var btnVisibleAndSave = btnVisible + ' && ' + btnSave
         +btn-save(btnVisible, btnSave)
         .input-tip
-            button.select-toggle.form-control(id=valFocusId bs-select ng-model=valModel data-placeholder='Mode' bs-options='item.value as item.label for item in igfsModes' tabindex='0' on-enter=btnVisibleAndSave on-escape='tableReset()')
+            button.select-toggle.form-control(id=valFocusId bs-select ng-model=valModel data-placeholder='Mode' bs-options='item.value as item.label for item in igfsModes' tabindex='0' ignite-on-enter=btnVisibleAndSave ignite-on-escape='tableReset()')
 
 form.panel.panel-default(name=form novalidate)
     .panel-heading(bs-collapse-toggle='' ng-click='ui.loadPanel("#{form}")')
@@ -75,10 +75,10 @@ form.panel.panel-default(name=form novalidate)
                 .settings-row
                     +checkbox('Colocate metadata', model + '.colocateMetadata', 'colocateMetadata', 'Whether to co-locate metadata on a single node')
                 .settings-row
-                    +checkbox('Relaxed consistency ', model + '.relaxedConsistency', 'relaxedConsistency',
-                        'If value of this flag is <b>true</b>, IGFS will skip expensive consistency checks. It is recommended to set\
-                        this flag to <b>false</b>b> if your application has conflicting operations, or you do not how exactly users will\
-                        use your system.')
+                    +checkbox('Relaxed consistency', model + '.relaxedConsistency', 'relaxedConsistency',
+                        'If value of this flag is <b>true</b>, IGFS will skip expensive consistency checks<br/>\
+                        It is recommended to set this flag to <b>false</b> if your application has conflicting\
+                        operations, or you do not know how exactly users will use your system')
                 .settings-row
                     ignite-form-group(ng-model=pathModes ng-form=pathModesForm)
                         ignite-form-field-label

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
index 8b3b37b..69179c0 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/igfs/secondary.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import template from './secondary.jade!';
+import templateUrl from './secondary.jade';
 
 export default ['igniteConfigurationIgfsSecondary', [() => {
     return {
         scope: true,
         restrict: 'E',
-        template,
+        templateUrl,
         replace: true
     };
 }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js b/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
index fb67326..be7bf1e 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/preview-panel.directive.js
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-import ace from 'ace';
+import ace from 'brace';
 
 export default ['previewPanel', ['$interval', '$timeout', ($interval, $timeout) => {
     let animation = {editor: null, stage: 0, start: 0, stop: 0};
     let prevContent = [];
 
-    const Range = ace.require('ace/range').Range;
+    const Range = ace.acequire('ace/range').Range;
 
     const _clearSelection = (editor) => {
         _.forEach(editor.session.getMarkers(false), (marker) => {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
index 866d97f..1b19e3a 100644
--- a/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
+++ b/modules/web-console/src/main/js/app/modules/states/configuration/summary/summary.controller.js
@@ -17,15 +17,16 @@
 
 import _ from 'lodash';
 import JSZip from 'jszip';
+import saver from 'file-saver';
 
 export default [
-    '$rootScope', '$scope', '$http', '$common', '$loading', '$filter', 'ConfigurationSummaryResource', 'JavaTypes', 'IgniteVersion', 'GeneratorDocker', 'GeneratorPom',
-    function($root, $scope, $http, $common, $loading, $filter, Resource, JavaTypes, IgniteVersion, docker, pom) {
+    '$rootScope', '$scope', '$http', 'IgniteLegacyUtils', 'IgniteLoading', '$filter', 'ConfigurationSummaryResource', 'JavaTypes', 'IgniteVersion', 'GeneratorDocker', 'GeneratorPom',
+    function($root, $scope, $http, LegacyUtils, Loading, $filter, Resource, JavaTypes, IgniteVersion, docker, pom) {
         const ctrl = this;
 
         $scope.ui = { ready: false };
 
-        $loading.start('summaryPage');
+        Loading.start('summaryPage');
 
         Resource.read().then(({clusters}) => {
             $scope.clusters = clusters;
@@ -38,7 +39,7 @@ export default [
                 return { _id, name };
             });
 
-            $loading.finish('summaryPage');
+            Loading.finish('summaryPage');
 
             $scope.ui.ready = true;
 
@@ -53,7 +54,7 @@ export default [
             return !row || !row._id || _.findIndex(rows, (item) => item._id === row._id) >= 0;
         };
 
-        $scope.widthIsSufficient = $common.widthIsSufficient;
+        $scope.widthIsSufficient = LegacyUtils.widthIsSufficient;
         $scope.dialects = {};
 
         $scope.projectStructureOptions = {
@@ -326,10 +327,8 @@ export default [
 
             $generatorOptional.optionalContent(zip, cluster);
 
-            const blob = zip.generate({type: 'blob', compression: 'DEFLATE', mimeType: 'application/octet-stream'});
-
-            // Download archive.
-            saveAs(blob, cluster.name + '-project.zip');
+            zip.generateAsync({type: 'blob', compression: 'DEFLATE', mimeType: 'application/octet-stream'})
+                .then((blob) => saver.saveAs(blob, cluster.name + '-project.zip'));
         };
 
         /**

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/states/signin.state.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/states/signin.state.js b/modules/web-console/src/main/js/app/modules/states/signin.state.js
index 91c84a3..a23a496 100644
--- a/modules/web-console/src/main/js/app/modules/states/signin.state.js
+++ b/modules/web-console/src/main/js/app/modules/states/signin.state.js
@@ -16,6 +16,7 @@
  */
 
 import angular from 'angular';
+import templateUrl from 'views/signin.jade';
 
 angular
 .module('ignite-console.states.login', [
@@ -28,7 +29,7 @@ angular
     $stateProvider
     .state('signin', {
         url: '/',
-        templateUrl: '/signin.html',
+        templateUrl,
         metaTags: {
         }
     });

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/modules/user/Auth.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/modules/user/Auth.service.js b/modules/web-console/src/main/js/app/modules/user/Auth.service.js
index f0aa397..080f4af 100644
--- a/modules/web-console/src/main/js/app/modules/user/Auth.service.js
+++ b/modules/web-console/src/main/js/app/modules/user/Auth.service.js
@@ -15,8 +15,8 @@
  * limitations under the License.
  */
 
-export default ['Auth', ['$http', '$rootScope', '$state', '$window', '$common', 'gettingStarted', 'User', 'IgniteAgentMonitor',
-    ($http, $root, $state, $window, $common, gettingStarted, User, agentMonitor) => {
+export default ['Auth', ['$http', '$rootScope', '$state', '$window', 'IgniteLegacyUtils', 'IgniteMessages', 'gettingStarted', 'User', 'IgniteAgentMonitor',
+    ($http, $root, $state, $window, LegacyUtils, Messages, gettingStarted, User, agentMonitor) => {
         let _auth = false;
 
         try {
@@ -44,7 +44,7 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', '$common',
             forgotPassword(userInfo) {
                 return $http.post('/api/v1/password/forgot', userInfo)
                     .success(() => $state.go('password.send'))
-                    .error((err) => $common.showPopoverMessage(null, null, 'forgot_email', $common.errorMessage(err)));
+                    .error((err) => LegacyUtils.showPopoverMessage(null, null, 'forgot_email', Messages.errorMessage(null, err)));
             },
             auth(action, userInfo) {
                 return $http.post('/api/v1/' + action, userInfo)
@@ -61,7 +61,7 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', '$common',
                             agentMonitor.init();
                         });
                     })
-                    .error((err) => $common.showPopoverMessage(null, null, action + '_email', $common.errorMessage(err)));
+                    .error((err) => LegacyUtils.showPopoverMessage(null, null, action + '_email', Messages.errorMessage(null, err)));
             },
             logout() {
                 return $http.post('/api/v1/logout')
@@ -70,7 +70,7 @@ export default ['Auth', ['$http', '$rootScope', '$state', '$window', '$common',
 
                         $window.open($state.href('signin'), '_self');
                     })
-                    .catch((err) => $common.showError(err));
+                    .catch(Messages.showError);
             }
         };
     }]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/ChartColors.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/ChartColors.service.js b/modules/web-console/src/main/js/app/services/ChartColors.service.js
index ec3f365..843aa5c 100644
--- a/modules/web-console/src/main/js/app/services/ChartColors.service.js
+++ b/modules/web-console/src/main/js/app/services/ChartColors.service.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import COLORS from 'app/data/colors.json!';
+import COLORS from 'app/data/colors.json';
 
 export default ['IgniteChartColors', function() {
     return COLORS;

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/Clone.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Clone.service.js b/modules/web-console/src/main/js/app/services/Clone.service.js
new file mode 100644
index 0000000..52a4e4e
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/Clone.service.js
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+// Service for clone objects.
+export default ['IgniteClone', ['$rootScope', '$q', '$modal', ($root, $q, $modal) => {
+    const scope = $root.$new();
+
+    let _names = [];
+    let deferred;
+    let _validator;
+
+    function _nextAvailableName(name) {
+        let num = 1;
+        let tmpName = name;
+
+        while (_.includes(_names, tmpName)) {
+            tmpName = name + '_' + num.toString();
+
+            num++;
+        }
+
+        return tmpName;
+    }
+
+    const cloneModal = $modal({templateUrl: '/templates/clone.html', scope, placement: 'center', show: false});
+
+    scope.ok = function(newName) {
+        if (!_validator || _validator(newName)) {
+            deferred.resolve(_nextAvailableName(newName));
+
+            cloneModal.hide();
+        }
+    };
+
+    cloneModal.confirm = function(oldName, names, validator) {
+        _names = names;
+
+        scope.newName = _nextAvailableName(oldName);
+
+        _validator = validator;
+
+        deferred = $q.defer();
+
+        cloneModal.$promise.then(cloneModal.show);
+
+        return deferred.promise;
+    };
+
+    return cloneModal;
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/Confirm.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Confirm.service.js b/modules/web-console/src/main/js/app/services/Confirm.service.js
new file mode 100644
index 0000000..c4e25a8
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/Confirm.service.js
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+// Confirm popup service.
+export default ['IgniteConfirm', ['$rootScope', '$q', '$modal', '$animate', ($root, $q, $modal, $animate) => {
+    const scope = $root.$new();
+
+    const modal = $modal({templateUrl: '/templates/confirm.html', scope, placement: 'center', show: false});
+
+    let deferred;
+
+    const _hide = (animate) => {
+        $animate.enabled(modal.$element, animate);
+
+        modal.hide();
+    };
+
+    scope.confirmYes = () => {
+        _hide(scope.animate);
+
+        deferred.resolve(true);
+    };
+
+    scope.confirmNo = () => {
+        _hide(scope.animate);
+
+        deferred.resolve(false);
+    };
+
+    scope.confirmCancel = () => {
+        _hide(true);
+
+        deferred.reject('cancelled');
+    };
+
+    /**
+     *
+     * @param {String } content
+     * @param {Boolean} [yesNo]
+     * @param {Boolean} [animate]
+     * @returns {Promise}
+     */
+    modal.confirm = (content, yesNo, animate) => {
+        scope.animate = !!animate;
+        scope.content = content || 'Confirm?';
+        scope.yesNo = !!yesNo;
+
+        deferred = $q.defer();
+
+        modal.$promise.then(modal.show);
+
+        return deferred.promise;
+    };
+
+    return modal;
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js b/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js
new file mode 100644
index 0000000..ef66335
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/ConfirmBatch.service.js
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Service for confirm or skip several steps.
+export default ['IgniteConfirmBatch', ['$rootScope', '$q', '$modal', ($root, $q, $modal) => {
+    const scope = $root.$new();
+
+    scope.confirmModal = $modal({
+        templateUrl: '/templates/batch-confirm.html',
+        scope,
+        placement: 'center',
+        show: false,
+        backdrop: 'static',
+        keyboard: false
+    });
+
+    const _done = (cancel) => {
+        scope.confirmModal.hide();
+
+        if (cancel)
+            scope.deferred.reject('cancelled');
+        else
+            scope.deferred.resolve();
+    };
+
+    const _nextElement = (skip) => {
+        scope.items[scope.curIx++].skip = skip;
+
+        if (scope.curIx < scope.items.length)
+            scope.content = scope.contentGenerator(scope.items[scope.curIx]);
+        else
+            _done();
+    };
+
+    scope.cancel = () => {
+        _done(true);
+    };
+
+    scope.skip = (applyToAll) => {
+        if (applyToAll) {
+            for (let i = scope.curIx; i < scope.items.length; i++)
+                scope.items[i].skip = true;
+
+            _done();
+        }
+        else
+            _nextElement(true);
+    };
+
+    scope.overwrite = (applyToAll) => {
+        if (applyToAll)
+            _done();
+        else
+            _nextElement(false);
+    };
+
+    return {
+        /**
+         * Show confirm all dialog.
+         *
+         * @param confirmMessageFn Function to generate a confirm message.
+         * @param itemsToConfirm Array of element to process by confirm.
+         */
+        confirm(confirmMessageFn, itemsToConfirm) {
+            scope.deferred = $q.defer();
+
+            scope.contentGenerator = confirmMessageFn;
+
+            scope.items = itemsToConfirm;
+            scope.curIx = 0;
+            scope.content = (scope.items && scope.items.length > 0) ? scope.contentGenerator(scope.items[0]) : null;
+
+            scope.confirmModal.$promise.then(scope.confirmModal.show);
+
+            return scope.deferred.promise;
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js b/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js
new file mode 100644
index 0000000..74c4764
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/CopyToClipboard.service.js
@@ -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.
+ */
+
+// Service to copy some value to OS clipboard.
+export default ['IgniteCopyToClipboard', ['$window', 'IgniteMessages', ($window, Messages) => {
+    const body = angular.element($window.document.body);
+
+    const textArea = angular.element('<textarea/>');
+
+    textArea.css({
+        position: 'fixed',
+        opacity: '0'
+    });
+
+    return {
+        copy(toCopy) {
+            textArea.val(toCopy);
+
+            body.append(textArea);
+
+            textArea[0].select();
+
+            try {
+                if (document.execCommand('copy'))
+                    Messages.showInfo('Value copied to clipboard');
+                else
+                    window.prompt('Copy to clipboard: Ctrl+C, Enter', toCopy);  // eslint-disable-line no-alert
+            }
+            catch (err) {
+                window.prompt('Copy to clipboard: Ctrl+C, Enter', toCopy);  // eslint-disable-line no-alert
+            }
+
+            textArea.remove();
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/Countries.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Countries.service.js b/modules/web-console/src/main/js/app/services/Countries.service.js
index 87d11fd..5ad3e6a 100644
--- a/modules/web-console/src/main/js/app/services/Countries.service.js
+++ b/modules/web-console/src/main/js/app/services/Countries.service.js
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-import COUNTRIES from 'app/data/countries.json!';
+import COUNTRIES from 'app/data/countries.json';
 
 export default ['IgniteCountries', function() {
     const indexByName = _.keyBy(COUNTRIES, 'name');

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/Focus.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Focus.service.js b/modules/web-console/src/main/js/app/services/Focus.service.js
new file mode 100644
index 0000000..a07e181
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/Focus.service.js
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+// Service to transfer focus for specified element.
+export default ['IgniteFocus', ['$timeout', ($timeout) => {
+    return {
+        move(id) {
+            // Timeout makes sure that is invoked after any other event has been triggered.
+            // E.g. click events that need to run before the focus or inputs elements that are
+            // in a disabled state but are enabled when those events are triggered.
+            $timeout(() => {
+                const elem = $('#' + id);
+
+                if (elem.length > 0)
+                    elem[0].focus();
+            }, 100);
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/JavaTypes.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/JavaTypes.service.js b/modules/web-console/src/main/js/app/services/JavaTypes.service.js
index a755e13..d34d669 100644
--- a/modules/web-console/src/main/js/app/services/JavaTypes.service.js
+++ b/modules/web-console/src/main/js/app/services/JavaTypes.service.js
@@ -16,12 +16,12 @@
  */
 
 // Java built-in class names.
-import JAVA_CLASSES from 'app/data/java-classes.json!';
+import JAVA_CLASSES from 'app/data/java-classes.json';
 
 // Java build-in primitive.
-import JAVA_PRIMITIVES from 'app/data/java-primitives.json!';
+import JAVA_PRIMITIVES from 'app/data/java-primitives.json';
 
-import JAVA_KEYWORDS from 'app/data/java-keywords.json!';
+import JAVA_KEYWORDS from 'app/data/java-keywords.json';
 
 export default ['JavaTypes', function() {
     return {

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/LegacyTable.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/LegacyTable.service.js b/modules/web-console/src/main/js/app/services/LegacyTable.service.js
new file mode 100644
index 0000000..8f3b791
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/LegacyTable.service.js
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+// TODO: Refactor this service for legacy tables with more than one input field.
+export default ['IgniteLegacyTable', ['IgniteLegacyUtils', 'IgniteFocus', (LegacyUtils, Focus) => {
+    function _model(item, field) {
+        return LegacyUtils.getModel(item, field);
+    }
+
+    const table = {name: 'none', editIndex: -1};
+
+    function _tableReset() {
+        delete table.field;
+        table.name = 'none';
+        table.editIndex = -1;
+
+        LegacyUtils.hidePopover();
+    }
+
+    function _tableSaveAndReset() {
+        const field = table.field;
+
+        const save = LegacyUtils.isDefined(field) && LegacyUtils.isDefined(field.save);
+
+        if (!save || !LegacyUtils.isDefined(field) || field.save(field, table.editIndex, true)) {
+            _tableReset();
+
+            return true;
+        }
+
+        return false;
+    }
+
+    function _tableState(field, editIndex, specName) {
+        table.field = field;
+        table.name = specName || field.model;
+        table.editIndex = editIndex;
+    }
+
+    function _tableUI(field) {
+        const ui = field.ui;
+
+        return ui ? ui : field.type;
+    }
+
+    function _tableFocus(focusId, index) {
+        Focus.move((index < 0 ? 'new' : 'cur') + focusId + (index >= 0 ? index : ''));
+    }
+
+    function _tablePairValue(filed, index) {
+        return index < 0 ? {key: filed.newKey, value: filed.newValue} : {key: filed.curKey, value: filed.curValue};
+    }
+
+    function _tableStartEdit(item, tbl, index, save) {
+        _tableState(tbl, index);
+
+        const val = _.get(_model(item, tbl), tbl.model)[index];
+
+        const ui = _tableUI(tbl);
+
+        tbl.save = save;
+
+        if (ui === 'table-pair') {
+            tbl.curKey = val[tbl.keyName];
+            tbl.curValue = val[tbl.valueName];
+
+            _tableFocus('Key' + tbl.focusId, index);
+        }
+        else if (ui === 'table-db-fields') {
+            tbl.curDatabaseFieldName = val.databaseFieldName;
+            tbl.curDatabaseFieldType = val.databaseFieldType;
+            tbl.curJavaFieldName = val.javaFieldName;
+            tbl.curJavaFieldType = val.javaFieldType;
+
+            _tableFocus('DatabaseFieldName' + tbl.focusId, index);
+        }
+        else if (ui === 'table-indexes') {
+            tbl.curIndexName = val.name;
+            tbl.curIndexType = val.indexType;
+            tbl.curIndexFields = val.fields;
+
+            _tableFocus(tbl.focusId, index);
+        }
+    }
+
+    function _tableNewItem(tbl) {
+        _tableState(tbl, -1);
+
+        const ui = _tableUI(tbl);
+
+        if (ui === 'table-pair') {
+            tbl.newKey = null;
+            tbl.newValue = null;
+
+            _tableFocus('Key' + tbl.focusId, -1);
+        }
+        else if (ui === 'table-db-fields') {
+            tbl.newDatabaseFieldName = null;
+            tbl.newDatabaseFieldType = null;
+            tbl.newJavaFieldName = null;
+            tbl.newJavaFieldType = null;
+
+            _tableFocus('DatabaseFieldName' + tbl.focusId, -1);
+        }
+        else if (ui === 'table-indexes') {
+            tbl.newIndexName = null;
+            tbl.newIndexType = 'SORTED';
+            tbl.newIndexFields = null;
+
+            _tableFocus(tbl.focusId, -1);
+        }
+    }
+
+    return {
+        tableState: _tableState,
+        tableReset: _tableReset,
+        tableSaveAndReset: _tableSaveAndReset,
+        tableNewItem: _tableNewItem,
+        tableNewItemActive(tbl) {
+            return table.name === tbl.model && table.editIndex < 0;
+        },
+        tableEditing(tbl, index) {
+            return table.name === tbl.model && table.editIndex === index;
+        },
+        tableEditedRowIndex() {
+            return table.editIndex;
+        },
+        tableField() {
+            return table.field;
+        },
+        tableStartEdit: _tableStartEdit,
+        tableRemove(item, field, index) {
+            _tableReset();
+
+            _.get(_model(item, field), field.model).splice(index, 1);
+        },
+        tablePairValue: _tablePairValue,
+        tablePairSave(pairValid, item, field, index, stopEdit) {
+            const valid = pairValid(item, field, index);
+
+            if (valid) {
+                const pairValue = _tablePairValue(field, index);
+
+                let pairModel = {};
+
+                const container = _.get(item, field.model);
+
+                if (index < 0) {
+                    pairModel[field.keyName] = pairValue.key;
+                    pairModel[field.valueName] = pairValue.value;
+
+                    if (container)
+                        container.push(pairModel);
+                    else
+                        _.set(item, field.model, [pairModel]);
+
+                    if (!stopEdit)
+                        _tableNewItem(field);
+                }
+                else {
+                    pairModel = container[index];
+
+                    pairModel[field.keyName] = pairValue.key;
+                    pairModel[field.valueName] = pairValue.value;
+
+                    if (!stopEdit) {
+                        if (index < container.length - 1)
+                            _tableStartEdit(item, field, index + 1);
+                        else
+                            _tableNewItem(field);
+                    }
+                }
+            }
+
+            return valid;
+        },
+        tablePairSaveVisible(field, index) {
+            const pairValue = _tablePairValue(field, index);
+
+            return !LegacyUtils.isEmptyString(pairValue.key) && !LegacyUtils.isEmptyString(pairValue.value);
+        },
+        tableFocusInvalidField(index, id) {
+            _tableFocus(id, index);
+
+            return false;
+        },
+        tableFieldId(index, id) {
+            return (index < 0 ? 'new' : 'cur') + id + (index >= 0 ? index : '');
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/LegacyUtils.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/LegacyUtils.service.js b/modules/web-console/src/main/js/app/services/LegacyUtils.service.js
new file mode 100644
index 0000000..c4c83e9
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/LegacyUtils.service.js
@@ -0,0 +1,948 @@
+/*
+ * 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.
+ */
+
+// TODO: Refactor this service for legacy tables with more than one input field.
+export default ['IgniteLegacyUtils', [
+    '$alert', '$popover', '$anchorScroll', '$location', '$timeout', '$window', 'IgniteFocus',
+    ($alert, $popover, $anchorScroll, $location, $timeout, $window, Focus) => {
+        $anchorScroll.yOffset = 55;
+
+        function isDefined(v) {
+            return !_.isNil(v);
+        }
+
+        function isEmptyString(s) {
+            if (isDefined(s))
+                return s.trim().length === 0;
+
+            return true;
+        }
+
+        const javaBuiltInClasses = [
+            'BigDecimal', 'Boolean', 'Byte', 'Date', 'Double', 'Float', 'Integer', 'Long', 'Object', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
+        ];
+
+        const javaBuiltInTypes = [
+            'BigDecimal', 'boolean', 'Boolean', 'byte', 'Byte', 'Date', 'double', 'Double', 'float', 'Float',
+            'int', 'Integer', 'long', 'Long', 'Object', 'short', 'Short', 'String', 'Time', 'Timestamp', 'UUID'
+        ];
+
+        const javaBuiltInFullNameClasses = [
+            'java.math.BigDecimal', 'java.lang.Boolean', 'java.lang.Byte', 'java.sql.Date', 'java.lang.Double',
+            'java.lang.Float', 'java.lang.Integer', 'java.lang.Long', 'java.lang.Object', 'java.lang.Short',
+            'java.lang.String', 'java.sql.Time', 'java.sql.Timestamp', 'java.util.UUID'
+        ];
+
+        /**
+         * @param clsName Class name to check.
+         * @returns {Boolean} 'true' if given class name is a java build-in type.
+         */
+        function isJavaBuiltInClass(clsName) {
+            if (isEmptyString(clsName))
+                return false;
+
+            return _.includes(javaBuiltInClasses, clsName) || _.includes(javaBuiltInFullNameClasses, clsName);
+        }
+
+        const SUPPORTED_JDBC_TYPES = [
+            'BIGINT',
+            'BIT',
+            'BOOLEAN',
+            'BLOB',
+            'CHAR',
+            'CLOB',
+            'DATE',
+            'DECIMAL',
+            'DOUBLE',
+            'FLOAT',
+            'INTEGER',
+            'LONGNVARCHAR',
+            'LONGVARCHAR',
+            'NCHAR',
+            'NUMERIC',
+            'NVARCHAR',
+            'REAL',
+            'SMALLINT',
+            'TIME',
+            'TIMESTAMP',
+            'TINYINT',
+            'VARCHAR'
+        ];
+
+        const ALL_JDBC_TYPES = [
+            {dbName: 'BIT', dbType: -7, javaType: 'Boolean', primitiveType: 'boolean'},
+            {dbName: 'TINYINT', dbType: -6, javaType: 'Byte', primitiveType: 'byte'},
+            {dbName: 'SMALLINT', dbType: 5, javaType: 'Short', primitiveType: 'short'},
+            {dbName: 'INTEGER', dbType: 4, javaType: 'Integer', primitiveType: 'int'},
+            {dbName: 'BIGINT', dbType: -5, javaType: 'Long', primitiveType: 'long'},
+            {dbName: 'FLOAT', dbType: 6, javaType: 'Float', primitiveType: 'float'},
+            {dbName: 'REAL', dbType: 7, javaType: 'Double', primitiveType: 'double'},
+            {dbName: 'DOUBLE', dbType: 8, javaType: 'Double', primitiveType: 'double'},
+            {dbName: 'NUMERIC', dbType: 2, javaType: 'BigDecimal'},
+            {dbName: 'DECIMAL', dbType: 3, javaType: 'BigDecimal'},
+            {dbName: 'CHAR', dbType: 1, javaType: 'String'},
+            {dbName: 'VARCHAR', dbType: 12, javaType: 'String'},
+            {dbName: 'LONGVARCHAR', dbType: -1, javaType: 'String'},
+            {dbName: 'DATE', dbType: 91, javaType: 'Date'},
+            {dbName: 'TIME', dbType: 92, javaType: 'Time'},
+            {dbName: 'TIMESTAMP', dbType: 93, javaType: 'Timestamp'},
+            {dbName: 'BINARY', dbType: -2, javaType: 'Object'},
+            {dbName: 'VARBINARY', dbType: -3, javaType: 'Object'},
+            {dbName: 'LONGVARBINARY', dbType: -4, javaType: 'Object'},
+            {dbName: 'NULL', dbType: 0, javaType: 'Object'},
+            {dbName: 'OTHER', dbType: 1111, javaType: 'Object'},
+            {dbName: 'JAVA_OBJECT', dbType: 2000, javaType: 'Object'},
+            {dbName: 'DISTINCT', dbType: 2001, javaType: 'Object'},
+            {dbName: 'STRUCT', dbType: 2002, javaType: 'Object'},
+            {dbName: 'ARRAY', dbType: 2003, javaType: 'Object'},
+            {dbName: 'BLOB', dbType: 2004, javaType: 'Object'},
+            {dbName: 'CLOB', dbType: 2005, javaType: 'String'},
+            {dbName: 'REF', dbType: 2006, javaType: 'Object'},
+            {dbName: 'DATALINK', dbType: 70, javaType: 'Object'},
+            {dbName: 'BOOLEAN', dbType: 16, javaType: 'Boolean', primitiveType: 'boolean'},
+            {dbName: 'ROWID', dbType: -8, javaType: 'Object'},
+            {dbName: 'NCHAR', dbType: -15, javaType: 'String'},
+            {dbName: 'NVARCHAR', dbType: -9, javaType: 'String'},
+            {dbName: 'LONGNVARCHAR', dbType: -16, javaType: 'String'},
+            {dbName: 'NCLOB', dbType: 2011, javaType: 'String'},
+            {dbName: 'SQLXML', dbType: 2009, javaType: 'Object'}
+        ];
+
+        /*eslint-disable */
+        const JAVA_KEYWORDS = [
+            'abstract',     'assert',        'boolean',      'break',           'byte',
+            'case',         'catch',         'char',         'class',           'const',
+            'continue',     'default',       'do',           'double',          'else',
+            'enum',         'extends',       'false',        'final',           'finally',
+            'float',        'for',           'goto',         'if',              'implements',
+            'import',       'instanceof',    'int',          'interface',       'long',
+            'native',       'new',           'null',         'package',         'private',
+            'protected',    'public',        'return',       'short',           'static',
+            'strictfp',     'super',         'switch',       'synchronized',    'this',
+            'throw',        'throws',        'transient',    'true',            'try',
+            'void',         'volatile',      'while'
+        ];
+        /*eslint-enable */
+
+        const VALID_JAVA_IDENTIFIER = new RegExp('^[a-zA-Z_$][a-zA-Z\\d_$]*$');
+
+        let popover = null;
+
+        function isElementInViewport(el) {
+            const rect = el.getBoundingClientRect();
+
+            return (
+                rect.top >= 0 &&
+                rect.left >= 0 &&
+                rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
+                rect.right <= (window.innerWidth || document.documentElement.clientWidth)
+            );
+        }
+
+        const _showPopoverMessage = (id, message, showTime) => {
+            const body = $('body');
+
+            let el = body.find('#' + id);
+
+            if (!el || el.length === 0)
+                el = body.find('[name="' + id + '"]');
+
+            if (el && el.length > 0) {
+                if (!isElementInViewport(el[0])) {
+                    $location.hash(el[0].id);
+
+                    $anchorScroll();
+                }
+
+                const newPopover = $popover(el, {content: message});
+
+                popover = newPopover;
+
+                $timeout(() => newPopover.$promise.then(() => {
+                    newPopover.show();
+
+                    // Workaround to fix popover location when content is longer than content template.
+                    // https://github.com/mgcrea/angular-strap/issues/1497
+                    $timeout(newPopover.$applyPlacement);
+                }), 400);
+                $timeout(() => newPopover.hide(), showTime || 5000);
+            }
+        };
+
+        function ensureActivePanel(ui, pnl, focusId) {
+            if (ui) {
+                const collapses = $('div.panel-collapse');
+
+                ui.loadPanel(pnl);
+
+                const idx = _.findIndex(collapses, function(collapse) {
+                    return collapse.id === pnl;
+                });
+
+                if (idx >= 0) {
+                    const activePanels = ui.activePanels;
+
+                    if (!_.includes(ui.topPanels, idx)) {
+                        ui.expanded = true;
+
+                        const customExpanded = ui[pnl];
+
+                        if (customExpanded)
+                            ui[customExpanded] = true;
+                    }
+
+                    if (!activePanels || activePanels.length < 1)
+                        ui.activePanels = [idx];
+                    else if (!_.includes(activePanels, idx)) {
+                        const newActivePanels = angular.copy(activePanels);
+
+                        newActivePanels.push(idx);
+
+                        ui.activePanels = newActivePanels;
+                    }
+                }
+
+                if (isDefined(focusId))
+                    Focus.move(focusId);
+            }
+        }
+
+        function showPopoverMessage(ui, panelId, id, message, showTime) {
+            if (popover)
+                popover.hide();
+
+            if (ui) {
+                ensureActivePanel(ui, panelId);
+
+                $timeout(() => _showPopoverMessage(id, message, showTime), ui.isPanelLoaded(panelId) ? 200 : 500);
+            }
+            else
+                _showPopoverMessage(id, message, showTime);
+
+            return false;
+        }
+
+        function isValidJavaIdentifier(msg, ident, elemId, panels, panelId) {
+            if (isEmptyString(ident))
+                return showPopoverMessage(panels, panelId, elemId, msg + ' is invalid!');
+
+            if (_.includes(JAVA_KEYWORDS, ident))
+                return showPopoverMessage(panels, panelId, elemId, msg + ' could not contains reserved java keyword: "' + ident + '"!');
+
+            if (!VALID_JAVA_IDENTIFIER.test(ident))
+                return showPopoverMessage(panels, panelId, elemId, msg + ' contains invalid identifier: "' + ident + '"!');
+
+            return true;
+        }
+
+        let context = null;
+
+        /**
+         * Calculate width of specified text in body's font.
+         *
+         * @param text Text to calculate width.
+         * @returns {Number} Width of text in pixels.
+         */
+        function measureText(text) {
+            if (!context) {
+                const canvas = document.createElement('canvas');
+
+                context = canvas.getContext('2d');
+
+                const style = window.getComputedStyle(document.getElementsByTagName('body')[0]);
+
+                context.font = style.fontSize + ' ' + style.fontFamily;
+            }
+
+            return context.measureText(text).width;
+        }
+
+        /**
+         * Compact java full class name by max number of characters.
+         *
+         * @param names Array of class names to compact.
+         * @param nameLength Max available width in characters for simple name.
+         * @returns {*} Array of compacted class names.
+         */
+        function compactByMaxCharts(names, nameLength) {
+            for (let nameIx = 0; nameIx < names.length; nameIx++) {
+                const s = names[nameIx];
+
+                if (s.length > nameLength) {
+                    let totalLength = s.length;
+
+                    const packages = s.split('.');
+
+                    const packageCnt = packages.length - 1;
+
+                    for (let i = 0; i < packageCnt && totalLength > nameLength; i++) {
+                        if (packages[i].length > 0) {
+                            totalLength -= packages[i].length - 1;
+
+                            packages[i] = packages[i][0];
+                        }
+                    }
+
+                    if (totalLength > nameLength) {
+                        const className = packages[packageCnt];
+
+                        const classNameLen = className.length;
+
+                        let remains = Math.min(nameLength - totalLength + classNameLen, classNameLen);
+
+                        if (remains < 3)
+                            remains = Math.min(3, classNameLen);
+
+                        packages[packageCnt] = className.substring(0, remains) + '...';
+                    }
+
+                    let result = packages[0];
+
+                    for (let i = 1; i < packages.length; i++)
+                        result += '.' + packages[i];
+
+                    names[nameIx] = result;
+                }
+            }
+
+            return names;
+        }
+
+        /**
+         * Compact java full class name by max number of pixels.
+         *
+         * @param names Array of class names to compact.
+         * @param nameLength Max available width in characters for simple name. Used for calculation optimization.
+         * @param nameWidth Maximum available width in pixels for simple name.
+         * @returns {*} Array of compacted class names.
+         */
+        function compactByMaxPixels(names, nameLength, nameWidth) {
+            if (nameWidth <= 0)
+                return names;
+
+            const fitted = [];
+
+            const widthByName = [];
+
+            const len = names.length;
+
+            let divideTo = len;
+
+            for (let nameIx = 0; nameIx < len; nameIx++) {
+                fitted[nameIx] = false;
+
+                widthByName[nameIx] = nameWidth;
+            }
+
+            // Try to distribute space from short class names to long class names.
+            let remains = 0;
+
+            do {
+                for (let nameIx = 0; nameIx < len; nameIx++) {
+                    if (!fitted[nameIx]) {
+                        const curNameWidth = measureText(names[nameIx]);
+
+                        if (widthByName[nameIx] > curNameWidth) {
+                            fitted[nameIx] = true;
+
+                            remains += widthByName[nameIx] - curNameWidth;
+
+                            divideTo -= 1;
+
+                            widthByName[nameIx] = curNameWidth;
+                        }
+                    }
+                }
+
+                const remainsByName = remains / divideTo;
+
+                for (let nameIx = 0; nameIx < len; nameIx++) {
+                    if (!fitted[nameIx])
+                        widthByName[nameIx] += remainsByName;
+                }
+            }
+            while (remains > 0);
+
+            // Compact class names to available for each space.
+            for (let nameIx = 0; nameIx < len; nameIx++) {
+                const s = names[nameIx];
+
+                if (s.length > (nameLength / 2 | 0)) {
+                    let totalWidth = measureText(s);
+
+                    if (totalWidth > widthByName[nameIx]) {
+                        const packages = s.split('.');
+
+                        const packageCnt = packages.length - 1;
+
+                        for (let i = 0; i < packageCnt && totalWidth > widthByName[nameIx]; i++) {
+                            if (packages[i].length > 1) {
+                                totalWidth -= measureText(packages[i].substring(1, packages[i].length));
+
+                                packages[i] = packages[i][0];
+                            }
+                        }
+
+                        let shortPackage = '';
+
+                        for (let i = 0; i < packageCnt; i++)
+                            shortPackage += packages[i] + '.';
+
+                        const className = packages[packageCnt];
+
+                        const classLen = className.length;
+
+                        let minLen = Math.min(classLen, 3);
+
+                        totalWidth = measureText(shortPackage + className);
+
+                        // Compact class name if shorten package path is very long.
+                        if (totalWidth > widthByName[nameIx]) {
+                            let maxLen = classLen;
+                            let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+
+                            while (middleLen !== minLen && middleLen !== maxLen) {
+                                const middleLenPx = measureText(shortPackage + className.substr(0, middleLen) + '...');
+
+                                if (middleLenPx > widthByName[nameIx])
+                                    maxLen = middleLen;
+                                else
+                                    minLen = middleLen;
+
+                                middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+                            }
+
+                            names[nameIx] = shortPackage + className.substring(0, middleLen) + '...';
+                        }
+                        else
+                            names[nameIx] = shortPackage + className;
+                    }
+                }
+            }
+
+            return names;
+        }
+
+        /**
+         * Compact any string by max number of pixels.
+         *
+         * @param label String to compact.
+         * @param nameWidth Maximum available width in pixels for simple name.
+         * @returns {*} Compacted string.
+         */
+        function compactLabelByPixels(label, nameWidth) {
+            if (nameWidth <= 0)
+                return label;
+
+            const totalWidth = measureText(label);
+
+            if (totalWidth > nameWidth) {
+                let maxLen = label.length;
+                let minLen = Math.min(maxLen, 3);
+                let middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+
+                while (middleLen !== minLen && middleLen !== maxLen) {
+                    const middleLenPx = measureText(label.substr(0, middleLen) + '...');
+
+                    if (middleLenPx > nameWidth)
+                        maxLen = middleLen;
+                    else
+                        minLen = middleLen;
+
+                    middleLen = (minLen + (maxLen - minLen) / 2 ) | 0;
+                }
+
+                return label.substring(0, middleLen) + '...';
+            }
+
+            return label;
+        }
+
+        /**
+         * Calculate available width for text in link to edit element.
+         *
+         * @param index Showed index of element for calculation of maximum width in pixels.
+         * @param id Id of contains link table.
+         * @returns {*[]} First element is length of class for single value, second element is length for pair vlaue.
+         */
+        function availableWidth(index, id) {
+            const idElem = $('#' + id);
+
+            let width = 0;
+
+            switch (idElem.prop('tagName')) {
+                // Detection of available width in presentation table row.
+                case 'TABLE':
+                    const cont = $(idElem.find('tr')[index - 1]).find('td')[0];
+
+                    width = cont.clientWidth;
+
+                    if (width > 0) {
+                        const children = $(cont).children(':not("a")');
+
+                        _.forEach(children, function(child) {
+                            if ('offsetWidth' in child)
+                                width -= $(child).outerWidth(true);
+                        });
+                    }
+
+                    break;
+
+                // Detection of available width in dropdown row.
+                case 'A':
+                    width = idElem.width();
+
+                    $(idElem).children(':not("span")').each(function(ix, child) {
+                        if ('offsetWidth' in child)
+                            width -= child.offsetWidth;
+                    });
+
+                    break;
+
+                default:
+            }
+
+            return width | 0;
+        }
+
+        function getModel(obj, field) {
+            let path = field.path;
+
+            if (!isDefined(path) || !isDefined(obj))
+                return obj;
+
+            path = path.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
+            path = path.replace(/^\./, '');           // strip a leading dot
+
+            const segs = path.split('.');
+            let root = obj;
+
+            while (segs.length > 0) {
+                const pathStep = segs.shift();
+
+                if (typeof root[pathStep] === 'undefined')
+                    root[pathStep] = {};
+
+                root = root[pathStep];
+            }
+
+            return root;
+        }
+
+        function extractDataSource(cache) {
+            if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) {
+                const storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind];
+
+                if (storeFactory.dialect || (storeFactory.connectVia === 'DataSource'))
+                    return storeFactory;
+            }
+
+            return null;
+        }
+
+        const cacheStoreJdbcDialects = [
+            {value: 'Generic', label: 'Generic JDBC'},
+            {value: 'Oracle', label: 'Oracle'},
+            {value: 'DB2', label: 'IBM DB2'},
+            {value: 'SQLServer', label: 'Microsoft SQL Server'},
+            {value: 'MySQL', label: 'MySQL'},
+            {value: 'PostgreSQL', label: 'PostgreSQL'},
+            {value: 'H2', label: 'H2 database'}
+        ];
+
+        function domainForStoreConfigured(domain) {
+            const isEmpty = !isDefined(domain) || (isEmptyString(domain.databaseSchema) &&
+                isEmptyString(domain.databaseTable) &&
+                _.isEmpty(domain.keyFields) &&
+                _.isEmpty(domain.valueFields));
+
+            return !isEmpty;
+        }
+
+        const DS_CHECK_SUCCESS = { checked: true };
+
+        function compareDataSources(firstCache, secondCache) {
+            const firstDs = extractDataSource(firstCache);
+            const secondDs = extractDataSource(secondCache);
+
+            if (firstDs && secondDs) {
+                const firstDB = firstDs.dialect;
+                const secondDB = secondDs.dialect;
+
+                if (firstDs.dataSourceBean === secondDs.dataSourceBean && firstDB !== secondDB)
+                    return {checked: false, firstCache, firstDB, secondCache, secondDB};
+            }
+
+            return DS_CHECK_SUCCESS;
+        }
+
+        function compareSQLSchemaNames(firstCache, secondCache) {
+            const firstName = firstCache.sqlSchema;
+            const secondName = secondCache.sqlSchema;
+
+            if (firstName && secondName && (firstName === secondName))
+                return {checked: false, firstCache, secondCache};
+
+            return DS_CHECK_SUCCESS;
+        }
+
+        function toJavaName(prefix, name) {
+            const javaName = name ? name.replace(/[^A-Za-z_0-9]+/g, '_') : 'dflt';
+
+            return prefix + javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1);
+        }
+
+        return {
+            getModel,
+            mkOptions(options) {
+                return _.map(options, (option) => {
+                    return {value: option, label: isDefined(option) ? option : 'Not set'};
+                });
+            },
+            isDefined,
+            hasProperty(obj, props) {
+                for (const propName in props) {
+                    if (props.hasOwnProperty(propName)) {
+                        if (obj[propName])
+                            return true;
+                    }
+                }
+
+                return false;
+            },
+            isEmptyString,
+            SUPPORTED_JDBC_TYPES,
+            findJdbcType(jdbcType) {
+                const res = _.find(ALL_JDBC_TYPES, function(item) {
+                    return item.dbType === jdbcType;
+                });
+
+                return res ? res : {dbName: 'Unknown', javaType: 'Unknown'};
+            },
+            javaBuiltInClasses,
+            javaBuiltInTypes,
+            isJavaBuiltInClass,
+            isValidJavaIdentifier,
+            isValidJavaClass(msg, ident, allowBuiltInClass, elemId, packageOnly, panels, panelId) {
+                if (isEmptyString(ident))
+                    return showPopoverMessage(panels, panelId, elemId, msg + ' could not be empty!');
+
+                const parts = ident.split('.');
+
+                const len = parts.length;
+
+                if (!allowBuiltInClass && isJavaBuiltInClass(ident))
+                    return showPopoverMessage(panels, panelId, elemId, msg + ' should not be the Java build-in class!');
+
+                if (len < 2 && !isJavaBuiltInClass(ident) && !packageOnly)
+                    return showPopoverMessage(panels, panelId, elemId, msg + ' does not have package specified!');
+
+                for (let i = 0; i < parts.length; i++) {
+                    const part = parts[i];
+
+                    if (!isValidJavaIdentifier(msg, part, elemId, panels, panelId))
+                        return false;
+                }
+
+                return true;
+            },
+            domainForQueryConfigured(domain) {
+                const isEmpty = !isDefined(domain) || (_.isEmpty(domain.fields) &&
+                    _.isEmpty(domain.aliases) &&
+                    _.isEmpty(domain.indexes));
+
+                return !isEmpty;
+            },
+            domainForStoreConfigured,
+            /**
+             * Cut class name by width in pixel or width in symbol count.
+             *
+             * @param id Id of parent table.
+             * @param index Row number in table.
+             * @param maxLength Maximum length in symbols for all names.
+             * @param names Array of class names to compact.
+             * @param divider String to visualy divide items.
+             * @returns {*} Array of compacted class names.
+             */
+            compactJavaName(id, index, maxLength, names, divider) {
+                divider = ' ' + divider + ' ';
+
+                const prefix = index + ') ';
+
+                const nameCnt = names.length;
+
+                const nameLength = ((maxLength - 3 * (nameCnt - 1)) / nameCnt) | 0;
+
+                try {
+                    const nameWidth = (availableWidth(index, id) - measureText(prefix) - (nameCnt - 1) * measureText(divider)) /
+                        nameCnt | 0;
+
+                    // HTML5 calculation of showed message width.
+                    names = compactByMaxPixels(names, nameLength, nameWidth);
+                }
+                catch (err) {
+                    names = compactByMaxCharts(names, nameLength);
+                }
+
+                let result = prefix + names[0];
+
+                for (let nameIx = 1; nameIx < names.length; nameIx++)
+                    result += divider + names[nameIx];
+
+                return result;
+            },
+            /**
+             * Compact text by width in pixels or symbols count.
+             *
+             * @param id Id of parent table.
+             * @param index Row number in table.
+             * @param maxLength Maximum length in symbols for all names.
+             * @param label Text to compact.
+             * @returns Compacted label text.
+             */
+            compactTableLabel(id, index, maxLength, label) {
+                label = index + ') ' + label;
+
+                try {
+                    const nameWidth = availableWidth(index, id) | 0;
+
+                    // HTML5 calculation of showed message width.
+                    label = compactLabelByPixels(label, nameWidth);
+                }
+                catch (err) {
+                    const nameLength = maxLength - 3 | 0;
+
+                    label = label.length > maxLength ? label.substr(0, nameLength) + '...' : label;
+                }
+
+                return label;
+            },
+            widthIsSufficient(id, index, text) {
+                try {
+                    const available = availableWidth(index, id);
+
+                    const required = measureText(text);
+
+                    return !available || available >= Math.floor(required);
+                }
+                catch (err) {
+                    return true;
+                }
+            },
+            ensureActivePanel(panels, id, focusId) {
+                ensureActivePanel(panels, id, focusId);
+            },
+            showPopoverMessage,
+            hidePopover() {
+                if (popover)
+                    popover.hide();
+            },
+            confirmUnsavedChanges(dirty, selectFunc) {
+                if (dirty) {
+                    if ($window.confirm('You have unsaved changes.\n\nAre you sure you want to discard them?'))
+                        selectFunc();
+                }
+                else
+                    selectFunc();
+            },
+            saveBtnTipText(dirty, objectName) {
+                if (dirty)
+                    return 'Save ' + objectName;
+
+                return 'Nothing to save';
+            },
+            download(type, name, data) {
+                const file = document.createElement('a');
+
+                file.setAttribute('href', 'data:' + type + ';charset=utf-8,' + data);
+                file.setAttribute('download', name);
+                file.setAttribute('target', '_self');
+
+                file.style.display = 'none';
+
+                document.body.appendChild(file);
+
+                file.click();
+
+                document.body.removeChild(file);
+            },
+            formUI() {
+                return {
+                    ready: false,
+                    expanded: false,
+                    loadedPanels: [],
+                    loadPanel(pnl) {
+                        if (!_.includes(this.loadedPanels, pnl))
+                            this.loadedPanels.push(pnl);
+                    },
+                    isPanelLoaded(pnl) {
+                        return _.includes(this.loadedPanels, pnl);
+                    }
+                };
+            },
+            getQueryVariable(name) {
+                const attrs = window.location.search.substring(1).split('&');
+                const attr = _.find(attrs, (a) => a === name || (a.indexOf('=') >= 0 && a.substr(0, a.indexOf('=')) === name));
+
+                if (!isDefined(attr))
+                    return null;
+
+                if (attr === name)
+                    return true;
+
+                return attr.substr(attr.indexOf('=') + 1);
+            },
+            cacheStoreJdbcDialects,
+            cacheStoreJdbcDialectsLabel(dialect) {
+                const found = _.find(cacheStoreJdbcDialects, function(dialectVal) {
+                    return dialectVal.value === dialect;
+                });
+
+                return found ? found.label : null;
+            },
+            checkCachesDataSources(caches, checkCacheExt) {
+                let res = DS_CHECK_SUCCESS;
+
+                _.find(caches, function(curCache, curIx) {
+                    if (isDefined(checkCacheExt)) {
+                        if (checkCacheExt._id !== curCache._id) {
+                            res = compareDataSources(checkCacheExt, curCache);
+
+                            return !res.checked;
+                        }
+
+                        return false;
+                    }
+
+                    return _.find(caches, function(checkCache, checkIx) {
+                        if (checkIx < curIx) {
+                            res = compareDataSources(checkCache, curCache);
+
+                            return !res.checked;
+                        }
+
+                        return false;
+                    });
+                });
+
+                return res;
+            },
+            checkCacheSQLSchemas(caches, checkCacheExt) {
+                let res = DS_CHECK_SUCCESS;
+
+                _.find(caches, (curCache, curIx) => {
+                    if (isDefined(checkCacheExt)) {
+                        if (checkCacheExt._id !== curCache._id) {
+                            res = compareSQLSchemaNames(checkCacheExt, curCache);
+
+                            return !res.checked;
+                        }
+
+                        return false;
+                    }
+
+                    return _.find(caches, function(checkCache, checkIx) {
+                        if (checkIx < curIx) {
+                            res = compareSQLSchemaNames(checkCache, curCache);
+
+                            return !res.checked;
+                        }
+
+                        return false;
+                    });
+                });
+
+                return res;
+            },
+            autoCacheStoreConfiguration(cache, domains) {
+                const cacheStoreFactory = isDefined(cache.cacheStoreFactory) &&
+                    isDefined(cache.cacheStoreFactory.kind);
+
+                if (!cacheStoreFactory && _.findIndex(domains, domainForStoreConfigured) >= 0) {
+                    const dflt = !cache.readThrough && !cache.writeThrough;
+
+                    return {
+                        cacheStoreFactory: {
+                            kind: 'CacheJdbcPojoStoreFactory',
+                            CacheJdbcPojoStoreFactory: {
+                                dataSourceBean: toJavaName('ds', cache.name),
+                                dialect: 'Generic'
+                            },
+                            CacheJdbcBlobStoreFactory: { connectVia: 'DataSource' }
+                        },
+                        readThrough: dflt || cache.readThrough,
+                        writeThrough: dflt || cache.writeThrough
+                    };
+                }
+            },
+            autoClusterSwapSpiConfiguration(cluster, caches) {
+                const swapConfigured = cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind;
+
+                if (!swapConfigured && _.find(caches, (cache) => cache.swapEnabled))
+                    return {swapSpaceSpi: {kind: 'FileSwapSpaceSpi'}};
+
+                return null;
+            },
+            randomString(len) {
+                const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+                const possibleLen = possible.length;
+
+                let res = '';
+
+                for (let i = 0; i < len; i++)
+                    res += possible.charAt(Math.floor(Math.random() * possibleLen));
+
+                return res;
+            },
+            checkFieldValidators(ui) {
+                const form = ui.inputForm;
+                const errors = form.$error;
+                const errKeys = Object.keys(errors);
+
+                if (errKeys && errKeys.length > 0) {
+                    const firstErrorKey = errKeys[0];
+
+                    const firstError = errors[firstErrorKey][0];
+                    const actualError = firstError.$error[firstErrorKey][0];
+
+                    const errNameFull = actualError.$name;
+                    const errNameShort = errNameFull.endsWith('TextInput') ? errNameFull.substring(0, errNameFull.length - 9) : errNameFull;
+
+                    const extractErrorMessage = function(errName) {
+                        try {
+                            return errors[firstErrorKey][0].$errorMessages[errName][firstErrorKey];
+                        }
+                        catch (ignored) {
+                            try {
+                                return form[firstError.$name].$errorMessages[errName][firstErrorKey];
+                            }
+                            catch (ignited) {
+                                return false;
+                            }
+                        }
+                    };
+
+                    const msg = extractErrorMessage(errNameFull) || extractErrorMessage(errNameShort) || 'Invalid value!';
+
+                    return showPopoverMessage(ui, firstError.$name, errNameFull, msg);
+                }
+
+                return true;
+            }
+        };
+    }
+]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/Messages.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/Messages.service.js b/modules/web-console/src/main/js/app/services/Messages.service.js
new file mode 100644
index 0000000..e679488
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/Messages.service.js
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+// Service to show various information and error messages.
+export default ['IgniteMessages', ['$alert', ($alert) => {
+    // Common instance of alert modal.
+    let msgModal;
+
+    const errorMessage = (prefix, err) => {
+        prefix = prefix || '';
+
+        if (err) {
+            if (err.hasOwnProperty('message'))
+                return prefix + err.message;
+
+            return prefix + err;
+        }
+
+        return prefix + 'Internal error.';
+    };
+
+    const hideAlert = () => {
+        if (msgModal)
+            msgModal.hide();
+    };
+
+    const _showMessage = (err, type, duration, icon) => {
+        hideAlert();
+
+        const title = errorMessage(null, err);
+
+        msgModal = $alert({type, title, duration});
+
+        msgModal.$scope.icon = icon;
+    };
+
+    return {
+        errorMessage,
+        hideAlert,
+        showError(err) {
+            _showMessage(err, 'danger', 10, 'fa-exclamation-triangle');
+
+            return false;
+        },
+        showInfo(err) {
+            _showMessage(err, 'success', 3, 'fa-check-circle-o');
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/ModelNormalizer.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/ModelNormalizer.service.js b/modules/web-console/src/main/js/app/services/ModelNormalizer.service.js
new file mode 100644
index 0000000..4c7052b
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/ModelNormalizer.service.js
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+// Service to normalize objects for dirty checks.
+export default ['IgniteModelNormalizer', () => {
+    /**
+     * Normalize object for dirty checks.
+     *
+     * @param original
+     * @param dest
+     * @returns {*}
+     */
+    const normalize = (original, dest) => {
+        if (_.isUndefined(original))
+            return dest;
+
+        if (_.isObject(original)) {
+            _.forOwn(original, (value, key) => {
+                if (/\$\$hashKey/.test(key))
+                    return;
+
+                const attr = normalize(value);
+
+                if (!_.isNil(attr)) {
+                    dest = dest || {};
+                    dest[key] = attr;
+                }
+            });
+        } else if (_.isBoolean(original) && original === true)
+            dest = original;
+        else if ((_.isString(original) && original.length) || _.isNumber(original))
+            dest = original;
+        else if (_.isArray(original) && original.length)
+            dest = _.map(original, (value) => normalize(value, {}));
+
+        return dest;
+    };
+
+    return {
+        normalize,
+        isEqual(prev, cur) {
+            return _.isEqual(prev, normalize(cur));
+        }
+    };
+}];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js b/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js
new file mode 100644
index 0000000..91244b0
--- /dev/null
+++ b/modules/web-console/src/main/js/app/services/UnsavedChangesGuard.service.js
@@ -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.
+ */
+
+const MSG = 'You have unsaved changes.\n\nAre you sure you want to discard them?';
+
+// Service that show confirmation about unsaved changes on user change location.
+export default ['IgniteUnsavedChangesGuard', ['$rootScope', ($root) => {
+    return {
+        install(scope, customDirtyCheck = () => scope.ui.inputForm.$dirty) {
+            scope.$on('$destroy', () => window.onbeforeunload = null);
+
+            const unbind = $root.$on('$stateChangeStart', (event) => {
+                if (_.get(scope, 'ui.inputForm', false) && customDirtyCheck()) {
+                    if (!confirm(MSG)) // eslint-disable-line no-alert
+                        event.preventDefault();
+                    else
+                        unbind();
+                }
+            });
+
+            window.onbeforeunload = () => _.get(scope, 'ui.inputForm.$dirty', false) ? MSG : null;
+        }
+    };
+}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/cleanup.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/cleanup.service.js b/modules/web-console/src/main/js/app/services/cleanup.service.js
deleted file mode 100644
index bec9ea3..0000000
--- a/modules/web-console/src/main/js/app/services/cleanup.service.js
+++ /dev/null
@@ -1,46 +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.
- */
-
-export default ['$cleanup', () => {
-    const cleanup = (original, dist) => {
-        if (_.isUndefined(original))
-            return dist;
-
-        if (_.isObject(original)) {
-            _.forOwn(original, (value, key) => {
-                if (/\$\$hashKey/.test(key))
-                    return;
-
-                const attr = cleanup(value);
-
-                if (!_.isNil(attr)) {
-                    dist = dist || {};
-                    dist[key] = attr;
-                }
-            });
-        } else if (_.isBoolean(original) && original === true)
-            dist = original;
-        else if ((_.isString(original) && original.length) || _.isNumber(original))
-            dist = original;
-        else if (_.isArray(original) && original.length)
-            dist = _.map(original, (value) => cleanup(value, {}));
-
-        return dist;
-    };
-
-    return cleanup;
-}];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/services/confirm.service.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/services/confirm.service.js b/modules/web-console/src/main/js/app/services/confirm.service.js
deleted file mode 100644
index bb07cfd..0000000
--- a/modules/web-console/src/main/js/app/services/confirm.service.js
+++ /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.
- */
-
-// Confirm popup service.
-export default ['$confirm', ['$modal', '$rootScope', '$q', '$animate', ($modal, $root, $q, $animate) => {
-    const scope = $root.$new();
-
-    const modal = $modal({templateUrl: '/templates/confirm.html', scope, placement: 'center', show: false});
-
-    let deferred;
-
-    const _hide = (animate) => {
-        $animate.enabled(modal.$element, animate);
-
-        modal.hide();
-    };
-
-    scope.confirmYes = () => {
-        _hide(scope.animate);
-
-        deferred.resolve(true);
-    };
-
-    scope.confirmNo = () => {
-        _hide(scope.animate);
-
-        deferred.resolve(false);
-    };
-
-    scope.confirmCancel = () => {
-        _hide(true);
-
-        deferred.reject('cancelled');
-    };
-
-    /**
-     *
-     * @param {String } content
-     * @param {Boolean} [yesNo]
-     * @param {Boolean} [animate]
-     * @returns {Promise}
-     */
-    modal.confirm = (content, yesNo, animate) => {
-        scope.animate = !!animate;
-        scope.content = content || 'Confirm?';
-        scope.yesNo = !!yesNo;
-
-        deferred = $q.defer();
-
-        modal.$promise.then(modal.show);
-
-        return deferred.promise;
-    };
-
-    return modal;
-}]];

http://git-wip-us.apache.org/repos/asf/ignite/blob/c38b3ba2/modules/web-console/src/main/js/app/vendor.js
----------------------------------------------------------------------
diff --git a/modules/web-console/src/main/js/app/vendor.js b/modules/web-console/src/main/js/app/vendor.js
new file mode 100644
index 0000000..a8eeea7
--- /dev/null
+++ b/modules/web-console/src/main/js/app/vendor.js
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+import 'jquery';
+import 'angular';
+import 'angular-animate';
+import 'angular-sanitize';
+import 'angular-strap';
+import 'angular-strap/dist/angular-strap.tpl';
+import 'angular-socket-io';
+import 'angular-retina';
+import 'angular-ui-router';
+import 'ui-router-metatags/dist/ui-router-metatags';
+import 'angular-smart-table';
+import 'angular-ui-grid/ui-grid';
+import 'angular-drag-and-drop-lists';
+import 'angular-nvd3';
+import 'angular-tree-control';
+import 'angular-gridster';
+import 'bootstrap-sass/assets/javascripts/bootstrap/transition';
+import 'bootstrap-sass/assets/javascripts/bootstrap/carousel';
+import 'brace';
+import 'brace/mode/xml';
+import 'brace/mode/sql';
+import 'brace/mode/java';
+import 'brace/mode/dockerfile';
+import 'brace/mode/snippets';
+import 'brace/theme/chrome';
+import 'brace/ext/language_tools';
+import 'brace/ext/searchbox';
+import 'file-saver';
+import 'jszip';
+import 'nvd3';
+import 'query-command-supported';
+import 'angular-gridster/dist/angular-gridster.min.css';
+import 'angular-tree-control/css/tree-control-attribute.css';
+import 'angular-tree-control/css/tree-control.css';
+import 'angular-ui-grid/ui-grid.css';
+import 'angular-motion/dist/angular-motion.css';
+import 'nvd3/build/nv.d3.css';